introducción a la programación en juliacomenzó la migración a julia v1.0 • robin deits...

303
Introducción a la Programación en Julia Ben Lauwens y Allen Downey. Traducido por Pamela Alejandra Bustamante Faúndez

Upload: others

Post on 27-Mar-2021

4 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar

Introduccioacuten a la Programacioacuten en JuliaBen Lauwens y Allen Downey

Traducido por Pamela Alejandra Bustamante Fauacutendez

Tabla de ContenidoLicencia 1Dedicatoria 2Prefacio 31 El camino de la programacioacuten 72 Variables expresiones y sentencias 173 Funciones 274 Estudio de Caso Disentildeo de Interfaz 425 Condicionales y recursividad 566 Funciones productivas 707 Iteracioacuten 868 Cadenas 979 Estudio de Caso Juego de Palabras 11310 Arreglos 12211 Diccionarios 14212 Tuplas 15813 Estudio de Caso Seleccioacuten de Estructura de Datos 17114 Archivos 18615 Estructuras y Objetos 19916 Estructuras y Funciones 20817 Dispatch Muacuteltiple 21618 Subtipos 22819 Extra Sintaxis 24320 Extra Base y Libreriacutea Estaacutendar 25921 Depuracioacuten 271Apeacutendice A Entrada de Unicode 281Apeacutendice B JuliaBox 282Apeacutendice C Cambios de ThinkJulia 285Index 286

LicenciaCopyright copy 2018 Allen Downey Ben Lauwens Todos los derechos reservados

Este libro estaacute disponible bajo la Licencia Creative Commons Atribucioacuten-NoComercial 30 No portada Es una traduccioacuten de ThinkJulia el cual tiene lamisma licencia Una lista de las diferencias entre ThinkJulia y este libro estaacutedisponible en el Apeacutendice C

Un PDF de este libro estaacute disponible aquiacute

Ben Lauwens es profesor de matemaacuteticas en Royal Military Academy (RMABeacutelgica) Tiene un doctorado en ingenieriacutea y maestriacuteas de KU Leuven y RMAademaacutes de una licenciatura de RMA

Allen Downey es profesor de informaacutetica en Olin College of Engineering Hadado clases en Wellesley College Colby College y UC Berkeley Tiene undoctorado en informaacutetica de UC Berkeley y maestriacuteas y licenciaturas del MIT

Licencia 1

DedicatoriaPara Emeline Arnaud y Tibo

2 Dedicatoria

PrefacioEn enero de 2018 comenceacute a preparar un curso de programacioacuten pensado paraestudiantes que no tuvieran experiencia previa en programacioacuten Queriacutea usarJulia como lenguaje de programacioacuten y descubriacute que no existiacutea ninguacuten libro paraaprender a programar que usara Julia como primer lenguaje de programacioacutenHay tutoriales maravillosos que explican los conceptos clave de Julia peroninguno de ellos se dedicaba lo suficiente a ensentildear a pensar como programador

Conociacutea el libro Think Python de Allen Downey el cual contiene todos loselementos clave para aprender a programar correctamente Sin embargo estelibro se basa en el lenguaje de programacioacuten Python Mi primer borrador delcurso fue una mezcla de muchas referencias pero a medida que trabajaba eneste el contenido comenzoacute a parecerse cada vez maacutes a los capiacutetulos de ThinkPython Pronto la idea de desarrollar mi curso como base para trasladar eselibro a Julia se hizo realidad

Todo el material estaba disponible en un repositorio de GitHub en forma denotebooks de Jupyter Despueacutes de publicar un mensaje en el sitio Discourse deJulia sobre el progreso de mi curso los comentarios fueron abrumadoresAparentemente un libro sobre conceptos baacutesicos de programacioacuten con Juliacomo primer lenguaje de programacioacuten era algo que faltaba en el universo deJulia Contacteacute a Allen para ver si podiacutea iniciar oficialmente la versioacuten de ThinkPython para Julia y su respuesta fue inmediata ldquoiexcladelanterdquo me puso encontacto con su editor de OrsquoReilly Media y ahora un antildeo despueacutes estoy haciendolos retoques finales a este libro

Fue un camino difiacutecil En Agosto de 2018 se lanzoacute Julia v10 y como todos miscolegas programadores de Julia tuve que hacer una migracioacuten del coacutedigo Todoslos ejemplos en el libro se prueban durante la conversioacuten de los archivos fuente aarchivos ASCIIDoc compatibles con OrsquoReilly Tanto la cadena de herramientascomo el coacutedigo de los ejemplos teniacutean que ser compatibles con Julia v10Afortunadamente no hay cursos en Agostohellip

Espero que disfrutes al trabajar con este libro y que te ayude a aprender aprogramar y pensar como informaacutetico al menos un poco

Ben Lauwens

iquestPor queacute JuliaJulia fue lanzado originalmente en 2012 por Alan Edelman Stefan Karpinski JeffBezanson y Viral Shah Es un lenguaje de programacioacuten gratuito y de coacutedigoabierto

La eleccioacuten de un lenguaje de programacioacuten es siempre subjetiva Para miacute lassiguientes caracteriacutesticas de Julia son decisivas

iquestPor queacute Julia 3

bull Julia estaacute desarrollado como un lenguaje de programacioacuten de altorendimiento

bull Julia usa enviacuteo muacuteltiple (ldquomultiple dispatchrdquo en ingleacutes) que le permite alprogramador elegir entre diferentes patrones de programacioacuten de acuerdoa la aplicacioacuten

bull Julia es un lenguaje de tipo dinaacutemico que se puede usar faacutecilmente de formainteractiva

bull Julia tiene una sintaxis de alto nivel que es faacutecil de aprender

bull Julia es un lenguaje de programacioacuten con tipos opcionales cuyos tipos dedatos (definidos por el usuario) hacen que el coacutedigo sea claro y robusto

bull Julia tiene una biblioteca estaacutendar extendida ademaacutes estaacuten disponiblesnumerosos paquetes de terceros

Julia es un lenguaje de programacioacuten uacutenico ya que resuelve el problema de losdos idiomas No se necesita de ninguacuten otro lenguaje de programacioacuten paraescribir coacutedigo de alto rendimiento Esto no significa que ocurraautomaacuteticamente Es responsabilidad del programador optimizar el coacutedigo quegenere cuellos de botella aunque esto puede hacerse directamente en Julia

iquestA quieacuten estaacute dirigido este libroEste libro es para cualquier persona que quiera aprender a programar No serequieren conocimientos formales previos

Los nuevos conceptos se introducen gradualmente y los temas maacutes avanzados sedescriben en capiacutetulos posteriores

Introduccioacuten a Julia puede ser usado como un curso de un semestre de nivelsecundario o universitario

Convenciones utilizadas en este libroEn este libro se siguen las siguientes convenciones tipograacuteficas

CursivaIndica nuevos teacuterminos URL direcciones de correo electroacutenico nombres dearchivo y extensiones de archivo

Ancho constanteSe utiliza para mostrar coacutedigo de programas asiacute como dentro de lospaacuterrafos para referirse a elementos del programa como nombres devariables o funciones bases de datos tipos de datos variables de entornosentencias y palabras reservadas

4 Prefacio

Ancho constante en negrita

Muestra comandos u otro texto que el usuario debe escribir

Ancho constante en cursivaMuestra el texto que debe reemplazarse con valores proporcionados por elusuario o por valores determinados por el contexto

OBSERVACIOacuteN Esto indica consejo o sugerencia

NOTA Esto es una nota general

AVISO Esto indica una advertencia o precaucioacuten

Usando los coacutedigos de ejemploTodo el coacutedigo utilizado en este libro estaacute disponible en un repositorio de Git enGitHub httpsgithubcomJuliaIntroIntroAJuliajl Si no estaacute familiarizado conGit es un sistema de control de versiones que le permite realizar seguimiento alos archivos que componen un proyecto Una coleccioacuten de archivos controladospor Git se denomina ldquorepositoriordquo GitHub es un servicio de hosting queproporciona almacenamiento para repositorios de Git y una interfaz webconveniente

El siguiente paquete puede ser de utilidad y se puede agregar directamente aJulia Simplemente escriba add httpsgithubcomJuliaIntroIntroAJuliajlen el REPL en modo Pkg

La forma maacutes faacutecil de ejecutar un coacutedigo de Julia es yendo a httpsjuliaboxcome iniciar una sesioacuten de prueba gratuita Es posible utilizar tanto las interfacesREPL como de notebooks Si desea tener Julia instalada localmente en sucomputadora puede descargar JuliaPro de Julia Computing gratuitamenteConsiste en una versioacuten reciente de Julia el IDE de Juno basado en Atom y variospaquetes de Julia preinstalados Si es maacutes aventurero puede descargar Juliadesde httpsjulialangorg instale el editor que prefiera por ejemplo Atom oVisual Studio Code activando los complementos para su integracioacuten de Julia Enel caso de una instalacioacuten local tambieacuten puede agregar el paquete IJulia que lepermite ejecutar un notebook de Jupyter en su computadora

AgradecimientosRealmente quiero agradecer a Allen por escribir Think Python y permitirmetrasladar este libro a Julia iexclTu entusiasmo es contagioso

Tambieacuten me gustariacutea agradecer a los revisores teacutecnicos de este libro quehicieron muchas sugerencias uacutetiles Tim Besard Bart Janssens y David P

Usando los coacutedigos de ejemplo 5

Sanders

Gracias a Melissa Potter de OrsquoReilly Media por hacer de este un mejor libro Meobligaste a hacer las cosas bien y hacer que este libro sea lo maacutes originalposible

Gracias a Matt Hacker de OrsquoReilly Media que me ayudoacute con la cadena deherramientas Atlas y algunos problemas al destacar la sintaxis

Gracias a todos los estudiantes que trabajaron con una versioacuten temprana de estelibro y a todos los colaboradores (enumerados a continuacioacuten) que enviaroncorrecciones y sugerencias

Lista de ColaboradoresSi tiene una sugerencia o correccioacuten abra un issue en GitHub Si se realiza uncambio basado en sus comentarios seraacute agregado a la lista de contribuyentes (amenos que solicite ser omitido)

Aviacutesenos con queacute versioacuten del libro estaacute trabajando y en queacute formato Si incluyeal menos parte de la oracioacuten en la que aparece el error eso facilita la buacutesquedaLos nuacutemeros de paacutegina y seccioacuten tambieacuten son uacutetiles pero no es tan faacutecil trabajarcon ellos iexclGracias

bull Scott Jones sentildealoacute el cambio de nombre de Void a Nothing y con esto secomenzoacute la migracioacuten a Julia v10

bull Robin Deits encontroacute algunos errores tipograacuteficos en el Capiacutetulo 2

bull Mark Schmitz sugirioacute destacar la sintaxis

bull Zigu Zhao encontroacute algunos errores en el Capiacutetulo 8

bull Oleg Soloviev detectoacute un error en la url al agregar el paquete ThinkJulia

bull Aaron Ang encontroacute algunos problemas de representacioacuten y nomenclatura

bull Sergey Volkov encontroacute un enlace caiacutedo en el Capiacutetulo 7

bull Sean McAllister sugirioacute mencionar el excelente paquete BenchmarkTools

bull Carlos Bolech envioacute una larga lista de correcciones y sugerencias

bull Krishna Kumar corrigioacute el ejemplo de Markov en el Capiacutetulo 18

6 Prefacio

Capiacutetulo 1 El camino de la programacioacutenEl objetivo de este libro es ensentildearle a pensar como un informaacutetico Esta manerade pensar combina las mejores caracteriacutesticas de las matemaacuteticas la ingenieriacutea ylas ciencias naturales Los informaacuteticos al igual que los matemaacuteticos usanlenguajes formales para expresar ideas (especiacuteficamente caacutelculos) De manerasimilar a los ingenieros disentildean estructuras ensamblan componentes paraformar sistemas evaluando los costos y beneficios entre las alternativasAdemaacutes observan el comportamiento de sistemas complejos elaboran hipoacutetesisy prueban predicciones como los cientiacuteficos

La habilidad maacutes importante para un informaacutetico es la resolucioacuten de problemasEsto implica ser capaz de formular problemas encontrar soluciones creativasexpresando una solucioacuten de forma clara y precisa Como resultado el proceso deaprender a programar es una excelente oportunidad para practicar habilidadesde resolucioacuten de problemas Es por ello que este capiacutetulo se llama El camino dela programacioacuten

Por una parte aprenderaacute a programar que es una habilidad muy uacutetil por siacutemisma Pero ademaacutes la programacioacuten se constituiraacute como un medio para un finA medida que avancemos este fin seraacute maacutes claro

iquestQueacute es un programa

Un programa es una secuencia de instrucciones que especifica coacutemo hacer uncaacutelculo El caacutelculo puede ser de naturaleza matemaacutetica tal como resolver unsistema de ecuaciones o encontrar las raiacuteces de un polinomio pero tambieacutenpuede ser un caacutelculo simboacutelico como buscar y reemplazar texto en undocumento o bien algo graacutefico tal como procesar una imagen o reproducir unvideo

Los detalles difieren para cada lenguaje pero algunas instrucciones baacutesicasaparecen en casi todos los lenguajes

EntradaInputSe obtienen datos a traveacutes del teclado un archivo una red u otrodispositivo

SalidaOutputLos datos se muestran por pantalla se guardan en un archivo se enviacutean atraveacutes de la red etc

MatemaacuteticasSe realizan operaciones matemaacuteticas baacutesicas como la suma y lamultiplicacioacuten

iquestQueacute es un programa 7

Ejecucioacuten condicionalSe verifican ciertas condiciones y se ejecuta el coacutedigo apropiado

RepeticioacutenSe realiza alguna accioacuten repetidamente generalmente con alguna variacioacuten

Aunque no lo crea eso es todo lo que se debe hacer Cada programa que hausado sin importar su complejidad estaacute construido basaacutendose en instruccionesque se asemejan a estas De esta manera la programacioacuten puede entendersecomo el proceso de dividir una tarea compleja y larga en pequentildeas subtareas losuficientemente simples como para realizarse con una de estas instruccionesbaacutesicas

Ejecutando Julia

Uno de los desafiacuteos al comenzar a utilizar Julia es su instalacioacuten ademaacutes delsoftware relacionado Si estaacute familiarizado con su sistema operativo y se sientecoacutemodo con la interfaz de liacutenea de comandos no tendraacute problemas No obstantepara los principiantes puede ser difiacutecil aprender sobre administracioacuten de sistemay programacioacuten al mismo tiempo

Para evitar ese problema se recomienda que comience ejecutando Julia en unnavegador Maacutes tarde cuando se sienta coacutemodo con Julia se haraacuten sugerenciaspara instalar Julia en su ordenador

En el navegador puede ejecutar Julia en JuliaBox No se requiere instalacioacutensimplemente abra su navegador y entre a la paacutegina de JuliaBox inicie sesioacuten ycomience a programar (consulte Apeacutendice B)

Julia REPL (de ReadndashEvalndashPrint Loop que se traduce en Bucle de Leer-Evaluar-Imprimir) es un programa que lee y ejecuta coacutedigo de Julia Puede iniciar REPLabriendo un terminal en JuliaBox y escribiendo julia en la liacutenea de comandoCuando comienza deberiacutea ver una salida como esta

_ _ _ _(_)_ | Documentation httpsdocsjulialangorg (_) | (_) (_) | _ _ _| |_ __ _ | Type for help ] for Pkg help | | | | | | | _` | | | | |_| | | | (_| | | Version 152 (2020-09-23) _ |___|_|_|___| | Official httpsjulialangorg release|__ |

juliagt

Las primeras liacuteneas contienen informacioacuten sobre el REPL por lo que esto puede

8 Capiacutetulo 1 El camino de la programacioacuten

mostrarse diferente en su computadora Debe verificar que la versioacuten sea almenos 100

El uacuteltima liacutenea es un indicador sentildealando que el REPL estaacute listo para que seingrese una instruccioacuten Si escribe una liacutenea de coacutedigo y presiona Enter la REPLmuestra el resultado

juliagt 1 + 12

Los fragmentos de coacutedigo se pueden copiar y pegar textualmente incluido elindicador juliagt y cualquier salida

Ahora ya estaacute listo para comenzar De aquiacute en adelante ya sabraacute coacutemo iniciar laREPL de Julia y ejecutar su coacutedigo

El primer programaTradicionalmente el primer programa que se escribe en un nuevo lenguaje sellama ldquoiexclHola mundordquo porque todo lo que hace es mostrar las palabras ldquoiexclHolamundordquo En Julia se ve asiacute

juliagt println(iexclHola mundo)iexclHola mundo

Este es un ejemplo de una sentencia de impresioacuten aunque en realidad noimprime nada en papel Muestra un resultado en la pantalla

Las comillas en el programa marcan el principio y el final del texto que semostraraacute y no apareceraacuten en el resultado

Los pareacutentesis indican que println es una funcioacuten Se estudiaraacuten funciones enCapiacutetulo 3

Operadores aritmeacuteticos

Despueacutes de nuestro programa ldquoiexclHola mundordquo el siguiente paso es laaritmeacutetica Julia tiene operadores los cuales son siacutembolos que representancaacutelculos como la suma y la multiplicacioacuten

Los operadores + - y realizan las operaciones de suma resta y multiplicacioacutenrespectivamente como se muestra en los siguientes ejemplos

El primer programa 9

juliagt 40 + 242juliagt 43 - 142juliagt 6 742

El operador realiza la divisioacuten

juliagt 842420

Quizaacutes se pregunte por queacute el resultado es 420 en vez de 42 Esto seraacuteexplicado en la siguiente seccioacuten

Finalmente el operador ^ realiza la potencicioacuten es decir eleva un nuacutemero a unapotencia

juliagt 6^2 + 642

Valores y tipos

Un valor es uno de los elementos baacutesicos con los que trabaja un programa talcomo una letra o un nuacutemero Algunos de los valores que hemos visto hasta ahorason 2 420 y Hola Mundo

Estos valores pertenecen a diferentes tipos 2 es un entero (integer en ingleacutes)420 es un nuacutemero de punto flotante (floating-point number en ingleacutes) y HolaMundo es una cadena de caracteres (string en ingleacutes) llamada asiacute porque lasletras que contiene estaacuten unidas

Si no estaacute seguro del tipo de un valor el REPL puede ayudarle

juliagt typeof(2)Int64juliagt typeof(420)Float64juliagt typeof(iexclHola mundo)String

Los enteros pertenecen al tipo Int64 las cadenas pertenecen a String y losnuacutemeros de punto flotante pertenecen a Float64

10 Capiacutetulo 1 El camino de la programacioacuten

iquestQueacute pasa con los valores 2 y 420 Parecen nuacutemeros pero estaacuten entrecomillas como si fueran cadenas Estos valores tambieacuten son cadenas

juliagt typeof(2)Stringjuliagt typeof(420)String

Si se quiere escribir un nuacutemero de grandes dimensiones se podriacutea caer en lacostumbre de usar comas para separar sus cifras como por ejemplo 1000000Este no es un entero vaacutelido en Julia aunque siacute es vaacutelido

juliagt 1000000(1 0 0)

iexclEsto no es lo que se podriacutea esperar Julia entiende 1000000 como unasecuencia de enteros separados por comas Maacutes adelante aprenderemos maacutessobre este tipo de secuencias

Sin embargo puede obtener el resultado esperado usando 1_000_000

Lenguajes formales y naturales

Los lenguajes naturales son los lenguajes hablados como el espantildeol el ingleacutes oel franceacutes no fueron disentildeados por personas (aunque las personas intentanimponerles un orden) sino que evolucionaron naturalmente

Los lenguajes formales son lenguajes disentildeados por personas para propoacutesitosespeciacuteficos Por ejemplo la notacioacuten que usan los matemaacuteticos es un lenguajeformal particularmente uacutetil para denotar relaciones entre nuacutemeros y siacutembolosLos quiacutemicos usan un lenguaje formal para representar la estructura quiacutemica delas moleacuteculas Los lenguajes de programacioacuten tambieacuten son lenguajes formales yhan sido disentildeados para expresar caacutelculos

Los lenguajes formales tienden a dictar reglas estrictas de sintaxis quegobiernan la estructura de las sentencias Por ejemplo en matemaacuteticas lasentencia tiene la sintaxis correcta pero no En quiacutemica esuna foacutermula sintaacutecticamente correcta pero no lo es

Las reglas de sintaxis pueden ser de dos tipos correspondientes a componentesleacutexicos y a estructura Los componentes leacutexicos son los elementos baacutesicos dellenguaje como palabras nuacutemeros y elementos quiacutemicos Uno de los problemascon es que no es un componente leacutexico vaacutelido en matemaacuteticas (al menos

Lenguajes formales y naturales 11

hasta donde conocemos) Del mismo modo no es vaacutelido porque no existeninguacuten elemento con la abreviatura

El segundo tipo de reglas de sintaxis se refiere a la forma en que se combinan loscomponentes leacutexicos La ecuacioacuten no es vaacutelida porque aunque y soncomponentes leacutexicos vaacutelidos no se puede tener uno justo despueacutes el otro Delmismo modo en una foacutermula quiacutemica el subiacutendice se coloca despueacutes del nombredel elemento no antes

Esta es un oracioacuten en espa$ol bien estructurada con cmponentes leacutexicos novaacutelidos Esta oracioacuten leacutexicos todos componentes los tiene pero estructura una novaacutelida con

Cuando se lee una oracioacuten en espantildeol o en un lenguaje formal se tiene quedescubrir la estructura (aunque en un lenguaje natural se haceinconscientemente) Este proceso se llama parsing o anaacutelisis de sintaxis

Aunque los lenguajes formales y naturales tienen muchas caracteriacutesticas encomuacutenmdashcomponentes leacutexicos estructura y sintaxismdashexisten algunas diferencias

AmbiguumledadLos lenguajes naturales estaacuten llenos de ambiguumledades este problema esabordado mediante el uso del contexto y otra informacioacuten Los lenguajesformales estaacuten disentildeados para ser casi completamente precisos lo quesignifica que cualquier declaracioacuten tiene exactamente un significadoindependientemente del contexto

RedundanciaPara compensar la ambiguumledad y reducir los malentendidos los lenguajesnaturales emplean mucha redundancia Como resultado a menudo sonverbosos Los lenguajes formales son menos redundantes y maacutes concisos

MetaacuteforaLos lenguajes naturales estaacuten llenos de modismos y metaacuteforas Si se diceldquoCaiacute en la cuentardquo probablemente no haya una cuenta y nada que se caiga(este modismo significa que alguien entendioacute algo despueacutes de un periacuteodo deconfusioacuten) Por otro lado los lenguajes formales significan exactamente loque expresan

Debido a que todo el mundo crece hablando lenguajes naturales a veces esdifiacutecil adaptarse a los lenguajes formales La diferencia entre lenguaje formal ynatural es como la diferencia entre la poesiacutea y la prosa

PoesiacuteaLas palabras se usan por sus sonidos y significados El poema en conjuntocrea un efecto o una respuesta emocional La ambiguumledad no soacutelo es comuacutensino a menudo deliberada

12 Capiacutetulo 1 El camino de la programacioacuten

ProsaEl significado literal de las palabras es maacutes importante y la estructuraaporta significado La prosa es maacutes faacutecil de analizar que la poesiacutea pero amenudo sigue siendo ambigua

ProgramasEl significado de un programa computacional es inequiacutevoco y literal ypuede entenderse por completo mediante el anaacutelisis de los componentesleacutexicos y de estructura

Los lenguajes formales son maacutes densos que los naturales por lo que lleva maacutestiempo leerlos Ademaacutes la estructura es importante por lo que no siempre esmejor leer de arriba a abajo y de izquierda a derecha En cambio aprenderaacute aanalizar el programa mentalmente identificando los componentes leacutexicos einterpretando la estructura Finalmente los detalles son importantes Pequentildeoserrores de ortografiacutea y puntuacioacuten que pueden pasar desapercibidos en loslenguajes naturales pueden hacer una gran diferencia en un lenguaje formal

Depuracioacuten

Los programadores cometen errores Los errores de programacioacuten se denominanbugs y el proceso para rastrearlos se denomina debugging o depuracioacuten

La programacioacuten y especialmente la depuracioacuten pueden provocar emocionesnegativas Frente a un error difiacutecil de solucionar puede sentir enojo verguumlenzaoacute cansancio

Existe evidencia de que las personas responden naturalmente a lascomputadoras como si fueran personas Cuando trabajan bien se los consideracompantildeeros de equipo y cuando son obstinados o groseros se los trata de lamisma manera que a personas groseras y obstinadas [1]

Prepararse para estas reacciones puede ayudarlo a lidiar con ellas Un enfoquees pensar en la computadora como un empleado con ciertas fortalezas como lavelocidad y la precisioacuten y debilidades particulares como la falta de empatiacutea y laincapacidad para comprender el panorama general

Su trabajo es ser un buen gerente debe encontrar formas de aprovechar lasfortalezas y mitigar las debilidades Ademaacutes debe encontrar formas de usar susemociones para involucrarse con el problema sin dejar que sus reaccionesinterfieran con su capacidad para trabajar de manera efectiva

Aprender a depurar puede ser frustrante pero es una habilidad valiosa que esuacutetil para muchas actividades maacutes allaacute de la programacioacuten Al final de cadacapiacutetulo hay una seccioacuten como esta con algunas sugerencias para ladepuracioacuten iexclEspero que le sean de ayuda

Depuracioacuten 13

Glosarioresolucioacuten de problemas

El proceso de formular un problema encontrar una solucioacuten y expresarla

programaUna secuencia de instrucciones que especifica un caacutelculo

REPLUn programa que de manera reiterada lee una entrada la ejecuta y generaresultados

indicadorCaracteres mostrados por el REPL para indicar que estaacute listo para recibirinformacioacuten de entrada de parte del usuario

sentencia de impresioacuten (print)Una instruccioacuten que hace que el REPL de Julia muestre un valor en lapantalla

operadorUn siacutembolo que representa un caacutelculo simple como la suma lamultiplicacioacuten o la concatenacioacuten de cadenas

valorUna de las unidades baacutesicas de datos como un nuacutemero o cadena quemanipula un programa

tipoUna categoriacutea de valores Los tipos que se han visto hasta ahora sonenteros (Int64) nuacutemeros de punto flotante (Float64) y cadenas (String)

enteroUn tipo que representa nuacutemeros enteros

punto flotanteUn tipo que representa nuacutemeros con un punto decimal

cadenaUn tipo que representa secuencias de caracteres

lenguaje naturalCualquier lenguaje hablado que evoluciona naturalmente

14 Capiacutetulo 1 El camino de la programacioacuten

lenguaje formalCualquier lenguaje disentildeado para fines especiacuteficos como la representacioacutende ideas matemaacuteticas o programas de computadora Todos los lenguajes deprogramacioacuten son lenguajes formales

sintaxisLas reglas que gobiernan la estructura de un programa

componente leacutexicoUno de los elementos baacutesicos de la estructura de un programa anaacutelogo auna palabra en un lenguaje natural

estructuraLa manera en que los componentes leacutexicos se combinan

anaacutelisis de sintaxisExaminar un programa y analizar la estructura sintaacutectica

bugUn error en un programa

depuracioacutendebuggingEl proceso de buacutesqueda y correccioacuten de errores

Ejercicios

OBSERVACIOacuteNEs una buena idea leer este libro frente a unacomputadora para hacer los ejemplos y ejerciciosconforme avance

Ejercicio 1-1

Siempre que esteacute experimentando con algo nuevo debe intentar cometererrores Por ejemplo en el programa ldquoiexclHola mundordquo iquestQueacute sucede si omite unade las comillas iquestQueacute pasa si omite ambas iquestQueacute ocurre si escribe mal println

Este tipo de ejercicios le ayuda a recordar lo que leyoacute tambieacuten le ayuda aprogramar porque puede saber queacute significan los mensajes de error Es mejorcometer errores ahora y a propoacutesito en lugar de despueacutes y accidentalmente

1 En un comando print iquestQueacute sucede si omite uno de los pareacutentesis o ambos

2 Si estaacute intentando imprimir un string iquestQueacute sucede si omite una de lascomillas o ambas

3 Se puede usar un signo menos para escribir un nuacutemero negativo como -2

Ejercicios 15

iquestQueacute sucede si pone un signo + antes de un nuacutemero iquestQueacute pasa con 2++2

4 En notacioacuten matemaacutetica los ceros a la izquierda son correctos como en 02iquestQueacute pasa si intenta esto en Julia

5 iquestQueacute sucede si tiene dos valores sin operador entre ellos

Ejercicio 1-2

Inicie el REPL de Julia y uacuteselo como una calculadora

1 iquestCuaacutentos segundos hay en 42 minutos y 42 segundos

2 iquestCuaacutentas millas hay en 10 kiloacutemetros

OBSERVACIOacuteN Hay 161 kiloacutemetros en una milla

3 Si corre una carrera de 10 kiloacutemetros en 37 minutos y 48 segundos iquestCuaacuteles su ritmo promedio (tiempo por milla en minutos y segundos) iquestCuaacutel es suvelocidad promedio en millas por hora

[1] Reeves Byron and Clifford Ivar Nass 1996 ldquoThe Media Equation How People Treat ComputersTelevision and New Media Like Real People and Placesrdquo Chicago IL Center for the Study of Language andInformation New York Cambridge University Press

16 Capiacutetulo 1 El camino de la programacioacuten

Capiacutetulo 2 Variables expresiones y sentenciasUna de las caracteriacutesticas maacutes poderosas de un lenguaje de programacioacuten es lacapacidad de manipular variables Una variable es un nombre que hacereferencia a un valor

Sentencias de asignacioacuten

Una sentencia de asignacioacuten crea una nueva variable y le asigna un valor

juliagt mensaje = Y ahora algo completamente diferenteY ahora algo completamente diferentejuliagt n = 1717juliagt π_val = 31415926535897933141592653589793

Este ejemplo realiza tres asignaciones La primera asigna una cadena a unanueva variable llamada mensaje la segunda le asigna el entero 17 a la variable nla tercera asigna el valor (aproximado) de π (pi TAB) a la variable π_val

Una forma comuacuten de representar variables en papel es escribir el nombre de lavariable con una flecha apuntando a su valor Este tipo de figura se llamaldquodiagrama de estadordquo porque muestra en queacute estado se encuentra cada una delas variables La Figura 1 Figura 1 muestra el resultado del ejemplo anterior

Figura 1 Diagrama de estado

Nombres de variablesLos programadores generalmente eligen nombres representativos para susvariables es decir nombres que explican para queacute se usa o queacute contiene lavariable

Los nombres de las variables pueden ser tan largos como se desee Puedencontener casi todos los caracteres Unicode (consulte Seccioacuten 81) pero nopueden comenzar con un nuacutemero Es vaacutelido usar letras mayuacutesculas pero locomuacuten es usar solo minuacutesculas para nombres de variables

Los caracteres Unicode se pueden ingresar mediante autocompletado portabulacioacuten de las abreviaturas tipo LaTeX en el REPL de Julia

El caraacutecter guioacuten bajo _ puede formar parte del nombre de una variable

Sentencias de asignacioacuten 17

Generalmente se usa como separador en nombres con varias palabras como porejemplo en tu_nombre ovelocidad_aerodinamica_de_una_golondrina_sin_cargamento

Si se le da un nombre invaacutelido a una variable aparece un error de sintaxis

juliagt 76trombones = un gran desfileERROR syntax 76 is not a valid function argument name (ERRORsintaxis 76 no es un nombre de argumento de funcioacuten vaacutelido)juliagt mas = 1000000ERROR syntax extra token after end of expression (ERROR sintaxiscomponente leacutexico adicional despueacutes del final de la expresioacuten)juliagt struct = Quiacutemica avanzadaERROR syntax unexpected = (ERROR sintaxis = inesperado)

76trombones es un nombre de variable invaacutelido porque comienza con un nuacutemeroTambieacuten es invaacutelido mas porque contiene el caraacutecter invaacutelido Pero iquestCuaacutel esel error en struct

Resulta que struct es una de las palabras reservadas de Julia Julia usa laspalabras reservadas para reconocer la estructura del programa por ello nopueden usarse como nombres de variables

Julia tiene las siguientes palabras reservadas

abstract type baremodule begin break catchconst continue do else elseifend export finally for functionglobal if import importall inlet local macro module mutable structprimitive type quote return try usingstruct where while

No es necesario memorizar esta lista En la mayoriacutea de los entornos dedesarrollo las palabras reservadas se muestran en un color diferente por lotanto si intenta usar una como nombre de variable lo sabraacute

Expresiones y sentenciasUna expresioacuten es una combinacioacuten de valores variables y operadores Un valor ouna variable por siacute solos se consideran una expresioacuten por lo que las siguientesexpresiones son vaacutelidas

18 Capiacutetulo 2 Variables expresiones y sentencias

juliagt 4242juliagt n17juliagt n + 2542

Cuando escribe una expresioacuten en el indicador el REPL la evaluacutea lo que significaque encuentra el valor de la expresioacuten En este ejemplo n tiene el valor 17previamente asignado y n+25 retorna el valor 42

Una sentencia es una unidad de coacutedigo que tiene un efecto tal como crear unavariable o mostrar un valor

juliagt n = 1717juliagt println(n)17

La primera liacutenea es una sentencia de asignacioacuten ya que asigna un valor a n Lasegunda liacutenea es una sentencia de impresioacuten que muestra el valor de n

Cuando escribe una sentencia REPL la ejecuta es decir hace lo que dice lasentencia

Modo scriptHasta ahora se ha ejecutado Julia en modo interactivo lo que significa que se hainteractuado directamente con el REPL Este modo es una buena manera decomenzar pero si estaacute trabajando con varias liacuteneas de coacutedigo puede resultarincoacutemodo

Una alternativa es guardar el coacutedigo en un archivo de oacuterdenes o script y luegoutilizar Julia en modo script para ejecutarlo Por convencioacuten los scripts de Juliatienen nombres que terminan con la extensioacuten jl

Si sabe coacutemo crear y ejecutar un script en su computadora estaacute listo paracomenzar De lo contrario es recomendable usar JuliaBox nuevamente Abra unarchivo de texto escriba el script y guaacuterdelo con la extensioacuten jl El script sepuede ejecutar en una terminal con el comando julia nombre_del_scriptjl

Debido a que Julia proporciona ambos modos puede probar liacuteneas de coacutedigo enmodo interactivo antes de colocarlos en un script Auacuten asiacute tenga enconsideracioacuten que existen diferencias entre el modo interactivo y el modo scriptque pueden generar confusioacuten

Por ejemplo si estaacute utilizando Julia como una calculadora puede escribir

Modo script 19

juliagt millas = 262262juliagt millas 16142182

La primera liacutenea asigna un valor a millas y muestra el valor La segunda liacutenea esuna expresioacuten por lo que el REPL la evaluacutea y muestra el resultado Gracias alcoacutedigo anterior sabemos que una maratoacuten tiene unos 42 kiloacutemetros

Pero si escribe el mismo coacutedigo en un script y lo ejecuta no obtendraacute ninguacutenresultado En el modo script una expresioacuten por siacute sola no tiene ninguacuten efectovisible Julia evaluacutea la expresioacuten pero no muestra el valor a menos que se loindique

millas = 262println(millas 161)

Al principio este comportamiento puede ser confuso

Un script generalmente contiene una secuencia de sentencias Si hay maacutes de unasentencia los resultados aparecen de uno a la vez a medida que se ejecutan lassentencias

Por ejemplo el script

println(1)x = 2println(x)

produce la salida

12

Notar que la sentencia de asignacioacuten x = 2 no tiene salida

Ejercicio 2-1

Para comprobar que ha comprendido lo recientemente explicado escriba lassiguientes sentencias en el REPL de Julia y vea lo que hace cada una

5x = 5x + 1

20 Capiacutetulo 2 Variables expresiones y sentencias

Ahora coloque las mismas sentencias en un script y ejecuacutetelo iquestCuaacutel es elresultado Modifique el script transformando cada expresioacuten en una sentencia deimpresioacuten y luego ejecuacutetelo de nuevo

Orden de operacionesCuando una expresioacuten contiene maacutes de un operador el orden de evaluacioacutendepende de las reglas de precedencia Julia sigue la convencioacuten matemaacutetica parael orden de evaluacioacuten de los operadores matemaacuteticos El acroacutenimo PAPOMUDASes una forma uacutetil de recordar estas reglas

bull PAreacutentesis tienen la mayor precedencia y se pueden utilizar para forzar laevaluacioacuten de una expresioacuten en el orden que se desee Dado que lasexpresiones entre pareacutentesis se evaluacutean primero 2(3-1) es 4 y (1+1)^(5-2) es 8 Tambieacuten puede usar pareacutentesis para hacer una expresioacuten maacutes faacutecilde leer como en (minuto100)60 incluso si no cambia el resultado

bull POtenciacioacuten tiene la siguiente precedencia maacutes alta por lo que 1+2^3 es9 no 27 y 23^2 es 18 no 36

bull MUltiplicacioacuten y Divisioacuten tienen mayor precedencia que la Adicioacuten ySustraccioacuten Entonces 23-1 es 5 no 4 y 6+42 es 8 no 5

bull Los operadores con la misma precedencia se evaluacutean de izquierda a derecha(excepto potencias) Entonces en la expresioacuten grados2π la divisioacuten ocurreprimero y el resultado se multiplica por π Para dividir entre puede usarpareacutentesis escribir grados2π o grados2π

OBSERVACIOacuteNNo se esfuerce demasiado en recordar el orden de lasoperaciones Si el orden no es evidente mirando laexpresioacuten use pareacutentesis para que siacute lo sea

Operaciones con cadenasEn general no se pueden realizar operaciones matemaacuteticas con cadenas aunquelas cadenas puedan parecer nuacutemeros por lo que lo siguiente es invaacutelido

2 - 1huevos faacuteciltercero + talismaacuten

No obstante hay dos excepciones y ^

El operador realiza concatenacioacuten de cadenas lo que significa que une lascadenas de extremo a extremo Por ejemplo

Orden de operaciones 21

juliagt primer_str = autoautojuliagt segundo_str = moacutevilmoacuteviljuliagt primer_str segundo_strautomoacutevil

El operador ^ tambieacuten funciona con cadenas generando repeticiones Porejemplo Spam^3 es SpamSpamSpam Si uno de los valores es una cadena elotro tiene que ser un nuacutemero entero

De manera anaacuteloga este uso de y ^ tambieacuten tiene sentido en la multiplicacioacuten ypotencia Asiacute como 4^3 es equivalente a 444 esperamos que el Spam^3 sea lomismo que el SpamSpamSpam y lo es

ComentariosA medida que los programas se hacen maacutes largos y complejos se vuelven maacutesdifiacuteciles de leer Los lenguajes formales son densos y a menudo es difiacutecil leer elcoacutedigo y entender queacute estaacute haciendo o por queacute

Por esta razoacuten es una buena idea agregar notas a sus programas para explicaren lenguaje natural lo que estaacute haciendo el programa Estas notas se llamancomentarios y comienzan con el siacutembolo

calcula el porcentaje de hora que ha transcurridoporcentaje = (minuto 100) 60

En este caso el comentario aparece soacutelo en una liacutenea Tambieacuten puede ponercomentarios al final de una liacutenea

porcentaje = (minuto 100) 60 porcentaje de una hora

Todo desde el hasta el final de la liacutenea se ignora y no tiene ninguacuten efecto en laejecucioacuten del programa

Los comentarios son maacutes uacutetiles cuando documentan caracteriacutesticas no obvias delcoacutedigo Es razonable suponer que el lector puede averiguar queacute hace el coacutedigopor lo tanto es maacutes uacutetil explicar por queacute

Este comentario es inuacutetil porque es redundante con el coacutedigo

v = 5 asigna 5 a v

Este comentario contiene informacioacuten uacutetil que no estaacute presente en el coacutedigo

22 Capiacutetulo 2 Variables expresiones y sentencias

v = 5 velocidad en metrossegundo

OBSERVACIOacuteNLos nombres de las variables tienen que ser descriptivospara asiacute reducir la necesidad de comentarios pero notan largos como para dificultar la lectura del coacutedigo

DepuracioacutenSe pueden producir tres tipos de errores en un programa errores de sintaxiserrores en tiempo de ejecucioacuten y errores semaacutenticos Es uacutetil distinguirlos pararastrearlos maacutes raacutepidamente

Error de sintaxisldquoSintaxisrdquo se refiere a la estructura de un programa y las reglas sobre esaestructura Por ejemplo los pareacutentesis deben presentarse de a pares por loque (1+2) es vaacutelido pero 8) es un error de sintaxis

Si hay un error de sintaxis en cualquier parte de su programa Julia muestraun mensaje de error y se cierra no pudiendo ejecutar el programa Durantesus primeras semanas como programador puede pasar mucho tiemporastreando errores de sintaxis A medida que gane experiencia cometeraacutemenos errores y los encontraraacute maacutes raacutepido

Error en tiempo de ejecucioacutenEl segundo tipo de error es el error en tiempo de ejecucioacuten llamado asiacuteporque aparece durante la ejecucioacuten del programa Estos errores tambieacutense denominan excepciones porque generalmente indican que ha sucedidoalgo excepcional (y malo)

Los errores en tiempo de ejecucioacuten son raros en los programas simples queveraacute en los primeros capiacutetulos por lo que puede pasar un tiempo antes deque encuentre uno

Error semaacutenticoEl tercer tipo de error es ldquosemaacutenticordquo es decir relacionado con elsignificado Si hay un error semaacutentico en su programa este se ejecutaraacute singenerar mensajes de error pero no haraacute lo que se desea sino que haraacute otracosa Especiacuteficamente haraacute lo que usted le dijo que hiciera (y no lo queusted desea que realice)

Identificar errores semaacutenticos puede ser complicado porque requiere que setrabaje a la inversa analizando la salida del programa para intentar descubrirqueacute estaacute haciendo

Depuracioacuten 23

Glosariovariable

Un nombre que hace referencia a un valor

asignacioacutenUna sentencia que asigna un valor a una variable

diagrama de estadoUna representacioacuten graacutefica de un conjunto de variables y los valores a losque hace referencia

palabra claveUna palabra reservada que se utiliza para definir la sintaxis y estructura deun programa no puede usar palabras reservadas como if function ywhile como nombres de variables

operandoUno de los valores sobre los que opera un operador

expresioacutenUna combinacioacuten de variables operadores y valores que representa un solovalor como resultado

evaluarSimplificar una expresioacuten realizando operaciones para obtener un solo valor

sentenciaUna seccioacuten de coacutedigo que representa un comando o accioacuten Hasta ahoralas sentencias que hemos visto son asignaciones e impresiones

ejecutarEjecutar una sentencia y hacer lo que eacutesta dice

modo interactivoUna forma de utilizar el REPL de Julia escribiendo coacutedigo en el indicador

modo scriptUna forma de usar Julia para leer coacutedigo desde un script y ejecutarlo

scriptUn programa almacenado en un archivo

24 Capiacutetulo 2 Variables expresiones y sentencias

precedencia del operadorReglas que rigen el orden en que se evaluacutean las expresiones que involucranmuacuteltiples operadores matemaacuteticos y operandos

concatenarUnir dos cadenas de extremo a extremo

comentarioInformacioacuten en un programa que estaacute destinada a otros programadores (ocualquier persona que lea el coacutedigo fuente) y que no tiene efecto en laejecucioacuten del programa

error de sintaxisUn error en un programa que hace que sea imposible de analizar (y por lotanto imposible de ejecutar)

error en tiempo de ejecucioacuten o excepcioacutenUn error que se detecta mientras se ejecuta el programa

semaacutenticaEl significado de un programa

error semaacutenticoEs un error en un programa que provoca que se haga algo diferente a loque el programador pretendiacutea

Ejercicios

Ejercicio 2-2

Repitiendo el consejo del capiacutetulo anterior cada vez que aprenda algo nuevodebe probarlo en el modo interactivo y cometer errores a propoacutesito para ver elresultado

1 Hemos visto que n=42 es vaacutelido iquestQueacute pasa con 42=n

2 iquestY con x=y=1

3 En algunos lenguajes cada sentencia termina con un punto y coma iquestQueacutesucede si pone un punto y coma al final de una sentencia en Julia

4 iquestQueacute pasa si pone un punto al final de una sentencia

5 En notacioacuten matemaacutetica puede multiplicar x e y de esta manera x y iquestQueacutepasa si intenta eso en Julia iquestY queacute sucede con 5x

Ejercicios 25

Ejercicio 2-3

Practique usando el REPL de Julia como una calculadora

1 El volumen de una esfera con radio es iquestCuaacutel es el volumen de unaesfera con radio 5

2 Supongamos que el precio de venta de un libro es de $2495 pero laslibreriacuteas obtienen un descuento del 40 El enviacuteo cuesta $3 por la primeracopia y 75 centavos por cada copia adicional iquestCuaacutel es el costo total al pormayor de 60 copias

3 Si una persona sale de casa a las 652 am y corre 1 milla a un ritmorelajado (815 minutos por milla) luego 3 millas maacutes raacutepido (712 minutospor milla) y 1 milla a ritmo relajado nuevamente iquestA queacute hora llega a casapara desayunar

26 Capiacutetulo 2 Variables expresiones y sentencias

Capiacutetulo 3 FuncionesEn el contexto de la programacioacuten una funcioacuten es una secuencia de sentenciasque ejecuta una operacioacuten deseada y tiene un nombre Cuando se define unafuncioacuten se especifica su nombre y secuencia de sentencias Una vez hecho estose puede llamar a la funcioacuten por su nombre

Llamada a funcioacuten

Ya se ha visto un ejemplo de una llamada a funcioacuten

juliagt println(iexclHola Mundo)iexclHola Mundo

El nombre de esta funcioacuten es println La expresioacuten entre pareacutentesis se llamaargumento de la funcioacuten

Es comuacuten decir que una funcioacuten toma un argumento y devuelve un resultadoEl resultado tambieacuten se llama valor de retorno

Julia tiene funciones integradas que convierten valores de un tipo a otro Lafuncioacuten parse toma una cadena y si es posible la convierte en cualquier tipo denuacutemero en caso contrario arroja error

juliagt parse(Int64 32)32juliagt parse(Float64 314159)314159juliagt parse(Int64 Hola)ERROR ArgumentError invalid base 10 digit H in Hola

(ERROR ArgumentError base invaacutelida de 10 diacutegitos H en Hola)

trunc puede convertir valores de punto flotante a enteros pero no redondea sinoque trunca

juliagt trunc(Int64 399999)3juliagt trunc(Int64 -23)-2

float convierte nuacutemeros enteros en nuacutemeros de punto flotante

Llamada a funcioacuten 27

juliagt float(32)320

Finalmente string convierte el argumento en una cadena

juliagt string(32)32juliagt string(314159)314159

Funciones matemaacuteticasEn Julia la mayoriacutea de las funciones matemaacuteticas conocidas estaacuten disponiblesdirectamente

proporcioacuten = potencia_de_sentildealpotencia_de_ruidodecibelios = 10log10(proporcioacuten)

Este primer ejemplo utiliza la funcioacuten log10 para calcular la proporcioacuten entresentildeal y ruido en decibelios (suponiendo que potencia_de_sentildeal ypotencia_de_ruido estaacuten definidos) Tambieacuten existe la funcioacuten log que calcula ellogaritmo natural

radianes = 07altura = sin(radianes)

Este segundo ejemplo encuentra la razoacuten seno (en ingleacutes sine) de la variableradianes El nombre de esta variable es una pista de que la funcioacuten sin y las otrasfunciones trigonomeacutetricas (cos tan etc) toman argumentos en radianes Paraconvertir grados a radianes se debe dividir por 180 y multiplicar por

juliagt grados=4545juliagt radianes=grados180π07853981633974483juliagt sin(radianes)07071067811865475

El valor de la variable π es una aproximacioacuten de punto flotante de con unaprecisioacuten de aproximadamente 16 diacutegitos

Si sabe de trigonometriacutea puede verificar el resultado anterior comparaacutendolo conla raiacutez cuadrada de dos dividido por dos

28 Capiacutetulo 3 Funciones

juliagt sqrt(2) 207071067811865476

ComposicioacutenHasta ahora hemos analizado los elementos de un programa (variablesexpresiones y sentencias) de forma aislada sin mencionar coacutemo se combinan

Una de las caracteriacutesticas maacutes uacutetiles de los lenguajes de programacioacuten es sucapacidad para combinar pequentildeos bloques de coacutedigo Por ejemplo elargumento de una funcioacuten puede ser cualquier tipo de expresioacuten incluidosoperadores aritmeacuteticos

x = sin(grados3602π)

E incluso llamadas a funciones

x = exp(log(x + 1))

Casi en cualquier lugar donde se pueda colocar un valor se puede colocar unaexpresioacuten arbitraria con una excepcioacuten el lado izquierdo de una sentencia deasignacioacuten debe ser un nombre de variable Cualquier otra expresioacuten en el ladoizquierdo genera un error de sintaxis (se veraacuten excepciones a esta regla maacutesadelante)

2

juliagt minutos = horas 60 bien120juliagt horas 60 = minutos malERROR syntax 60 is not a valid function argument name

(ERROR sintaxis 60 no es un nombre de argumento de funcioacuten vaacutelido)

Agregar nuevas funcionesHasta ahora solo hemos usado las funciones integradas en Julia pero tambieacuten esposible agregar nuevas funciones Una definicioacuten de funcioacuten especifica el nombrede una nueva funcioacuten y la secuencia de sentencias que se ejecutan cuando sellama a la funcioacuten A continuacioacuten se muestra un ejemplo

Composicioacuten 29

function imprimirletras() println(Juguemos en el bosque) println(mientras el lobo no estaacute)end

function es una palabra reservada que indica que esta es una definicioacuten defuncioacuten El nombre de la funcioacuten es imprimirletras Las reglas para losnombres de funciones son las mismas que para los nombres de variables puedencontener casi todos los caracteres Unicode (consulte Seccioacuten 81) pero el primercaraacutecter no puede ser un nuacutemero No puede usar una palabra reservada comonombre de una funcioacuten y debe evitar tener una variable y una funcioacuten con elmismo nombre

Los pareacutentesis vaciacuteos despueacutes del nombre indican que esta funcioacuten no tieneargumentos

La primera liacutenea de una definicioacuten de funcioacuten se llama encabezado el resto sellama cuerpo El cuerpo termina con la palabra reservada end y puede contenertodas las sentencias que desee Para facilitar la lectura el cuerpo de la funcioacutendeberiacutea tener sangriacutea

Las comillas deben ser comillas rectas () generalmente ubicadas junto a latecla Enter en el teclado Las comillas inglesas (ldquordquo)no son vaacutelidas en Julia

Si escribe una definicioacuten de funcioacuten en modo interactivo Julia REPL inserta unasangriacutea para informarle que la definicioacuten no estaacute completa

juliagt function imprimirletras() println(Juguemos en el bosque)

Para finalizar la funcioacuten debe escribir end

La sintaxis para llamar a la nueva funcioacuten es la misma que para las funcionesintegradas en Julia

juliagt imprimirletras()Juguemos en el bosquemientras el lobo no estaacute

Una vez definida una funcioacuten puede usarla dentro de otra funcioacuten Por ejemplopara repetir el estribillo anterior se podriacutea escribir una funcioacuten llamadarepetirletras

30 Capiacutetulo 3 Funciones

function repetirletras() imprimirletras() imprimirletras()end

Y luego llamar a repetirletras

juliagt repetirletras()Juguemos en el bosquemientras el lobo no estaacuteJuguemos en el bosquemientras el lobo no estaacute

Definiciones y usosAl unir los fragmentos de coacutedigo de la seccioacuten anterior todo el programa se veasiacute

function imprimirletras() println(Jueguemos en el bosque) println(mientras el lobo no estaacute)end

funcioacuten repetirletras() imprimirletras() imprimirletras()end

repetirletras()

Este programa contiene dos definiciones de funcioacuten imprimirletras yrepetirletras Las definiciones de funcioacuten se ejecutan al igual que otrassentencias pero su ejecucioacuten crea nuevas funciones Las sentencias dentro de lafuncioacuten no se ejecutan hasta que se llama a la funcioacuten y la definicioacuten de lafuncioacuten no genera salida

Como es de esperar debe crear una funcioacuten antes de poder ejecutarla En otraspalabras la definicioacuten de la funcioacuten tiene que ejecutarse antes de que se llame ala funcioacuten

Ejercicio 3-1

Mueva la uacuteltima liacutenea de este programa a la parte superior de modo que lallamada a funcioacuten aparezca antes de las definiciones Ejecute el programa y veaqueacute mensaje de error obtiene

Definiciones y usos 31

Ahora mueva la llamada a funcioacuten hacia abajo y coloque la definicioacuten deimprimirletras despueacutes de la definicioacuten de repetirletras iquestQueacute sucede cuandoejecuta este programa

Flujo de ejecucioacutenPara asegurarse de que una funcioacuten sea definida antes de su primer uso debeconocer el orden en que se ejecutan las instrucciones lo que se denomina flujode ejecucioacuten

La ejecucioacuten siempre comienza con la primera sentencia del programa Lassentencias se ejecutan una a la vez en orden descendente

Las definiciones de funcioacuten no alteran el flujo de ejecucioacuten del programa pero sedebe recordar que las sentencias dentro de la funcioacuten no se ejecutan hasta quese llama a la funcioacuten

Una llamada a funcioacuten es como un desviacuteo en el flujo de ejecucioacuten En lugar depasar a la siguiente sentencia el flujo salta al cuerpo de la funcioacuten ejecuta lassentencias que estaacuten alliacute y luego regresa para continuar el coacutedigo donde lo dejoacute

Esto suena bastante simple hasta que se tiene en cuenta que una funcioacuten puedellamar a otra Mientras se estaacute ejecutando una funcioacuten el programa podriacutea tenerque ejecutar las sentencias de otra funcioacuten Luego mientras ejecuta esa nuevafuncioacuten iexclel programa podriacutea tener que ejecutar otra funcioacuten maacutes

Afortunadamente Julia es capaz de hacer el seguimiento de sus movimientos asiacuteque cada vez que una funcioacuten termina el programa retoma la funcioacuten que lallamoacute justo donde la dejoacute Cuando llega al final del programa la ejecucioacutentermina

En resumen cuando lee un programa no siempre debe leer de arriba haciaabajo A veces tiene maacutes sentido seguir el flujo de ejecucioacuten

Paraacutemetros y argumentosAlgunas de las funciones que se han visto requieren argumentos Por ejemplo lafuncioacuten cos necesita un nuacutemero como argumento Algunas funciones toman maacutesde un argumento por ejemplo parse toma dos un nuacutemero y una cadena

Dentro de la funcioacuten los argumentos se asignan a variables llamadasparaacutemetros A continuacioacuten se muestra un ejemplo de definicioacuten de funcioacuten quetoma un argumento

32 Capiacutetulo 3 Funciones

function imprimirdosveces(juan) println(juan) println(juan)end

Esta funcioacuten asigna el argumento a un paraacutemetro llamado juan Cuando se llamaa la funcioacuten esta imprime el valor del paraacutemetro (cualquiera que sea) dos veces

Esta funcioacuten funciona con cualquier valor que se pueda imprimir

juliagt imprimirdosveces(Correo no deseado)Correo no deseadoCorreo no deseadojuliagt imprimirdosveces(42)4242juliagt imprimirdosveces(π)π = 31415926535897 π = 31415926535897

Las mismas reglas de composicioacuten que se aplican a las funciones integradastambieacuten se aplican a las funciones definidas por el programador por lo quepodemos usar cualquier tipo de expresioacuten como argumento paraimprimirdosveces

juliagt imprimirdosveces(Correo no deseado ^4)Correo no deseado Correo no deseado Correo no deseado Correo no deseadoCorreo no deseado Correo no deseado Correo no deseado Correo no deseadojuliagt imprimirdosveces(cos(π))-10-10

El argumento se evaluacutea antes de llamar a la funcioacuten por lo que en los ejemploslas expresiones Correo no deseado ^4 y cos(π) solo se evaluacutean una vez

Tambieacuten puede usar una variable como argumento

juliagt michael = La vida es bellaLa vida es bellajuliagt imprimirdosveces(michael)La vida es bellaLa vida es bella

El nombre de la variable que pasamos como argumento (michael) no tiene nadaque ver con el nombre del paraacutemetro (juan) Para la funcioacuten imprimirdosveces

Paraacutemetros y argumentos 33

todos los paraacutemetros se llaman juan sin importar el nombre de la variable quepasemos como argumento (en este caso michael)

Las variables y los paraacutemetros son localesCuando se crea una variable dentro de una funcioacuten esta es local es decir soloexiste dentro de la funcioacuten Por ejemplo

function concatenar_dos(parte1 parte2) concat = parte1 parte2 imprimirdosveces(concat)end

Esta funcioacuten toma dos argumentos los concatena e imprime el resultado dosveces Aquiacute hay un ejemplo

juliagt linea1 = Hola holaHola holajuliagt linea2 = adioacutes adioacutesadioacutes adioacutesjuliagt concatenar_dos(liacutenea1 liacutenea2)Hola hola adioacutes adioacutesHola hola adioacutes adioacutes

Cuando concatenar_dos termina la variable concat es destruida Si intentamosimprimirla obtendremos un error

juliagt println(concat)ERROR UndefVarError concat not defined

Los paraacutemetros tambieacuten son locales Por ejemplo fuera de la funcioacutenimprimirdosveces no existe juan

Diagramas de pilaPara seguir la pista de queacute variables se usan en queacute lugares es uacutetil dibujar undiagrama de pila Al igual que los diagramas de estado los diagramas de pilamuestran el valor de cada variable pero tambieacuten muestran la funcioacuten a la quepertenece cada una

Cada funcioacuten se representa por un marco Un marco es un recuadro con elnombre de una funcioacuten a un costado y los paraacutemetros y variables de la funcioacutendentro El diagrama de pila para el ejemplo anterior se muestra en Figura 2

34 Capiacutetulo 3 Funciones

Figura 2 Diagrama de pila

Los marcos se ordenan de tal manera que cada funcioacuten llama a la funcioacuteninmediatamente inferior En este ejemplo imprimirdosveces fue llamado porconcatenar_dos y concatenar_dos fue llamado por Main que es un nombreespecial para la funcioacuten de maacutes alto nivel Cuando se crea una variable afuera decualquier funcioacuten pertenece a Main

Cada paraacutemetro se refiere al mismo valor que su argumento correspondienteEntonces parte1 tiene el mismo valor que linea1 parte2 tiene el mismo valorque linea2 y juan tiene el mismo valor que concat

Si se produce un error durante una llamada a funcioacuten Julia imprime el nombrede la funcioacuten el nombre de la funcioacuten que la llamoacute el nombre de la funcioacuten que asu vez llamoacute a esta otra y asiacute sucesivamente hasta llegar a la funcioacuten de maacutes altonivel Main

Por ejemplo si intenta acceder a concat desde imprimirdosveces obtendraacute unUndefVarError

ERROR UndefVarError concat not definedStacktrace [1] imprimirdosveces at REPL[1]gt2 [inlined] [2] concatenar_dos(String String) at REPL[2]gt3

Esta lista de funciones se llama trazado inverso Indica en queacute archivo deprograma se produjo el error en queacute liacutenea y queacute funciones se estaban ejecutandoen ese momento Tambieacuten muestra la liacutenea de coacutedigo que causoacute el error

El orden de las funciones en el trazado inverso es el opuesto del orden de losrecuadros en el diagrama de pila La funcioacuten que se estaacute ejecutando actualmenteestaacute en la parte superior

Funciones productivas y funciones nulasAlgunas de las funciones que hemos utilizado como las funciones matemaacuteticasdevuelven resultados A este tipo de funciones se les llamaraacute funcionesproductivas a falta de un nombre mejor Otras funciones comoimprimirdosveces realizan una accioacuten pero no devuelven un valor Estas sellaman funciones nulas

Funciones productivas y funciones nulas 35

Cuando se llama a una funcioacuten productiva casi siempre se quiere hacer algo conel resultado por ejemplo asignarlo a una variable o usarlo como parte de unaexpresioacuten

x = cos(radianes)aurea = (sqrt(5)+1)2

Cuando se llama a una funcioacuten en modo interactivo Julia muestra el resultado

juliagt sqrt(5)223606797749979

Pero en un script si se llama a una funcioacuten productiva iexclel valor de retorno sepierde para siempre

sqrt(5)

Output

223606797749979

Este script calcula la raiacutez cuadrada de 5 pero como no almacena ni muestra elresultado no es muy uacutetil

Las funciones nulas pueden mostrar algo en la pantalla o tener alguacuten otro efectopero no tienen un valor de retorno Si asigna el resultado a una variableobtendraacute un valor especial llamado nothing (nada en ingleacutes)

juliagt resultado = imprimirdosveces(Bing)BingBingjuliagt show(resultado)nothing

Para imprimir el valor nothing debe usar la funcioacuten show que es como la funcioacutenprint pero permite el valor nothing

El valor nothing no es lo mismo que la cadena nothing Es un valor especial quetiene su propio tipo

juliagt typeof (nothing)Nothing

Las funciones que hemos escrito hasta ahora son nulas Comenzaremos a escribir

36 Capiacutetulo 3 Funciones

funciones productivas en unos pocos capiacutetulos

iquestPor queacute se necesitan funcionesPuede que no esteacute claro por queacute vale la pena dividir un programa en funcionesHay varias razones

bull Crear una nueva funcioacuten le brinda la oportunidad de darle nombre a ungrupo de sentencias lo que hace que su programa sea maacutes faacutecil de leer ydepurar

bull Las funciones pueden hacer que un programa sea maacutes corto al eliminarcoacutedigo repetitivo Ademaacutes si realiza un cambio solo tiene que hacerlo en unsolo lugar

bull Dividir un programa largo en funciones le permite depurar las partes de unaen una y luego unirlas

bull Las funciones bien disentildeadas pueden ser uacutetiles para muchos programasUna vez que escribe y depura una puede reutilizarla

bull En Julia las funciones pueden mejorar mucho el rendimiento

DepuracioacutenUna de las habilidades maacutes importantes que adquiriraacute es la depuracioacuten Aunquepuede ser frustrante la depuracioacuten es una de las partes maacutes intelectualmentegratificantes desafiantes e interesantes de la programacioacuten

La depuracioacuten puede ser vista como un trabajo de detective El programador seenfrenta a pistas y tiene que inferir los procesos y eventos que generaron losresultados que ve

La depuracioacuten tambieacuten es como una ciencia experimental Una vez que se tieneuna idea de lo que estaacute mal se modifica el programa y se intenta nuevamente Sila hipoacutetesis era correcta se puede predecir el resultado de la modificacioacuten y asiacuteestar un paso maacutes cerca de un programa totalmente funcional Si la hipoacutetesis eraincorrecta se tiene que encontrar una nueva Como Sherlock Holmes sentildealoacute

Cuando todo aquello que es imposible ha sido eliminado lo que quede pormuy improbable que parezca es la verdad

mdash A Conan Doyle El signo de los cuatro

Para algunas personas la programacioacuten y la depuracioacuten son lo mismo Es decirla programacioacuten es el proceso de depurar gradualmente un programa hasta quehaga lo que desea Lo ideal es comenzar con un programa que funcione y hacer

iquestPor queacute se necesitan funciones 37

pequentildeas modificaciones depuraacutendolas a medida que avanza

Por ejemplo Linux es un sistema operativo que contiene millones de liacuteneas decoacutedigo pero comenzoacute como un programa simple que Linus Torvalds usoacute paraexplorar el chip Intel 80386 Seguacuten Larry Greenfield Uno de los proyectosanteriores de Linus fue un programa que cambiariacutea entre imprimir AAAA yBBBB Esto luego evolucionoacute a Linux (The Linux Usersrsquo Guide Beta Version1)

Glosariofuncioacuten

secuencia de sentencias que ejecuta una operacioacuten deseada y tiene unnombre Las funciones pueden tomar o no argumentos y pueden producir ono un resultado

definicioacuten de funcioacutenUna sentencia que crea una nueva funcioacuten especificando su nombreparaacutemetros y las sentencias que contiene

objeto de funcioacutenUn valor creado por una definicioacuten de funcioacuten El nombre de la funcioacuten esuna variable que se refiere a un objeto de funcioacuten

encabezadoLa primera liacutenea de una definicioacuten de funcioacuten

cuerpoSecuencia de sentencias dentro de una definicioacuten de funcioacuten

paraacutemetroUn nombre usado dentro de una funcioacuten para referirse al valor pasado comoargumento

Llamada a funcioacutenUna sentencia que ejecuta una funcioacuten Compuesta por el nombre de lafuncioacuten seguido por la lista de argumentos que usa entre pareacutentesis

argumentoValor que se le pasa a una funcioacuten cuando se la llama Este valor se asignaal paraacutemetro correspondiente en la funcioacuten

variable localUna variable definida dentro de una funcioacuten Una variable local solo puedeusarse dentro de su funcioacuten

38 Capiacutetulo 3 Funciones

valor de retornoEl resultado de una funcioacuten Si se utiliza una llamada a funcioacuten como unaexpresioacuten el valor de retorno es el valor de la expresioacuten

funcioacuten productivaUna funcioacuten que devuelve un valor

funcioacuten vaciacuteaUna funcioacuten que siempre devuelve nothing

nothingUn valor especial devuelto por las funciones nulas

composicioacutenUsar una expresioacuten como parte de una expresioacuten maacutes grande o unasentencia como parte de una sentencia maacutes grande

flujo de ejecucioacutenEl orden en que las sentencias se ejecutan

diagrama de pilaUna representacioacuten graacutefica de una pila de funciones sus variables y losvalores a los que se refieren

marcoUn recuadro que en un diagrama de pila representa una llamada de funcioacutenContiene las variables locales y los paraacutemetros de la funcioacuten

trazado inversoUna lista de las funciones que se estaacuten ejecutando las cuales son impresascuando ocurre una excepcioacuten

Ejercicios

OBSERVACIOacuteN Estos ejercicios deben realizarse utilizando soacutelo lo quese ha tratado hasta ahora

Ejercicio 3-2

Escriba una funcioacuten llamada justificar_a_la_derecha que tome una cadena s comoparaacutemetro y que imprima la cadena con suficientes espacios en blanco para quela uacuteltima letra de la cadena se encuentre en la columna 70 de la pantalla

using IntroAJulia

Ejercicios 39

justificar_a_la_derecha(Celia)

OBSERVACIOacuteN

Use concatenacioacuten de cadenas y repeticioacuten AdemaacutesJulia tiene integrada una funcioacuten llamada length quedevuelve la longitud de una cadena por lo que el valorde length(Celia) es 5

Ejercicio 3-3

Un objeto de funcioacuten es un valor que se puede asignar a una variable o serpasado como argumento Por ejemplo dosveces es una funcioacuten que toma unobjeto de funcioacuten como argumento y lo llama dos veces

function dosveces(f) f() f()end

A continuacioacuten se muestra un ejemplo que usa dosveces para llamar a unafuncioacuten llamada imprimirgato dos veces

function imprimirpalabra() println(palabra)end

dosveces(imprimirpalabra)

1 Escriba este ejemplo en un script y prueacutebelo

2 Modifique dosveces para que tome dos argumentos un objeto de funcioacuten yun valor y que llame a la funcioacuten dos veces pasando el valor comoargumento

3 Copie la definicioacuten de imprimirdosveces mencionada antes en este capiacutetuloa su secuencia de comandos

4 Use la versioacuten modificada de dosveces para llamar a imprimirdosveces dosveces pasando palabra como argumento

5 Defina una nueva funcioacuten llamada cuatroveces que tome un objeto defuncioacuten y un valor y que llame a la funcioacuten cuatro veces pasando el valorcomo paraacutemetro Debe haber solo dos sentencias en el cuerpo de estafuncioacuten no cuatro

40 Capiacutetulo 3 Funciones

Ejercicio 3-4

1 Escriba la funcioacuten imprimircuadricula que dibuje una cuadriacutecula como lasiguiente

juliagt imprimircuadricula()+ - - - - + - - - - +| | || | || | || | |+ - - - - + - - - - +| | || | || | || | |+ - - - - + - - - - +

1 Escriba una funcioacuten que dibuje una cuadriacutecula similar con cuatro filas ycuatro columnas

Creacuteditos Este ejercicio se basa en un ejercicio en Oualline Practical CProgramming Third Edition OrsquoReilly Media 1997

OBSERVACIOacuteN

Para imprimir maacutes de un valor por liacutenea se puedeimprimir una secuencia de valores separados por comas

println (+ -)

La funcioacuten print no avanza a la siguiente liacutenea

print(+)println(-)

El resultado de estas sentencias es + - en la mismaliacutenea El resultado de una siguiente sentencia deimpresioacuten comenzariacutea en la siguiente liacutenea

Ejercicios 41

Capiacutetulo 4 Estudio de Caso Disentildeo de InterfazEste capiacutetulo presenta un segundo estudio de caso que muestra el proceso dedisentildear funciones que trabajen en conjunto

Se presentan graacuteficos turtle que es una forma de crear dibujos a traveacutes de laprogramacioacuten Los graacuteficos turtle no estaacuten incluidos en la Biblioteca Estaacutendarpor lo que se debe agregar el moacutedulo IntroAJulia a su configuracioacuten de Julia

Los ejemplos de este capiacutetulo se pueden ejecutar en un notebook graacutefico enJuliaBox el cual combina coacutedigo texto formateado matemaacuteticas y multimedia enun solo documento (vea Apeacutendice B)

TurtlesUn modulo es un archivo que contiene una coleccioacuten de funciones relacionadasJulia proporciona algunos moacutedulos en su Biblioteca Estaacutendar Ademaacutes es posibleagregar maacutes funciones a una gran cantidad de paquetes(httpsjuliaobservercom)

Los paquetes se pueden instalar en REPL ingresando al modo Pkg REPL con latecla ]

(v12) pkggt add httpsgithubcomJuliaIntroIntroAJuliajl

Esto puede demorar un poco

Antes de que podamos usar las funciones de un moacutedulo tenemos que importarlocon una sentencia using

juliagt using IntroAJulia

juliagt ὂ = Turtle()LuxorTurtle(00 00 true 00 (00 00 00))

El moacutedulo IntroAJulia proporciona una funcioacuten llamada Turtle (tortuga enespantildeol) que crea un objeto LuxorTurtle el cual es asignado a una variablellamada ὂ (turtle TAB)

Una vez que crea una tortuga puede llamar a una funcioacuten para moverla y asiacutehacer un dibujo con ella Por ejemplo para mover la tortuga hacia adelante(forward en ingleacutes)

42 Capiacutetulo 4 Estudio de Caso Disentildeo de Interfaz

svg begin forward(ὂ 100)end

Figura 3 Haciendo avanzar a la tortuga

La palabra reservada svg ejecuta una macro que dibuja una imagen SVG Lasmacros son una caracteriacutestica importante pero avanzada de Julia

Los argumentos de forward son la tortuga y una distancia en piacutexeles por lo queel tamantildeo real depende de su pantalla

Tambieacuten es posible hacer girar a la tortuga con la funcioacuten turn Los argumentosde esta funcioacuten son la tortuga y un aacutengulo en grados

Ademaacutes cada tortuga estaacute sosteniendo un laacutepiz que puede estar hacia arriba ohacia abajo si el laacutepiz estaacute hacia abajo la tortuga deja un rastro cuando semueve Figura 3 muestra el rastro dejado por la tortuga Las funciones penup ypendown significan laacutepiz hacia arriba y laacutepiz hacia abajo

Para dibujar un aacutengulo recto modifique la llamada a la macro

ὂ = Turtle()svg begin forward(ὂ 100) turn(ὂ -90) forward(ὂ 100)end

Ejercicio 4-1

Ahora modifique la macro para que dibuje un cuadrado iexclNo sigas hasta haberloterminado

Repeticioacuten Simple

Es probable que haya escrito algo como esto

Repeticioacuten Simple 43

ὂ = Turtle()svg begin forward(ὂ 100) turn(ὂ -90) forward(ὂ 100) turn(ὂ -90) forward(ὂ 100) turn(ὂ -90) forward(ὂ 100)end

Se puede hacer lo mismo de manera maacutes concisa con una sentencia for

juliagt for i in 14 println(iexclHola) endiexclHolaiexclHolaiexclHolaiexclHola

Este es el uso maacutes simple de la sentencia for aunque se veraacuten maacutes usos despueacutesEacutesto deberiacutea ser suficiente para reescribir su programa que dibuja un cuadradoNo continuacutee hasta que lo haga

Aquiacute hay una sentencia for que dibuja un cuadrado

ὂ = Turtle()svg begin for i in 14 forward(ὂ 100) turn(ὂ -90) endend

La sintaxis de una sentencia for es similar a la definicioacuten de una funcioacuten Tieneun encabezado y un cuerpo que termina con la palabra reservada end El cuerpopuede contener el nuacutemero de sentencias que desee

Una sentencia for tambieacuten es llamada bucle porque el flujo de ejecucioacuten recorreel cuerpo y luego vuelve a la parte superior En este caso ejecuta el cuerpocuatro veces

Esta versioacuten es en realidad un poco diferente del coacutedigo anterior que dibujaba uncuadrado porque hace otro giro despueacutes de dibujar el uacuteltimo lado del cuadradoEl giro adicional lleva maacutes tiempo pero simplifica el coacutedigo si se hace lo mismo

44 Capiacutetulo 4 Estudio de Caso Disentildeo de Interfaz

en cada iteracioacuten del ciclo Esta versioacuten tambieacuten tiene el efecto de dejar a latortuga nuevamente en la posicioacuten inicial mirando hacia la direccioacuten inicial

EjerciciosLos siguientes ejercicios usan tortugas Son divertidos pero tambieacuten tienen untrasfondo Mientras trabaja en ellos piense cuaacutel es ese trasfondo

OBSERVACIOacuteNLas siguientes secciones muestran las soluciones paraestos ejercicios asiacute que no mire hasta que hayaterminado (o al menos lo haya intentado)

Ejercicio 4-2

Escriba una funcioacuten llamada cuadrado que tome como paraacutemetro a un turtle tDeberiacutea usar este turtle para dibujar un cuadrado

Ejercicio 4-3

Escriba una llamada a funcioacuten que pase t como argumento a cuadrado y luegovuelva a ejecutar la macro

Ejercicio 4-4

Agregue otro paraacutemetro llamado lon a cuadrado Modifique el cuerpo para quela longitud de los lados sea lon y luego modifique la llamada a funcioacutenagregando este segundo argumento Ejecute la macro nuevamente Pruebe conun rango de valores para lon

Ejercicio 4-5

Haga una copia de cuadrado y cambie su nombre a poliacutegono Agregue otroparaacutemetro llamado n y modifique el cuerpo para que dibuje un poliacutegono regularde -lados

OBSERVACIOacuteN Los aacutengulos exteriores de un poliacutegono regular de -ladosson grados

Ejercicio 4-6

Escriba una funcioacuten llamada ciacuterculo que tome un turtle t y un radio r comoparaacutemetros y que dibuje un ciacuterculo aproximado llamando a poliacutegono con unalongitud y nuacutemero de lados apropiados Pruebe su funcioacuten con un rango devalores de r

Ejercicios 45

OBSERVACIOacuteN Calcule la circunferencia del ciacuterculo y aseguacuterese de quelen n == circunferencia

Ejercicio 4-7

Haga una versioacuten maacutes general de circulo llamada arco que tome un paraacutemetroadicional angulo y que determine queacute fraccioacuten de un ciacuterculo dibujar angulo estaacuteen grados entonces cuando angulo= 360 arco deberiacutea dibujar un ciacuterculocompleto

EncapsulacioacutenEl primer ejercicio le pide que coloque el coacutedigo que permite dibujar uncuadrado en una definicioacuten de funcioacuten y que luego llame a la funcioacuten pasando aturtle como paraacutemetro Aquiacute hay una solucioacuten

function cuadrado(t) for i in 14 forward(t 100) turn(t -90) endendὂ = Turtle()svg begin cuadrado(ὂ)end

Las sentencias maacutes internas forward y turn tienen doble sangriacutea para mostrarque estaacuten dentro del bucle for que a su vez estaacute dentro de la definicioacuten defuncioacuten

Dentro de la funcioacuten t se refiere a la misma tortuga ὂ entonces turn(t -90)tiene el mismo efecto que turn(ὂ -90) En ese caso iquestpor queacute no llamar alparaacutemetro ὂ La razoacuten es que t puede ser cualquier tortuga no solo ὂ por loque podriacuteamos crear una segunda tortuga y pasarla como argumento a cuadrado

ὂ = Turtle()svg begin cuadrado(ὂ)end

Colocar una porcioacuten de coacutedigo en una funcioacuten se denomina encapsulacioacuten Unode los beneficios de la encapsulacioacuten es que al ponerle un nombre al coacutedigo estosirve como una especie de documentacioacuten Otra ventaja es que si reutiliza elcoacutedigo iexcles maacutes conciso llamar a una funcioacuten dos veces que copiar y pegar el

46 Capiacutetulo 4 Estudio de Caso Disentildeo de Interfaz

cuerpo

GeneralizacioacutenEl siguiente paso es agregar un paraacutemetro lon a cuadrado Aquiacute hay unasolucioacuten

function cuadrado(t lon) for i in 14 forward(t lon) turn(t -90) endendὂ = Turtle()svg begin cuadrado(ὂ 100)end

Agregar un paraacutemetro a una funcioacuten se llama generalizacioacuten porque hace que lafuncioacuten sea maacutes general en la versioacuten anterior el cuadrado siempre teniacutea elmismo tamantildeo en esta versioacuten puede ser de cualquier tamantildeo

El siguiente paso tambieacuten es una generalizacioacuten En vez de dibujar cuadradospoligono dibuja poliacutegonos regulares con cualquier nuacutemero de lados Aquiacute hay unasolucioacuten

function poligono(t n lon) angulo = 360 n for i in 1n forward(t lon) turn(t -angulo) endendὂ = Turtle()svg begin poligono(ὂ 7 70)end

Este ejemplo dibuja un poliacutegono de 7 lados con una longitud de 70 por lado

Disentildeo de InterfazEl siguiente paso es escribir circulo que toma un radio r como paraacutemetro Aquiacutehay una solucioacuten simple que usa poligono para dibujar un poliacutegono de 50 lados

Generalizacioacuten 47

function circulo(t r) circunferencia = 2 π r n = 50 lon = circunferencia n poligono(t n lon)end

La primera liacutenea calcula la circunferencia de un ciacuterculo con radio usando lafoacutermula n es el nuacutemero de segmentos de liacutenea de nuestra aproximacioacuten a unciacuterculo y lon es la longitud de cada segmento Por lo tanto poliacutegono dibuja unpoliacutegono de 50 lados que se aproxima a un ciacuterculo de radio r

Una limitante de esta solucioacuten es que n es constante lo que significa que paraciacuterculos muy grandes los segmentos de liacutenea son demasiado largos y paraciacuterculos pequentildeos perdemos tiempo dibujando segmentos muy pequentildeos Unasolucioacuten seriacutea generalizar la funcioacuten tomando n como paraacutemetro Esto le dariacutea alusuario (quien llama a ciacuterculo) maacutes control pero la interfaz seriacutea menos pulcra

La interfaz de una funcioacuten es un resumen de coacutemo se usa iquestcuaacuteles son losparaacutemetros iquestQueacute hace la funcioacuten iquestY cuaacutel es el valor de retorno Una interfazes pulcra si le permite al usuario que la llama hacer lo que quiera sin tener quelidiar con detalles innecesarios

En este ejemplo r pertenece a la interfaz porque especifica el ciacuterculo a dibujar nes menos apropiado porque se refiere a los detalles de coacutemo se debe representarel ciacuterculo

En lugar de saturar la interfaz es mejor elegir un valor apropiado de ndependiendo de la circunferencia

function circulo(t r) circunferencia = 2 π r n = trunc(circunferencia 3) + 3 lon = circunferencia n poligono(t n lon)end

Ahora el nuacutemero de segmentos es un nuacutemero entero cercano a circunferencia3por lo que la longitud de cada segmento es aproximadamente 3 que es losuficientemente pequentildeo como para que los ciacuterculos se vean bien pero losuficientemente grandes como para ser eficientes y aceptables para cualquierciacuterculo

Agregar 3 a n garantiza que el poliacutegono tenga al menos 3 lados

48 Capiacutetulo 4 Estudio de Caso Disentildeo de Interfaz

RefactorizacioacutenCuando se escribioacute circulo se pudo reutilizar poligono ya que un poliacutegono demuchos lados es una buena aproximacioacuten de un ciacuterculo Pero arco no es tanversaacutetil no se puede usar poligono o circulo para dibujar un arco

Una alternativa es comenzar con una copia de poligono y transformarla en arcoEl resultado podriacutea verse asiacute

function arco(t r angulo) arco_lon = 2 π r angulo 360 n = trunc(arco_lon 3) + 1 paso_lon = arco_lon n paso_angulo = angulo n for i in 1n forward(t paso_lon) turn(t -paso_angulo) endend

La segunda mitad de esta funcioacuten se parece a poligono pero no se puedereutilizar poligono sin cambiar la interfaz Se podriacutea generalizar poligono paratomar un angulo como tercer argumento iexclpero entonces poligono ya no seriacutea unnombre apropiado En su lugar se puede llamar a esta funcioacuten maacutes generalpolilinea

function polilinea(t n lon angulo) for i in 1n forward(t lon) turn(t -angulo) endend

Ahora se puede reescribir poligono y arco usando polilinea

Refactorizacioacuten 49

function poligono(t n lon) angulo = 360 n polilinea(t n lon angulo)end

function arco(t r angulo) arco_lon = 2 π r angulo 360 n = trunc(arco_lon 3) + 1 paso_lon = arco_lon n paso_angulo = angulo n polilinea(t n paso_lon paso_angulo)end

Finalmente se puede reescribir circulo usando arco

function circulo(t r) arco(t r 360)end

Este proceso que reorganiza un programa para mejorar las interfaces y facilitarla reutilizacioacuten del coacutedigo se denomina refactorizacioacuten En este caso se observaque habiacutea un coacutedigo similar en arco y poligono por lo que lo factorizamos enpolilinea

Si se hubiese planeado con anticipacioacuten se podriacutea haber escrito polilineaprimero y haber evitado la refactorizacioacuten pero a menudo no se sabe losuficiente al comienzo de un proyecto para disentildear todas las interfaces Una vezque se comienza a programar se comprende mejor el problema A vecesrefactorizar es una sentildeal de que se ha aprendido algo

Un Plan de DesarrolloUn plan de desarrollo de programa es un proceso para escribir programas Elproceso que se utiliza en este estudio de caso es encapsulacioacuten ygeneralizacioacuten Los pasos de este proceso son

1 Comience escribiendo un pequentildeo programa sin definiciones de funciones

2 Una vez que el programa funcione identifique una porcioacuten de coacutedigo quetenga un objetivo especiacutefico encapsule esta porcioacuten en una funcioacuten yasiacutegnele un nombre

3 Generalice la funcioacuten agregando los paraacutemetros apropiados

4 Repita los pasos 1ndash3 hasta que tenga un conjunto de funciones De serposible copie y pegue coacutedigo para evitar volver a escribir (y volver adepurar)

50 Capiacutetulo 4 Estudio de Caso Disentildeo de Interfaz

5 Busque oportunidades para mejorar el programa refactorizando Porejemplo si tiene un coacutedigo similar en varios lugares considere factorizarloen una funcioacuten general apropiada

Este proceso tiene algunos inconvenientes se exploraraacuten alternativas maacutesadelante pero puede ser uacutetil si no sabe de antemano coacutemo dividir el programaen funciones Este enfoque permite disentildear conforme se avanza

DocstringUn docstring es una cadena que va antes de una funcioacuten y que explica la interfaz(doc es la abreviatura de documentacioacuten) Aquiacute hay un ejemplo

polilinea(t n lon angulo)

Dibuja n segmentos de liacutenea de la longitud dada y conaacutengulo entre ellos (en grados) dado t es una tortugafunction polilinea(t n lon angulo) for i in 1n forward(t lon) turn(t -angulo) endend

Se puede acceder a la documentacioacuten en REPL o en un notebook escribiendo seguido del nombre de una funcioacuten o macro y presionando ENTER

helpgt polilineasearch

polilinea(t n lon angulo)

Dibuja n segmentos de liacutenea de la longitud dada y con aacutengulo entre ellos(en grados) dado t es una tortuga

Los docstring generalmente son cadenas de comillas triples tambieacuten conocidascomo cadenas de liacuteneas muacuteltiples ya que las comillas triples permiten que lacadena abarque maacutes de una liacutenea

Un docstring contiene la informacioacuten esencial que alguien necesitariacutea para usaresta funcioacuten Explica de manera concisa lo que hace la funcioacuten (sin entrar endetalles sobre coacutemo lo hace) Explica queacute efecto tiene cada paraacutemetro en elcomportamiento de la funcioacuten y de queacute tipo debe ser cada paraacutemetro (si no esobvio)

Docstring 51

OBSERVACIOacuteN

Escribir este tipo de documentacioacuten es una parteimportante del disentildeo de la interfaz Una interfaz biendisentildeada debe ser simple de explicar si tienedificultades para explicar una de sus funciones tal vez lainterfaz podriacutea mejorarse

DepuracioacutenUna interfaz es como un contrato entre una funcioacuten y el usuario El usuarioacepta proporcionar ciertos paraacutemetros y la funcioacuten acepta hacer cierto trabajo

Por ejemplo polilinea requiere cuatro argumentos t tiene que ser una tortuga ntiene que ser un nuacutemero entero lon deberiacutea ser un nuacutemero positivo y angulotiene que ser un nuacutemero en grados

Estos requisitos se llaman precondiciones porque se supone que son verdaderosantes de que la funcioacuten comience a ejecutarse Por el contrario las condicionesal final de la funcioacuten son postcondiciones Las postcondiciones incluyen el efectodeseado de la funcioacuten (como dibujar segmentos de liacutenea) y cualquier efectosecundario (como mover la tortuga o hacer otros cambios)

Las condiciones previas son responsabilidad del usuario Si el usuario viola unaprecondicioacuten (iexcldebidamente documentada) y la funcioacuten no funcionacorrectamente el error estaacute en el usuario no en la funcioacuten

Si se cumplen las precondiciones pero no las postcondiciones el error estaacute en lafuncioacuten Si sus pre y postcondiciones son claras pueden ayudar con ladepuracioacuten

Glosariomodulo

Un archivo que contiene una coleccioacuten de funciones relacionadas y otrasdefiniciones

paqueteUna biblioteca externa con maacutes funcionalidades

sentencia usingUna sentencia que lee un archivo de moacutedulo y crea un objeto de moacutedulo

bucleUna parte de un programa que puede ejecutarse repetidamente

52 Capiacutetulo 4 Estudio de Caso Disentildeo de Interfaz

encapsulacioacutenEl proceso de transformar una secuencia de sentencias en una definicioacuten defuncioacuten

generalizacioacutenEl proceso de reemplazar algo innecesariamente especiacutefico (como unnuacutemero) con algo maacutes general (como una variable o paraacutemetro)

interfazUna descripcioacuten de coacutemo usar una funcioacuten incluido el nombre y lasdescripciones de los argumentos y el valor de retorno

refactorizacioacutenEl proceso de modificar un programa para mejorar las interfaces de lasfunciones y otras cualidades del coacutedigo

plan de desarrollo de programaUn proceso para escribir programas

docstringUna cadena que aparece en la parte superior de una definicioacuten de funcioacutenpara documentar la interfaz de la funcioacuten

precondicioacutenUn requisito que debe cumplir el usuario antes de que comience unafuncioacuten

postcondicioacutenUn requisito que debe cumplir la funcioacuten antes de que finalice

Ejercicios

Ejercicio 4-8

Copie y pegue el coacutedigo de este capiacutetulo en un notebook

1 Dibuje un diagrama de pila que muestre el estado del programa mientrasejecuta circulo(ὂ radio) Puede hacer la aritmeacutetica a mano o agregarsentencias de impresioacuten al coacutedigo

2 La versioacuten de arco en Seccioacuten 47 no es muy precisa ya que la aproximacioacutenlineal del ciacuterculo siempre queda por afuera del ciacuterculo verdadero Comoresultado la tortuga termina a unos pocos piacutexeles del destino correcto Lasiguiente solucioacuten muestra una forma de reducir el efecto de este error Leael coacutedigo y vea si tiene sentido Si dibuja un diagrama es posible queentienda mejor coacutemo funciona

Ejercicios 53

arco(t r angulo)

Dibuja un arco con el radio y el aacutengulo dados

t tortuga r radio angulo aacutengulo subtendido por el arco en gradosfunction arco(t r angulo) arco_lon = 2 π r abs(angulo) 360 n = trunc(arco_lon 4) + 3 paso_lon = arco_lon n paso_angulo = angulo n

haciendo un ligero giro a la izquierda antes de comenzar se reduce el error causado por la aproximacioacuten lineal del arco turn(t -paso_angulo2) polilinea(t n paso_lon paso_angulo) turn(t paso_angulo2)end

Ejercicio 4-9

Escriba un conjunto de funciones generales que permitan dibujar flores como enFigura 4

Figura 4 Flores con Turtle

Ejercicio 4-10

Escriba un conjunto de funciones generales que puedan dibujar formas como enFigura 5

Figura 5 Poliacutegonos con Turtle

54 Capiacutetulo 4 Estudio de Caso Disentildeo de Interfaz

Ejercicio 4-11

Las letras del alfabeto se pueden construir a partir de un nuacutemero pequentildeo deelementos baacutesicos como liacuteneas verticales y horizontales y algunas curvasDisentildee un alfabeto que se pueda dibujar con un nuacutemero miacutenimo de elementosbaacutesicos y luego escriba funciones que dibujen las letras

Deberiacutea escribir una funcioacuten para cada letra con nombres dibujar_a dibujar_betc y colocar sus funciones en un archivo llamado letrasjl

Ejercicio 4-12

Lea sobre espirales en httpseswikipediaorgwikiEspiral luego escriba unprograma que dibuje una espiral de Arquiacutemedes como en Figura 6

Figura 6 Espiral de Arquiacutemedes

Ejercicios 55

Capiacutetulo 5 Condicionales y recursividadEl tema principal de este capiacutetulo es la sentencia if la cual permite ejecutardiferentes acciones dependiendo del estado del programa Inicialmente sepresentan dos nuevos operadores divisioacuten entera y moacutedulo

Divisioacuten entera y MoacuteduloEl operador divisioacuten entera divide (div TAB) divide dos nuacutemeros y redondea haciaabajo el resultado Por ejemplo suponga que la duracioacuten de una peliacutecula es de105 minutos Es posible que desee saber la duracioacuten en horas La divisioacutenconvencional devuelve un nuacutemero de punto flotante

juliagt minutos = 105105juliagt minutos 60175

No obstante las horas no se suelen escribir con decimales La divisioacuten enteradevuelve el nuacutemero entero de horas redondeado hacia abajo

juliagt horas = minutos divide 601

Para obtener el resto de la divisioacuten se puede restar una hora (en minutos) a laduracioacuten total de la peliacutecula

juliagt resto = minutos - horas 6045

Otra alternativa es usar el operador moacutedulo que divide dos nuacutemeros ydevuelve el resto

juliagt resto = minutos 6045

OBSERVACIOacuteN

El operador moacutedulo es maacutes uacutetil de lo que parecePermite verificar por ejemplo si un nuacutemero es divisiblepor otro si xy es cero entonces x es divisible por y

Ademaacutes puede extraer el (o los) diacutegito(s) maacutes a laderecha de un nuacutemero Por ejemplo x10 devuelve eldiacutegito maacutes a la derecha de un entero x (en base 10) Delmismo modo x100 devuelve los dos uacuteltimos diacutegitos

56 Capiacutetulo 5 Condicionales y recursividad

Expresiones booleanasUna expresioacuten booleana es una expresioacuten que es verdadera o falsa Lossiguientes ejemplos usan el operador == que compara dos operandos ydevuelve el valor true (verdadero en espantildeol) si son iguales y el valor false(falso) de lo contrario

juliagt 5 == 5truejuliagt 5 == 6false

true y false son valores especiales que pertenecen al tipo Bool no son cadenas

juliagt typeof(true)Booljuliagt typeof(false)Bool

El operador == es un operador relacional El resto de operadores relacionalesson

x = y x no es igual a y x ne y (ne TAB) x gt y x es mayor que y x lt y x es menor que y x gt= y x es mayor o igual que y x ge y (ge TAB) x lt= y x es menor o igual que y x le y (le TAB)

AVISO

Aunque estas operaciones probablemente le sean familiares lossiacutembolos de Julia son diferentes de los siacutembolos matemaacuteticos Unerror comuacuten es usar un solo signo igual (=) en vez de un doblesigno igual (== Recuerde que = es un operador de asignacioacuten y== es un operador relacional No existe =lt o =gt

Operadores LoacutegicosHay tres operadores loacutegicos ampamp (y) || (o) y (no) La semaacutentica (significado) deestos operadores es similar a su significado en espantildeol Por ejemplo xgt0 ampampxlt10 es verdadero solo si x es mayor que 0 y menor que 10

n2==0 || n3 == 0 es verdadero si una o ambas condiciones son verdaderases decir si el nuacutemero es divisible por 2 o por 3

Expresiones booleanas 57

Tanto ampamp como || se asocian en primer lugar con el objeto a su derecha pero ampamptiene preferencia por sobre ||

Finalmente el operador niega una expresioacuten booleana entonces (xgty) esverdadero si xgty es falso es decir si x es menor o igual que y

Ejecucioacuten CondicionalPara escribir programas uacutetiles generalmente se necesita verificar condiciones ycambiar el comportamiento del programa acorde a ellas Las sentenciascondicionales permiten llevar esto a cabo La forma maacutes simple es la sentencia if(si en ingleacutes)

if x gt 0 println(x es positivo)end

La expresioacuten booleana despueacutes de if se llama condicioacuten Si es verdadera seejecuta la instruccioacuten con sangriacutea Si no nada ocurre

Las sentencias if tienen la misma estructura que las definiciones de funcioacuten unencabezado seguido del cuerpo terminado con la palabra reservada end (enespantildeol fin) Las sentencias como esta se denominan sentencias compuestas

No hay liacutemite en el nuacutemero de sentencias que pueden aparecer en el cuerpo Aveces es uacutetil tener un cuerpo sin sentencias (por lo general como un marcadorde posicioacuten para el coacutedigo que auacuten no se ha escrito)

if x lt 0 TODO se necesita realizar alguna accioacuten con los valores negativosend

Ejecucioacuten alternativaUna segunda forma de la sentencia if es la ejecucioacuten alternativa en la que haydos posibilidades y la condicioacuten determina cuaacutel se ejecuta La sintaxis se ve asiacute

if x 2 == 0 println(x es par)else println(x es impar)end

Si el resto de x dividido por 2 es 0 entonces x es par y el programa muestra unmensaje acorde Si la condicioacuten es falsa se ejecuta el segundo conjunto de

58 Capiacutetulo 5 Condicionales y recursividad

sentencias Como la condicioacuten debe ser verdadera o falsa se ejecutaraacuteexactamente una de las alternativas Las alternativas se llaman ramas porqueson ramas en el flujo de ejecucioacuten

Condicionales encadenadasA veces hay maacutes de dos posibilidades y se necesitan maacutes de dos ramas Unamanera de expresar este coacutemputo es a traveacutes de una condicional encadenada

if x lt y println(x es menor que y)elseif x gt y println(x es mayor que y)else println(x e y son iguales)end

De nuevo soacutelo se ejecutaraacute una rama No hay liacutemite al nuacutemero de sentenciaselseif Si hay una sentencia else debe estar al final (aunque no es necesario queesteacute)

if alternativa == a dibujar_a()elseif alternativa == b dibujar_b()elseif alternativa == c dibujar_c()end

Cada condicioacuten se comprueba en orden Si la primera es falsa se comprueba lasiguiente y asiacute se sigue con las demaacutes Si una de ellas es verdadera se ejecuta larama correspondiente y la sentencia se termina Si es verdadera maacutes de unacondicioacuten soacutelo se ejecuta la primera rama verdadera

Condicionales anidadasUna condicional puede estar anidada (nested en ingleacutes) dentro de otraPodriacuteamos haber escrito el ejemplo de la seccioacuten anterior de la siguiente manera

Condicionales encadenadas 59

if x == y println(x e y son iguales)else if x lt y println(x es menor a y) else println(x es mayor a y) endend

La condicional externa contiene dos ramas La primera rama contiene unasentencia simple La segunda rama contiene otra sentencia if que tiene dosramas propias Estas dos ramas son ambas sentencias simples aunque podriacuteanser sentencias condicionales

Aunque la sangriacutea no obligatoria de las sentencias hace evidente su estructuralas condicionales anidadas muy pronto se vuelven difiacuteciles de leer Se recomiendaevitarlas cuando pueda

Los operadores loacutegicos a menudo proporcionan una forma de simplificar lassentencias condicionales anidadas Por ejemplo es posible reescribir el siguientecoacutedigo usando un solo condicional

if 0 lt x if x lt 10 println(x es un nuacutemero positivo de un solo diacutegito) endend

La sentencia print soacutelo se ejecuta si conseguimos superar ambas condicionalesde modo que se puede obtener el mismo efecto con el operador ampamp

if 0 lt x ampamp x lt 10 println(x es un nuacutemero positivo de un solo diacutegito)end

Para este tipo de condicioacuten Julia proporciona una sintaxis maacutes concisa

if 0 lt x lt 10 println(x es un nuacutemero positivo de un solo diacutegito)end

60 Capiacutetulo 5 Condicionales y recursividad

RecursividadEstaacute permitido que una funcioacuten llame a otra y tambieacuten que una funcioacuten se llamea siacute misma Puede no parecer uacutetil pero siacute lo es como puede verse en la siguientefuncioacuten

function cuentaregresiva(n) if n le 0 println(Despegue) else print(n ) cuentaregresiva(n-1) endend

Si n es 0 o negativo muestra la palabra Despegue En otro caso muestra elvalor n y luego llama a la funcioacuten cuentaregresiva pasaacutendole n-1 comoargumento

iquestQueacute sucede si llamamos a una funcioacuten como esta

juliagt cuentaregresiva(3)3 2 1 Despegue

La ejecucioacuten de cuentaregresiva empieza con n = 3 y como n es mayor que 0muestra el valor 3 y luego se llama a siacute mismahellip

 La ejecucioacuten de cuentaregresiva empieza con n = 2 y como n es mayor que 0   muestra el valor 2 y luego se llama a siacute mismahellip

  La ejecucioacuten de cuentaregresiva empieza con n = 1 y como n es mayor que0    muestra el valor 1 y luego se llama a siacute mismahellip

   La ejecucioacuten de cuentaregresiva empieza con n = 0 y como n no es mayorque 0     muestra la palabra Despegue y luego termina

  La cuentaregresiva cuyo argumento es n = 1 termina

 La cuentaregresiva cuyo argumento es n = 2 termina

La cuentaregresiva cuyo argumento es n = 3 termina

Y volvemos a Main

Una funcioacuten que se llama a siacute misma es una funcioacuten recursiva y el proceso deejecucioacuten se llama recursividad

Recursividad 61

Como otro ejemplo se puede escribir una funcioacuten que imprima una cadena veces

function printn(s n) if n le 0 return end println(s) printn(s n-1)end

Si n lt= 0 se usa la sentencia return para salir de la funcioacuten El flujo de laejecucioacuten vuelve inmediatamente a la sentencia de llamada a funcioacuten y no seejecutan las liacuteneas restantes de la funcioacuten

El resto de la funcioacuten es similar a cuenta regresiva muestra s y luego se llama asiacute misma para mostrar s veces maacutes de modo que el nuacutemero de lineasmostradas es es decir

Para ejemplos simples como este es maacutes faacutecil usar un ciclo for Se mostraraacutenejemplos que son difiacuteciles de escribir con un ciclo for y faacuteciles de escribir conrecursividad

Diagramas de pila para funciones recursivasEn Seccioacuten 39 se usoacute un diagrama de pila para representar el estado de unprograma durante una llamada de funcioacuten El mismo tipo de diagrama puede serde utilidad para interpretar una funcioacuten recursiva

Cada vez que se llama a una funcioacuten Julia crea un marco que contiene lasvariables locales de la funcioacuten y los paraacutemetros En una funcioacuten recursiva puedehaber maacutes de un marco en el diagrama de pila al mismo tiempo

Figura 7 Diagrama de pila

Figura 7 muestra un diagrama de pila para cuentaregresiva utilizando n=3

Como siempre la parte superior de la pila es el marco para Main Estaacute vaciacuteopues no se crearon variables en Main ni tampoco se pasaron argumentos

62 Capiacutetulo 5 Condicionales y recursividad

Los cuatro marcos de cuentaregresiva tienen diferentes valores del paraacutemetro nLa parte inferior del diagrama de pila donde n = 0 es llamado caso base Nohace una llamada recursiva asiacute que no hay maacutes marcos

Ejercicio 5-1

Como ejercicio dibuje un diagrama de pila para printn llamada con s = Hola yn = 2 Luego escriba una funcioacuten llamada hacer_n que tome como argumentosuna funcioacuten y un nuacutemero n y que luego llame a la funcioacuten dada veces

Recursioacuten infinitaSi una recursioacuten nunca alcanza un caso base continuacutea haciendo llamadasrecursivas para siempre y el programa nunca termina Esto se conoce comorecursioacuten infinita y generalmente no es una buena idea Aquiacute hay un coacutedigo conuna recursioacuten infinita

function recursion() recursion()end

En la mayoriacutea de los entornos de programacioacuten un programa con recursioacuteninfinita realmente no se ejecuta para siempre Julia entrega un mensaje de errorcuando se alcanza la profundidad de recursioacuten maacutexima

juliagt recursion()ERROR StackOverflowErrorStacktrace [1] recursion() at REPL[1]2 (repeats 80000 times)

Este stacktrace es un poco maacutes grande que el que vimos en el capiacutetulo anteriorCuando se produce el error iexclhay 80000 marcos de recursion en el diagrama depila

Si por accidente encuentra una recursioacuten infinita en su coacutedigo revise su funcioacutenpara confirmar que hay un caso base que no realiza una llamada recursiva Sihay un caso base verifique si realmente puede ocurrir

Entrada por tecladoLos programas que se han escrito hasta ahora no aceptan entradas del usuarioSimplemente hacen lo mismo cada vez

Julia tiene una funcioacuten incorporada llamada readline que detiene el programa yespera a que el usuario escriba algo Cuando el usuario presiona RETURN oENTER el programa se reanuda y readline devuelve lo que el usuario escribioacute

Recursioacuten infinita 63

como una cadena

juliagt text = readline()iquestQueacute estaacute esperandoiquestQueacute estaacute esperando

Antes de recibir una entrada por teclado del usuario es una buena idea imprimirun mensaje que le diga al usuario queacute escribir

juliagt print(iquestCuaacutel es su nombre ) readline()iquestCuaacutel es su nombre iexclArturo Rey de los BretonesiexclArturo Rey de los Bretones

Un punto y coma permite colocar varias sentencias en la misma liacutenea En elREPL solo la uacuteltima sentencia devuelve su valor

Si espera que el usuario escriba un nuacutemero entero puede intentar convertir elvalor de retorno a Int64

juliagt println(iquestCuaacutentos dejaron su casa su tierra o su posesioacuten)numero = readline()iquestCuaacutentos dejaron su casa su tierra o su posesioacuten115115juliagt parse(Int64 numero)115

Pero si el usuario no escribe una cadena de diacutegitos obtendraacute un error

juliagt println(iquestCuaacutentos dejaron su casa su tierra o su posesioacuten)numero = readline()iquestCuaacutentos dejaron su casa su tierra o su posesioacutenMaacutes de ciento quince sonMaacutes de ciento quince sonjuliagt parse(Int64 speed)ERROR ArgumentError invalid base 10 digit M in Maacutes de ciento quinceson[]

Veremos queacute hacer con este tipo de error maacutes adelante

DepuracioacutenCuando se produce un error de sintaxis o de tiempo de ejecucioacuten el mensaje deerror contiene mucha informacioacuten lo cual puede ser abrumador Las partes maacutes

64 Capiacutetulo 5 Condicionales y recursividad

uacutetiles suelen ser

bull Queacute tipo de error fue

bull Doacutende ocurrioacute tal error

Los errores de sintaxis suelen ser faacuteciles de encontrar y hay algunos trucos Engeneral los mensajes de error indican doacutende se descubrioacute el problema pero elerror real podriacutea estar antes en el coacutedigo a veces en una liacutenea anterior

Lo mismo aplica para los errores de tiempo de ejecucioacuten Suponga que estaacutetratando de calcular una relacioacuten sentildealruido en decibelios La foacutermula es

En Julia se podriacutea escribir algo como esto

intensidad_sentildeal = 9intensidad_ruido = 10relacion = intensidad_sentildeal divide intensidad_ruidodecibeles = 10 log10(relacion)print(decibeles)

Obteniendo

-Inf

Este no es el resultado que esperaacutebamos

Para encontrar el error puede ser uacutetil imprimir el valor de la variable relacionque resulta ser 0 El problema estaacute en la liacutenea 3 que usa la divisioacuten entera enlugar de la divisioacuten de punto flotante

AVISOEl usuario debe tomarse el tiempo de leer los mensajes de errorcuidadosamente pero no se debe asumir que todo lo que dicen escorrecto

GlosarioDivisioacuten entera

Un operador denotado por divide que divide dos nuacutemeros y redondea haciaabajo (hacia el infinito negativo) a un entero

operador moacuteduloUn operador denotado con el signo de porcentaje () que se utiliza conenteros y devuelve el resto cuando un nuacutemero se divide por otro

Glosario 65

expresioacuten booleanaUna expresioacuten cuyo valor es verdadero o falso

operador relacionalUno de los operadores que compara sus operandos == ne (=) gt lt ge(gt=) and le (lt=)

operador loacutegicoUno de los operadores que combina expresiones booleanas ampamp (and) ||(or) and (not)

sentencia condicionalUna sentencia que controla el flujo de ejecucioacuten dependiendo de algunacondicioacuten

condicioacutenLa expresioacuten booleana en una sentencia condicional que determina queacuterama se ejecuta

sentencia compuestaUna sentencia que consta de un encabezado y un cuerpo El cuerpo terminacon la palabra reservada end

ramaUna de las secuencias alternativas de sentencias en una sentenciacondicional

condicional encadenadaUna sentencia condicional con una serie de ramas alternativas

condicional anidadaUna sentencia condicional que aparece en una de las ramas de otrasentencia condicional

sentencia returnUna sentencia que hace que una funcioacuten finalice de inmediato y que vuelvaa la sentencia de llamada a funcioacuten

recursividad o recursioacutenEl proceso de llamar a la funcioacuten que se estaacute ejecutando actualmente

caso baseUna rama condicional en una funcioacuten recursiva que no realiza una llamadarecursiva

66 Capiacutetulo 5 Condicionales y recursividad

recursioacuten infinitaUna recursioacuten que no tiene un caso base o que nunca llega a eacutelEventualmente una recursioacuten infinita provoca un error de tiempo deejecucioacuten

Ejercicios

Ejercicio 5-2

La funcioacuten time devuelve el tiempo medio de Greenwich actual en segundosdesde la eacutepoca que es un tiempo arbitrario utilizado como punto de referenciaEn sistemas UNIX la eacutepoca es el 1 de enero de 1970

juliagt time()1603600382165353e9

Escriba un script que lea la hora actual y la convierta a una hora del diacutea enhoras minutos y segundos maacutes el nuacutemero de diacuteas transcurridos desde la eacutepoca

Ejercicio 5-3

El uacuteltimo teorema de Fermat dice que no hay enteros positivos and tal que

para cualquier valor de mayor que 2

1 Escriba una funcioacuten llamada verificarfermat que tome cuatroparaacutemetrosmdasha b c y nmdash y que verifique si el teorema de Fermat es vaacutelidoSi n es mayor que 2 y a^n + b^n == c^n el programa deberiacutea imprimiriexclSanto cielo Fermat estaba equivocado De lo contrario el programadeberiacutea imprimir No eso no funciona

2 Escriba una funcioacuten que solicite al usuario ingresar valores para a b c y nque los convierta en enteros y que use verificarfermat para verificar siviolan el teorema de Fermat

Ejercicio 5-4

Si tiene tres barras estas podriacutean o no formar un triaacutengulo Por ejemplo si unade las barras tiene 12 centiacutemetros de largo y las otras dos tienen un centiacutemetrode largo no es posible que las barras pequentildeas puedan juntarse al medio Paracualquier triacuteo de longitudes hay una prueba simple para ver si es posible formarun triaacutengulo

Ejercicios 67

OBSERVACIOacuteN

Si cualquiera de las tres longitudes es mayor que lasuma de las otras dos entonces no se puede formar untriaacutengulo De lo contrario se puede (Si la suma de doslongitudes es igual a la tercera forman lo que se llamaun triaacutengulo degenerado)

1 Escriba una funcioacuten llamada estriangulo que tome tres enteros comoargumentos y que imprima ldquoSiacuterdquo o ldquoNordquo dependiendo de si se puede o noformar un triaacutengulo a partir de barras de las longitudes dadas

2 Escriba una funcioacuten que solicite al usuario ingresar tres longitudes debarras las convierta en enteros y use estriangulo para verificar si las barrascon las longitudes dadas pueden formar un triaacutengulo

Ejercicio 5-5

iquestCuaacutel es el resultado del siguiente programa Dibuje un diagrama de pila quemuestre el estado del programa cuando imprima el resultado

function recursion(n s) if n == 0 println(s) else recursion(n-1 n+s) endend

recursion(3 0)

1 iquestQueacute pasariacutea si se llamara a esta funcioacuten asiacute recursion(-1 0)

2 Escriba un documento que explique todo lo que alguien necesitariacutea saberpara usar esta funcioacuten (y nada maacutes)

Los siguientes ejercicios utilizan el moacutedulo IntroAJulia descrito en Capiacutetulo 4

Ejercicio 5-6

Lea la siguiente funcioacuten y vea si puede averiguar queacute hace (vea los ejemplos enCapiacutetulo 4) Luego ejecuacutetelo y vea si lo hizo bien

68 Capiacutetulo 5 Condicionales y recursividad

function dibujar(t distancia n) if n == 0 return end angulo = 50 adelante(t distancian) girar(t -angulo) dibujar(t distancia n-1) girar(t 2angulo) dibujar(t distancia n-1) girar(t -angulo) adelante(t -distancian)end

Ejercicio 5-7

Figura 8 Una curva de Koch

La curva de Koch es un fractal que luce como Figura 8 Para dibujar una curva deKoch con longitud todo lo que tiene que hacer es

1 Dibuje una curva de Koch con longitud

2 Gire a la izquierda 60 grados

3 Dibuje una curva de Koch con longitud

4 Gire a la derecha 120 grados

5 Dibuje una curva de Koch con longitud

6 Gire a la izquierda 60 grados

7 Dibuje una curva de Koch con longitud

La excepcioacuten es cuando es menor que 3 en ese caso puede dibujar una liacutenearecta con una longitud

1 Escribe una funcioacuten llamada koch que tome una tortuga y una longitudcomo paraacutemetros y que use la tortuga para dibujar una curva de Koch con lalongitud dada

2 Escriba una funcioacuten llamada copodenieve que dibuje tres curvas de Kochpara hacer el contorno de un copo de nieve

3 La curva de Koch se puede generalizar de varias maneras ConsultehttpsenwikipediaorgwikiKoch_snowflake para ver ejemplos eimplementar su favorito

Ejercicios 69

Capiacutetulo 6 Funciones productivasMuchas de las funciones de Julia que se han utilizado como las funcionesmatemaacuteticas producen valores de retorno Todas las funciones que se hanescrito hasta ahora son nulas es decir tienen un efecto (como imprimir un valor)pero devuelven el valor nothing En este capiacutetulo se ensentildea a escribir funcionesproductivas

Valores de retornoLlamar a una funcioacuten genera un valor de retorno que generalmente se asigna auna variable o se usa como parte de una expresioacuten

e = exp(10)altura = radio sin(radio)

Las funciones que se han escrito hasta ahora son nulas Coloquialmentehablando no tienen valor de retorno de manera formal su valor de retorno esnothing En este capiacutetulo (finalmente) se van a escribir funciones productivas Elprimer ejemplo es area que devuelve el aacuterea de un ciacuterculo dado un radio

function area(radio) a = π radio^2 return aend

Se ha visto la sentencia return antes pero en una funcioacuten productiva la sentenciareturn incluye una expresioacuten Esta sentencia significa Retorne inmediatamentede esta funcioacuten y use la siguiente expresioacuten como valor de retorno La expresioacutendada puede ser arbitrariamente complicada Asiacute pues se podriacutea haber escritoesta funcioacuten maacutes concisamente

function area(radio) π radio^2end

El valor devuelto por una funcioacuten es el valor de la uacuteltima expresioacuten evaluadaque por defecto es la uacuteltima expresioacuten en el cuerpo de la definicioacuten de lafuncioacuten

Por otro lado las variables temporales como a y las sentencias return expliacutecitaspueden facilitar la depuracioacuten

A veces es uacutetil tener muacuteltiples sentencias return una en cada rama de unasentencia condicional

70 Capiacutetulo 6 Funciones productivas

function valorabsoluto(x) if x lt 0 return -x else return x endend

Dado que estas sentencias return estaacuten en una condicional alternativa solo seejecuta una

En cuanto se ejecuta una sentencia return la funcioacuten termina sin ejecutarninguna de las sentencias siguientes El coacutedigo que aparece despueacutes de lasentencia return o en cualquier otro lugar al que el flujo de ejecucioacuten nuncallegaraacute se llama coacutedigo muerto

En una funcioacuten productiva es una buena idea asegurarse que cualquier posiblerecorrido del programa llegue a una sentencia return Por ejemplo

function valorabsoluto(x) if x lt 0 return -x end if x gt 0 return x endend

Esta versioacuten no es correcta porque si x es igual a 0 ninguna de las condicioneses verdadera y la funcioacuten termina sin alcanzar una sentencia return Si el flujo deejecucioacuten llega al final de la funcioacuten el valor de retorno es nothing queclaramente no es el valor absoluto de 0

juliagt show(valorabsoluto(0))nothing

OBSERVACIOacuteN Julia tiene una funcioacuten incorporada llamada abs quecalcula los valores absolutos

Ejercicio 6-1

Escriba la funcioacuten comparar que tome dos valores x y y y que devuelva 1 si x gty 0 si x == y y -1 si x lt y

Valores de retorno 71

Desarrollo incrementalConforme vaya escribiendo funciones maacutes extensas puede empezar a dedicarmaacutes tiempo a la depuracioacuten

Para lidiar con programas de complejidad creciente se sugiere una teacutecnicallamada desarrollo incremental El objetivo del desarrollo incremental es evitarlargas sesiones de depuracioacuten antildeadiendo y probando solamente pequentildeasporciones de coacutedigo cada vez

Por ejemplo suponga que desea encontrar la distancia entre dos puntos dadospor las coordenadas y Por el teorema de Pitaacutegoras la distancia es

El primer paso es considerar queacute aspecto tendriacutea la funcioacuten distancia en Julia Enotras palabras iquestcuaacuteles son las entradas (paraacutemetros) y cuaacutel es la salida (valor deretorno)

En este caso las entradas son los dos puntos que se pueden representar usandocuatro nuacutemeros El valor devuelto es la distancia que es un nuacutemero de puntoflotante

He aquiacute una primera versioacuten de la funcioacuten

function distancia(x₁ y₁ x₂ y₂) 00end

Obviamente esta versioacuten de la funcioacuten no calcula distancias sino que siempredevuelve cero Aun asiacute es correcta sintaacutecticamente hablando y se ejecutaraacute loque implica que se puede probar antes de hacerla maacutes compleja Los nuacutemeros desubiacutendice estaacuten disponibles en la codificacioacuten de caracteres Unicode (_1 TAB_2 TAB etc)

Para probar la nueva funcioacuten se llama con una muestra de valores

distance(1 2 4 6)

Se eligen estos valores de tal forma que la distancia horizontal sea igual a 3 y ladistancia vertical sea igual a 4 y de esa manera el resultado es 5 (la hipotenusadel triaacutengulo 3-4-5) Cuando se comprueba una funcioacuten es uacutetil conocer larespuesta correcta

Hasta el momento se ha podido confirmar que la funcioacuten es sintaacutecticamentecorrecta por lo que se puede empezar a agregar liacuteneas de coacutedigo El paso loacutegico

72 Capiacutetulo 6 Funciones productivas

siguiente es encontrar las diferencias y En la siguiente versioacuten de lafuncioacuten se almacenaraacuten estos valores en variables temporales y se mostraraacuten conel macro show

function distancia(x₁ y₁ x₂ y₂) dx = x₂ - x₁ dy = y₂ - y₁ show dx dy 00end

Si la funcioacuten trabaja bien las salidas deben ser dx = 3 y dy = 4 Si es asiacute se sabeque la funcioacuten estaacute obteniendo los paraacutemetros correctos y realizando el primercaacutelculo correctamente Si no entonces soacutelo hay unas pocas liacuteneas que revisar

A continuacioacuten se calcula la suma de los cuadrados de dx y dy

function distancia(x₁ y₁ x₂ y₂) dx = x₂ - x₁ dy = y₂ - y₁ dsup2 = dx^2 + dy^2 show dsup2 00end

De nuevo se quiere ejecutar el programa en esta etapa y comprobar la salida(que deberiacutea ser 25) Los nuacutemeros en superiacutendice tambieacuten estaacuten disponibles (^2TAB) Finalmente se puede usar sqrt para calcular y devolver el resultado

function distancia(x₁ y₁ x₂ y₂) dx = x₂ - x₁ dy = y₂ - y₁ dsup2 = dx^2 + dy^2 sqrt(dsup2)end

Si esto funciona correctamente ya se habriacutea terminado Si no se podriacutea mostrarel valor de la variable resultado antes de la sentencia de retorno

La versioacuten final de la funcioacuten no muestra nada cuando se ejecuta soacutelo retorna unvalor Las sentencias print son uacutetiles para la depuracioacuten pero una vez que elprograma esteacute funcionando correctamente se deben eliminar El coacutedigoeliminado se llama andamiaje porque es uacutetil para construir el programa pero noes parte del producto final

Al principio deberiacutea antildeadir solamente una o dos liacuteneas de coacutedigo cada vez

Desarrollo incremental 73

Conforme vaya ganando experiencia puede que se encuentre escribiendo ydepurando fragmentos mayores de coacutedigo Sin embargo el proceso de desarrolloincremental puede ahorrarle mucho tiempo de depuracioacuten

Los aspectos clave del proceso son

1 Iniciar con un programa que funcione y hacerle pequentildeos cambiosincrementales En cualquier momento si hay un error sabraacute exactamentedoacutende estaacute

2 Usar variables temporales para guardar valores intermedios para que puedamostrarlos y verificarlos

3 Una vez que el programa esteacute funcionando tal vez prefiera eliminar partedel andamiaje o consolidar muacuteltiples sentencias en expresiones compuestaspero soacutelo si eso no hace que el programa sea difiacutecil de leer

Ejercicio 6-2

Use la teacutecnica de desarrollo incremental para escribir una funcioacuten llamadahipotenusa que retorne el largo de la hipotenusa de un triaacutengulo rectaacutengulo dadoel largo de las otras dos aristas Registre cada etapa del proceso de desarrollo

ComposicioacutenAhora como usted esperariacutea se puede llamar a una funcioacuten desde otra Comoejemplo se escribe una funcioacuten que tome dos puntos el centro del ciacuterculo y unpunto del periacutemetro y calcule el aacuterea del ciacuterculo

Suponga que el punto central estaacute almacenado en las variables xc y yc y que elpunto del periacutemetro lo estaacute en xp y yp El primer paso es hallar el radio delciacuterculo que es la distancia entre los dos puntos La funcioacuten distancia que realizaesta tarea seriacutea

radio = distancia(xc yc xp yp)

El siguiente paso es encontrar el aacuterea del ciacuterculo usando este radio De nuevo seusa una de las funciones definidas previamente

resultado = area(radio)

Envolviendo todo en una funcioacuten se obtiene

74 Capiacutetulo 6 Funciones productivas

function areacirculo(xc yc xp yp) radio = distancia(xc yc xp yp) resultado = area(radio) return resultadoend

Las variables temporales radio y resultado son uacutetiles para el desarrollo y ladepuracioacuten pero una vez que el programa estaacute funcionando se puede hacer maacutesconciso componiendo las llamadas a funcioacuten

function areacirculo(xc yc xp yp) area(distancia(xc yc xp yp))end

Funciones BooleanasLas funciones pueden devolver valores booleanos lo que a menudo esconveniente para ocultar complicadas comprobaciones dentro de funciones Porejemplo

function esdivisible(x y) if x y == 0 return true else return false endend

Es comuacuten dar a las funciones booleanas nombres que suenan como preguntasque tienen como respuesta un si oacute un no esdivisible devuelve true o false paraindicar si x es o no divisible por y

Por ejemplo

juliagt esdivisible(6 4)falsejuliagt esdivisible(6 3)true

El resultado del operador == es booleano por lo tanto se puede escribir lafuncioacuten de una manera maacutes concisa devolviendo el resultado directamente

Funciones Booleanas 75

function esdivisible(x y) x y == 0end

Las funciones booleanas se usan a menudo en las sentencias condicionales

if esdivisible(x y) println(x es divisible por y)end

Puede parecer tentador escribir algo como

if esdivisible(x y) == true println(x es divisible por y)end

pero la comparacioacuten extra con true es innecesaria

Ejercicio 6-3

Escriba la funcioacuten entremedio(xyz) que devuelva true si x le y le z o false enotro caso

Maacutes recursividadSolo se ha cubierto una pequentildea parte de Julia pero le puede interesar saber queesta parte ya es un lenguaje de programacioacuten completo lo que significa quecualquier coacutemputo puede expresarse en este lenguaje Cualquier programa quese haya escrito podriacutea reescribirse usando solo lo que ha aprendido hasta ahora(en realidad necesitariacutea algunos comandos para controlar dispositivos como elmouse discos etc pero eso es todo)

Probar esta afirmacioacuten es un ejercicio no trivial realizado por primera vez porAlan Turing uno de los primeros cientiacuteficos de la computacioacuten (algunosargumentariacutean que era matemaacutetico pero muchos de los primeros cientiacuteficosinformaacuteticos comenzaron como matemaacuteticos) En consecuencia esto se conocecomo la Tesis de Turing Para una discusioacuten maacutes completa (y precisa) de la Tesisde Turing se recomienda el libro de Michael Sipser Introduccioacuten a la Teoriacutea de laComputacioacuten

Para darle una idea de lo que puede hacer con las herramientas que haaprendido hasta ahora se evaluacutean algunas funciones matemaacuteticas definidasrecursivamente Una definicioacuten recursiva es similar a una definicioacuten circular enel sentido de que la definicioacuten contiene una referencia a lo que estaacute siendodefinido Una definicioacuten verdaderamente circular no es muy uacutetil

76 Capiacutetulo 6 Funciones productivas

vorpalUn adjetivo usado para describir algo que es vorpal

Si esta definicioacuten apareciese en el diccionario la persona que la leyera podriacuteamolestarse Por otro lado si se busca la definicioacuten de la funcioacuten factorialdenotada con el siacutembolo se encuentra encontrar algo como esto

Esta definicioacuten dice que el factorial de 0 es 1 y el factorial de cualquier otrovalor es multiplicado por el factorial de

Entonces es 3 veces que es 2 veces que es 1 vez Es decir es igual a3 por 2 por 1 por 1 que es 6

Si se puede escribir una definicioacuten recursiva se puede escribir un programa deJulia para evaluarlo El primer paso es decidir cuaacuteles deberiacutean ser losparaacutemetros En este caso debe quedar claro que factorial toma valores enteros

function fact(n) end

Si el argumento es 0 la funcioacuten debe devolver 1

function fact(n) if n == 0 return 1 endend

De lo contrario y esto es lo interesante se tiene que hacer una llamada recursivapara encontrar el factorial de n-1 y luego multiplicarlo por n

function fact(n) if n == 0 return 1 else recursion = fact(n-1) resultado = n recursion return resultado endend

El flujo de ejecucioacuten de este programa es similar al flujo de cuentaregresiva enSeccioacuten 58 Si llamamos a fact con el valor 3

Maacutes recursividad 77

Como 3 no es 0 se toma la segunda rama y se calcula el factorial de n-1 hellip

 Como 2 no es 0 se toma la segunda rama y se calcula el factorial de n-1 hellip

  Como 1 no es 0 se toma la segunda rama y se calcula el factorial de + n-1 +hellip

   Como 0 es igual a 0 se toma la primera rama y devuelve 1 sin realizar      maacutes llamadas recursivas

  El valor de retorno 1 se multiplica por n que es 1 y se devuelve elresultado

 El valor de retorno 1 se multiplica por n que es 2 y se devuelve el resultado

El valor de retorno 2 se multiplica por n que es 3 y el resultado 6 se convierteen el valor de retorno de la llamada a funcioacuten que inicioacute todo el proceso

Figura 9 Diagrama de pila

Figura 9 muestra coacutemo se ve el diagrama de pila para esta secuencia dellamadas a funciones

Los valores de retorno se pasan de nuevo a la pila En cada marco el valor deretorno es el valor de resultado que es el producto de n y recursion

En el uacuteltimo marco las variables locales recursion y resultado no existen porquela rama que las crea no se ejecuta

OBSERVACIOacuteN Julia tiene la funcioacuten factorial para calcular el factorialde un nuacutemero entero

Voto de confianzaSeguir el flujo de ejecucioacuten es una forma de leer programas pero puede llegar aser abrumador Una alternativa es lo que se conoce como el voto deconfianza(en ingleacutes leap of faith) Cuando llega a una llamada de funcioacuten enlugar de seguir el flujo de ejecucioacuten asume que la funcioacuten funcionacorrectamente y devuelve el resultado correcto

De hecho ya se estaacute dando este voto de confianza cuando se usan funciones

78 Capiacutetulo 6 Funciones productivas

integradas de Julia Cuando se llaman a cos o exp no se examinan los cuerpos deesas funciones Simplemente se asume que funcionan porque las personas quelas escribieron eran buenos programadores

Lo mismo ocurre cuando el usuario llama a una de sus propias funciones Porejemplo en Seccioacuten 64 se escribe una funcioacuten llamada esdivisible quedetermina si un nuacutemero es divisible por otro Una vez que se confirme que estafuncioacuten es correcta mdashal examinar y probar el coacutedigomdash se puede usar la funcioacutensin mirar nuevamente el cuerpo

Lo mismo aplica a los programas recursivos Cuando llegue a la llamadarecursiva en lugar de seguir el flujo de ejecucioacuten debe suponer que la llamadarecursiva funciona (devuelve el resultado correcto) y luego preguntarseSuponiendo que pueda encontrar el factorial de iquestse puede calcular elfactorial de Estaacute claro que es posible multiplicando por

Por supuesto es un poco extrantildeo suponer que la funcioacuten funciona correctamentecuando no ha terminado de escribirla iexclpero por eso se llama voto de confianza

Un Ejemplo MaacutesDespueacutes de los factoriales el ejemplo maacutes comuacuten de una funcioacuten matemaacuteticadefinida de manera recursiva es fibonacci que tiene la siguiente definicioacuten (verhttpsenwikipediaorgwikiFibonacci_number)

Traducido a Julia se ve asiacute

function fib(n) if n == 0 return 0 elseif n == 1 return 1 else return fib(n-1) + fib(n-2) endend

Si intenta seguir el flujo de ejecucioacuten en esta funcioacuten incluso para valoresbastante pequentildeos de n su cabeza podriacutea estallar Dando un voto de confianzaes decir asumiendo que las dos llamadas recursivas funcionan correctamenteentonces estaacute claro que se obtiene el resultado correcto al sumarlas

Un Ejemplo Maacutes 79

Tipos de Comprobacioacuten

iquestQueacute pasa si se llama a fact con 15 como argumento

juliagt fact(15)ERROR StackOverflowErrorStacktrace [1] fact(Float64) at REPL[3]2

Parece una recursioacuten infinita iquestComo es esto posible La funcioacuten tiene un casobase (cuando n == 0) Pero si n no es un nuacutemero entero es posible perderse elcaso base y hacer recursioacuten para siempre

En la primera llamada recursiva el valor de n es 05 En la siguiente es -05 Apartir de ahiacute se vuelve maacutes pequentildeo (maacutes negativo) pero nunca seraacute 0

Existen dos opciones Se puede intentar generalizar la funcioacuten factorial paratrabajar con nuacutemeros de punto flotante o se puede hacer que fact verifique eltipo del argumento La primera opcioacuten se llama funcioacuten gamma y estaacute un pocomaacutes allaacute del alcance de este libro En este libro se proseguiraacute con la segunda

Se puede usar el operador integrado isa para verificar el tipo de argumentoTambieacuten podemos asegurarnos de que el argumento sea positivo

function fact(n) if (n isa Int64) error(El factorial uacutenicamente estaacute definido para nuacutemerosenteros) elseif n lt 0 error(El factorial no estaacute definido para enteros negativos) elseif n == 0 return 1 else return n fact(n-1) endend

El primer caso base se hace cargo de nuacutemeros no enteros y el segundo deenteros negativos En ambos casos el programa imprime un mensaje de error ydevuelve nothing para indicar que algo salioacute mal

juliagt fact(fred)ERROR El factorial uacutenicamente estaacute definido para nuacutemeros enterosjuliagt fact(-2)ERROR El factorial no estaacute definido para enteros negativos

80 Capiacutetulo 6 Funciones productivas

Si se superan ambas verificaciones se sabe que n es positivo o cero por lo quees posible probar que la recursioacuten termina

Este programa muestra un patroacuten a veces llamado guardian Los dos primeroscondicionales actuacutean como guardianes protegiendo el coacutedigo que sigue de losvalores que pueden causar un error Los guardianes hacen posible demostrar queel coacutedigo es correcto

En Seccioacuten 145 se exploraraacute una alternativa maacutes flexible para imprimir unmensaje de error generar una excepcioacuten

DepuracioacutenDividir un coacutedigo extenso en pequentildeas funciones crea naturalmente puntos decontrol para la depuracioacuten Si un programa no estaacute funcionando existen tresposibilidades a considerar

bull Hay algo incorrecto en los argumentos de la funcioacuten se viola una condicioacutenprevia

bull Hay algo incorrecto en la funcioacuten se viola una condicioacuten posterior

bull Hay algo incorrecto en el valor de retorno o la forma en que se estaacuteutilizando

Para descartar la primera posibilidad puede agregar una sentencia de impresioacutenal comienzo de la funcioacuten para mostrar los valores de los paraacutemetros (y tal vezsus tipos) o bien escribir liacuteneas de coacutedigo que verifiquen las condiciones previasde manera expliacutecita

Si los paraacutemetros estaacuten bien agregue una sentencia de impresioacuten antes de cadasentencia return y muestre el valor de retorno Si es posible verifique elresultado a mano Considere tambieacuten llamar a la funcioacuten con valores quefaciliten la verificacioacuten del resultado (como en Seccioacuten 62)

Si la funcioacuten parece estar funcionando revise la llamada a la funcioacuten paraasegurarse de que el valor de retorno se estaacute utilizando correctamente (iexcloincluso si se estaacute utilizando)

Agregar sentencias de impresioacuten al principio y al final de una funcioacuten puedeayudar a que el flujo de ejecucioacuten sea maacutes transparente Por ejemplo aquiacute hayuna versioacuten de fact con sentencias de impresioacuten

Depuracioacuten 81

function fact(n) espacio = ^ (4 n) println(espacio factorial n) if n == 0 println(espacio devolviendo 1) return 1 else recursion = fact(n-1) resultado = n recursion println(espacio devolviendo resultado) return resultado endend

espacio es una cadena de caracteres de espacios que permite generar sangriacutea enla salida

juliagt fact(4) factorial 4 factorial 3 factorial 2 factorial 1factorial 0devolviendo 1 devolviendo 1 devolviendo 2 devolviendo 6 devolviendo 2424

Si estaacute confundido con el flujo de ejecucioacuten este tipo de salida puede ser uacutetilDesarrollar un buen andamiaje toma tiempo pero un poco de andamiaje puedeahorrar al usuario mucha depuracioacuten

Glosariovariable temporal

Variable usada para almacenar un valor intermedio en un caacutelculo complejo

coacutedigo muertoParte de un programa que nunca puede ser ejecutado a menudo porqueaparece despueacutes de una sentencia return

desarrollo incrementalPlan de desarrollo de un programa que intenta evitar la depuracioacutenagregando y probando solamente una pequentildea porcioacuten de coacutedigo a la vez

82 Capiacutetulo 6 Funciones productivas

andamiajeCoacutedigo que se usa durante el desarrollo de un programa pero que no esparte de la versioacuten final del mismo

guardiaacutenUn patroacuten de programacioacuten que usa una sentencia condicional paraverificar y manejar circunstancias que pueden causar un error

Ejercicios

Ejercicio 6-4

Dibuje un diagrama de pila para el siguiente programa iquestQueacute imprime elprograma

function b(z) prod = a(z z) println(z prod) prodend

function a(x y) x = x + 1 x yend

function c(x y z) total = x + y + z cuadrado = b(total)^2 cuadradoend

x = 1y = x + 1println(c(x y+3 x+y))

Ejercicio 6-5

La funcioacuten de Ackermann se define

Vea httpsenwikipediaorgwikiAckermann_function Escriba una funcioacutenllamada ack que evaluacutee la funcioacuten de Ackermann Use su funcioacuten para evaluarack(3 4) que deberiacutea ser 125 iquestQueacute sucede para valores mayores de m y n

Ejercicios 83

Ejercicio 6-6

Un paliacutendromo es una palabra que se escribe igual en un sentido que en otrocomo ana y radar De manera recursiva una palabra es un paliacutendromo si laprimera y la uacuteltima letra son iguales y lo que estaacute entre ellas es un paliacutendromo

Las siguientes funciones toman un argumento de tipo cadena y devuelven laprimera letra la uacuteltima y las intermedias

function primera(palabra) primera = firstindex(palabra) palabra[primera]end

function ultima(palabra) ultima = lastindex(palabra) palabra[ultima]end

function medio(palabra) primera = firstindex(palabra) ultima = lastindex(palabra) palabra[nextind(palabra primera) prevind(palabra ultima)]end

Se veraacute coacutemo funcionan en Capiacutetulo 8

1 Pruebe estas funciones iquestQueacute sucede si llama a la funcioacuten medio con unacadena de dos letras iquestY con una cadena de una letra iquestQueacute pasa con lacadena vaciacutea que no contiene letras

2 Escriba una funcioacuten llamada espalindromo que tome un argumento de tipocadena y devuelva true si es un paliacutendromo y false de lo contrario Recuerdeque puede usar la funcioacuten integrada length para verificar la longitud de unacadena

Ejercicio 6-7

Un nuacutemero es una potencia de si es divisible por y es una potencia de Escriba una funcioacuten llamada espotencia que tome los paraacutemetros a y b ydevuelva true si a es una potencia de b

OBSERVACIOacuteN Tendraacute que pensar en el caso base

Ejercicio 6-8

El maacuteximo comuacuten divisor (MCD) de y es el nuacutemero maacutes grande que los divide

84 Capiacutetulo 6 Funciones productivas

a ambos con resto 0

Una forma de encontrar el MCD de dos nuacutemeros se basa en la observacioacuten deque si es el resto cuando se divide por entonces mcd(a b) = mcd(b r)Como caso base podemos usar mcd(a 0) = a

Escriba una funcioacuten llamada mcd que tome los paraacutemetros a y b y devuelva sumaacuteximo divisor comuacuten

Creacuteditos Este ejercicio se basa en un ejemplo del libro Estructura einterpretacioacuten de programas informaacuteticos de Abelson y Sussman

Ejercicios 85

Capiacutetulo 7 IteracioacutenEste capiacutetulo se centra en la iteracioacuten que es la capacidad de ejecutarrepetidamente un bloque de sentencias Se han visto dos tipos de iteracioacutenusando recursioacuten en Seccioacuten 58 y usando ciclos for en Seccioacuten 42 En estecapiacutetulo veremos otro tipo maacutes usando sentencias while Primeramente seintroduciraacuten algunos teacuterminos sobre asignacioacuten de variables

Asignacioacuten muacuteltiplePuede que ya haya descubierto que estaacute permitido realizar maacutes de unaasignacioacuten a la misma variable Una nueva asignacioacuten hace que la variableexistente se refiera a un nuevo valor (y deje de referirse al viejo valor)

juliagt x = 55juliagt x = 77

La primera vez que se muestra x su valor es 5 y la segunda vez su valor es 7

Figura 10 Diagrama de estado

Figura 10 muestra el aspecto de una asignacioacuten muacuteltiple en un diagrama deestado

Es necesario aclarar algo que puede causar confusioacuten Puesto que Julia usa elsigno igual (=) para la asignacioacuten es tentador interpretar una sentencia a = bcomo una sentencia de igualdad Pero esta interpretacioacuten es incorrecta

Para empezar la igualdad es simeacutetrica y la asignacioacuten no lo es Por ejemplo enmatemaacuteticas si entonces Pero en Julia la sentencia a = 7 es vaacutelida y 7= a no lo es

Ademaacutes en matemaacuteticas una sentencia de igualdad es verdadera o falsasiempre Si ahora entonces siempre seraacute igual a En Julia una sentenciade asignacioacuten puede hacer que dos variables sean iguales pero no tienen porqueacute quedarse asiacute

86 Capiacutetulo 7 Iteracioacuten

juliagt a = 55juliagt b = a a y b son iguales5juliagt a = 3 a y b ya no son iguales3juliagt b5

La tercera liacutenea cambia el valor de a pero no cambia el valor de b por lo tanto yadejan de ser iguales

AVISO

Reasignar variables puede ser uacutetil pero se debe tener precaucioacutenSi los valores cambian frecuentemente la reasignacioacuten puedehacer que el coacutedigo sea difiacutecil de leer y depurar

Estaacute permitido definir una funcioacuten con el mismo nombre de unavariable definida anteriormente

Actualizacioacuten de variablesUna de las formas maacutes comunes de asignacioacuten muacuteltiple es la actualizacioacutendoacutende el nuevo valor de la variable depende del anterior

juliagt x = x + 18

Esto significa ldquotome el valor actual de x suacutemele uno y despueacutes actualice x con elnuevo valorrdquo

Si intenta actualizar una variable que no existe obtendraacute un error puesto queJulia evaluacutea la expresioacuten del lado derecho antes de asignar un valor a x

juliagt y = y + 1ERROR UndefVarError y not defined

Antes de actualizar una variable tiene que inicializarla usualmente con unaasignacioacuten simple

juliagt y = 00juliagt y = y + 11

Actualizar una variable sumaacutendole 1 se denomina un incremento y restaacutendole 1

Actualizacioacuten de variables 87

se llama un decremento

La Sentencia whileLas computadoras se usan a menudo para automatizar tareas repetitivasRealizar repetidamente tareas ideacutenticas o similares sin cometer errores es algoque las computadoras hacen bien y que los seres humanos hacen limitadamenteLa ejecucioacuten repetida de un conjunto de sentencias se llama iteracioacuten

Ya se han visto dos funciones cuentaregresiva y printn que iteran usandorecursividad Por ser la iteracioacuten tan comuacuten Julia proporciona variascaracteriacutesticas que la hacen maacutes faacutecil Una es la sentencia for que se vio enSeccioacuten 42 a la cual se volveraacute maacutes adelante

Otra caracteriacutestica es la sentencia while Aquiacute hay una versioacuten decuentaregresiva que muestra el uso de la sentencia while

function cuentaregresiva(n) while n gt 0 print(n ) n = n - 1 end println(iexclDespegue)end

Casi podriacutea leer la sentencia while como si fuera Espantildeol La funcioacuten anteriorsignifica ldquoMientras n sea mayor que 0 continuacutee mostrando el valor de n y luegoreduciendo el valor de n en 1 Cuando llegue a 0 muestre la palabra iexclDespegueldquo

Maacutes formalmente el flujo de ejecucioacuten de una sentencia while es el siguiente

1 Se determina si la condicioacuten es verdadera o falsa

2 Si es falsa se sale de la sentencia while y continuacutea la ejecucioacuten con lasiguiente sentencia

3 Si es verdadera ejecuta cada una de las sentencias en el cuerpo y regresa alpaso 1

Este tipo de flujo se llama bucle porque el tercer paso vuelve a la parte superior

El cuerpo del bucle deberiacutea cambiar el valor de una o maacutes variables de maneraque en alguacuten momento la condicioacuten sea falsa y el bucle termine En casocontrario el bucle se repetiraacute indefinidamente lo cual se llama bucle infinitoUna interminable fuente de diversioacuten para los informaacuteticos es la observacioacuten deque las instrucciones del champuacute ldquoEnjabone enjuague repitardquo son un bucleinfinito

88 Capiacutetulo 7 Iteracioacuten

En el caso de cuentaregresiva podemos probar que el bucle termina si n es ceroo negativo el ciclo termina En otro caso el valor de n se hace maacutes pequentildeocada vez que pasa por el bucle asiacute en cierto momento se llega a 0

En otros casos no es tan faacutecil decirlo Por ejemplo

function seq(n) while n = 1 println(n) if n 2 == 0 n is par n = n 2 else n is impar n = n3 + 1 end endend

La condicioacuten de este bucle es n = 1 de manera que el bucle continuaraacute hastaque n sea 1 que haraacute que la condicioacuten sea falsa

Cada vez que pasa por el bucle el programa muestra como salida el valor de n yluego comprueba si es par o impar Si es par el valor de n se divide por dos Si esimpar el valor de n se sustituye por n3 + 1 Por ejemplo si el argumento pasadoa la funcioacuten seq es 3 los valores resultantes n son 3 10 5 16 8 4 2 1

Puesto que n a veces aumenta y a veces disminuye no hay una prueba obvia deque n alcance alguna vez el valor 1 o de que el programa vaya a terminar Paraalgunos valores particulares de n se puede probar que siacute termina Por ejemplosi el valor de inicio es una potencia de dos entonces el valor de n seraacute par cadavez que se pasa por el bucle hasta que llegue a 1 El ejemplo anterior producedicha secuencia si se inicia con 16

Lo diacuteficil es preguntarse si se puede probar que este programa termina paratodos los valores positivos de n Hasta ahora nadie ha sido capaz de probar quelo hace o iexclque no lo hace (Vea httpseswikipediaorgwikiConjetura_de_Collatz)

Ejercicio 7-1

Reescribe la funcioacuten printn de Seccioacuten 58 utilizando iteracioacuten en vez derecursioacuten

breakA veces no se sabe que un ciclo debe terminar hasta que se llega al cuerpo Enese caso se puede usar la sentencia break para salir del bucle

break 89

Por ejemplo suponga que se desea recibir entradas del usuario hasta que esteescriba listo Podriacuteamos escribir

while true print(gt ) linea = readline() if line == listo break end println(linea)endprintln(iexclListo)

La condicioacuten del bucle es true que siempre es verdadero por lo que el bucle seejecuta hasta que llega a la sentencia break

En cada iteracioacuten se le pide al usuario (con el siacutembolo gt ) una entrada Si elusuario escribe listo la sentencia break sale del bucle De lo contrario elprograma repite lo que escriba el usuario y vuelve a la parte superior del bucleA continuacioacuten se muestra coacutemo funciona este programa

gt no listono listogt listoiexclListo

Esta forma de escribir bucles while es comuacuten porque permite verificar lacondicioacuten en cualquier parte del bucle (no solo en la parte superior) y puedeexpresar la condicioacuten de teacutermino de manera afirmativa (detenerse cuando estosuceda) en vez de negativamente (continuar hasta que esto suceda)

continueLa sentencia break permite terminar el bucle Cuando aparece una sentenciacontinue dentro de un bucle se regresa al comienzo del bucle ignorando todoslas sentencias que quedan en la iteracioacuten actual del bucle e inicia la siguienteiteracioacuten Por ejemplo

for i in 110 if i 3 == 0 continue end print(i )end

Output

90 Capiacutetulo 7 Iteracioacuten

1 2 4 5 7 8 10

Si i es divisible por 3 la sentencia continue detiene la iteracioacuten actual ycomienza la siguiente iteracioacuten Solo se imprimen los nuacutemeros en el rango de 1 a10 no divisibles por 3

Raiacuteces CuadradasLos bucles son comuacutenmente utilizados en programas que calculan resultadosnumeacutericos y que comienzan con una respuesta aproximada que es iterativamentemejorada

Por ejemplo una forma de calcular raiacuteces cuadradas es el meacutetodo de NewtonSuponga que desea conocer la raiacutez cuadrada de Si comienza con casi cualquierestimacioacuten puede calcular una mejor aproximacioacuten con la siguiente foacutermula

Por ejemplo si es 4 y es 3

juliagt a = 44juliagt x = 33juliagt y = (x + ax) 221666666666666665

El resultado estaacute maacutes cerca de la respuesta correcta ( ) Si se repite elproceso con la nueva estimacioacuten se acerca auacuten maacutes

juliagt x = y21666666666666665juliagt y = (x + ax) 220064102564102564

Despueacutes de algunas actualizaciones la estimacioacuten es casi exacta

Raiacuteces Cuadradas 91

juliagt x = y20064102564102564juliagt y = (x + ax) 220000102400262145juliagt x = y20000102400262145juliagt y = (x + ax) 220000000000262146

En general no se sabe de antemano cuaacutentos pasos se necesitan para llegar a larespuesta correcta pero se sabe que se ha llegado a ella cuando la estimacioacutendeja de cambiar

juliagt x = y20000000000262146juliagt y = (x + ax) 220juliagt x = y20juliagt y = (x + ax) 220

Cuando y == x ya se pueden detener los coacutemputos A continuacioacuten se muestraun ciclo que comienza con una estimacioacuten inicial x la cual mejora hasta que dejade cambiar

while true println(x) y = (x + ax) 2 if y == x break end x = yend

Para la mayoriacutea de los valores de a esto funciona bien aunque en general no serecomienda probar igualdad entre nuacutemeros de punto flotante Los nuacutemeros depunto flotante son aproximadamente correctos la mayoriacutea de los nuacutemerosracionales como e irracionales como no pueden ser representadosexactamente con un Float64

En lugar de verificar si x e y son exactamente iguales es maacutes seguro usar lafuncioacuten integrada abs para calcular el valor absoluto o la magnitud de ladiferencia entre ellos

92 Capiacutetulo 7 Iteracioacuten

if abs(y-x) lt ε breakend

Donde ε (varepsilon TAB) toma un valor como 00000001 que determina coacutemode cerca es suficientemente cerca

AlgoritmosEl meacutetodo de Newton es un ejemplo de un algoritmo un proceso mecaacutenico quepermite resolver una categoriacutea de problemas (en este caso el caacutelculo de raiacutecescuadradas)

Para comprender queacute es un algoritmo podriacutea ayudar empezar con algo que no esun algoritmo Cuando aprendioacute a multiplicar nuacutemeros de un solo diacutegitoprobablemente memorizoacute la tabla de multiplicar En efecto memorizoacute 100soluciones especiacuteficas Ese tipo de conocimiento no es un algoritmo

Pero si fuera perezoso podriacutea haber aprendido algunos trucos Por ejemplopara encontrar el producto de y 9 puede escribir como el primer diacutegito y

como el segundo diacutegito Este truco es una solucioacuten general para multiplicarcualquier nuacutemero de un solo diacutegito por 9 iexclEsto siacute es un algoritmo

Del mismo modo las teacutecnicas que aprendioacute para la suma con ldquollevamos tantordquo laresta con ldquopedimos prestado tantordquo y la divisioacuten ldquolarga o con galera o de casitardquoson todas ellas algoritmos Una de las caracteriacutesticas de los algoritmos es que norequieren inteligencia para realizarlos Son procesos mecaacutenicos donde cada pasose sigue de acuerdo con un conjunto simple de reglas

Ejecutar algoritmos es aburrido pero disentildearlos es interesante intelectualmentedesafiante y constituyen una parte central de la informaacutetica

Algunas de las cosas que las personas hacen naturalmente sin dificultad oconscientemente son las maacutes difiacuteciles de expresar en algoritmos Comprender ellenguaje natural es un buen ejemplo Todo el mundo lo hace pero hasta ahoranadie ha podido explicar coacutemo se hace al menos no en forma de algoritmo

DepuracioacutenA medida que comience a escribir programas maacutes extensos es posible que pasemaacutes tiempo depurando Maacutes coacutedigo significa maacutes posibilidades de cometer unerror y maacutes lugares doacutende se pueden esconder los errores

Una forma de reducir el tiempo de depuracioacuten es depurar por biseccioacuten Porejemplo si hay 100 liacuteneas en su programa y las revisa una a la vez seriacutean 100revisiones

Algoritmos 93

Es mejor tratar de dividir el problema en dos Busque en la mitad del programa oun valor intermedio que pueda verificar Agregue una sentencia de impresioacuten (oalgo que permita verificar) y ejecute el programa

Si esta verificacioacuten es incorrecta debe haber un problema en la primera mitaddel programa Si es correcta el problema estaacute en la segunda mitad

Cada vez que realiza una verificacioacuten como esta reduce a la mitad el nuacutemero deliacuteneas que debe revisar Despueacutes de seis pasos (que es mucho menos que 100) sereduciriacutea a una o dos liacuteneas de coacutedigo al menos en teoriacutea

En la praacutectica no siempre se conoce doacutende estaacute la mitad del programa y nosiempre es posible verificarlo No tiene sentido contar liacuteneas y encontrar el puntomedio exacto En su lugar piense en los lugares del programa donde puedehaber errores y en los lugares donde es faacutecil verificar Luego elija un lugar endonde usted crea que las posibilidades de encontrar un error antes o despueacutes deesta verificacioacuten son maacutes o menos las mismas

Glosarioasignacioacuten muacuteltiple

Asignar un nuevo valor a una variable que ya existe

actualizacioacutenAsignacioacuten donde el nuevo valor de la variable depende del antiguo

inicializacioacutenAsignacioacuten que le da un valor inicial a una variable que seraacute actualizada

incrementoActualizacioacuten que incrementa el valor de la variable (usualmente en 1)

decrementoActualizacioacuten que disminuye el valor de la variable (usualmente en 1)

iteracioacutenEjecucioacuten repetida de un conjunto de sentencias usando una funcioacutenrecursiva o un bucle

sentencia whileSentencia que permite iteraciones controladas por una condicioacuten

sentencia breakSentencia que permite salir de un bucle

94 Capiacutetulo 7 Iteracioacuten

sentencia continueSentencia localizada dentro de un bucle que obliga a iniciar una nuevaiteracioacuten desde el inicio del bucle

bucle infinitoUn bucle cuya condicioacuten de teacutermino no es satisfecha

algoritmoProceso general para resolver una categoriacutea de problemas

Ejercicios

Ejercicio 7-2

Copie el bucle de Seccioacuten 76 e inseacutertelo en una funcioacuten llamada miraiz que tomea como paraacutemetro elija un valor razonable de x y devuelva una estimacioacuten de laraiacutez cuadrada de a

Para probarla escriba una funcioacuten llamada probarraiz que imprima una tablacomo esta

a mysqrt sqrt diff- ------ ---- ----10 10 10 0020 1414213562373095 14142135623730951 2220446049250313e-1630 17320508075688772 17320508075688772 0040 20 20 0050 223606797749979 223606797749979 0060 2449489742783178 2449489742783178 0070 26457513110645907 26457513110645907 0080 282842712474619 28284271247461903 4440892098500626e-1690 30 30 00

La primera columna es un nuacutemero a la segunda columna es la raiacutez cuadrada dea calculada con miraiz la tercera columna es la raiacutez cuadrada calculada con lafuncioacuten integrada sqrt y la cuarta columna es el valor absoluto de la diferenciaentre las dos estimaciones

Exercise 7-3

La funcioacuten integrada Metaparse toma una cadena y la transforma en unaexpresioacuten Esta expresioacuten se puede evaluar en Julia con la funcioacuten Coreeval Porejemplo

Ejercicios 95

juliagt expr = Metaparse(1+23)(1 + 2 3)juliagt eval(expr)7juliagt expr = Metaparse(sqrt(π))(sqrt(π))juliagt eval(expr)17724538509055159

Escriba una funcioacuten llamada evalbucle que iterativamente solicite una entrada alusuario tome la entrada resultante la evaluacutee usando eval y pase posteriormentea imprimir el resultado Debe continuar hasta que el usuario ingrese listo y luegodevolver el valor de la uacuteltima expresioacuten que evaluoacute

Exercise 7-4

El matemaacutetico Srinivasa Ramanujan encontroacute una serie infinita que puede usarsepara generar una aproximacioacuten numeacuterica de

Escriba una funcioacuten llamada estimarpi que utilice esta foacutermula para calcular ydevolver una estimacioacuten de π Debe usar un ciclo while para calcular losteacuterminos de la suma hasta que el uacuteltimo teacutermino sea menor que 1e-15 (que es lanotacioacuten de Julia para ) Puede verificar el resultado comparaacutendolo con π

96 Capiacutetulo 7 Iteracioacuten

Capiacutetulo 8 CadenasLas cadenas son diferentes de los nuacutemeros enteros flotantes y booleanos Unacadena es una secuencia es decir una coleccioacuten ordenada de valores En estecapiacutetulo se veraacute coacutemo acceder a los caracteres que forman una cadena y seconoceraacuten algunas funciones integradas en Julia relacionadas con cadenas

CaracteresLos hispanohablantes estaacuten familiarizados con algunos caracteres tales como lasletras del alfabeto (A B C hellip) los nuacutemeros y los signos de puntuacioacuten comunesEstos caracteres estaacuten estandarizados en el coacutedigo ASCII (Coacutedigo EstaacutendarEstadounidense para el Intercambio de Informacioacuten)

Por supuesto hay muchos otros caracteres utilizados en idiomas distintos delespantildeol que no estaacuten en el coacutedigo ASCII tales como aquellos usados en losidiomas griego aacuterabe chino hebreo hindi japoneacutes y coreano

Definir queacute es un caraacutecter es altamente complejo La norma Unicode permiteabordar este problema y se considera como el estaacutendar definitivo para ello Estanorma funciona asignando un nuacutemero uacutenico para cada caraacutecter a nivel global

Un valor Char representa un uacutenico caraacutecter y estaacute entre comillas simples

juliagt xx ASCIIUnicode U+0078 (category Ll Letter lowercase)juliagt ἴἴ Unicode U+1F34C (category So Symbol other)juliagt typeof(x)Char

Incluso los emojis son parte del estaacutendar Unicode (banana TAB)

Una Cadena es una SecuenciaUna cadena es una secuencia de caracteres Se puede acceder a un caraacutecter conel operador corchete

juliagt fruta = bananabananajuliagt letra = fruta[1]b ASCIIUnicode U+0062 (category Ll Letter lowercase)

La segunda sentencia selecciona el caraacutecter nuacutemero 1 de fruta y la asigna a lavariable letra

Caracteres 97

La expresioacuten entre corchetes se llama indice El iacutendice indica el caraacutecter de lasecuencia a obtener (de ahiacute el nombre)

La indexacioacuten en Julia es base 1 es decir el primer elemento de cualquier objetoindexado con enteros estaacute en el iacutendice 1 y el uacuteltimo en el iacutendice end

juliagt fruta[end]a ASCIIUnicode U+0061 (category Ll Letter lowercase)

Como iacutendice se pueden usar expresiones que contengan variables y operadores

juliagt i = 11juliagt fruta[i+1]a ASCIIUnicode U+0061 (category Ll Letter lowercase)juliagt fruta[end-1]n ASCIIUnicode U+006E (category Ll Letter lowercase)

No obstante el valor del iacutendice tiene que ser un nuacutemero entero De lo contrariose obtiene

juliagt letra = fruta[15]ERROR MethodError no method matching getindex(String Float64)

lengthlength es una funcioacuten integrada que devuelve el nuacutemero de caracteres de unacadena

juliagt frutas = ἴ ἴ ἵἴ ἴ ἵjuliagt len = length(frutas)5

Para obtener la uacuteltima letra de una cadena puede sentirse tentado a probar algocomo esto

juliagt last = frutas[len] ASCIIUnicode U+0020 (category Zs Separator space)

Pero con esto no se obtiene el resultado esperado

Las cadenas se codifican usando codificacioacuten UTF-8 UTF-8 es una codificacioacutende longitud variable lo que significa que no todos los caracteres estaacuten

98 Capiacutetulo 8 Cadenas

codificados con el mismo nuacutemero de bytes

La funcioacuten sizeof devuelve el nuacutemero de bytes de una cadena

juliagt sizeof(ἴ)4

Dado que un emoji estaacute codificado en 4 bytes y la indexacioacuten de cadenas estaacutebasada en bytes el quinto elemento de frutas es un ESPACIO

Esto significa que no todos los iacutendices de byte de una cadena UTF-8 sonnecesariamente iacutendices vaacutelidos para un caraacutecter Si en una cadena se indexa conun iacutendice de bytes no vaacutelido se genera un error

juliagt frutas[2]ERROR StringIndexError(ἴ ἴ ἵ 2)

En el caso de frutas el caraacutecter ἴ es un caraacutecter de cuatro bytes por lo que losiacutendices 2 3 y 4 no son vaacutelidos y el iacutendice del siguiente caraacutecter es 5 el siguienteiacutendice vaacutelido se puede calcular con nextind(frutas 1) el subsiguiente connextind(frutas5) y asiacute sucesivamente

RecorridoMuchos caacutelculos implican procesar una cadena caraacutecter por caraacutecter A menudoempiezan por el principio seleccionan cada caraacutecter por turno hacen algo con eacutely continuacutean hasta el final Este patroacuten de proceso se llama recorrido Una formade escribir un recorrido es con una sentencia while

indice = firstindex(frutas)while indice lt= sizeof(frutas) letra = frutas[indice] println(letra) global indice = nextind(frutas indice)end

Este bucle recorre la cadena y muestra cada letra en una liacutenea distinta Lacondicioacuten del bucle es index lt= sizeof(fruta) de modo que cuando el iacutendice esmayor al nuacutemero de bytes en la cadena la condicioacuten es falsa y no se ejecuta elcuerpo del bucle

La funcioacuten firstindex devuelve el primer iacutendice de bytes vaacutelido La palabrareservada global antes de indice indica que queremos reasignar la variableindice definida en Main (ver Seccioacuten 117)

Recorrido 99

Ejercicio 8-1

Escriba una funcioacuten que tome una cadena como argumento y que muestre lasletras desde la uacuteltima a la primera una por liacutenea

Otra forma de escribir un recorrido es con un bucle for

for letra in frutas println(letra)end

Cada vez que se recorre el bucle se asigna a la variable letra el siguientecaraacutecter de la cadena El bucle continuacutea hasta que no quedan maacutes caracteres

El ejemplo siguiente muestra coacutemo usar la concatenacioacuten (multiplicacioacuten decadenas) y un bucle for para generar una serie abecedaria (es decir una seriecon elementos en orden alfabeacutetico) Por ejemplo en el libro de Robert McCloskeyMake Way for Ducklings los nombres de los patitos son Jack Kack Lack MackNack Ouack Pack y Quack Este bucle muestra esos nombres en orden

prefijos = JKLMNOPQsufijo = ack

for letra in prefijos println(letra sufijo)end

Output

JackKackLackMackNackOackPackQack

Por supuesto esto no es del todo correcto porque ldquoOuackrdquo y ldquoQuackrdquo no estaacutencorrectamente escritos

Ejercicio 8-2

Modifique este programa para solucionar este error

100 Capiacutetulo 8 Cadenas

Porciones de CadenasA la subcadena de una cadena se le llama porcioacuten La seleccioacuten de una porcioacuten essimilar a la seleccioacuten de un caraacutecter

juliagt str = Julio Cesar

juliagt str[15]Julio

El operador [nm] devuelve la parte de la cadena desde el n-eacutesimo byte hasta elm-eacutesimo Por lo tanto se siguen las mismas reglas que para la indexacioacuten simple

La palabra reservada end se puede usar para indicar al uacuteltimo byte de la cadena

juliagt str[7end]Cesar

Si el primer iacutendice es mayor que el segundo el resultado es una cadena vaciacutearepresentada por dos comillas

juliagt str[87]

Una cadena vaciacutea no contiene caracteres y tiene una longitud de 0 pero apartede eso es igual a cualquier otra cadena

Ejercicio 8-3

Continuando este ejemplo iquestqueacute cree que significa str[] Pruebe y veraacute

Las Cadenas son InmutablesEs tentador usar el operador [] en el lado izquierdo de una asignacioacuten con laintencioacuten de cambiar un caraacutecter en una cadena Por ejemplo

juliagt saludo = iexclHola mundoiexclHola mundojuliagt saludo[3] = JERROR MethodError no method matching setindex(String CharInt64)

Nota del traductor De acuerdo con la codificacioacuten de caracteres en utf-8 o latin-

Porciones de Cadenas 101

1 el caraacutecter de exclamacioacuten lsquoiexclrsquo en la variable saludo ocupa dos posiciones deahiacute que la letra lsquoHrsquo esteacute localizada en el iacutendice 3

La razoacuten del error es que las cadenas son inmutables lo que significa que no sepuede cambiar una cadena existente Lo maacuteximo que se puede hacer es crearuna nueva cadena que sea una variacioacuten de la original

juliagt saludo = iexclJ saludo[4end]iexclJola mundo

Este ejemplo concatena la apertura del signo de exclamacioacuten y una nuevaprimera letra a una porcioacuten de saludo Esta operacioacuten no tiene efecto sobre lacadena original

Interpolacioacuten de CadenasConstruir cadenas usando concatenacioacuten puede ser un poco engorroso Paradisminuir la necesidad de las llamadas a string o multiplicaciones repetidas Juliapermite la interpolacioacuten de cadenas usando $

juliagt saludo = iexclHolaiexclHolajuliagt paraquien = mundomundojuliagt $saludo $(paraquien)iexclHola mundo

Esto es maacutes entendible y conveniente que la concatenacioacuten de cadenas saludo paraquien

La expresioacuten inmediatamente siguiente a $ se toma como la expresioacuten cuyo valorse va a interpolar en la cadena Por lo tanto puede interpolar cualquierexpresioacuten en una cadena usando pareacutentesis

juliagt 1 + 2 = $(1 + 2)1 + 2 = 3

Buacutesqueda

iquestQueacute hace la siguiente funcioacuten

102 Capiacutetulo 8 Cadenas

function busqueda(palabra letra) indice = primerindice(palabra) while indice lt= sizeof(palabra) if palabra[indice] == letra return indice end indice = nextind(palabra indice) end -1end

En cierto sentido la funcioacuten buacutesqueda es lo contrario del operador [] En lugarde tomar un iacutendice y extraer el caraacutecter correspondiente toma un caraacutecter yencuentra el iacutendice donde aparece el caraacutecter Si el caraacutecter no se encuentra lafuncioacuten devuelve -1

Este es el primer ejemplo de una sentencia return dentro de un bucle Sipalabra[indice] == letra la funcioacuten devuelve inmediatamente el iacutendiceescapando del bucle prematuramente

Si el caraacutecter no aparece en la cadena entonces el programa sale del buclenormalmente y devuelve -1

Este patroacuten de computacioacuten se llama a veces un recorrido eureka porque tanpronto como encontramos lo que buscamos podemos gritar ldquoiexclEureka rdquo y dejarde buscar

Ejercicio 8-4

Modifique la funcioacuten busqueda para que tenga un tercer paraacutemetro el iacutendice depalabra donde deberiacutea comenzar a buscar

Iterando y contandoEl siguiente programa cuenta el nuacutemero de veces que aparece la letra a en unacadena

palabra = bananacontador = 0for letra in palabra if letra == a global contador = contador + 1 endendprintln(contador)

Iterando y contando 103

Este programa es otro ejemplo del patroacuten de computacioacuten llamado conteo Lavariable contador se inicializa en 0 y se incrementa cada vez que encuentra laletra a Cuando termina el bucle contador contiene el resultado (el nuacutemero totalde letras a)

Ejercicio 8-5

Coloque este coacutedigo en una funcioacuten llamada conteo y generaliacutecelo de tal maneraque tome como argumentos una cadena y una letra

Luego vuelva a escribir la funcioacuten para que en vez de revisar toda la cadenautilice la funcioacuten busqueda de tres paraacutemetros de la seccioacuten anterior

Libreriacutea con cadenasJulia tiene funciones integradas que realizan una variedad de operaciones uacutetilesen cadenas Por ejemplo la funcioacuten uppercase toma una cadena y devuelve unanueva cadena con todas las letras mayuacutesculas

juliagt uppercase(iexclHola mundo)iexclHOLA MUNDO

Existe una funcioacuten llamada findfirst que es notablemente similar a la funcioacutenbusqueda que escribimos

juliagt findfirst(a banana)22

La funcioacuten findfirst es maacutes general que la funcioacuten creada puede encontrarsubcadenas no solo caracteres

juliagt findfirst(na banana)34

Por defecto findfirst empieza la buacutesqueda al comienzo de la cadena pero lafuncioacuten findnext toma un tercer argumento el indice donde deberiacutea comenzar

juliagt findnext(na banana 4)56

El operador isinEl operador isin (in TAB) es un operador booleano que toma un caraacutecter y unacadena y devuelve true si el primero aparece en el segundo

104 Capiacutetulo 8 Cadenas

juliagt a isin banana a en bananatrue

Por ejemplo la siguiente funcioacuten imprime todas las letras de palabra1 quetambieacuten aparecen en palabra2

function ambas(palabra1 palabra2) for letra in palabra1 if letra isin palabra2 print(letra ) end endend

Una buena eleccioacuten de nombres de variables permite que Julia se pueda leercomo el espantildeol Este bucle puede leerse como para (cada) letra en (la primera)palabra si (la) letra es un elemento de (la segunda) palabra imprima (la) letra

Esto es lo que se obtiene si se compara manzanas y naranjas

juliagt ambas(manzanas naranjas)a n a n a s

Comparacioacuten de CadenasLos operadores de comparacioacuten trabajan sobre cadenas Para ver si dos cadenasson iguales

palabra = Pintildeaif palabra == banana println(iexclTenemos bananas)end

Otras operaciones de comparacioacuten son uacutetiles para ordenar alfabeacuteticamentepalabras

if palabra lt banana println(Su palabra $palabra va antes de banana)elseif word gt banana println(Su palabra $palabra va antes de banana)else println(iexclTenemos bananas)end

Comparacioacuten de Cadenas 105

Julia no maneja las letras mayuacutesculas y minuacutesculas del mismo modo que sonmanejadas en cualquier lengua hablada Todas las letras mayuacutesculas van antesde las letras minuacutesculas seguacuten el estaacutendar de codificacioacuten Por lo tanto

Su palabra Pintildea va antes de banana

OBSERVACIOacuteNUna forma comuacuten de abordar este problema es convertirlas cadenas a un formato estaacutendar como por ejemplo aminuacutesculas antes de realizar la comparacioacuten

DepuracioacutenCuando se usan iacutendices para recorrer los valores en una secuencia es difiacutecilacceder al principio y al final del recorrido Aquiacute hay una funcioacuten que comparados palabras y devuelve true si una de las palabras es el reverso de la otra perocontiene dos errores

function espalindroma(palabra1 palabra2) if length(palabra1) = length(palabra2) return false end i = firstindex(palabra1) j = lastindex(palabra2) while j gt= 0 j = prevind(palabra2 j) if palabra1[i] = palabra2[j] return false end i = nextind(palabra1 i) end trueend

La primera sentencia if verifica si las palabras tienen la misma longitud Si no sedevuelve false inmediatamente De lo contrario para el resto de la funcioacuten sepuede suponer que las palabras tienen la misma longitud Este es un ejemplo delpatroacuten guardiaacuten

i y j son iacutendices i recorre palabra1 de derecha a izquierda mientras que j recorrepalabra2 de izquierda a derecha Si dos letras no coinciden se devuelve falseinmediatamente Si el ciclo termina y todas las letras coinciden se devuelve true

La funcioacuten lastindex devuelve el uacuteltimo iacutendice de bytes vaacutelido de una cadena yprevind el iacutendice vaacutelido anterior a un caraacutecter

Si se prueba esta funcioacuten con las palabras amor y roma se espera el valor de

106 Capiacutetulo 8 Cadenas

retorno true pero se obtiene false

juliagt espalindroma(amor roma)false

Para depurar este tipo de error primeramente se imprimen los valores de losiacutendices

espalindroma (generic function with 1 method)

Ahora al ejecutar el programa se obtiene maacutes informacioacuten

juliagt espalindroma(amor roma)i = 1j = 3false

En la primera iteracioacuten del bucle el valor de j es 3 pero tendriacutea que ser 4 Estose puede solucionar trasladando la liacutenea j = prevind (palabra2 j) al final del ciclowhile

Si se soluciona ese error y se ejecuta el programa nuevamente se obtiene

espalindroma (generic function with 1 method)

juliagt espalindroma(amor roma)i = 1j = 4i = 2j = 3i = 3j = 2i = 4j = 1i = 5j = 0ERROR BoundsError attempt to access String at index [5]

Esta vez se ha producido un BoundsError El valor de i es 5 que estaacute fuera delrango de la cadena amor

Depuracioacuten 107

Ejercicio 8-6

Ejecute el programa en papel cambiando los valores de i y j durante cadaiteracioacuten Encuentre y arregle el segundo error en esta funcioacuten

Glosariosecuencia

Una coleccioacuten ordenada de valores donde cada valor se identifica medianteun iacutendice entero

coacutedigo ASCIICoacutedigo de caracteres estaacutendar para el intercambio de informacioacuten

norma UnicodeUn estaacutendar en la industria informaacutetica para la codificacioacuten representacioacuteny manejo consistentes de texto en la mayoriacutea de los sistemas de escrituradel mundo

iacutendiceUn valor entero usado para seleccionar un miembro de un conjuntoordenado como puede ser un caraacutecter de una cadena En Julia los iacutendicescomienzan en 1

codificacioacuten UTF-8Una codificacioacuten de caracteres de longitud variable capaz de codificar todoslos 1112064 puntos de coacutedigo vaacutelidos en Unicode utilizando de uno a cuatrobytes de 8 bits

recorrerIterar sobre los elementos de un conjunto realizando una operacioacuten similaren cada uno de ellos

porcioacutenUna parte de una cadena especificada mediante un rango de iacutendices

cadena vaciacuteaUna cadena sin caracteres y longitud 0 representada por dos comillas

immutableLa propiedad de una secuencia que hace que a sus elementos no se lespueda asignar nuevos valores

interpolacioacuten de cadenasEl proceso de evaluar una cadena que contiene uno o maacutes marcadores de

108 Capiacutetulo 8 Cadenas

posicioacuten produciendo un resultado en el que los marcadores de posicioacuten sereemplazan con sus valores correspondientes

buacutesquedaUn patroacuten de recorrido que se detiene cuando encuentra lo que estaacutebuscando

contadorUna variable utilizada para contar algo generalmente inicializada en cero yluego incrementada

Ejercicios

Ejercicio 8-7

Lea la documentacioacuten de las funciones relacionadas con cadenas enhttpsdocsjulialangorgenv1manualstrings Es posible que desee probaralgunas de ellas para asegurarse de comprender coacutemo funcionan strip y replaceson particularmente uacutetiles

La documentacioacuten utiliza una sintaxis que puede ser confusa Por ejemplo ensearch(cadenaAbstractString caracterChars [comienzoInteger]) loscorchetes indican argumentos opcionales Por lo tanto cadena y caracter sonobligatorios pero comienzo es opcional

Ejercicio 8-8

Hay una funcioacuten integrada llamada count que es similar a la funcioacuten en Seccioacuten89 Lea la documentacioacuten de esta funcioacuten y uacutesela para contar el nuacutemero deletras a en banana

Ejercicio 8-9

Una porcioacuten de cadena puede tomar un tercer iacutendice El primero especifica elinicio el tercero el final y el segundo el tamantildeo del paso es decir el nuacutemero deespacios entre caracteres sucesivos Un tamantildeo de paso de 2 significa cada uncaracter 3 significa cada dos etc

juliagt fruta = bananabananajuliagt fruta[126]bnn

Un tamantildeo de paso de -1 recorre la palabra hacia la izquierda por lo que laporcioacuten [end-11] genera una cadena invertida

Ejercicios 109

Use esto para escribir una versioacuten de una liacutenea de coacutedigo de espalindroma deSeccioacuten 6113

Exercise 8-10

Las siguientes funciones estaacuten destinadas a verificar si una cadena contieneletras minuacutesculas pero algunas de ellas son incorrectas Para cada funcioacutendescriba queacute hace realmente la funcioacuten (suponiendo que el paraacutemetro es unacadena)

110 Capiacutetulo 8 Cadenas

function cualquierminuscula1(s) for c in s if islowercase(c) return true else return false end endend

function cualquierminuscula2(s) for c in s if islowercase(c) return true else return false end endend

function cualquierminuscula3(s) for c in s bandera = islowercase(c) end flagend

function cualquierminuscula4(s) bandera = false for c in s bandera = bandera || islowercase(c) end flagend

function cualquierminuscula5(s) for c in s if islowercase(c) return false end end trueend

Exercise 8-11

Un cifrado Ceacutesar es una forma simple de cifrado que implica desplazar cada letraun nuacutemero fijo de lugares Desplazar una letra significa reemplazarla por otra

Ejercicios 111

letra que se encuentra un nuacutemero fijo de posiciones maacutes adelante en el alfabetoEs posible desplazarse hasta el principio del abecedario si fuera necesario Deesta manera con un desplazamiento de 3 A es D y con un desplazamiento de1 Z es A

Para desplazar una palabra desplace cada letra en la misma cantidad Porejemplo con un desplazamiento de 6 ABCDEF es GHIJKL y con undesplazamiento de -6 BCDE es VWXY En la peliacutecula 2001 Una odisea delespacio la computadora de la nave se llama HAL que es IBM desplazada por -1

Escriba una funcioacuten llamada desplazarpalabra que tome una cadena y un nuacutemeroentero como paraacutemetros y devuelva una nueva cadena que contenga las letrasde la cadena original desplazadas por la cantidad dada

OBSERVACIOacuteN

Es posible que desee utilizar la funcioacuten integrada Intque convierte un caraacutecter en un coacutedigo numeacuterico yChar que convierte los coacutedigos numeacutericos encaracteres Las letras del alfabeto estaacuten codificadas enorden alfabeacutetico por ejemplo

juliagt Int(c) - Int(a)2

Porque c es la tercera letra del alfabeto Pero cuidadolos coacutedigos numeacutericos para las letras mayuacutesculas sondiferentes

juliagt Char(Int(A) + 32)a ASCIIUnicode U+0061 (category Ll Letterlowercase)

Algunos chistes ofensivos en Internet estaacuten codificados en ROT13 que es uncifrado Ceacutesar con desplazamiento 13 Si no se ofende faacutecilmente encuentre ydecodifice algunos de ellos

112 Capiacutetulo 8 Cadenas

Capiacutetulo 9 Estudio de Caso Juego de PalabrasEste capiacutetulo presenta un segundo estudio de caso que consiste en resolverpuzzles buscando palabras que tengan ciertas propiedades Por ejemplo sebuscaraacuten palabras cuyas letras aparezcan en orden alfabeacutetico Ademaacutes sepresentaraacute otra forma de desarrollar programas la reduccioacuten a un problemapreviamente resuelto

Leer listas de palabrasPara los ejercicios de este capiacutetulo se necesita una lista de palabras en espantildeolHay muchas listas de palabras disponibles en la Web pero la maacutes adecuada paranuestro propoacutesito es una de las listas de palabras recopiladas y contribuidas aldominio puacuteblico por Ismael Olea (see httpoleaorgproyectoslemarios) Estalista de 87900 palabras se encuentra en la paacutegina de Olea con el nombre dearchivo lemario-general-del-espanoltxt Tambieacuten es posible descargar una copiadesde httpsgithubcomJuliaIntroIntroAJuliajlblobmasterdatapalabrastxt

Este archivo es un archivo de texto simple por lo que puede ser abierto con uneditor de texto o leiacutedo con Julia La funcioacuten integrada open toma el nombre delarchivo como paraacutemetro y devuelve un objeto archivo que puede ser usado parala lectura del archivo

IOStream(ltfilehometravisbuildJuliaIntroIntroAJuliajlsrcdatapalabrastxtgt)

juliagt fin = open(palabrastxt)IOStream(ltfile palabrastxtgt)

fin es un objeto archivo que puede ser utilizado como entrada y cuando se dejade utilizar debe cerrarse con close(fin)

Julia tiene integradas varias funciones de lectura entre ellas readline que lee loscaracteres del archivo hasta que llega a un salto de liacutenea devolviendo elresultado como una cadena

juliagt readline(fin)a

La primera palabra en esta lista particular es a que indica direccioacuten intervalode tiempo finalidad entre otros

El objeto archivo lleva registro de doacutende quedoacute por uacuteltima vez por lo que sillama a readline nuevamente se obtendraacute la siguiente palabra

Leer listas de palabras 113

juliagt readline(fin)a-

La siguiente palabra es a- que es un prefijo que indica privacioacuten

Tambieacuten se puede usar un archivo como parte de un bucle for El siguienteprograma lee palabrastxt e imprime cada palabra una por liacutenea

for line in eachline(palabrastxt) println(line)end

Ejercicios

Ejercicio 9-1

Escriba un programa que lea palabrastxt e imprima solo las palabras con maacutes de20 caracteres (sin contar espacios en blanco)

Ejercicio 9-2

En 1927 Enrique Jardiel Poncela publicoacute cinco historias cortas omitiendo encada una de ellas una vocal Estas historias incluyen El Chofer Nuevonarracioacuten escrita sin la letra a y Un marido sin vocacioacuten sin la letra e Dadoque la letra e es la maacutes frecuente del espantildeol esto no es faacutecil de lograr

De hecho es difiacutecil pensar oraciones que no utilicen esta letra Intentarlo escomplicado pero con la praacutectica se vuelve maacutes faacutecil

Bueno volviendo al tema importante

Escriba una funcioacuten llamada notiene_e que devuelva true si una palabra dada notiene la letra e

Modifique su programa de la seccioacuten anterior para que imprima solo las palabrasque no tienen e y que ademaacutes calcule el porcentaje de palabras en la lista queno tengan e

Ejercicio 9-3

Escriba una funcioacuten llamada evitar que tome como argumentos una palabra yuna cadena de letras prohibidas y que devuelva true si la palabra no usaninguna de las letras prohibidas

Modifique su programa de la seccioacuten anterior para solicitar al usuario queingrese una cadena de letras prohibidas y que luego imprima el nuacutemero de

114 Capiacutetulo 9 Estudio de Caso Juego de Palabras

palabras que no contengan ninguna de ellas iquestEs posible encontrar unacombinacioacuten de 5 letras prohibidas que excluya la menor cantidad de palabras

Ejercicio 9-4

Escriba una funcioacuten llamada usasolo que tome una palabra y una cadena deletras y que devuelva true si la palabra contiene solo letras de la lista iquestPuedehacer una oracioacuten usando solo las letras oneacmil Aparte de iquestEl camino

Ejercicio 9-5

Escriba una funcioacuten llamada usatodo que tome una palabra y una cadena deletras y que devuelva true si la palabra usa todas las letras requeridas al menosuna vez iquestCuaacutentas palabras usan todas las vocales aeiou

Ejercicio 9-6

Escriba una funcioacuten llamada esabecedaria que devuelva true si las letras de unapalabra aparecen en orden alfabeacutetico iquestCuaacutentas palabras de este tipo hay

BuacutesquedaTodos los ejercicios en la seccioacuten anterior tienen algo en comuacuten se puedenresolver con el patroacuten de buacutesqueda El ejemplo maacutes simple es

function notiene_e(palabra) for letra in palabra if letra == e return false end end trueend

El bucle for recorre los caracteres de palabra Si encontramos la letra e puededevolver inmediatamente false de lo contrario hay que pasar a la siguiente letraSi se sale del bucle normalmente eso significa que no se encontroacute una e por loque la funcioacuten devuelve true

Esta funcioacuten podriacutea ser escrita de manera maacutes concisa usando el operador notin(notin TAB) pero se comienza con esta versioacuten porque muestra la loacutegica delpatroacuten de buacutesqueda

evita es una versioacuten maacutes general de notiene_e pero tiene la misma estructura

Buacutesqueda 115

function evita(palabra prohibidas) for letra in palabra if letter isin prohibidas return false end end trueend

Se devuelve false tan pronto como se encuentre una letra prohibida si llegamosal final del ciclo se devuelve true

usasolo es similar excepto que el sentido de la condicioacuten se invierte

function usasolo(palabra disponibles) for letra in palabra if letra notin disponibles return false end end trueend

En vez de un conjunto de letras prohibidas se tiene un conjunto de letrasdisponibles Si se encuentra una letra en palabra que no estaacute en disponible sedevuelve false

usatodo es similar excepto que se invierte el papel de la palabra y la cadena deletras

function usatodo(palabra requeridas) for letra in requeridas if letra notin palabra return false end end trueend

En lugar de recorrer las letras de la palabra el bucle recorre las letrasrequeridas Si alguna de las letras requeridas no aparece en la palabra sedevuelve false

Si se pensara como un informaacutetico se reconoceriacutea que usatodo es una instanciade un problema previamente resuelto y se podriacutea haber escrito

116 Capiacutetulo 9 Estudio de Caso Juego de Palabras

function usatodo(palabra requeridas) usasolo(requeridas palabra)end

Este es un ejemplo de una forma de desarrollar programas llamada reduccioacuten aun problema resuelto previamente lo que significa que se reconoce el problemaen el que se estaacute trabajando como una instancia de un problema ya resuelto y seaplica la solucioacuten existente

Bucle con iacutendicesLas funciones de la seccioacuten anterior fueron escritas con ciclos for porque solo senecesitaban los caracteres en las cadenas y no hubo necesidad de trabajar conlos iacutendices

Para esabecedaria tenemos que comparar letras adyacentes lo cual es un pococomplicado con un ciclo for

function esabecedaria(palabra) i = firstindex(palabra) previa = palabra[i] j = nextind(palabra i) for c in palabra[jend] if c lt previa return false end previa = c end trueend

Otra alternativa es usar recursividad

function esabecedaria(palabra) if length(palabra) lt= 1 return true end i = firstindex(palabra) j = nextind(palabra i) if palabra[i] gt palabra[j] return false end esabecedaria(palabra[jend])end

Una tercera opcioacuten es usar un ciclo while

Bucle con iacutendices 117

function esabecedaria(palabra) i = firstindex(palabra) j = nextind(palabra 1) while j lt= sizeof(palabra) if palabra[j] lt palabra[i] return false end i = j j = nextind(palabra i) end trueend

El ciclo comienza en i=1 y j=nextind(palabra 1) y termina cuandojgtsizeof(palabra) En cada iteracioacuten se compara el caraacutecter ieacutesimo (que sepuede considerar como el caraacutecter actual) con el caraacutecter jeacutesimo (que se puedeconsiderar como el siguiente)

Si el siguiente caraacutecter es menor (va antes en el alfabeto) que el actual entoncesla palabra no tiene sus letras en orden alfabeacutetico y se devuelve false

Si se llega al final del ciclo sin encontrar letras que imposibiliten el ordenalfabeacutetico entonces la palabra pasa la prueba Para convencerse de que el ciclotermina correctamente considere como ejemplo la palabra Abel

A continuacioacuten se muestra una versioacuten de espalindromo que usa dos iacutendices unocomienza al principio de la palabra y aumenta su valor y el otro comienza al finaly disminuye su valor

function espalindromo(palabra) i = firstindex(palabra) j = lastindex(palabra) while iltj if palabra[i] = palabra[j] return false end i = nextind(palabra i) j = prevind(palabra j) end trueend

O podriacuteamos reducir este problema a uno previamente resuelto y escribir

118 Capiacutetulo 9 Estudio de Caso Juego de Palabras

function espalindromo(palabra) isreverse(palabra palabra)end

Usando esreverso de Seccioacuten 813

DepuracioacutenComprobar el correcto funcionamiento de los programas es difiacutecil Las funcionesde este capiacutetulo son relativamente faacuteciles de probar porque se pueden verificarlos resultados a mano Aun asiacute es casi imposible elegir un conjunto de palabrasque permitan evaluar todos los posibles errores

Tomando notiene_e como ejemplo hay dos casos obvios que verificar laspalabras que tienen una e deberiacutean devolver false y las palabras que nodeberiacutean devolver true No deberiacutean haber problemas para encontrar un ejemplode cada uno

Dentro de cada caso hay algunos subcasos menos obvios Entre las palabras quetienen una e se deben probar las palabras con una e al principio al final y almedio Ademaacutes se deben probar palabras largas cortas y muy cortas como unacadena vaciacutea La cadena vaciacutea es un ejemplo de un caso especial no obviodonde pueden originarse errores

Ademaacutes de las instancias de prueba generadas tambieacuten puede probar suprograma con una lista de palabras como palabrastxt Al escanear el resultadoes posible que pueda detectar errores pero tenga cuidado puede detectar untipo de error (palabras que no deberiacutean incluirse pero lo estaacuten) y no otro(palabras que deberiacutean incluirse pero no lo estaacuten)

Por lo general las pruebas pueden ayudarlo a encontrar errores pero no es faacutecilgenerar un buen conjunto de instancias de prueba e incluso si lo hace no puedeestar seguro de que su programa sea correcto Seguacuten un informaacutetico muyfamoso

Las pruebas de programa se pueden usar para mostrar la presencia deerrores iexclpero nunca para mostrar su ausencia

mdash Edsger W Dijkstra

Glosarioobjeto archivo o file stream

Un valor que representa un archivo abierto

Depuracioacuten 119

reduccioacuten a un problema previamente resueltoUna manera de resolver un problema expresaacutendolo como una instancia deun problema previamente resuelto

caso especialUna instancia de prueba que es atiacutepica o no obvia (y por lo tanto menosprobable que se maneje correctamente)

Ejercicios

Ejercicio 9-7

Esta pregunta se basa en un Puzzle que se transmitioacute en el programa de radioCar Talk (httpswwwcartalkcompuzzlerbrowse)

Se tiene una secuencia de nuacutemeros y se desea saber cuaacutel es el siguiente Losnuacutemeros son 4 6 12 18 30 42 60 y luego X

Pista 1 Todos los nuacutemeros de la secuencia son pares Pista 2 El nuacutemero queva despueacutes del que estoy buscando es 102

iquestCuaacutel es el nuacutemero

Primero piense el patroacuten que busca y luego escriba un programa que le permitaencontrar el nuacutemero que sigue este patroacuten que se encuentra entre 60 y 102

Ejercicio 9-8

A continuacioacuten se muestra otro puzzle de Car Talk (httpswwwcartalkcompuzzlerbrowse)

120 Capiacutetulo 9 Estudio de Caso Juego de Palabras

Estaba conduciendo por la autopista el otro diacutea y vi mi odoacutemetro Como lamayoriacutea de los odoacutemetros muestra seis diacutegitos y solo en kiloacutemetros enterosEntonces si mi automoacutevil tuviera un kilometraje de 300000 por ejemploseriacutea 3-0-0-0-0-0

Ahora lo que vi ese diacutea fue muy interesante Noteacute que los uacuteltimos 4 diacutegitoseran palindroacutemicos es decir se leiacutean igual hacia adelante que hacia atraacutesPor ejemplo 5-4-4-5 es un paliacutendromo por lo que mi odoacutemetro podriacuteahaberse leiacutedo 3-1-5-4-4-5

Un kiloacutemetro despueacutes los uacuteltimos 5 nuacutemeros fueron palindroacutemicos Porejemplo podriacutea haberse leiacutedo 3-6-5-4-5-6 Un kiloacutemetro despueacutes de eso los 4nuacutemeros del medio eran palindroacutemicos iquestYhellip estaacutes listo para esto iexclUnkiloacutemetro despueacutes los 6 eran palindroacutemicos

La pregunta es iquestqueacute nuacutemero estaba en el odoacutemetro cuando mireacute porprimera vez

Escriba un programa de Julia que pruebe todos los nuacutemeros de seis diacutegitos eimprima cualquier nuacutemero que satisfaga estos requisitos

Ejercicio 9-9

Aquiacute hay otro puzzle de Car Talk que puede resolver con una buacutesqueda(httpswwwcartalkcompuzzlerbrowse)

Hace poco visiteacute a mi madre y nos dimos cuenta de que los dos diacutegitos quecomponen mi edad cuando se invertiacutean daban como resultado su edad Porejemplo si tiene 73 antildeos yo tengo 37 Nos preguntamos con queacute frecuenciaesto ha sucedido a lo largo de los antildeos pero nos desviamos de otros temas ynunca obtuvimos una respuesta

Cuando llegueacute a casa descubriacute que los diacutegitos de nuestras edades han sidoreversibles seis veces hasta ahora Tambieacuten descubriacute que si teniacuteamos suertevolveriacutea a suceder en unos antildeos y si tenemos mucha suerte sucederiacutea unavez maacutes despueacutes de eso En otras palabras habriacutea sucedido 8 vecesEntonces la pregunta es iquestcuaacutentos antildeos tengo ahora

Escriba un programa de Julia que busque soluciones para este puzzle

OBSERVACIOacuteN Puede encontrar la funcioacuten lpad uacutetil

Ejercicios 121

Capiacutetulo 10 ArreglosEste capiacutetulo presenta uno de los tipos maacutes uacutetiles de Julia los arreglos Tambieacutense trataraacuten objetos y lo que puede suceder cuando se tiene maacutes de un nombrepara el mismo objeto

Un arreglo es una secuenciaAl igual que una cadena de texto un arreglo es una secuencia de valores En unacadena los valores son caracteres en un arreglo pueden ser de cualquier tipoLos valores en un arreglo se denominan elementos o a veces items

Hay varias formas de crear un nuevo arreglo la maacutes sencilla es encerrar loselementos entre corchetes ([ ])

[10 20 30 40][abadejo falsiacutea estrambote]

El primer ejemplo es un arreglo de cuatro enteros El segundo es un arreglo detres cadenas de texto Los elementos de un arreglo no tienen por queacute ser delmismo tipo El siguiente arreglo contiene una cadena un nuacutemero de puntoflotante un entero y otro arreglo

[spam 20 5 [10 20]]

Se dice que un arreglo dentro de otro arreglo estaacute anidado

Un arreglo que no contiene elementos se llama arreglo vaciacuteo y se puede crearuno con corchetes vaciacuteos []

Como es de esperar se pueden asignar valores de arreglos a variables

juliagt quesos = [Cheddar Edam Gouda]

juliagt numeros = [42 123]

juliagt vacio = []

juliagt print(quesos numeros vacio)[Cheddar Edam Gouda] [42 123] Any[]

La funcioacuten typeof se puede usar para conocer el tipo del arreglo

122 Capiacutetulo 10 Arreglos

juliagt typeof(quesos)ArrayString1juliagt typeof(numeros)ArrayInt641juliagt typeof(vacio)ArrayAny1

El tipo del arreglo se especifica entre llaves y se compone de un tipo y unnuacutemero El nuacutemero indica las dimensiones El conjunto vaciacuteo contiene valores detipo Any es decir puede contener valores de todos los tipos

Los arreglos son mutablesLa sintaxis para acceder a los elementos de un arreglo es el mismo que paraacceder a los caracteres de una cadena el operador corchete La expresioacutendentro de los corchetes especifica el iacutendice Recuerde que los iacutendices comienzanen 1

juliagt quesos[1]Cheddar

A diferencia de las cadenas los arreglos son mutables lo que significa quepodemos cambiar sus elementos Se puede modificar uno de sus elementosusando el operador corchetes en el lado izquierdo de una asignacioacuten

juliagt numeros[2] = 55juliagt print(numeros)[42 5]

El segundo elemento de numeros que era 123 ahora es 5

Figura 11 muestra los diagramas de estado para quesos numeros y vacio

Figura 11 Diagrama de estado

Los arreglos son representados mediante cuadros con elementos del arreglo en

Los arreglos son mutables 123

su interior El arreglo quesos hace referencia a un arreglo con tres elementosindexados 1 2 y 3 El arreglo numeros contiene dos elementos El diagramamuestra que el valor del segundo elemento de numeros se ha reasignado de 123a 5 Finalmente vacio hace referencia a un arreglo sin elementos

Los iacutendices de un arreglo funcionan de la misma manera que los iacutendices de unacadena (pero sin los problemas generados por la codificacioacuten UTF-8)

bull Cualquier expresioacuten entera se puede usar como iacutendice

bull Si se intenta leer o escribir un elemento que no existe se obtiene unBoundsError

bull La palabra reservada end indica el uacuteltimo iacutendice del arreglo

El operador isin tambieacuten funciona en arreglos

juliagt Edam isin quesostruejuliagt Brie in quesosfalse

Recorriendo un ArregloLa forma maacutes comuacuten de recorrer los elementos de un arreglo es con un ciclo forLa sintaxis es la misma que para las cadenas

for queso in quesos println(queso)end

Esto funciona bien si solo se necesita leer los elementos del arreglo pero si sedesea escribir o actualizar los elementos es necesario utilizar iacutendices Una formacomuacuten de hacerlo es usando la funcioacuten integrada eachindex

for i in eachindex(numeros) numeros[i] = numeros[i] 2end

Este bucle recorre el arreglo y actualiza cada elemento En cada iteracioacuten delciclo i representa el iacutendice del elemento actual La sentencia de asignacioacuten usanumeros[i] para leer el valor original del elemento y asignar el nuevo valor

Por otra parte length devuelve el nuacutemero de elementos en el arreglo

Un ciclo for sobre un arreglo vaciacuteo nunca ejecuta el cuerpo del bucle

124 Capiacutetulo 10 Arreglos

for x in [] println(Esto nunca pasa)end

Aunque un arreglo puede contener otro arreglo este arreglo anidado cuentacomo un elemento uacutenico Por ejemplo la longitud de este arreglo es cuatro

[spam 1 [Brie Roquefort Camembert] [1 2 3]]

Porciones de arreglos

El operador porcioacuten tambieacuten funciona en arreglos

juliagt t = [a b c d e f]

juliagt print(t[13])[a b c]juliagt print(t[3end])[c d e f]

El operador porcioacuten [] hace una copia de todo el arreglo

juliagt print(t[])[a b c d e f]

Como los arreglos son mutables es uacutetil hacer una copia antes de realizaroperaciones que las modifiquen

Un operador porcioacuten en el lado izquierdo de una asignacioacuten puede actualizarvarios elementos

juliagt t[23] = [x y]

juliagt print(t)[a x y d e f]

Libreriacutea de ArreglosJulia tiene funciones integradas que operan en arreglos Por ejemplo pushagrega un nuevo elemento al final de un arreglo

Porciones de arreglos 125

juliagt t = [a b c]

juliagt push(t d)

juliagt print(t)[a b c d]

append agrega elementos de un arreglo al final de otro

juliagt t1 = [a b c]

juliagt t2 = [d e]

juliagt append(t1 t2)

juliagt print(t1)[a b c d e]

En este ejemplo t2 no es modificado

sort ordena los elementos de un arreglo de menor a mayor

juliagt t = [d c e b a]

juliagt sort(t)

juliagt print(t)[a b c d e]

sort devuelve una copia ordenada de los elementos de un arreglo

juliagt t1 = [d c e b a]

juliagt t2 = sort(t1)

juliagt print(t1)[d c e b a]juliagt print(t2)[a b c d e]

NOTA Como convencioacuten en Julia se agrega a los nombres de lasfunciones que modifican sus argumentos

126 Capiacutetulo 10 Arreglos

Mapear Filtrar y ReducirPara sumar todos los nuacutemeros en un arreglo se puede usar un ciclo como este

function sumartodo(t) total = 0 for x in t total += x end totalend

total se inicializa en 0 En cada iteracioacuten con += se antildeade un elemento delarreglo a la suma total El operador += es una forma simple de actualizar estavariable Esta sentencia de asignacioacuten aumentada

total += x

es equivalente a

total = total + x

A medida que se ejecuta el ciclo total acumula la suma de los elementos A vecesse denomina acumulador a una variable utilizada de esta manera

Sumar los elementos de un arreglo es una operacioacuten tan comuacuten que Julia tieneuna funcioacuten integrada para ello sum

juliagt t = [1 2 3 4]

juliagt sum(t)10

Una operacioacuten como esta que combina una secuencia de elementos en un solovalor a veces se denomina operacioacuten de reduccioacuten

Es comuacuten querer recorrer un arreglo mientras se construye otro Por ejemplo lasiguiente funcioacuten toma un arreglo de cadenas y devuelve un nuevo arreglo quecontiene las mismas cadenas pero en mayuacutesculas

Mapear Filtrar y Reducir 127

function todoenmayusculas(t) res = [] for s in t push(res uppercase(s)) end resend

res se inicializa con un arreglo vaciacuteo y en cada iteracioacuten se le agrega un nuevoelemento De esta manera res es otro tipo de acumulador

Una operacioacuten como todoenmayusculas a veces se denomina mapeo porqueasigna una funcioacuten (en este caso uppercase) a cada uno de los elementos deuna secuencia

Otra operacioacuten comuacuten es seleccionar solo algunos de los elementos de un arregloy devolver una sub-arreglo Por ejemplo la siguiente funcioacuten toma un arreglo decadenas y devuelve un arreglo que contiene solamente las cadenas enmayuacutesculas

function solomayusculas(t) res = [] for s in t if s == uppercase(s) push(res s) end end resend

Operaciones como solomayusculas se llaman filtro porque seleccionan soloalgunos elementos filtrando otros

Las operaciones de arreglos maacutes comunes son una combinacioacuten de mapeo filtroy reduccioacuten

Sintaxis de puntoPara cada operador binario como por ejemplo ^ existe un operador puntocorrespondiente ^ que automaacuteticamente define la operacioacuten ^ para cadaelemento de un arreglo Por ejemplo [1 2 3] ^ 3 no estaacute definido pero [12 3] ^ 3 se define como el resultado de realizar la operacioacuten ^ en cadaelemento [1^3 2^3 3^3]

128 Capiacutetulo 10 Arreglos

juliagt print([1 2 3] ^ 3)[1 8 27]

Cualquier funcioacuten f de Julia puede ser aplicada a cada elemento de cualquierarreglo con la sintaxis de punto Por ejemplo para poner en mayuacutesculas unarreglo de cadenas no es necesario un bucle expliacutecito

juliagt t = uppercase([abc def ghi])

juliagt print(t)[ABC DEF GHI]

Esta es una forma elegante de crear un mapeo Siguiendo esta loacutegica la funcioacutentodoenmayusculas puede implementarse con una liacutenea

function todoenmayusculas(t) uppercase(t)end

Borrando (Insertando) ElementosHay varias formas de eliminar elementos de un arreglo Si se conoce el iacutendice delelemento que se desea eliminar se puede usar splice

juliagt t = [a b c]

juliagt splice(t 2)b ASCIIUnicode U+0062 (category Ll Letter lowercase)juliagt print(t)[a c]

splice modifica el arreglo y devuelve el elemento que se eliminoacute

pop elimina y devuelve el uacuteltimo elemento

juliagt t = [a b c]

juliagt pop(t)c ASCIIUnicode U+0063 (category Ll Letter lowercase)juliagt print(t)[a b]

popfirst elimina y devuelve el primer elemento

Borrando (Insertando) Elementos 129

juliagt t = [a b c]

juliagt popfirst(t)a ASCIIUnicode U+0061 (category Ll Letter lowercase)juliagt print(t)[b c]

Las funciones pushfirst y push insertan un elemento al principio y al final delarreglo respectivamente

Si no se necesita el valor eliminado se puede usar la funcioacuten deleteat

juliagt t = [a b c]

juliagt print(deleteat(t 2))[a c]

La funcioacuten insert inserta un elemento en un iacutendice dado

juliagt t = [a b c]

juliagt print(insert(t 2 x))[a x b c]

Arreglos y CadenasUna cadena es una secuencia de caracteres y un arreglo es una secuencia devalores pero un arreglo de caracteres no es lo mismo que una cadena Paraconvertir una cadena a un arreglo de caracteres se puede usar la funcioacutencollect

juliagt t = collect(spam)

juliagt print(t)[s p a m]

La funcioacuten collect divide una cadena u otra secuencia en elementos individuales

Si desea dividir una cadena en palabras puede usar la funcioacuten split

juliagt t = split(En un lugar de la Mancha)

juliagt print(t)SubStringString[En un lugar de la Mancha]

130 Capiacutetulo 10 Arreglos

Un argumento opcional llamado delimitador especifica queacute caracteres usar comoliacutemites de palabra El siguiente ejemplo usa un guioacuten como delimitador

juliagt t = split(hola-hola-hola -)

juliagt print(t)SubStringString[hola hola hola]

join es el inverso de split Toma un arreglo de cadenas y concatena loselementos

juliagt t = [En un lugar de la Mancha]

juliagt s = join(t )En un lugar de la Mancha

En este caso el delimitador es un caraacutecter de espacio en blanco Para concatenarcadenas sin espacios no especifique un delimitador

Objeto y ValoresUn objeto es algo a lo que una variable puede referirse Hasta ahora podriacutea usarobjeto y valor indistintamente

Si ejecutamos estas sentencias de asignacioacuten

a = bananab = banana

Se sabe que a y b apuntan a una cadena pero no se sabe si estaacuten apuntando a lamisma cadena Hay dos estados posibles los cuales se muestran en la Figura 10-2

Figura 12 Diagramas de estado

En un caso a y b se refieren a dos objetos diferentes que tienen el mismo valorEn el segundo caso se refieren al mismo objeto

Para verificar si dos variables se refieren al mismo objeto se puede usar eloperador equiv (equiv TAB)) o ===

Objeto y Valores 131

juliagt a = bananabananajuliagt b = bananabananajuliagt a equiv btrue

En este ejemplo Julia solo creoacute un objeto de cadena y ambas variables a y bapuntan a ella Pero cuando se crean dos arreglos se obtienen dos objetos

juliagt a = [1 2 3]

juliagt b = [1 2 3]

juliagt a equiv bfalse

Entonces el diagrama de estado se ve asiacute Figura 13

Figura 13 Diagrama de estado

En este caso se podriacutea decir que los dos arreglos son equivalentes porquetienen los mismos elementos pero no ideacutenticos ya que no son el mismo objetoSi dos objetos son ideacutenticos tambieacuten son equivalentes pero si son equivalentesno son necesariamente ideacutenticos

Para ser precisos un objeto tiene un valor Si se evaluacutea [1 2 3] se obtendraacute unobjeto arreglo cuyo valor es una secuencia de enteros Si otro arreglo tiene losmismos elementos se dice que tiene el mismo valor pero no es el mismo objeto

Alias (poner sobrenombres)Si a apunta a un objeto y se asigna b = a entonces ambas variables se refierenal mismo objeto

juliagt a = [1 2 3]

juliagt b = a

juliagt b equiv atrue

El diagrama de estado seriacutea como este Figura 14

132 Capiacutetulo 10 Arreglos

Figura 14 Diagrama de estado

La asociacioacuten de una variable con un objeto se llama referencia En este ejemplohay dos referencias al mismo objeto

Un objeto con maacutes de una referencia tiene maacutes de un nombre por lo quedecimos que el objeto tiene un alias

Si el objeto con alias es mutable los cambios hechos a un alias afectan al otro

juliagt b[1] = 4242juliagt print(a)[42 2 3]

AVISOAunque este comportamiento puede ser uacutetil a veces puede inducira errores En general es maacutes seguro evitar los alias cuando setrabaje con objetos mutables

No hay problema con los alias al trabajar con objetos inmutables tales comocadenas de texto En este ejemplo

a = bananab = banana

Casi nunca es relevante que a y b se refieran a la misma cadena o no

Arreglos como argumentosCuando se pasa un arreglo como argumento de una funcioacuten en realidad se pasauna referencia a ella Si la funcioacuten modifica el arreglo el que hizo la llamadaveraacute el cambio Por ejemplo la funcioacuten borrarprimero elimina el primer elementode un arreglo

function borrarprimero(t) popfirst(t)end

Aquiacute se aprecia el uso de borrarprimero

Arreglos como argumentos 133

juliagt letras = [a b c]

juliagt borrarprimero(letras)

juliagt print(letras)[b c]

El paraacutemetro t y la variable letras son alias de un mismo objeto El diagrama deestado es asiacute Figura 15

Figura 15 Diagrama de estado

Como el arreglo estaacute compartido por dos marcos se dibuja entre ambos

Es importante distinguir entre operaciones que modifiquen arreglos yoperaciones que creen nuevas arreglos Por ejemplo push modifica un arreglopero vcat crea un nuevo arreglo

Aquiacute hay un ejemplo de push

juliagt t1 = [1 2]

juliagt t2 = push(t1 3)

juliagt print(t1)[1 2 3]

t2 es un alias de t1

Aquiacute hay un ejemplo de vcat

juliagt t3 = vcat(t1 [4])

juliagt print(t1)[1 2 3]juliagt print(t3)[1 2 3 4]

El resultado de vcat es un nuevo arreglo El arreglo original no ha sufridocambios

Esta diferencia es importante al momento de escribir funciones que modificanarreglos

134 Capiacutetulo 10 Arreglos

Por ejemplo esta funcioacuten no elimina el primer elemento de un arrreglo

function noborrarprimero(t) t = t[2end] MALOend

El operador porcioacuten crea un nuevo arreglo y la asignacioacuten hace que t se refiera aella pero eso no afecta al arreglo t fuera de la funcioacuten

juliagt t4 = noborrarprimero(t3)

juliagt print(t3)[1 2 3 4]juliagt print(t4)[2 3 4]

Al comienzo de noborrarprimero t y t3 se refieren al mismo arreglo Al final t serefiere a un nuevo arreglo pero t3 todaviacutea se refiere al arreglo original nomodificado

Una alternativa es escribir una funcioacuten que cree y devuelva un nuevo arregloPor ejemplo la funcioacuten cola devuelve todos menos el primer elemento de unarreglo

function cola(t) t[2end]end

Esta funcioacuten no modifica el arreglo original y se usa de la siguiente manera

juliagt letras = [a b c]

juliagt demas = cola(letras)

juliagt print(demas)[b c]

DepuracioacutenUn uso inadecuado de los arreglos (y otros objetos mutables) puede llevar alargas horas de depuracioacuten A continuacioacuten se muestran algunos errorescomunes y coacutemo evitarlos

bull La mayoriacutea de las funciones que operan en arreglos modifican el argumentoEsto es lo opuesto a lo que ocurre en las funciones que operan en cadenas

Depuracioacuten 135

de texto que devuelven una nueva cadena y dejan la original sinmodificaciones

Si estaacute acostumbrado a escribir coacutedigo con cadenas de texto como este

nueva_palabra = strip(palabra)

Puede parecer tentador escribir coacutedigo con arreglos como este

t2 = sort(t1)

Pero como sort devuelve el arreglo original t1 modificado t2 es un alias det1

OBSERVACIOacuteN

Antes de utilizar funciones y operadores dearreglos debe leer la documentacioacutendetenidamente y luego probarla en modointeractivo

bull Escoja una expresioacuten y queacutedese con ella

Parte del problema con los arreglos es que hay demasiadas formas de hacerlas cosas Por ejemplo para eliminar un elemento de un arreglo se puedeusar pop popfirst delete_at o incluso una asignacioacuten de porcioacuten Paraagregar un elemento se puede usar push pushfirst insert or vcatSuponiendo que t es un arreglo y x es un elemento estas formas soncorrectas

insert(t 4 x)push(t x)append(t [x])

Y estas incorrectas

insert(t 4 [x]) MALOpush(t [x]) MALOvcat(t [x]) MALO

bull Haga copias para evitar usar alias

Si se desea utilizar una funcioacuten como sort que modifica el argumento perotambieacuten se necesita mantener el arreglo original es posible hacer unacopia

136 Capiacutetulo 10 Arreglos

juliagt t = [3 1 2]

juliagt t2 = t[] t2 = copy(t)

juliagt sort(t2)

juliagt print(t)[3 1 2]juliagt print(t2)[1 2 3]

En este ejemplo tambieacuten podriacutea usar la funcioacuten incorporada sort quedevuelve un nuevo arreglo ordenado y no modifica el original

juliagt t2 = sort(t)

juliagt println(t)[3 1 2]juliagt println(t2)[1 2 3]

Glosarioarreglo

Una secuencia de valores

elementoUno de los valores de un arreglo (u otra secuencia) tambieacuten llamado iacutetem

lista anidadaUn arreglo que es elemento de otro arreglo

acumuladorUna variable utilizada en un ciclo para sumar o acumular un resultado

asignacioacuten aumentadaUna sentencia que actualiza el valor de una variable usando un operadorcomo +=

operador puntoOperador binario que se aplica a cada elemento de un arreglo

Glosario 137

sintaxis de puntoSintaxis utilizada para aplicar una funcioacuten a todos los elementos decualquier arreglo

operacioacuten de reduccioacutenUn patroacuten de procesamiento que recorre una secuencia y acumula loselementos en un solo resultado

mapeoUn patroacuten de procesamiento que recorre una secuencia y realiza unaoperacioacuten en cada elemento

filtroUn patroacuten de procesamiento que recorre una secuencia y selecciona loselementos que satisfacen alguacuten criterio

objetoUna cosa a la que se puede referir una variable Un objeto tiene tipo y valor

equivalenteTener el mismo valor

ideacutenticoSer el mismo objeto (lo que implica equivalencia)

referenciaLa asociacioacuten entre una variable y su valor

aliasMuacuteltiples variables que contienen referencias al mismo objeto

argumentos opcionalesArgumentos que no son necesarios

delimitadorUn caraacutecter o cadena utilizado para indicar donde debe cortarse unacadena

Ejercicios

estaordenada (generic function with 1 method)

138 Capiacutetulo 10 Arreglos

Ejercicio 10-1

Escriba una funcioacuten llamada sumaanidada que tome un arreglo de arreglos deenteros y sume los elementos de todos los arreglos anidados Por ejemplo

juliagt t = [[1 2] [3] [4 5 6]]

juliagt sumaanidada(t)21

Ejercicio 10-2

Escriba una funcioacuten llamada sumaacumulada que tome un arreglo de nuacutemeros ydevuelva la suma acumulativa es decir un nuevo arreglo donde el eacutesimoelemento es la suma de los primeros elementos del arreglo original Porejemplo

juliagt t = [1 2 3]

juliagt print(sumaacumulada(t))Any[1 3 6]

Ejercicio 10-3

Escriba una funcioacuten llamada interior que tome un arreglo y devuelva un nuevoarreglo que contenga todos los elementos excepto el primero y el uacuteltimo Porejemplo

juliagt t = [1 2 3 4]

juliagt print(interior(t))[2 3]

Ejercicio 10-4

Escriba una funcioacuten llamada interior que tome un arreglo lo modifiqueeliminando el primer y el uacuteltimo elemento y que no devuelva un valor Porejemplo

Ejercicios 139

juliagt t = [1 2 3 4]

juliagt interior(t)

juliagt print(t)[2 3]

Ejercicio 10-5

Escriba una funcioacuten llamada estaordenada que tome un arreglo como paraacutemetroy devuelva true si el arreglo se ordena en orden ascendente y false de locontrario Por ejemplo

juliagt estaordenada([1 2 2])truejuliagt estaordenada([b a])false

Ejercicio 10-6

Dos palabras son anagramas si se pueden ordenar las letras de una para escribirla otra Escriba una funcioacuten llamada esanagrama que tome dos cadenas ydevuelva true si son anagramas

Ejercicio 10-7

Escriba una funcioacuten llamada repetido que tome un arreglo y devuelva true si hayalguacuten elemento que aparece maacutes de una vez No debe modificar el arreglooriginal

Ejercicio 10-8

Este ejercicio se relaciona con la llamada paradoja del cumpleantildeos sobre la cualpuede leer en httpseswikipediaorgwikiParadoja_del_cumpleaC3B1os

Si hay 23 estudiantes en su clase iquestcuaacuteles son las posibilidades de que dos deustedes tengan el mismo cumpleantildeos Puede estimar esta probabilidadgenerando muestras aleatorias de 23 cumpleantildeos y buscando coincidencias

OBSERVACIOacuteN Puede generar cumpleantildeos aleatorios con rand(1365)

Ejercicio 10-9

Escriba una funcioacuten que lea el archivo palabrastxt y construya un arreglo con unelemento por palabra Escriba dos versiones de esta funcioacuten una con push y la

140 Capiacutetulo 10 Arreglos

otra con la expresioacuten t = [t x] iquestCuaacutel tarda maacutes en ejecutarse iquestPor queacute

Ejercicio 10-10

Para verificar si una palabra estaacute en el arreglo de palabras se puede usar eloperador isin Esto seriacutea lento pues este operador busca las palabras en orden

Debido a que las palabras estaacuten en orden alfabeacutetico se puede acelerar laverificacioacuten con una buacutesqueda de biseccioacuten (tambieacuten conocida como buacutesquedabinaria) que es similar a lo que se hace cuando se busca una palabra en eldiccionario Se comienza en el medio y se verifica si la palabra que se estaacutebuscando va antes que la palabra localizada en el medio Si es asiacute se busca en laprimera mitad de la matriz de la misma manera De lo contrario se busca en lasegunda mitad

En ambos casos se reduce el espacio de buacutesqueda restante a la mitad Si elarreglo de palabras tiene 113809 palabras se necesitaraacuten unos 17 pasos paraencontrar la palabra o concluir que no estaacute alliacute

Escriba una funcioacuten llamada enbiseccion que tome un arreglo ordenado y unvalor objetivo y devuelva true si la palabra estaacute en el arreglo y false si no lo estaacute

Ejercicio 10-11

Dos palabras son un par inverso si cada una es la inversa de la otra Escriba unprograma llamado parinverso que encuentre todos los pares inversos en elarreglo de palabras

Ejercicio 10-12

Dos palabras se entrelazan si al tomar letras alternando entre cada palabra seforma una nueva palabra Por ejemplo pi y as se entrelazan para formarpais

Creacutedito Este ejercicio estaacute inspirado en un ejemplo de httppuzzlersorg

1 Escriba un programa que encuentre todos los pares de palabras que seentrelazan

OBSERVACIOacuteN iexclNo enumere todos los pares

2 iquestPuede encontrar tres palabras que se entrelacen es decir cada terceraletra forma una palabra empezando de la primera segunda o tercera letrade la palabra

Ejercicios 141

Capiacutetulo 11 DiccionariosEste capiacutetulo presenta otro tipo integrado llamado diccionario

Un Diccionario es un MapeoUn diccionario es como una matriz pero maacutes general En una matriz los iacutendicestienen que ser enteros en un diccionario pueden ser (casi) de cualquier tipo

Un diccionario contiene una coleccioacuten de iacutendices llamados claves y unacoleccioacuten de valores Cada clave estaacute asociada a un solo valor La asociacioacutenentre una clave y un valor se denomina par clave-valor o a veces item

En lenguaje matemaacutetico un diccionario representa un mapeo de las claves a losvalores es decir cada clave apunta a un valor A modo de ejemplo se crea undiccionario que asocia palabras en espantildeol con palabras en ingleacutes En estediccionario las claves y los valores son cadenas

La funcioacuten Dict crea un nuevo diccionario sin elementos Como Dict es el nombrede una funcioacuten integrada de Julia debe evitar usarla como nombre de variable

juliagt ing_a_esp = Dict()DictAnyAny()

El tipo de este diccionario estaacute compuesto por el tipo de las claves y de losvalores entre llaves En este caso las claves y los valores son de tipo Any

El diccionario estaacute vaciacuteo Para agregar elementos a eacutel se pueden usar corchetes

juliagt ing_a_esp[one] = uno

Esta liacutenea de coacutedigo crea un elemento con la clave one que apunta al valoruno Si se imprime el diccionario nuevamente se ve un par clave-valor con unaflecha =gt entre la clave y el valor

juliagt ing_a_espDictAnyAny with 1 entry one =gt uno

Este formato de salida tambieacuten es un formato de entrada Por ejemplo se puedecrear un nuevo diccionario con tres iacutetems de la siguiente manera

142 Capiacutetulo 11 Diccionarios

juliagt ing_a_esp = Dict(one =gt uno two =gt dos three =gt tres)DictStringString with 3 entries two =gt dos one =gt uno three =gt tres

Todas las claves y valores iniciales son cadenas por lo que se crea unDictStringString

AVISO

El orden de los pares clave-valor podriacutea no ser el mismo Siescribe el mismo ejemplo en su computadora podriacutea obtener unresultado diferente En general el orden de los elementos en undiccionario es impredecible

Esto no significa un problema ya que los elementos de un diccionario nunca seindexan con iacutendices enteros En lugar de ello se utilizan las claves para buscarlos valores correspondientes

juliagt ing_a_esp[two]dos

La clave two da el valor dos asiacute que el orden de los iacutetems no importa

Si la clave no estaacute en el diccionario se da un mensaje de error

juliagt ing_a_esp[four]ERROR KeyError key four not found

La funcioacuten length tambieacuten funciona con diccionarios y devuelve el nuacutemero depares clave-valor

juliagt length(ing_a_esp)3

La funcioacuten keys devuelve una coleccioacuten con las claves del diccionario

juliagt ks = keys(ing_a_esp)

juliagt print(ks)[two one three]

Tambieacuten se puede usar el operador isin para ver si algo es una clave en undiccionario

Un Diccionario es un Mapeo 143

juliagt one isin kstruejuliagt uno isin ksfalse

Para ver si algo es un valor en un diccionario se puede usar la funcioacuten valuesque devuelve una coleccioacuten de valores y luego usar el operador isin

juliagt vs = values(ing_a_esp)

juliagt uno isin vstrue

El operador isin utiliza diferentes algoritmos para matrices y diccionarios Para lasmatrices busca los elementos de la matriz en orden como en Seccioacuten 88 Eltiempo de buacutesqueda es directamente proporcional al largo de la matriz

Para los diccionarios Julia usa un algoritmo llamado tabla hash que tiene unapropiedad importante el operador isin toma aproximadamente la misma cantidadde tiempo sin importar cuaacutentos elementos haya en el diccionario

Diccionario como una Coleccioacuten de FrecuenciasSuponga que tiene una cadena y desea contar cuaacutentas veces aparece cada letraHay varias formas de hacerlo

bull Podriacutea crear 27 variables una para cada letra del alfabeto Luego recorrerla cadena y para cada caraacutecter incrementar el contador correspondienteprobablemente utilizando condiciones encadenadas

bull Podriacutea crear una matriz con 27 elementos Luego podriacutea convertir cadacaraacutecter en un nuacutemero (usando la funcioacuten integrada Int) usar el nuacutemerocomo iacutendice en la matriz e incrementar el contador apropiado

bull Puede crear un diccionario con caracteres como claves y contadores comolos valores correspondientes La primera vez que vea un caraacutecter agregariacuteaun elemento al diccionario Despueacutes de eso incrementariacutea el valor de unelemento existente

Cada una de estas opciones realiza el mismo caacutelculo pero la implementacioacuten esdiferente

Una implementacioacuten es una forma de realizar un caacutelculo Algunasimplementaciones son mejores que otras por ejemplo una ventaja de laimplementacioacuten del diccionario es que no hace falta saber de antemano queacuteletras aparecen en la cadena y solo hay que agregar las letras que aparecen

144 Capiacutetulo 11 Diccionarios

Asiacute es como se veriacutea el coacutedigo

function histograma(s) d = Dict() for c in s if c notin keys(d) d[c] = 1 else d[c] += 1 end end dend

La funcioacuten se llama histograma que es un teacutermino en estadiacutestica para unacoleccioacuten de frecuencias (o conteos)

La primera liacutenea de la funcioacuten crea un diccionario vaciacuteo El ciclo for recorre lacadena s En cada iteracioacuten de este ciclo si el caraacutecter c no estaacute en eldiccionario se crea un nuevo elemento con la clave c y el valor inicial 1 (ya quehemos visto esta letra una vez) Si c ya estaacute en el diccionario se incrementa d[c]

Asiacute es como funciona

juliagt h = histograma(brontosaurus)DictAnyAny with 8 entries n =gt 1 s =gt 2 a =gt 1 r =gt 2 t =gt 1 o =gt 2 u =gt 2 b =gt 1

El histograma indica que las letras a y b aparecen una vez o aparece dosveces y asiacute sucesivamente

Los diccionarios tienen una funcioacuten llamada get que toma como argumentos undiccionario una clave y un valor predeterminado Si la clave aparece en eldiccionario get devuelve el valor correspondiente de lo contrario devuelve elvalor predeterminado Por ejemplo

Diccionario como una Coleccioacuten de Frecuencias 145

juliagt h = histograma(a)DictAnyAny with 1 entry a =gt 1juliagt get(h a 0)1juliagt get(h b 0)0

Ejercicio 11-1

Use get para escribir la funcioacuten histograma de manera maacutes concisa Deberiacuteapoder eliminar la declaracioacuten if

Iteracioacuten y DiccionariosEs posible recorrer las claves del diccionario con un ciclo for Por ejemploimprimirhist imprime cada clave y su valor correspondiente

function imprimirhist(h) for c in keys(h) println(c h[c]) endend

Asiacute es como se ve la salida

juliagt h = histograma(perros)

juliagt imprimirhist(h)s 1e 1p 1r 2o 1

Nuevamente las claves no estaacuten en un orden particular Para recorrer las clavesen orden puede usar sort y collect

146 Capiacutetulo 11 Diccionarios

juliagt for c in sort(collect(keys(h))) println(c h[c]) ende 1o 1p 1r 2s 1

Buacutesqueda inversaDado un diccionario d y una clave k es faacutecil encontrar el valor correspondiente v= d[k] Esta operacioacuten se llama buacutesqueda

Pero iquestqueacute pasa si se tiene v y se quiere encontrar k Existen dos problemasprimeramente puede haber maacutes de una clave que apunta al valor v Dependiendode lo que se quiera es posible que se pueda elegir una de estas claves o que setenga que hacer una matriz que las contenga a todas En segundo lugar no hayuna sintaxis simple para hacer una buacutesqueda inversa solo se debe buscar

A continuacioacuten se muestra una funcioacuten que toma un valor y que devuelve laprimera clave que apunta a ese valor

function busquedainversa(d v) for k in keys(d) if d[k] == v return k end end error(Error de Busqueda)end

Esta funcioacuten es otro ejemplo del patroacuten de buacutesqueda pero utiliza una funcioacutenque no hemos visto antes error La funcioacuten error se usa para producir unErrorException que interrumpe el flujo normal En este caso tiene el mensajeError de Busqueda que indica que no existe una clave

Si llega al final del ciclo eso significa que v no aparece en el diccionario como unvalor por lo que se produce una excepcioacuten

A continuacioacuten se muestra un ejemplo de una buacutesqueda inversa exitosa

juliagt h = histograma(perros)

juliagt key = busquedainversa(h 2)r ASCIIUnicode U+0072 (category Ll Letter lowercase)

Buacutesqueda inversa 147

y una no exitosa

juliagt key = busquedainversa(h 3)ERROR Error de Busqueda

El efecto cuando generamos una excepcioacuten es el mismo que cuando Julia generauna se imprime un trazado inverso y un mensaje de error

Julia proporciona una forma optimizada de hacer una buacutesqueda inversafindall(isequal(3)h)

AVISO

Una buacutesqueda inversa es mucho maacutes lenta que una buacutesquedadirecta Si tiene que hacer buacutesquedas inversas con frecuencia o siel diccionario es muy grande el rendimiento de su programa severaacute afectado

Diccionarios y MatricesLas matrices pueden aparecer como valores en un diccionario Por ejemplo si setiene un diccionario que asigna frecuencias a letras y se quiere invertir es decirtener un diccionario que asigne letras a frecuencias Dado que pueden habervarias letras con la misma frecuencia cada valor en el diccionario invertidodeberiacutea ser una matriz de letras

Aquiacute hay una funcioacuten que invierte un diccionario

function invertirdic(d) inverso = Dict() for clave in keys(d) val = d[clave] if val notin keys(inverso) inverso[val] = [clave] else push(inverso[val] clave) end end inversoend

Cada vez que se recorre el bucle se asigna a la variable clave una clave de d y aval el valor correspondiente Si val no estaacute en el diccionario inverso significa queno se ha visto este valor antes por lo que se crea un nuevo item y se inicializacon un singleton (una matriz que contiene un solo elemento) De lo contrario seha visto este valor antes por lo que se agrega la clave correspondiente a lamatriz

148 Capiacutetulo 11 Diccionarios

Aquiacute hay un ejemplo

juliagt hist = histograma(perros)

juliagt inverso = invertirdic(hist)DictAnyAny with 2 entries 2 =gt [r] 1 =gt [s e p o]

Figura 16 Diagrama de estado

Figura 16 es un diagrama de estado que muestra hist e inverso Un diccionariose representa como un cuadro con los pares clave-valor dentro En este libro silos valores son enteros nuacutemeros de punto flotante o cadenas de texto se dibujandentro del cuadro y las matrices (generalmente) se dibujan fuera del cuadrosolo para mantener el diagrama simple

NOTA

Anteriormente se mencionoacute que un diccionario se implementausando una tabla hash (tambieacuten llamada matriz asociativahashing mapa hash tabla de dispersioacuten o tabla fragmentada) locual significa que las claves deben ser hashable

Un hash es una funcioacuten que toma un valor (de cualquier tipo) ydevuelve un entero Los diccionarios usan estos enteros llamadosvalores hash para almacenar y buscar pares clave-valor

PistasSi estuvo jugando con la funcioacuten fibonacci de Seccioacuten 67 es posible que hayanotado que cuanto maacutes grande el argumento que le da maacutes tiempo tarda lafuncioacuten en ejecutarse Maacutes auacuten el tiempo de ejecucioacuten aumenta muyraacutepidamente

Para entender por queacute considere Figura 17 que muestra el graacutefico de llamadaspara la funcioacuten fibonacci con n = 4

Pistas 149

Figura 17 Graacutefico de llamadas

Un graacutefico de llamadas muestra un conjunto de cuadros de funciones con liacuteneasque conectan cada cuadro con los cuadros de las funciones a las que llama En laparte superior del graacutefico fibonacci con n = 4 llama a fibonacci con n = 3 y n =2 A su vez fibonacci con n = 3 llama a fibonacci con n = 2 y n = 1 Y asiacutesucesivamente

Cuente cuaacutentas veces se llama a fibonacci(0) y fibonacci(1) Esta es una solucioacutenineficiente al problema y empeora a medida que el argumento aumenta entamantildeo

Una solucioacuten es llevar un registro de los valores que ya se han calculadoalmacenaacutendolos en un diccionario Un valor que ya ha sido calculado yalmacenado para un uso posterior se le denomina pista Aquiacute hay unaimplementacioacuten de fibonacci con pistas

anteriores = Dict(0=gt0 1=gt1)

function fibonacci(n) if n isin keys(anteriores) return anteriores[n] end res = fibonacci(n-1) + fibonacci(n-2) anteriores[n] = res resend

El diccionario llamado anteriores mantiene un registro de los valores deFibonacci que ya conocemos El programa comienza con dos pares 0corresponde a 1 y 1 corresponde a 1

Siempre que se llama a fibonacci se comprueba si el diccionario contiene elresultado ya calculado Si estaacute ahiacute la funcioacuten puede devolver el valorinmediatamente Si no tiene que calcular el nuevo valor antildeadirlo al diccionario ydevolverlo

150 Capiacutetulo 11 Diccionarios

Si ejecuta esta versioacuten de fibonacci y la compara con la original se daraacute cuentaque es mucho maacutes raacutepida

Variables GlobalesEn el ejemplo anterior el diccionario anteriores se crea fuera de la funcioacuten porlo que pertenece al marco especial llamado Main Las variables en Main a vecesson llamadas globales porque se puede acceder a ellas desde cualquier funcioacutenA diferencia de las variables locales que desaparecen cuando finaliza su funcioacutenlas variables globales existen de una llamada de funcioacuten a la siguiente

Es comuacuten usar variables globales como flags o banderas es decir variablesbooleanas que indican si una condicioacuten es verdadera Por ejemplo algunosprogramas usan una bandera llamada verbosa para controlar el nivel de detalleen la salida

verbose = true

function ejemplo1() if verbosa println(Ejecutando ejemplo1) endend

Si intenta reasignar una variable global se sorprenderaacute El siguiente ejemplotrata de llevar registro sobre si se ha llamado o no a una funcioacuten

ha_sido_llamada = false

function ejemplo2() ha_sido_llamada = true MALOend

Pero si lo ejecuta veraacute que el valor de ha_sido_llamada no cambia El problemaes que ejemplo2 + crea una nueva variable local llamada +ha_sido_llamada Lavariable local desaparece cuando finaliza la funcioacuten y no tiene efecto en lavariable global

Para reasignar una variable global dentro de una funcioacuten debe declarar lavariable global antes de usarla (reasignacioacuten

Variables Globales 151

been_called = false

function ejemplo2() global ha_sido_llamada ha_sido_llamada = trueend

La sentencia global le dice al inteacuterprete algo como esto ldquoEn esta funcioacuten cuandodigo ha_sido_llamada me refiero a la variable global asiacute que no crees unavariable local

A continuacioacuten se muestra un ejemplo que intenta actualizar una variable global

conteo = 0

function ejemplo3() conteo = conteo + 1 MALOend

Si lo ejecuta obtiene

juliagt ejemplo3()ERROR UndefVarError conteo not defined

Julia asume que conteo es local y bajo esa suposicioacuten lo estaacute leyendo antes deescribirlo La solucioacuten nuevamente es declarar conteo como global

conteo = 0

function ejemplo3() global conteo conteo += 1end

Si una variable global se refiere a un valor mutable puede modificar el valor sindeclarar la variable global

anteriores = Dict(0=gt0 1=gt1)

function ejemplo4() anteriores[2] = 1end

Por lo tanto puede agregar eliminar y reemplazar elementos de una matriz

152 Capiacutetulo 11 Diccionarios

global o diccionario pero si desea reasignar la variable debe declararla global

anteriores = Dict(0=gt0 1=gt1)

function ejemplo5() global anteriores anteriores = Dict()end

Para mejorar el rendimiento puede declarar la variable global como constanteCon esto ya no se puede reasignar la variable pero si se refiere a un valormutable siacute se puede modificar el valor

const known = Dict(0=gt0 1=gt1)

function example4() known[2] = 1end

AVISOLas variables globales pueden ser uacutetiles pero si tiene muchas deellas y las modifica con frecuencia pueden dificultar ladepuracioacuten y empeorar el desempentildeo de los programas

DepuracioacutenA medida que trabaja con conjuntos de datos maacutes grandes la depuracioacutenmediante la impresioacuten y verificacioacuten de la salida de manera manual puedetornarse difiacutecil Aquiacute hay algunas sugerencias para depurar grandes conjuntos dedatos

bull Reduzca la entrada

Si es posible reduzca el tamantildeo del conjunto de datos Por ejemplo si elprograma lee un archivo de texto comience con solo las primeras 10 liacuteneaso con el ejemplo maacutes pequentildeo que pueda encontrar que produzca erroresNo debe editar los archivos sino modificar el programa para que solo lea lasprimeras liacuteneas

Si hay un error puede reducir al valor maacutes pequentildeo que manifieste elerror y luego aumentarlo gradualmente a medida que encuentre y corrijaerrores

bull Revisar resuacutemenes y tipos

En lugar de imprimir y verificar todo el conjunto de datos considereimprimir resuacutemenes de los datos Por ejemplo el nuacutemero de elementos en

Depuracioacuten 153

un diccionario o el total de una serie de nuacutemeros

Una causa comuacuten de los errores de tiempo de ejecucioacuten son los valores detipo incorrecto Para depurar este tipo de error generalmente es suficienteimprimir el tipo de un valor

bull Escribir autocomprobaciones

Puede escribir coacutedigo que verifique errores automaacuteticamente Por ejemplosi estaacute calculando el promedio de una matriz de nuacutemeros puede verificarque el resultado no sea mayor que el elemento maacutes grande de la matriz omenor que el maacutes pequentildeo Esto se llama prueba de cordura

Otro tipo de verificacioacuten compara los resultados de dos caacutelculos diferentespara ver si son consistentes Esta se llama prueba de consistencia

bull Formatear la salida

Formatear la salida de depuracioacuten puede hacer que sea maacutes faacutecil detectarun error Vimos un ejemplo en Seccioacuten 69

Nuevamente el tiempo que dedica a construir andamiaje puede reducir eltiempo que dedica a la depuracioacuten

Glosariomapeo

Una relacioacuten en la que cada elemento de un conjunto corresponde a unelemento de otro conjunto

diccionarioUna asignacioacuten de claves a sus valores correspondientes

par clave-valorLa representacioacuten de la asociacioacuten entre una clave y un valor

itemEn un diccionario otro nombre para un par clave-valor

claveUn objeto que aparece en un diccionario como la primera parte de un parclave-valor

valorUn objeto que aparece en un diccionario como la segunda parte de un parclave-valor Este teacutermino es maacutes especiacutefico que nuestro uso previo de lapalabra valor

154 Capiacutetulo 11 Diccionarios

implementacioacutenUna forma de realizar un caacutelculo

tabla hashEl algoritmo utilizado para implementar los diccionarios de Julia

funcioacuten hashUna funcioacuten utilizada por una tabla hash para calcular la ubicacioacuten de unaclave

hashableUn tipo que tiene una funcioacuten hash

buacutesquedaUna operacioacuten sobre un diccionario que toma una clave y encuentra el valorcorrespondiente

buacutesqueda inversaUna operacioacuten sobre un diccionario que toma un valor y encuentra una omaacutes claves que se asignan a eacutel

singletonUna matriz (u otra secuencia) con un solo elemento

graacutefico de llamadaUn diagrama que muestra cada cuadro creado durante la ejecucioacuten de unprograma con una flecha entre cada funcioacuten y sus respectivas funcionesllamadas

pistaValor precalculado y almacenado temporalmente para evitar caacutelculosredundantes

variable globalUna variable definida fuera de una funcioacuten Se puede acceder a las variablesglobales desde cualquier funcioacuten

sentencia globalUna sentencia que declara un nombre de variable global

banderaUna variable booleana utilizada para indicar si una condicioacuten es verdadera

Glosario 155

declaracioacutenUna sentencia como global que le dice al inteacuterprete algo sobre una variable

variable global constanteUna variable global que no se puede reasignar

Ejercicios

Ejercicio 11-2

Escriba una funcioacuten que lea las palabras en palabrastxt y las almacene comoclaves en un diccionario No importa cuaacuteles sean los valores Luego puede usar eloperador isin como una forma raacutepida de verificar si una cadena estaacute en eldiccionario

Si hizo Seccioacuten 101510 puede comparar la velocidad de esta implementacioacutencon el operador array isin y la buacutesqueda binaria

Ejercicio 11-3

Lea la documentacioacuten de la funcioacuten que opera sobre diccionarios get y uacuteselapara escribir una versioacuten maacutes concisa de invertirdic

Ejercicio 11-4

Use pistas en la funcioacuten de Ackermann de Seccioacuten 6112 y vea si esto permiteevaluar la funcioacuten con argumentos de mayor tamantildeo

Ejercicio 11-5

Si hizo Seccioacuten 10157 ya tiene una funcioacuten llamada repetido que toma unamatriz como paraacutemetro y devuelve true si hay alguacuten objeto que aparece maacutes deuna vez en la matriz

Use un diccionario para escribir una versioacuten maacutes raacutepida y simple de repetido

Ejercicio 11-6

Dos palabras son pares desplazados si puede desplazar una de ellas y obtenerla otra (vea desplazarpalabra en Seccioacuten 8155)

Escriba un programa que lea una matriz de palabras y encuentre todos los paresdesplazados

156 Capiacutetulo 11 Diccionarios

Ejercicio 11-7

Aquiacute hay otro Puzzle de Car Talk (httpswwwcartalkcompuzzlerbrowse)

This was sent in by a fellow named Dan OrsquoLeary He came upon a commonone-syllable five-letter word recently that has the following unique propertyWhen you remove the first letter the remaining letters form a homophone ofthe original word that is a word that sounds exactly the same Replace thefirst letter that is put it back and remove the second letter and the result isyet another homophone of the original word And the question is whatrsquos theword

Now Irsquom going to give you an example that doesnrsquot work Letrsquos look at thefive-letter word lsquowrackrsquo W-R-A-C-K you know like to lsquowrack with painrsquo If Iremove the first letter I am left with a four-letter word rsquoR-A-C-Krsquo As inlsquoHoly cow did you see the rack on that buck It must have been a nine-pointerrsquo Itrsquos a perfect homophone If you put the lsquowrsquo back and remove thelsquorrsquo instead yoursquore left with the word lsquowackrsquo which is a real word itrsquos justnot a homophone of the other two words

But there is however at least one word that Dan and we know of which willyield two homophones if you remove either of the first two letters to maketwo new four-letter words The question is whatrsquos the word

You can use the dictionary from Seccioacuten 11101 to check whether a string is inthe word array

OBSERVACIOacuteNTo check whether two words are homophones you canuse the CMU Pronouncing Dictionary You can downloadit from httpwwwspeechcscmueducgi-bincmudict

Write a program that lists all the words that solve the Puzzler

Ejercicios 157

Capiacutetulo 12 TuplasEste capiacutetulo presenta otro tipo integrado las tuplas Luego muestra coacutemo losarreglos los diccionarios y las tuplas funcionan en conjunto Tambieacuten se presentauna caracteriacutestica uacutetil para los arreglos de longitud variable como argumento losoperadores de recopilacioacuten y dispersioacuten

Las Tuplas son ImmutablesUna tupla es una secuencia de valores Estos valores pueden ser de cualquiertipo y estaacuten indexados por enteros por lo que las tuplas son muy parecidas a losarreglos La diferencia maacutes importante es que las tuplas son inmutables y quecada elemento puede tener su propio tipo

Una tupla es una lista de valores separados por comas

juliagt t = a b c d e(a b c d e)

Aunque no es necesario es comuacuten encerrar las tuplas entre pareacutentesis

juliagt t = (a b c d e)(a b c d e)

Para crear una tupla con un solo elemento se debe incluir una coma final

juliagt t1 = (a)(a)juliagt typeof(t1)TupleChar

AVISO

Un valor entre pareacutentesis sin coma no es una tupla

juliagt t2 = (a)a ASCIIUnicode U+0061 (category Ll Letter lowercase)juliagt typeof(t2)Char

Otra forma de crear una tupla es la funcioacuten de tupla integrada en Julia Sinargumento esta funcioacuten crea una tupla vaciacutea

juliagt tuple()()

158 Capiacutetulo 12 Tuplas

Si se tienen muacuteltiples argumentos el resultado es una tupla con los argumentosdados

juliagt t3 = tuple(1 a pi)(1 a π)

Ya que tuple es el nombre de una funcioacuten integrada debe evitar usarla comonombre de variable

La mayoriacutea de los operadores de arreglos tambieacuten sirven en las tuplas Eloperador corchete indexa un elemento

juliagt t = (a b c d e)

juliagt t[1]a ASCIIUnicode U+0061 (category Ll Letter lowercase)

Y el operador porcioacuten selecciona un rango de elementos

juliagt t[24](b c d)

Pero si se intenta modificar uno de los elementos de la tupla se obtendraacute unerror

juliagt t[1] = AERROR MethodError no method matching setindex(NTuple5Char CharInt64)

Como las tuplas son inmutables sus elementos no se pueden modificar

Los operadores relacionales funcionan con las tuplas y otras secuencias Juliacomienza comparando el primer elemento de cada secuencia Si son igualespasa a los siguientes elementos y asiacute sucesivamente hasta que encuentraelementos que difieren Los elementos posteriores no se consideran (incluso sison realmente grandes)

juliagt (0 1 2) lt (0 3 4)truejuliagt (0 1 2000000) lt (0 3 4)true

Las Tuplas son Immutables 159

Asignacioacuten de tuplaDe vez en cuando es uacutetil intercambiar los valores de dos variables Para hacerlocon sentencias de asignacioacuten convencionales se debe usar una variable temporalPor ejemplo para intercambiar a y b

temp = aa = bb = temp

Esta solucioacuten resulta aparatosa La asignacioacuten de tuplas soluciona este problemaelegantemente

a b = b a

El lado izquierdo es una tupla de variables y el lado derecho es una tupla deexpresiones Cada valor se asigna a su respectiva variable Todas las expresionesdel lado derecho se evaluacutean antes de las asignaciones

El nuacutemero de variables de la izquierda tiene que ser menor o igual que el nuacutemerode valores a la derecha

juliagt (a b) = (1 2 3)(1 2 3)juliagt a b c = 1 2ERROR BoundsError attempt to access (1 2) at index [3]

El lado derecho puede ser cualquier tipo de secuencia (cadena arreglo o tupla)Por ejemplo para dividir una direccioacuten de correo electroacutenico en nombre deusuario y dominio se puede escribir

juliagt addr = juliocesarromajuliocesarromajuliagt unombre dominio = split(addr )

El valor de retorno de split es un arreglo con dos elementos el primer elementose asigna a unombre y el segundo a dominio

juliagt unombrejuliocesarjuliagt dominioroma

160 Capiacutetulo 12 Tuplas

Tuplas como valor de retornoEstrictamente hablando una funcioacuten solo puede devolver un valor pero si elvalor es una tupla el efecto es el mismo que devolver muacuteltiples valores Porejemplo si desea dividir dos enteros y calcular el cociente y el resto esineficiente calcular x divide y y luego x y Es mejor calcular ambos al mismotiempo

La funcioacuten integrada divrem toma dos argumentos y devuelve una tupla de dosvalores el cociente y el resto El resultado puede ser almacenado como unatupla

juliagt t = divrem(7 3)(2 1)

Tambieacuten se puede utilizar asignacioacuten de tuplas para almacenar los elementos porseparado

juliagt q r = divrem(7 3)

juliagt show q rq = 2r = 1

Aquiacute hay un ejemplo de una funcioacuten que devuelve una tupla

function minmax(t) minimum(t) maximum(t)end

maximum y minimum son funciones integradas que encuentran los elementosmaacutes grandes y maacutes pequentildeos de una secuencia respectivamente La funcioacutenminmax calcula ambos y devuelve una tupla de dos valores Otra alternativa esutilizar la funcioacuten integrada extrema lo cual es maacutes eficiente

Tupla con Argumentos de Longitud VariableLas funciones pueden tomar un nuacutemero variable de argumentos Un nombre deparaacutemetro que termina con recopila argumentos en una tupla Por ejemploimprimirtodo toma cualquier nuacutemero de argumentos y los imprime

function imprimirtodo(args) println(args)end

Tuplas como valor de retorno 161

El paraacutemetro de recopilacioacuten puede tener cualquier nombre pero la convencioacutenes llamarlo args A continuacioacuten se muestra coacutemo funciona la funcioacuten

juliagt imprimirtodo(1 20 3)(1 20 3)

El opuesto de la recopilacioacuten es la dispersioacuten Si tiene una secuencia de valores ydesea pasarla a una funcioacuten como argumento muacuteltiple puede usar el operador Por ejemplo divrem toma exactamente dos argumentos y no funciona contuplas

juliagt t = (7 3)

juliagt divrem(t)ERROR MethodError no method matching divrem(TupleInt64Int64)

No obstante si dispersamos la tupla funciona

juliagt divrem(t)(2 1)

Muchas de las funciones integradas usan tuplas con argumentos de longitudvariable Por ejemplo max y min pueden tomar cualquier nuacutemero deargumentos

juliagt max(1 2 3)3

Pero sum no

juliagt sum(1 2 3)ERROR MethodError no method matching sum(Int64 Int64 Int64)

Ejercicio 12-1

Escriba una funcioacuten llamada sumartodo que tome cualquier nuacutemero deargumentos y devuelva su suma

En el mundo de Julia generalmente se le llama ldquoslurprdquo (sorber en espantildeol) areunir y splat (plaf en espantildeol como el ruido cuando cae algo) a dispersar

162 Capiacutetulo 12 Tuplas

Arreglos y tuplaszip es una funcioacuten integrada que toma dos o maacutes secuencias y devuelve unacoleccioacuten de tuplas donde cada tupla contiene un elemento de cada secuencia Elnombre de la funcioacuten se refiere a una cremallera que une e intercala dos filas dedientes

Este ejemplo une e intercala una cadena y un arreglo

juliagt s = abc

juliagt t = [1 2 3]

juliagt zip(s t)zip(abc [1 2 3])

El resultado es un objeto zip que permite iterar a traveacutes de los pares El uso maacutescomuacuten de zip es en un bucle for

juliagt for par in zip(s t) println(par) end(a 1)(b 2)(c 3)

Un objeto zip es un tipo de iterador que es cualquier objeto que itera a traveacutes deuna secuencia Los iteradores son en cierto modo similares a los arreglos peroa diferencia de estos uacuteltimos no se puede usar un iacutendice para seleccionar unelemento de un iterador

Si desea usar operadores y funciones de arreglos puede usar un objeto zip parahacer un arreglo

juliagt collect(zip(s t))3-element ArrayTupleCharInt641 (a 1) (b 2) (c 3)

El resultado es una serie de tuplas En este ejemplo cada tupla contiene uncaraacutecter de la cadena y el elemento correspondiente del arreglo

Si las secuencias no tienen la misma longitud el resultado tiene la longitud de lamaacutes corta

Arreglos y tuplas 163

juliagt collect(zip(Juan Gabriel))4-element ArrayTupleCharChar1 (J G) (u a) (a b) (n r)

Se puede usar asignacioacuten de tuplas en un bucle for para recorrer un arreglo detuplas

juliagt t = [(a 1) (b 2) (c 3)]

juliagt for (letra numero) in t println(numero letra) end1 a2 b3 c

En cada iteracioacuten del ciclo Julia selecciona la siguiente tupla en el arreglo yasigna estos elementos a letra y nuacutemero Los pareacutentesis de (letra nuacutemero) sonobligatorios

Combinando zip for y asignacioacuten de tuplas se obtiene una forma para recorrerdos (o maacutes) secuencias al mismo tiempo Por ejemplo la funcioacuten coinciden tomados secuencias t1 y t2 y devuelve true si hay un iacutendice i tal que t1[i] == t2[i]

function coinciden(t1 t2) for (x y) in zip(t1 t2) if x == y return true end end falseend

Si se necesita recorrer los elementos de una secuencia y sus iacutendices se puedeusar la funcioacuten integrada enumerate

juliagt for (indice elemento) in enumerate(abc) println(indice elemento) end1 a2 b3 c

164 Capiacutetulo 12 Tuplas

El resultado de enumerate es un objeto enumerate el cual hace una iteracioacutensobre una secuencia de pares doacutende cada par contiene un iacutendice (a partir de 1) yun elemento de la secuencia dada

Diccionarios y TuplasLos diccionarios se pueden usar como iteradores que iteran sobre los paresclave-valor Puede usarlos en un bucle for como este

juliagt d = Dict(a=gt1 b=gt2 c=gt3)

juliagt for (key value) in d println(key value) enda 1c 3b 2

Como es de esperar en un diccionario los elementos no estaacuten en un ordenparticular

Ahora si se quiere hacer lo contrario se puede usar una serie de tuplas parainicializar un nuevo diccionario

juliagt t = [(a 1) (c 3) (b 2)]

juliagt d = Dict(t)DictCharInt64 with 3 entries a =gt 1 c =gt 3 b =gt 2

Al combinar Dict con zip podemos crear un diccionario de una manera muysimple

juliagt d = Dict(zip(abc 13))DictCharInt64 with 3 entries a =gt 1 c =gt 3 b =gt 2

Es comuacuten usar tuplas como claves en los diccionarios Por ejemplo un directoriotelefoacutenico puede asignar nuacutemeros de teleacutefono a una tupla con apellido y nombreSuponiendo que se ha definido apellido nombre y numero podriacuteamos escribir

Diccionarios y Tuplas 165

directorio[apellido nombre] = numero

La expresioacuten entre pareacutentesis es una tupla Se podriacutea usar asignacioacuten de tuplaspara recorrer este diccionario

for ((apellido nombre) numero) in directorio println(nombre apellido numero)end

Este bucle recorre los pares clave-valor en directorio los cuales son tuplasAsigna los elementos de la clave de cada tupla a apellido y nombre y el valor anumero luego imprime el nombre y el nuacutemero de teleacutefono correspondiente

Hay dos formas de representar tuplas en un diagrama de estado La versioacuten maacutesdetallada muestra los iacutendices y elementos tal como aparecen en un arreglo Porejemplo la tupla (Cortaacutezar Julio) se veriacutea como en Figura 18

Figura 18 Diagrama de estado

Pero en un diagrama maacutes grande es posible que desee omitir algunos detallesPor ejemplo un diagrama del directorio telefoacutenico puede verse como en Figura19

Figura 19 Diagrama de estado

Aquiacute las tuplas se muestran usando la sintaxis de Julia para tener un esquemamaacutes simple El nuacutemero de teleacutefono del diagrama es el nuacutemero de reclamos de laBBC asiacute que no intentes llamar

Secuencias de SecuenciasHasta ahora el capiacutetulo se ha centrado en los arreglos de tuplas pero casi todoslos ejemplos que se han visto tambieacuten funcionan con arreglos de arreglos tuplasde tuplas y tuplas de arreglos Para evitar enumerar todas las posiblescombinaciones a veces es maacutes faacutecil hablar sobre secuencias de secuencias

En muchos contextos los diferentes tipos de secuencias (cadenas arreglos ytuplas) se pueden usar indistintamente Entonces iquestcoacutemo elegir uno u otro

166 Capiacutetulo 12 Tuplas

Para comenzar con lo mas obvio las cadenas son maacutes limitadas que las demaacutessecuencias porque los elementos deben ser caracteres Ademaacutes son inmutablesSi se necesita poder cambiar los caracteres en una cadena (en vez de crear unanueva) puede que lo mas adecuado sea elegir un arreglo de caracteres

Los arreglos se usan con mas frecuencia que las tuplas principalmente porqueson mutables No obstante hay algunos casos donde es posible que seapreferible usar tuplas

bull En algunos contextos como en una sentencia return resultasintaacutecticamente maacutes simple crear una tupla que un arreglo

bull Si se pasa una secuencia como argumento de una funcioacuten el uso de tuplasreduce los comportamientos potencialmente indeseados debido a lacreacioacuten de alias

bull Por rendimiento El compilador puede especializarse en este tipo

Dado que las tuplas son inmutables no tienen funciones como sort y reverseque modifiquen arreglos ya existentes Sin embargo Julia proporciona lasfunciones integradas sort que toma un arreglo y devuelve una secuencia nuevacon los mismos elementos ordenados y reverse que toma cualquier secuencia ydevuelve una secuencia nueva del mismo tipo con los mismos elementos en elorden contrario

DepuracioacutenLos arreglos diccionarios y tuplas son ejemplos de estructuras de datos En estecapiacutetulo se empiezan a ver estructuras de datos compuestas como arreglos otuplas y diccionarios que contienen tuplas como claves y arreglos como valoresLas estructuras de datos compuestas son uacutetiles aunque tambieacuten resultanpropensas a lo que se llaman errores de forma es decir errores causados cuandouna estructura de datos tiene el tipo tamantildeo o estructura incorrecta Porejemplo si estaacute esperando una lista con un entero y se le pasa simplemente unentero (no en una lista) no funcionaraacute

Julia permite antildeadir el tipo a elementos de una secuencia Esto se detalla enCapiacutetulo 17 Especificar el tipo elimina muchos errores de forma

Glosariotupla

Una secuencia inmutable de elementos donde cada elemento puede tener supropio tipo

asignacioacuten en tuplaUna asignacioacuten con una secuencia en el lado derecho y una tupla devariables en el izquierdo Primero se evaluacutea el lado derecho y luego sus

Depuracioacuten 167

elementos son asignados a las variables de la izquierda

reunirLa operacioacuten de armar una tupla con argumentos de longitud variable

dispersarLa operacioacuten de tratar una secuencia como una lista de argumentos

objeto zipEl resultado de llamar a la funcioacuten integrada zip un objeto que itera atraveacutes de una secuencia de tuplas

iteradorUn objeto que puede iterar a traveacutes de una secuencia pero que no tiene losoperadores y funciones de arreglos

estructura de datosUna coleccion de valores relacionados a menudo organizados en arreglosdiccionarios tuplas etc

error de formaUn error causado porque un valor tiene la forma incorrecta es decir el tipoo tamantildeo incorrecto

Ejercicios

Ejercicio 12-2

Escriba una funcioacuten llamada masfrecuente que tome una cadena e imprima lasletras en orden decreciente de frecuencia Encuentre muestras de texto de variosidiomas diferentes y vea coacutemo la frecuencia de las letras variacutea entre idiomasCompare sus resultados con las tablas en httpsenwikipediaorgwikiLetter_frequencies

Ejercicio 12-3

iexclMaacutes anagramas

1 Escriba un programa que lea una lista de palabras de un archivo (veaSeccioacuten 91) e imprima todos los conjuntos de palabras que son anagramas

Aquiacute hay un ejemplo de coacutemo se veriacutea la salida

168 Capiacutetulo 12 Tuplas

[brazo zobra broza zarbo][palabra parlaba][vida diva][gato toga gota]

OBSERVACIOacuteN

Es posible que desee crear un diccionario queasigne a una coleccioacuten de letras una serie depalabras que se puedan deletrear con esas letrasLa pregunta es iquestcoacutemo representar la coleccioacuten deletras de una manera que pueda usarse comoclave

2 Modifique el programa anterior para que imprima primero el arreglo maacuteslargo de anagramas seguido del segundo maacutes larga y asiacute sucesivamente

3 En Scrabble un bingo es cuando juegas las siete fichas de tu atril juntocon una letra del tablero para formar una palabra de ocho letras iquestQueacutecoleccioacuten de 8 letras forman parte del bingo maacutes probable

Ejercicio 12-4

Dos palabras metatizan si se puede transformar una en la otra intercambiandodos letras como es el caso de conversar y conservar Escriba un programaque encuentre todos los pares de metaacutetesis en el diccionario

OBSERVACIOacuteN No pruebe con todos los pares de palabras ni tampococon todos los intercambios posibles

Creacuteditos Este ejercicio estaacute inspirado en un ejemplo de httppuzzlersorg

Ejercicio 12-5

Aquiacute hay otro Puzzle de Car Talk (httpswwwcartalkcompuzzlerbrowse)

Ejercicios 169

iquestCuaacutel es la palabra en espantildeol maacutes larga que sigue siendo una palabra enespantildeol vaacutelida a medida que se eliminan sus letras una a una

Las letras se pueden eliminar de cualquier extremo o del medio pero no sepuede reordenar ninguna de ellas Cada vez que elimina una letra se quedacon otra palabra en espantildeol Eventualmente terminaraacute con una letra la cualtambieacuten seraacute una palabra en espantildeol que puede encontrar en el diccionarioSe desea saber cuaacutel es la palabra maacutes larga y cuaacutentas letras tiene

A modo de ejemplo piense en la palabra Palote iquestDe acuerdo Comienza conpalote elimina la letra p y queda alote luego se quita la t y queda aloe setoma la e y se tiene alo quitando la o se tiene al y finalmente eliminando lal queda a

Escriba un programa que encuentre todas las palabras que se pueden reducir deesta manera y luego encuentre la maacutes larga

OBSERVACIOacuteN

Este ejercicio es un poco maacutes desafiante que el resto asiacuteque aquiacute hay algunas sugerencias

1 Es posible que quiera escribir una funcioacuten que tomeuna palabra y calcule un arreglo de todas laspalabras que se pueden formar al eliminar unaletra Estos son los hijos de la palabra

2 De manera recursiva una palabra es reducible sialguno de sus hijos es reducible Como caso basepuede considerar la cadena vaciacutea reducible

3 La lista de palabras palabrastxt no tiene la cadenavaciacutea por lo que tendraacute que agregarla

4 Para mejorar el rendimiento de su programa esposible que desee guardar las palabras que se sabeque son reducibles

170 Capiacutetulo 12 Tuplas

Capiacutetulo 13 Estudio de Caso Seleccioacuten deEstructura de DatosHasta ahora hemos aprendido sobre las principales estructuras de datos de Juliay hemos visto algunos de los algoritmos que las utilizan

Este capiacutetulo presenta un estudio de caso con ejercicios que le permitenpracticar la eleccioacuten de estructuras de datos y su uso

Anaacutelisis de Frecuencia de PalabrasComo de costumbre se recomienda intentar resolver los ejercicios antes de leerlas soluciones

Ejercicio 13-1

Escriba un programa que lea un archivo divida cada liacutenea en palabras elimine elespacio en blanco y la puntuacioacuten de las palabras y luego las convierta enminuacutesculas

OBSERVACIOacuteN La funcioacuten isletter permite saber si un caraacutecterpertenece al alfabeto

Ejercicio 13-2

Vaya a la paacutegina de Proyecto Gutenberg (httpsgutenbergorg) y descargue sulibro favorito sin derechos de autor en formato de texto plano La mayoriacutea de loslibros estaacuten en ingleacutes pero existen algunos en espantildeol

Modifique su programa del ejercicio anterior para leer el libro que descargoacuteomita la informacioacuten del encabezado al comienzo del archivo y procese el restode las palabras tal como en el ejercicio previo

Luego modifique el programa para contar la cantidad total de palabras en ellibro y la cantidad de veces que se usa cada palabra

Imprima la cantidad de palabras diferentes que se usan en el libro Comparediferentes libros de diferentes autores escritos en diferentes eacutepocas iquestQueacute autorusa un vocabulario maacutes extenso

Ejercicio 13-3

Modifique el programa del ejercicio anterior para imprimir las 20 palabras maacutesutilizadas en el libro

Anaacutelisis de Frecuencia de Palabras 171

Ejercicio 13-4

Modifique el programa anterior para que lea una lista de palabras y luegoimprima todas las palabras del libro que no esteacuten en la lista de palabrasiquestCuaacutentos de ellos son errores tipograacuteficos iquestCuaacutentos de ellos son palabrascomunes que deberiacutean estar en la lista de palabras iquest Cuaacutentos de ellos sonteacuterminos realmente macabros

Nuacutemeros aleatoriosDadas las mismas entradas la mayor parte de los programas generan la mismasalida cada vez que los ejecutamos por lo que se dice que son deterministasNormalmente el determinismo es algo bueno ya que esperamos que un caacutelculonos entregue siempre el mismo resultado Para algunas aplicaciones sinembargo queremos que el computador sea impredecible Por ejemplo en losjuegos entre otros casos

Hacer que un programa sea realmente no determinista resulta difiacutecil pero hayformas de que hacer que al menos parezca no determinista Una de ellas es usaralgoritmos para generar nuacutemeros pseudoaleatorios Los nuacutemerospseudoaleatorios no son verdaderamente aleatorios porque se generan medianteun caacutelculo determinista pero al mirar estos nuacutemeros es casi imposibledistinguirlos de lo aleatorio

La funcioacuten rand devuelve un numero de punto flotante entre 00 y 10(incluyendo 00 pero no 10) Cada vez que usted llama a rand obtiene elsiguiente numero de una larga serie Para ver un ejemplo ejecute este bucle

for i in 110 x = rand() println(x)end

La funcioacuten rand puede tomar un iterador o arreglo como argumento y devuelveun elemento aleatorio de ellos

for i in 110 x = rand(16) print(x )end

Ejercicio 13-5

Escriba una funcioacuten llamada escogerdelhistograma que tome un histogramadefinido como en Seccioacuten 112 y devuelva un valor aleatorio del histogramaelegido con probabilidad proporcional a la frecuencia Por ejemplo para este

172 Capiacutetulo 13 Estudio de Caso Seleccioacuten de Estructura de Datos

histograma

juliagt t = [a a b]

juliagt histograma(t)DictAnyAny with 2 entries a =gt 2 b =gt 1

su funcioacuten debe devolver a con probabilidad y b con probabilidad

Histograma de PalabrasDebe hacer los ejercicios anteriores antes de continuar Tambieacuten necesitaraacutehttpsgithubcomJuliaIntroIntroAJuliajlblobmasterdataDonQuijotetxt

Aquiacute hay un programa que lee un archivo y construye un histograma de laspalabras en el archivo

function procesararchivo(nombrearchivo) hist = Dict() for linea in eachline(nombrearchivo) procesarlinea(linea hist) end histend

function procesarlinea(linea hist) linea = replace(linea - =gt ) for palabra in split(linea) palabra = string(filter(isletter [palabra])) palabra = lowercase(palabra) hist[palabra] = get(hist palabra 0) + 1 endend

Histograma de Palabras 173

DictAnyAny with 23607 entries enojoacute =gt 1 angosta =gt 1 hurto =gt 10 sirviesen =gt 2 solene =gt 1 coronan =gt 1 endereacutecese =gt 2 alteza =gt 15 rescatarlos =gt 1 enderezador =gt 1 libertad =gt 81 abundante =gt 5 bajeza =gt 4 embotoacute =gt 1 estime =gt 1 renovaban =gt 1 acreciente =gt 4 debieron =gt 8 garci =gt 1 ⋮ =gt ⋮

hist = procesararchivo(DonQuijotetxt)

Este programa lee DonQuijotetxt que contiene el texto de Don Quijote deMiguel de Cervantes

procesararchivo recorre las liacuteneas del archivo pasando una liacutenea a la vez aprocesarlinea El histograma hist se estaacute utilizando como acumulador

procesarlinea usa la funcioacuten replace para reemplazar los guiones por espaciosantes de usar split para dividir la liacutenea en un arreglo de cadenas Recorre elconjunto de palabras y usa filter isletter y lowercase para eliminar los signos depuntuacioacuten y convertir las palabras a minuacutesculas (Decir que las cadenas seconvierten es incorrecto recuerde que las cadenas son inmutables por lo queuna funcioacuten como lowercase devuelve cadenas nuevas)

Finalmente procesarlinea actualiza el histograma creando un nuevo elemento oincrementando uno existente

Para contar el nuacutemero total de palabras en el archivo podemos sumar lasfrecuencias en el histograma

function palabrastotales(hist) sum(values(hist))end

174 Capiacutetulo 13 Estudio de Caso Seleccioacuten de Estructura de Datos

El nuacutemero de palabras diferentes es el nuacutemero de elementos en el diccionario

function palabrasdiferentes(hist) length(hist)end

Para imprimir los resultados se puede usar el siguiente coacutedigo

juliagt println(Nuacutemero total de palabras palabrastotales(hist))Nuacutemero total de palabras 385925

juliagt println(Nuacutemero de palabras diferentes palabrasdiferentes(hist))Nuacutemero de palabras diferentes 23607

Observacioacuten No se considera el encabezado del archivo de texto soacutelo el libro

Palabras Maacutes ComunesPara encontrar las palabras maacutes comunes podemos hacer un arreglo de tuplasdonde cada tupla contiene una palabra y su frecuencia y ordenarlas Lasiguiente funcioacuten toma un histograma y devuelve un arreglo de tuplas defrecuencia de palabras

function mascomun(hist) t = [] for (clave valor) in hist push(t (valorclave)) end reverse(sort(t))end

En cada tupla la frecuencia aparece primero por lo que el arreglo resultante seordena por frecuencia A continuacioacuten se muestra un bucle que imprime las 10palabras maacutes comunes

t = mascomun(hist)println(Las palabras maacutes comunes son)for (frec palabra) in t[110] println(palabra t frec)end

En este ejemplo utilizamos un caraacutecter de tabulacioacuten (t) como separador envez de un espacio por lo que la segunda columna estaacute alineada A continuacioacutense muestran los resultados de Don Quijote

Palabras Maacutes Comunes 175

Las palabras maacutes comunes sonque 20626de 18217y 18188la 10363a 9881en 8241el 8210no 6345los 4748se 4690

OBSERVACIOacuteN

Este coacutedigo se puede simplificar usando comoargumento la palabra reservada rev de la funcioacuten sortPuede leer sobre esto en httpsdocsjulialangorgenv1basesortBasesort

Parametros OpcionalesSe han tratado funciones integradas de Julia que toman argumentos opcionalesTambieacuten es posible escribir funciones definidas por el programador conargumentos opcionales Por ejemplo aquiacute hay una funcioacuten que imprime laspalabras maacutes comunes en un histograma

function imprimirmascomun(hist num=10) t = mascomun(hist) println(Las palabras maacutes comunes son ) for (frec palabra) in t[1num] println(palabra t frec) endend

El primer paraacutemetro es obligatorio y el segundo es opcional El valorpredeterminado de num es 10

Si solo pasas un argumento

imprimirmascomun(hist)

num toma el valor predeterminado Si pasas dos argumentos

imprimirmascomun(hist 20)

num toma el valor del argumento En otras palabras el argumento opcional

176 Capiacutetulo 13 Estudio de Caso Seleccioacuten de Estructura de Datos

anula el valor predeterminado

Si una funcioacuten tiene paraacutemetros obligatorios y opcionales los paraacutemetrosobligatorios deben ir primero seguidos de los opcionales

Resta de DiccionarioEncontrar las palabras de un libro que no estaacuten en la lista de palabras depalabrastxt es un problema similar a una resta de conjuntos es decir se quiereencontrar todas las palabras de un conjunto (las palabras en el libro) que noestaacuten en el otro (las palabras en la lista)

resta toma los diccionarios d1 y d2 y devuelve un nuevo diccionario que contienetodas las claves de d1 que no estaacuten en d2 Como realmente no importan losvalores se fijan como nothing

function resta(d1 d2) res = Dict() for clave in keys(d1) if clave notin keys(d2) res[clave] = nothing end end resend

Para encontrar las palabras en el libro que no estaacuten en palabrastxt se ouedeusar procesararchivo para construir un histograma para palabrastxt y luego lafuncioacuten resta

palabras = procesararchivo(palabrastxt)dif = resta(hist palabras)

println(Palabras en el libro que no estaacuten en la lista de palabras)for palabra in keys(dif) print(palabra )end

Estos son algunos de los resultados de Don Quijote

Palabras en el libro que no estaacuten en la lista de palabrasenojoacute angosta coronan sirviesen solene endereacutecese rescatarlos embotoacuteestime renovaban

Algunas de estas palabras son conjugaciones de verbos Otros como solene yano son de uso comuacuten iexclPero algunas son palabras comunes que deberiacutean estar en

Resta de Diccionario 177

la lista

Ejercicio 13-6

Julia proporciona una estructura de datos llamada Set que permite muchasoperaciones comunes de conjuntos Puede leer sobre ellas en Seccioacuten 202 oconsultar la documentacioacuten en httpsdocsjulialangorgenv1basecollectionsSet-Like-Collections-1

Escriba un programa que use la resta de conjuntos para encontrar palabras en ellibro que no estaacuten en la lista de palabras

Palabras al AzarPara elegir una palabra aleatoria del histograma el algoritmo maacutes simple esconstruir un arreglo con muacuteltiples copias de cada palabra de acuerdo con lafrecuencia observada y luego elegir una palabra del arreglo

function palabraalazar(h) t = [] for (palabra frec) in h for i in 1frec push(t palabra) end end rand(t)end

Este algoritmo funciona pero no es muy eficiente ya que cada vez que elige unapalabra aleatoria reconstruye el arreglo que es tan grande como el librooriginal Una mejora es construir el arreglo una vez y luego hacer muacuteltiplesselecciones pero el arreglo sigue siendo grande

Una alternativa es

1 Use las claves para obtener un arreglo de palabras del libro

2 Cree un arreglo que contenga la suma acumulada de las frecuencias depalabras (vea Seccioacuten 10152) El uacuteltimo elemento en este arreglo es elnuacutemero total de palabras en el libro

3 Elija un nuacutemero aleatorio del 1 al Use buacutesqueda binaria (vea Seccioacuten101510) para encontrar el iacutendice donde se insertaraacute el nuacutemero aleatorio enla suma acumulada

4 Use el iacutendice para encontrar la palabra correspondiente en el arreglo depalabras

178 Capiacutetulo 13 Estudio de Caso Seleccioacuten de Estructura de Datos

Ejercicio 13-7

Escriba un programa que use este algoritmo para elegir una palabra aleatoriadel libro

Anaacutelisis de MarkovSi elige palabras del libro al azar puede tener una idea del vocabulario usadopero probablemente no se va a obtener una oracioacuten

rocinante plaacuteticas sazoacuten ojos Dulcinea Dios

Una serie de palabras aleatorias rara vez tiene sentido porque no hay relacioacutenentre palabras sucesivas Por ejemplo en una oracioacuten real se esperariacutea que unartiacuteculo como el fuese seguido por un sustantivo y probablemente no un verboo un adverbio

Una forma de medir este tipo de relaciones es con el anaacutelisis de Markov quedefine para una secuencia dada de palabras la probabilidad de las palabras quepodriacutean venir despueacutes Por ejemplo en la cancioacuten La vida es un carnaval (deCeliz Cruz)

Todo aquelQue piense que la vida siempre es cruelTiene que saber que no es asiacuteQue tan solo hay momentos malosY todo pasa

Todo aquelQue piense que esto nunca va cambiarTiene que saber que no es asiacuteQue al mal tiempo buena caraY todo cambia

Ay no hay que llorar (No hay que llorar)Que la vida es un carnavalQue es maacutes bello vivir cantando

En este texto la frase que piense siempre va seguida de la palabra que perola frase piense que puede ir seguida de la o esto

El resultado del anaacutelisis de Markov es un mapeo de cada prefijo (como quepiense y piense que) a todos los sufijos posibles (como la y esto)

Dada esta asignacioacuten se puede generar un texto aleatorio comenzando concualquier prefijo y eligiendo aleatoriamente entre los posibles sufijos A

Anaacutelisis de Markov 179

continuacioacuten puede combinar el final del prefijo y el nuevo sufijo para formar elsiguiente prefijo y repetir

Por ejemplo si comienza con el prefijo Que la la siguiente palabra seraacute vidaporque el prefijo solo aparece dos veces en el texto y siempre estaacute seguido deeste sufijo El siguiente prefijo es la vida por lo que el siguiente sufijo podriacuteaser siempre o es

En este ejemplo la longitud del prefijo siempre es dos pero puede hacer anaacutelisisde Markov con un prefijo de cualquier longitud

Ejercicio 13-8

Anaacutelisis de Markov

1 Escriba un programa que lea un texto desde un archivo y realice un anaacutelisisde Markov El resultado debe ser un diccionario que asocie prefijos y unacoleccioacuten de posibles sufijos La coleccioacuten puede ser un arreglo tupla odiccionario depende de usted hacer una eleccioacuten adecuada Puede probarsu programa con una longitud de prefijo de dos pero debe escribir elprograma de manera tal que sea faacutecil probar con otras longitudes

2 Agregue una funcioacuten al programa anterior para generar un texto aleatoriobasado en anaacutelisis de Markov Aquiacute hay un ejemplo de Don Quijote conlongitud de prefijo 2

Trifaldi habiacutea de Troya ni por la majestad real Y con mis quejasDesechaacutesteme iexcloh estremo su friacuteo del agravio a la espada tenieacutendolapor aca y maacutes que soacutelo se trueca y con el cual encendiacutea el ejemplo deaquellos cazadores

Para este ejemplo se dejoacute la puntuacioacuten anexa a las palabras El resultadoes casi sintaacutecticamente correcto Semaacutenticamente casi tiene sentido perono del todo

iquestQueacute sucede si aumenta la longitud del prefijo iquestEl texto aleatorio tiene maacutessentido

3 Una vez que su programa esteacute funcionando podriacutea probar combinandotexto de dos o maacutes libros El texto aleatorio que genere combinaraacute elvocabulario y las frases de las fuentes de maneras interesantes

Creacutedito Este estudio de caso se basa en un ejemplo de Kernighan y Pike ThePractice of Programming Addison-Wesley 1999

OBSERVACIOacuteN Debe hacer este ejercicio antes de continuar

180 Capiacutetulo 13 Estudio de Caso Seleccioacuten de Estructura de Datos

Estructuras de DatosUsar anaacutelisis de Markov para generar texto aleatorio es divertido pero ademaacuteseste ejercicio tiene un trasfondo la seleccioacuten de la estructura de datos En los losejercicios anteriores teniacutea que elegir

bull Coacutemo representar los prefijos

bull Coacutemo representar la coleccioacuten de los posibles sufijos

bull Coacutemo representar la asociacioacuten de cada prefijo con la coleccioacuten de posiblessufijos

El uacuteltimo es faacutecil un diccionario es la opcioacuten obvia para una asociacioacuten entreclaves y valores correspondientes

Para los prefijos las opciones maacutes obvias son cadena arreglo de cadenas o tuplade cadenas

Para los sufijos puede ser un arreglo o un histograma (diccionario)

iquestCoacutemo se elige El primer paso es pensar en las operaciones que deberaacuteimplementar para cada estructura de datos Para los prefijos se debe ser capazde eliminar palabras del principio y agregarlas al final Por ejemplo si el prefijoactual es que piense y la siguiente palabra es que debe poder formar elsiguiente prefijo piense que

Para los prefijos podriacutea elegir un arreglo ya que en eacutel es faacutecil agregar y eliminarelementos

Para la coleccioacuten de sufijos las operaciones que se deben realizar incluyenagregar un nuevo sufijo (o aumentar la frecuencia de uno existente) y elegir unsufijo aleatorio

Agregar un nuevo sufijo es igualmente faacutecil para la implementacioacuten del arreglo odel histograma Elegir un elemento aleatorio de un arreglo es faacutecil pero elegireficientemente de un histograma es maacutes difiacutecil (ver Seccioacuten 1371)

Hasta ahora se ha hablado principalmente sobre la facilidad de implementacioacutenpero hay otros factores a considerar al elegir las estructuras de datos Uno es eltiempo de ejecucioacuten A veces hay una razoacuten teoacuterica para esperar que unaestructura de datos sea maacutes raacutepida que otra Por ejemplo anteriormente semencionoacute que el operador in es maacutes raacutepido para los diccionarios que para losarreglos al menos cuando el nuacutemero de elementos es grande

Aunque generalmente no se sabe de antemano queacute implementacioacuten seraacute maacutesraacutepida una opcioacuten es implementar ambos y ver cuaacutel es mejor Este enfoque sellama benchmarking Una alternativa praacutectica es elegir la estructura de datosque sea maacutes faacutecil de implementar y luego ver si es lo suficientemente raacutepida parala aplicacioacuten prevista Si es asiacute no hay necesidad de continuar Si no hay

Estructuras de Datos 181

herramientas como el moacutedulo Profile que pueden identificar los lugares en unprograma que toman maacutes tiempo

El otro factor a considerar es el espacio de almacenamiento Por ejemplo usar unhistograma para la coleccioacuten de sufijos puede tomar menos espacio porque solotiene que almacenar cada palabra una vez sin importar cuaacutentas veces aparezcaen el texto En algunos casos ahorrar espacio tambieacuten puede hacer que suprograma se ejecute maacutes raacutepido En el peor de los casos su programa podriacutea noejecutarse si se queda sin memoria pero para muchas aplicaciones el espacio esuna consideracioacuten secundaria despueacutes del tiempo de ejecucioacuten

Una uacuteltima reflexioacuten en esta discusioacuten se ha dado a entender que se deberiacuteausar una estructura de datos para el anaacutelisis y la generacioacuten Pero dado queestas son fases separadas tambieacuten seriacutea posible usar una estructura para elanaacutelisis y luego convertirla en otra estructura para la generacioacuten Esto seriacuteaconveniente si el tiempo ahorrado durante la generacioacuten excede el tiempodedicado a la conversioacuten

OBSERVACIOacuteNEl paquete de Julia DataStructures (verhttpsgithubcomJuliaCollectionsDataStructuresjl)implementa una variedad de estructuras de datos

DepuracioacutenCuando estaacute depurando un programa y especialmente si estaacute tratando deresolver un error difiacutecil hay cinco cosas que puede probar

LeeExamine su coacutedigo leacutealo y verifique que dice lo que queriacutea decir

EjecutaExperimente haciendo cambios y ejecutando diferentes versiones Amenudo si muestra lo correcto en el lugar correcto del programa elproblema se vuelve obvio pero para ello a veces tiene que desarrollarandamiaje

ReflexionaiexclToacutemese un tiempo para pensar iquestQueacute tipo de error es de sintaxis tiempode ejecucioacuten o semaacutentica iquestQueacute informacioacuten puede obtener de los mensajesde error o de la salida del programa iquestQueacute tipo de error podriacutea causar elproblema que estaacutes viendo iquestQueacute cambioacute antes de que apareciera elproblema

HablaSi le explica el problema a otra persona a veces puede encontrar larespuesta incluso antes de terminar de hacer la pregunta Generalmente no

182 Capiacutetulo 13 Estudio de Caso Seleccioacuten de Estructura de Datos

es necesaria otra persona incluso se podriacutea hablar con un pato de gomaEste es el origen de la conocida estrategia llamada depuracioacuten del pato degoma Esto es real vea httpsenwikipediaorgwikiRubber_duck_debugging

Vuelve atraacutesEn ocasiones lo mejor que puede hacer es retroceder deshacer los cambiosrecientes hasta regresar a un programa que funcione y que comprenda Unavez logrado esto puede comenzar a reconstruir

Los programadores principiantes a veces se atascan en una de estas actividadesy olvidan las otras Cada actividad viene con su propia forma de fallar

Por ejemplo leer su coacutedigo podriacutea ayudar si el problema es un error tipograacuteficopero no si el problema es un malentendido conceptual Si no comprende lo quehace su programa puede leerlo 100 veces y nunca ver el error porque el errorestaacute en su cabeza

Ejecutar experimentos puede ayudar especialmente si ejecuta pruebas pequentildeasy simples pero si ejecuta experimentos sin pensar o leer su coacutedigo puede caeren un patroacuten llamado programacioacuten de caminata aleatoria que es el proceso dehacer cambios aleatorios hasta que el programa haga lo correcto No hace faltadecir que la programacioacuten de caminata aleatoria puede llevar mucho tiempo

La persona que programa tiene que tomarse su tiempo para pensar Ladepuracioacuten es como una ciencia experimental Debe tener al menos una hipoacutetesissobre la causa del problema Si hay dos o maacutes opciones trate de pensar en unaprueba que elimine una de ellas

Incluso las mejores teacutecnicas de depuracioacuten fallaraacuten si hay demasiados errores osi el coacutedigo que estaacute tratando de corregir es demasiado grande y complicado Aveces la mejor opcioacuten es volver atraacutes simplificando el programa hasta quellegue a algo que funcione y que comprenda

Los programadores principiantes a menudo son reacios a volver atraacutes porque nopueden soportar eliminar una liacutenea de coacutedigo (incluso si es incorrecto) Si le hacesentir mejor copie su programa en otro archivo antes de comenzar a eliminarloLuego puede copiar las piezas una por una

Encontrar un error difiacutecil requiere leer ejecutar reflexionar y a veces volveratraacutes Si se queda atascado en una de estas actividades pruebe las otras

Glosariodeterminiacutestico

Perteneciente a un programa que hace lo mismo cada vez que se ejecuta apartir de las mismas entradas

Glosario 183

pseudoaleatorioPerteneciente a una secuencia de nuacutemeros que parecen ser aleatorios peroque son generados por un programa determinista

valor por defecto (o valor por omisioacuten)El valor dado a un paraacutemetro opcional si no se proporciona un argumento

anularReemplazar un valor por defecto con un argumento

benchmarkingEl proceso de elegir entre estructuras de datos implementando alternativasy probaacutendolas con una muestra de las posibles entradas

depuracioacuten del pato de gomaDepuracioacuten en doacutende se explica el problema a un objeto inanimado talcomo un pato de goma Articular el problema puede ayudarle a resolverloincluso si el pato de goma no sabe de Julia

Ejercicios

Ejercicio 13-9

El rango de una palabra es su posicioacuten en un arreglo de palabras ordenadaspor frecuencia la palabra maacutes comuacuten tiene rango 1 la segunda maacutes comuacuten tienerango 2 etc

La ley de Zipf describe una relacioacuten entre los rangos y las frecuencias de laspalabras en idiomas naturales (httpsenwikipediaorgwikiZipfs_law)Especiacuteficamente predice que la frecuencia de la palabra con rango es

donde y son paraacutemetros que dependen del idioma y el texto Si aplicaslogaritmo a ambos lados de esta ecuacioacuten obtienes

Entonces si se grafica versus se deberiacutea obtener una liacutenea recta conpendiente e intercepto

Escriba un programa que lea un texto de un archivo cuente las frecuencias delas palabras e imprima una liacutenea para cada palabra en orden descendente defrecuencia con y

Instale una libreriacutea para graficar

184 Capiacutetulo 13 Estudio de Caso Seleccioacuten de Estructura de Datos

(v10) pkggt add Plots

Su uso es muy sencillo

using Plotsx = 110y = x^2plot(x y)

Use la libreriacutea Plots para graficar los resultados y verificar si forman una liacutenearecta

Ejercicios 185

Capiacutetulo 14 ArchivosEste capiacutetulo presenta el concepto de persistencia que alude a los programasque mantienen los datos en almacenamiento permanente y muestra coacutemo usardiferentes tipos de almacenamiento permanente tales como archivos y bases dedatos

PersistenciaLa mayoriacutea de los programas que hemos visto hasta ahora han sido transitorioses decir se ejecutan por un tiempo corto y generan una salida pero cuandofinalizan sus datos desaparecen Si ejecuta el programa nuevamente estecomienza de cero

Otros programas en cambio son persistentes se ejecutan durante un largoperiacuteodo de tiempo (o todo el tiempo) mantienen al menos parte de sus datos enalmacenamiento permanente (en un disco duro por ejemplo) y si se apagan yvuelven a comenzar retoman donde lo dejaron

Ejemplos de programas persistentes son los sistemas operativos que se ejecutansiempre que una computadora esteacute encendida y los servidores web que seejecutan todo el tiempo esperando a que lleguen solicitudes a la red

Una de las formas maacutes simples para que los programas mantengan sus datos esleyendo y escribiendo archivos de texto Ya se han visto programas que leenarchivos de texto y en este capiacutetulo se van a ver programas que los escriben

Otra alternativa es almacenar el estado del programa en una base de datos Eneste capiacutetulo tambieacuten se presentaraacute coacutemo usar una base de datos simple

Lectura y EscrituraUn archivo de texto es una secuencia de caracteres almacenados en un mediopermanente como un disco duro o una memoria flash Ya se vio coacutemo abrir y leerun archivo en Seccioacuten 91

Para escribir un archivo debe abrirlo usando el modo w (de write) comosegundo paraacutemetro

juliagt fout = open(salidatxt w)IOStream(ltfile salidatxtgt)

Si el archivo ya existe abrirlo en modo de escritura borra los datos antiguos ycomienza de nuevo iexclasiacute que tenga cuidado Si el archivo no existe se crea unonuevo open devuelve un objeto de archivo y la funcioacuten write escribe datos en elarchivo

186 Capiacutetulo 14 Archivos

juliagt linea1 = El Cid convoca a sus vasallosn

juliagt write(fout linea1)31

El valor de retorno es el nuacutemero de caracteres que se escribieron El objeto dearchivo fout lleva el registro de doacutende se quedoacute por uacuteltima vez por lo que sillama a write nuevamente esta agrega nuevos datos al final del archivo

juliagt linea2 = eacutestos se destierran con eacuteln

juliagt write(fout linea2)30

Cuando el usuario haya terminado de escribir debe cerrar el archivo

juliagt close(fout)

Si no cierra el archivo este se cierra cuando finaliza el programa

FormateoEl argumento de write tiene que ser una cadena por lo que si queremos ponerotros valores en un archivo tenemos que convertirlos a cadenas La forma maacutesfaacutecil de hacerlo es con la funcioacuten string o con interpolacioacuten de cadenas

juliagt fout = open(salidatxt w)IOStream(ltfile salidatxtgt)juliagt write(fout string(150))3

Otra alternativa es utilizar la familia de funciones de print(ln)

juliagt camellos = 4242juliagt println(fout He visto $camellos camellos)

OBSERVACIOacuteN

Una alternativa maacutes potente es la macro printf queimprime utilizando cadenas con especificacioacuten deformato al maacutes puro estilo C Puede leer maacutes sobre estoen httpsdocsjulialangorgenv1stdlibPrintf

Formateo 187

Nombre de Archivo y RutaLos archivos estaacuten organizados en directorios (tambieacuten llamados carpetas)Cada programa en ejecucioacuten tiene su propio directorio actual que es eldirectorio que usaraacute por defecto para para la mayoriacutea de las operaciones Porejemplo cuando abre un archivo para leer Julia lo busca en el directorio actual

La funcioacuten pwd (en ingleacutes print working directory) devuelve el nombre deldirectorio actual

juliagt cwd = pwd()homeben

cwd significa directorio del trabajo actual (en ingleacutes ldquocurrent workingdirectoryrdquo) El resultado en este ejemplo es homeben que es el directorio deinicio de un usuario llamado ben

Una cadena como homeben que identifica un archivo o directorio se llamaruta o path

Un nombre de archivo simple como memotxt tambieacuten se considera una rutaaunque es una ruta relativa porque comienza en el directorio actual Si eldirectorio actual es homeben el nombre de archivo memotxt se refiere ahomebenmemotxt

Una ruta que comienza con no depende del directorio actual Este tipo de rutase llama ruta absoluta Para encontrar la ruta absoluta de un archivo puede usarabspath

juliagt abspath(memotxt)homebenmemotxt

Julia tambieacuten tiene otras funciones para trabajar con nombres de archivo y rutasPor ejemplo ispath comprueba si existe un archivo o directorio

juliagt ispath(memotxt)true

Si existe isdir comprueba si es un directorio

juliagt isdir(memotxt)falsejuliagt isdir(homeben)true

188 Capiacutetulo 14 Archivos

Del mismo modo isfile comprueba que se trate de un archivo

readdir devuelve un arreglo de los archivos (y otros directorios) en el directoriodado

juliagt readdir(cwd)3-element ArrayString1 memotxt musica fotos

Para mostrar el comportamiento de estas funciones el siguiente ejemplorecorre un directorio imprime los nombres de todos los archivos y se llama a siacutemisma de manera recursiva en todos los directorios

function recorrer(nombredir) for nombre in readdir(nombredir) ruta = joinpath(nombredir nombre) if isfile(ruta) println(ruta) else recorrer(ruta) end endend

joinpath toma un directorio y un nombre de archivo y los une en una rutacompleta

OBSERVACIOacuteN

Julia tiene una funcioacuten integrada llamada walkdir (veahttpsdocsjulialangorgenv1basefileBaseFilesystemwalkdir) que es similar a esta pero maacutesversaacutetil Como ejercicio lea la documentacioacuten y uacuteselapara imprimir los nombres de los archivos en undirectorio dado y sus subdirectorios

Captura de ExcepcionesMuchas cosas pueden salir mal al intentar leer y escribir archivos Al intentarabrir un archivo que no existe se obtiene un SystemError

juliagt fin = open(archivo_malo)ERROR SystemError opening file archivo_malo No such file or directory

Si el usuario intenta abrir un archivo pero no tiene permiso para acceder a eacutel

Captura de Excepciones 189

obtiene el error de sistema Permission denied (Permiso denegado)

Para evitar estos errores se podriacutean usar funciones como ispath e isfile perotomariacutea mucho tiempo y liacuteneas de coacutedigo verificar todas las posibilidades

Es maacutes faacutecil intentar lidiar con los problemas a medida que ocurren que esexactamente lo que hace la sentencia try La sintaxis es similar a una sentenciaif

try fin = open(archivo_malotxt)catch exc println(Algo salioacute mal $exc)end

Julia comienza ejecutando el bloque try Si nada falla se saltaraacute el bloque catch yfinalizaraacute Si ocurre una excepcioacuten Julia saltaraacute fuera del bloque try y ejecutaraacuteel bloque catch

Gestionar una excepcioacuten con try recibe el nombre de capturar una excepcioacuten Eneste ejemplo el bloque catch muestra un mensaje de error que no es muy uacutetil Engeneral capturar una excepcioacuten da la oportunidad de corregir el problemavolverlo a intentar o al menos terminar el programa con elegancia

Cuando el coacutedigo realiza cambios de estado o usa recursos como archivosgeneralmente se deben hacer ciertas cosas al finalizar la programacioacuten delcoacutedigo como por ejemplo cerrar los archivos Las excepciones pueden complicaresta tarea ya que se podriacutea salir antes de lo esperado de un bloque de coacutedigo Lapalabra reservada finally permite ejecutar un coacutedigo al salir de un bloque decoacutedigo determinado independientemente de coacutemo salga

f = open(salidatxt)try linea = readline(f) println(linea)finally close(f)end

En este ejemplo la funcioacuten close siempre se ejecutaraacute

Bases de datosUna base de datos es un archivo que estaacute organizado para almacenar datos Lamayoriacutea de las bases de datos estaacuten organizadas como diccionarios en el sentidode que realizan asociaciones entre claves y valores La diferencia maacutes importanteentre un diccionario y una base de datos es que la base de datos se encuentra en

190 Capiacutetulo 14 Archivos

el disco (u otro almacenamiento permanente) de modo que su contenido seconserva despueacutes de que el programa haya finalizado

IntroAJulia proporciona una interfaz para GDBM (GNU dbm) que permite creary actualizar archivos de base de datos A modo de ejemplo se crea una base dedatos que contiene pies de foto para archivos de imagen

Abrir una base de datos es similar a abrir otros archivos

juliagt using IntroAJulia

juliagt bd = DBM(piedefoto c)DBM(ltpiedefotogt)

El modo c significa que la base de datos debe crearse si no existe El resultadoes un objeto de base de datos que se puede usar (para la mayoriacutea de lasoperaciones) como un diccionario

Cuando se crea un nuevo elemento GDBM actualiza el archivo de base de datos

juliagt bd[luismipng] = Foto de Luis MiguelFoto de Luis Miguel

Cuando accede a uno de los elementos GDBM lee el archivo

juliagt bd[luismipng]Foto de Luis Miguel

Si realiza otra asignacioacuten a una clave existente GDBM reemplaza el valoranterior

juliagt bd[luismipng] = Foto de Luis Miguel cantandoFoto de Luis Miguel cantandojuliagt bd[luismipng]Foto de Luis Miguel cantando

Algunas funciones que tienen un diccionario como argumento con claves yvalores no funcionan con objetos de base de datos No obstante la iteracioacuten conun bucle for siacute

for (clave valor) in bd println(clave valor)end

Al igual que con otros archivos debe cerrar la base de datos cuando haya

Bases de datos 191

terminado

juliagt close(bd)

SerializacioacutenUna limitacioacuten de GDBM es que las claves y los valores deben ser cadenas oconjuntos de bytes Si intenta utilizar cualquier otro tipo se produciraacute un error

Las funciones serialize y deserialize pueden ser uacutetiles Traducen casi cualquiertipo de objeto en un arreglo de bytes (un iobuffer) adecuado para elalmacenamiento en una base de datos y luego traducen los arreglos de bytesnuevamente en objetos

juliagt using Serialization

juliagt io = IOBuffer()

juliagt t = [1 2 3]

juliagt serialize(io t)24juliagt print(take(io))UInt8[0x37 0x4a 0x4c 0x0a 0x04 0x00 0x00 0x00 0x15 0x00 0x080xe2 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x02 0x00 0x000x00 0x00 0x00 0x00 0x00 0x03 0x00 0x00 0x00 0x00 0x00 0x000x00]

El formato no es intuitivo para nosotros pero es faacutecil de interpretar para Juliadeserialize reconstituye el objeto

juliagt io = IOBuffer()

juliagt t1 = [1 2 3]

juliagt serialize(io t1)24juliagt s = take(io)

juliagt t2 = deserialize(IOBuffer(s))

juliagt print(t2)[1 2 3]

serialize y deserialize escriben y leen desde un objeto iobuffer que representa unIO stream en memoria La funcioacuten take recupera el contenido del iobuffer como

192 Capiacutetulo 14 Archivos

un arreglo de bytes y reestablece el iobuffer a su estado inicial

Aunque el nuevo objeto tiene el mismo valor que el anterior no es (en general) elmismo objeto

juliagt t1 == t2truejuliagt t1 equiv t2false

En otras palabras la serializacioacuten y luego la deserializacioacuten tienen el mismoefecto que copiar el objeto

Esto se puede usar para almacenar valores que no sean cadenas en una base dedatos

OBSERVACIOacuteN

De hecho el almacenamiento de valores que no soncadenas en una base de datos es tan comuacuten que se haencapsulado en un paquete llamado JLD2 (consultehttpsgithubcomJuliaIOJLD2jl)

Objetos de ComandoLa mayoriacutea de los sistemas operativos proporcionan una interfaz de liacutenea decomandos tambieacuten conocida como shell Las shells generalmente proporcionancomandos para navegar por el sistema de archivos y ejecutar aplicaciones Porejemplo en Unix puede cambiar los directorios con cd mostrar el contenido deun directorio con ls e iniciar un navegador web escribiendo (por ejemplo) firefox

Cualquier programa que se pueda iniciar desde la shell tambieacuten puede iniciarsedesde Julia usando un objeto de comando

juliagt cmd = `echo hola``echo hola`

Las comillas invertidas se usan para delimitar el comando

La funcioacuten run ejecuta el comando

juliagt run(cmd)hola

hola es la salida del comando echo enviado a STDOUT La funcioacuten run devuelveun objeto de proceso y genera un ErrorException si el comando externo no se

Objetos de Comando 193

ejecuta correctamente

Si se desea leer la salida del comando externo se puede usar read en su lugar

juliagt a = read(cmd String)holan

Por ejemplo la mayoriacutea de los sistemas Unix tienen un comando llamadomd5sum o md5 que lee el contenido de un archivo y calcula una suma deverificacioacuten Puede leer sobre Md5 en httpsenwikipediaorgwikiMd5 Estecomando proporciona una manera eficiente de verificar si dos archivos tienen elmismo contenido La probabilidad de que diferentes contenidos produzcan lamisma suma de comprobacioacuten es muy pequentildea

Puede usar un objeto de comando para ejecutar md5 desde Julia y obtener elresultado

juliagt nombrearchivo = salidatxtsalidatxtjuliagt cmd = `md5 $nombrearchivo``md5 salidatxt`juliagt res = read(cmd String)ERROR IOError could not spawn `md5 salidatxt` no such file ordirectory (ENOENT)

Modulos

Supongamos que tenemos un archivo llamado wcjl con el siguiente coacutedigo

function contarlineas(nombrearchivo) conteo = 0 for linea in eachline(nombrearchivo) conteo += 1 end conteoend

print(contarlineas(wcjl))

Si ejecuta este programa se leen las liacuteneas de coacutedigo y se imprime el nuacutemero deliacuteneas en el archivo que es 9 Tambieacuten puede incluirlo en REPL de esta manera

juliagt include(wcjl)9

194 Capiacutetulo 14 Archivos

Los moacutedulos permiten crear espacios de trabajo separados es decir nuevosglobal scopes (aacutembitos de tipo global) Una sentencia tiene global scope si tieneefecto en todo el programa

Un moacutedulo comienza con la palabra reservada module y termina con end Al usarmoacutedulos se evitan los conflictos de nombres entre sus propias definiciones denivel superior y las que se encuentran en el coacutedigo de otra persona importpermite controlar queacute nombres de otros moacutedulos estaacuten visibles y exportespecifica cuaacuteles de sus nombres son puacuteblicos es decir aquellos que se puedenusar fuera del moacutedulo sin tener el prefijo del nombre del moacutedulo

module ContarLineas export contarlineas

function contarlineas(nombrearchivo) conteo = 0 for linea in eachline(nombrearchivo) conteo += 1 end conteo endend

El moacutedulo ContarLineas proporciona la funcioacuten contarlineas

juliagt using ContarLineas

juliagt contarlineas(wcjl)11

Ejercicio 14-1

Escriba este ejemplo en un archivo llamado wcjl incluacuteyalo en REPL (coninclude) y escriba using ContarLineas

AVISO

Si importa un moacutedulo que ya se ha importado Julia no hace nadaNo se vuelve a leer el archivo incluso si ha sido modificado

Si desea volver a cargar un moacutedulo debe reiniciar REPL Elpaquete Revise puede ayudarlo a no reiniciar tan seguido (veahttpsgithubcomtimholyRevisejl)

DepuracioacutenAl leer y escribir archivos el usuario puede tener problemas con los espacios enblanco Estos errores pueden ser difiacuteciles de depurar porque los espacios las

Depuracioacuten 195

tabulaciones y las nuevas liacuteneas son generalmente invisibles

juliagt s = 1 2t 3n 4

juliagt println(s)1 2 3 4

Las funciones integradas repr o dump pueden ser de ayuda Toman cualquierobjeto como argumento y devuelven una representacioacuten de tipo cadena delobjeto

1 2t 3n 4

juliagt repr(s)1 2t 3n 4juliagt dump(s)String 1 2t 3n 4

Esto puede ser uacutetil para la depuracioacuten

Otro problema con el que es faacutecil encontrarse es que en diferentes sistemasoperativos se usan diferentes caracteres para indicar el final de una liacuteneaAlgunos sistemas usan una nueva liacutenea representada por n Otros usan uncaraacutecter de retorno r Algunos usan ambos Si un archivo es usado en diferentessistemas estas inconsistencias podriacutean causar problemas

Para la mayoriacutea de los sistemas hay aplicaciones para convertir de un formato aotro Puede encontrarlas (y leer maacutes sobre este tema) enhttpsenwikipediaorgwikiNewline O por supuesto podriacutea escribir una ustedmismo

Glosariopersistente

Perteneciente a un programa que se ejecuta indefinidamente y mantiene almenos algunos de sus datos en almacenamiento permanente

archivo de textoUna secuencia de caracteres almacenados en almacenamiento permanentetal como en un disco duro

directorioUna coleccioacuten de archivos con nombre tambieacuten llamada carpeta

196 Capiacutetulo 14 Archivos

rutaUna cadena que identifica a un archivo

ruta relativaUna ruta que comienza en el directorio actual

ruta absolutaUna ruta que comienza en el directorio superior del sistema de archivos

capturar (catch)Evitar que una excepcioacuten haga terminar un programa utilizando lassentencias try catch finally

base de datosUn archivo cuyo contenido estaacute organizado como un diccionario con clavesque corresponden a valores

shellUn programa que permite a los usuarios escribir comandos y luegoejecutarlos iniciando otros programas

objeto de comandoUn objeto que representa un comando de shell Esto permite que unprograma de Julia ejecute comandos y lea los resultados

Ejercicios

Ejercicio 14-2

Escriba una funcioacuten llamada sed que tome como argumentos una cadena depatrones una cadena de reemplazo y dos nombres de archivo La funcioacuten debeleer el primer archivo y escribir el contenido en el segundo archivo (creaacutendolo sies necesario) Si la cadena de patrones aparece en alguacuten lugar del archivo debereemplazarse con la cadena de reemplazo

Si se produce un error al abrir leer escribir o cerrar los archivos su programadebe detectar la excepcioacuten imprimir un mensaje de error y terminar

Ejercicio 14-3

Si hizo Seccioacuten 12102 recordaraacute que debiacutea crear un diccionario que asociabauna cadena ordenada de letras al conjunto de palabras que se podiacutea deletrearcon esas letras Por ejemplo cuaderno estaba asociado al arreglo [cuadernoeducaron encuadro]

Escriba un moacutedulo que importe conjuntoanagramas y proporcione dos nuevas

Ejercicios 197

funciones almacenaranagramas que almacena el diccionario de anagramasusando JLD2 (vea httpsgithubcomJuliaIOJLD2jl) y leeranagramas que buscauna palabra y devuelve un arreglo de sus anagramas

Ejercicio 14-4

En una gran coleccioacuten de archivos MP3 puede haber maacutes de una copia de lamisma cancioacuten almacenada en diferentes directorios o con diferentes nombresde archivo El objetivo de este ejercicio es buscar duplicados

1 Escriba un programa que busque un directorio y todos sus subdirectoriosde forma recursiva y devuelva un arreglo de rutas completas para todos losarchivos con un sufijo dado (como mp3)

2 Para reconocer duplicados puede usar md5sum o md5 para calcular unasuma de verificacioacuten para cada archivo Si dos archivos tienen la mismasuma de verificacioacuten probablemente tengan el mismo contenido

3 Para verificarlo puede usar el comando de Unix diff

198 Capiacutetulo 14 Archivos

Capiacutetulo 15 Estructuras y ObjetosA esta altura ya debe saber coacutemo usar funciones para tener un coacutedigo maacutesorganizado y coacutemo usar los tipos integrados de Julia para organizar sus datos Elsiguiente paso es aprender a construir sus propios tipos para organizar tanto elcoacutedigo como los datos Este es un gran tema y por lo tanto tomaraacute un par decapiacutetulos abarcar todo

Tipos CompuestosSe han utilizado muchos tipos integrados en Julia y ahora se va a definir unnuevo tipo A modo de ejemplo se crea un tipo llamado Punto que representa unpunto en un espacio bidimensional

En notacioacuten matemaacutetica los puntos suelen escribirse entre pareacutentesis con unacoma que separa las coordenadas Por ejemplo representa el origen y representa el punto localizado unidades a la derecha y unidades hacia arribadel origen

Hay varias formas en que se podriacutean representar puntos del plano cartesiano enJulia

bull Almacenando las coordenadas por separado en dos variables x e y

bull Almacenando las coordenadas como elementos de un arreglo o tupla

bull Creando un nuevo tipo para representar puntos como objetos

Crear un nuevo tipo exige un poco maacutes de esfuerzo que las otras dos opcionespero tiene algunas ventajas como pronto se veraacute

Un tipo compuesto definido por el programador tambieacuten se denomina estructura(struct en ingleacutes) La definicioacuten de estructura de un punto se ve asiacute

struct Punto x yend

El encabezado indica que la nueva estructura se llama Punto El cuerpo definelos atributos o campos de la estructura La estructura de Punto tiene doscampos x e y

Una estructura es como una faacutebrica que crea objetos Para crear un punto sedebe llamar a Punto como si fuera una funcioacuten que tiene como argumentos losvalores de los campos Cuando Punto se usa como una funcioacuten se llamaconstructor

Tipos Compuestos 199

juliagt p = Punto(30 40)Punto(30 40)

El valor de retorno es una referencia a un objeto Punto el cual es asignado a p

La creacioacuten de un nuevo objeto se llama instanciacioacuten y el objeto creado es unainstancia del tipo

Cuando se imprime una instancia Julia dice a queacute tipo pertenece y cuaacuteles son losvalores de los atributos

Cada objeto es una instancia de alguacuten tipo por lo que objeto e instancia sonintercambiables No obstante en este capiacutetulo se utiliza instancia para indicarque se estaacute hablando de un tipo definido por el programador

Un diagrama de estado que muestra un objeto y sus atributos se denominadiagrama de objeto (ver Figura 20)

Figura 20 Diagrama de objeto

Las Estructuras son Inmutables

Puede obtener los valores de los campos utilizando la notacioacuten

juliagt x = px30juliagt py40

La expresioacuten px significa Vaya al objeto al que se apunta p y obtenga el valorde x En el ejemplo se asigna ese valor a una variable llamada x No hayconflicto entre la variable x y el atributo x

Puede usar esa notacioacuten de punto como parte de cualquier expresioacuten Porejemplo

juliagt distancia = sqrt(px^2 + py^2)50

Sin embargo las estructuras son inmutables por defecto y despueacutes de laconstruccioacuten los campos no pueden cambiar su valor

200 Capiacutetulo 15 Estructuras y Objetos

juliagt py = 10ERROR setfield immutable struct of type Punto cannot be changed

Esto puede parecer extrantildeo al principio pero tiene varias ventajas

bull Puede ser maacutes eficiente

bull No es posible violar las invariantes (requisitos que deberiacutean cumplirse entodos los objetos en todo momento) de los constructores de un tipocompuesto (ver Seccioacuten 174)

bull El coacutedigo que usa objetos inmutables puede ser maacutes faacutecil de entender

Estructuras MutablesDe ser necesario se pueden declarar tipos compuestos mutables con la palabrareservada mutable struct A continuacioacuten se muestra la definicioacuten de un puntomutable

mutable struct MPunto x yend

Puede asignar valores a una instancia de una estructura mutable utilizandonotacioacuten de punto ()

juliagt blanco = MPunto(00 00)MPunto(00 00)juliagt blancox = 3030juliagt blancoy = 4040

RectaacutengulosA veces decidir cuaacuteles deberiacutean ser los campos de un objeto es faacutecil pero enotros casos no Por ejemplo imagine que se quiere un tipo que represente unrectaacutengulo iquestQueacute campos usariacutea para especificar la ubicacioacuten y el tamantildeo de unrectaacutengulo Puede ignorar el aacutengulo Para simplificar las cosas suponga que elrectaacutengulo es vertical u horizontal

Hay al menos dos posibilidades

bull Puede especificar una esquina del rectaacutengulo (o el centro) el ancho y laaltura

Estructuras Mutables 201

bull Puede especificar dos esquinas opuestas

Es difiacutecil decir que una opcioacuten es mejor que la otra por lo que implementaremosla primera a modo de ejemplo

Representa un rectaacutengulo

atributos ancho alto esquinastruct Rectangulo ancho alto esquinaend

El texto escrito entre comillas triples es llamado cadena de documentacioacuten (odocstring) y permite documentar La documentacioacuten es el acto de comentarconvenientemente cada una de las partes que tiene el programa

En este ejemplo la cadena de documentacioacuten (o docstring) enumera losatributos Los atributos ancho y alto son nuacutemeros y esquina es un objeto Puntoque especifica la esquina inferior izquierda

Para representar un rectaacutengulo debe crear una instancia del tipo Rectangulo

juliagt origen = MPunto(00 00)MPunto(00 00)juliagt caja = Rectangulo(1000 2000 origen)Rectangulo(1000 2000 MPunto(00 00))

Figura 21 muestra el estado de este objeto Un objeto es embebido si es atributode otro objeto Debido a que el atributo esquina se refiere a un objeto mutablese dibuja fuera del objeto Rectangulo

Figura 21 Diagrama de objeto

Instancias como ArgumentosPodemos pasar una instancia como argumento de la manera habitual Porejemplo

202 Capiacutetulo 15 Estructuras y Objetos

function imprimirpunto(p) println(($(px) $(py)))end

imprimirpunto toma un Punto como argumento y lo muestra en notacioacutenmatemaacutetica Puede llamar a imprimirpunto con un argumento p

juliagt imprimirpunto(blanco)(30 40)

Ejercicio 15-1

Escriba una funcioacuten llamada distanciaentrepuntos que tome dos puntos comoargumentos y devuelva la distancia entre ellos

Si un objeto de estructura mutable se pasa a una funcioacuten como argumento lafuncioacuten puede modificar los campos del objeto Por ejemplo moverpunto tomaun objeto mutable Punto y dos nuacutemeros dx y dy los cuales suma a los atributos xe y de Punto respectivamente

function moverpunto(p dx dy) px += dx py += dy nothingend

Aquiacute hay un ejemplo que muestra como funciona

juliagt origen = MPunto(00 00)MPunto(00 00)juliagt moverpunto(origen 10 20)

juliagt origenMPunto(10 20)

Dentro de la funcioacuten p es un alias de origen por lo que cuando la funcioacutenmodifica p origen tambieacuten cambia

Al pasar un objeto inmutable Punto a moverpunto se produce un error

juliagt moverpunto(p 10 20)ERROR setfield immutable struct of type Punto cannot be changed

Sin embargo se puede modificar el valor de un atributo mutable de un objeto

Instancias como Argumentos 203

inmutable Por ejemplo moverrectangulo tiene como argumentos un objetoRectangulo y dos nuacutemeros dx y dy Esta funcioacuten usa moverpunto para mover laesquina del rectaacutengulo

function moverrectangulo(rect dx dy) moverpunto(rectesquina dx dy)end

Ahora p en moverpunto es un alias para rectesquina por lo que cuando p semodifica rectesquina tambieacuten cambia

juliagt cajaRectangulo(1000 2000 MPunto(00 00))juliagt moverrectangulo(caja 10 20)

juliagt cajaRectangulo(1000 2000 MPunto(10 20))

AVISO

No puede reasignar un atributo mutable de un objeto inmutable

juliagt cajaesquina = MPunto(10 20)ERROR setfield immutable struct of type Rectangulo cannotbe changed

Instancias como Valores de RetornoLas funciones pueden devolver instancias Por ejemplo encontrarcentro toma unRectangulo como argumento y devuelve un Punto que contiene las coordenadasdel centro del rectaacutengulo

function encontrarcentro(rect) Punto(rectesquinax + rectancho 2 rectesquinay + rectalto 2)end

La expresioacuten rectcornerx significa ldquoVaya al objeto al que rect apunta yseleccione el atributo llamado esquina Luego vaya a ese objeto y seleccione elatributo llamado x

A continucioacuten se observa un ejemplo que toma caja como argumento y asigna elPunto resultante a centro

juliagt centro = encontrarcentro(caja)Punto(510 1020)

204 Capiacutetulo 15 Estructuras y Objetos

CopiadoEl uso de alias puede hacer que un programa sea difiacutecil de leer ya que loscambios hechos en un lugar pueden tener efectos inesperados en otro lugar Esdifiacutecil estar al tanto de todas las variables a las que puede apuntar un objetodado

Copiar un objeto es muchas veces una alternativa a la creacioacuten de un alias Juliaprovee una funcioacuten llamada copy que puede duplicar cualquier objeto

juliagt p1 = MPunto(30 40)MPunto(30 40)juliagt p2 = deepcopy(p1)MPunto(30 40)juliagt p1 equiv p2falsejuliagt p1 == p2false

El operador equiv indica que p1 y p2 no son el mismo objeto lo cual es esperable Loque no es del todo esperable es que == no devuelva true aunque estos puntoscontengan los mismos datos Resulta que para los objetos mutables elcomportamiento predeterminado del operador == es el mismo que el operador=== es decir comprueba la identidad del objeto no la equivalencia del objetoEsto se debe a que Julia no sabe queacute deberiacutea considerarse equivalente para lostipos compuestos mutables Al menos no todaviacutea

Ejercicio 15-2

Cree una instancia de Punto haga una copia y verifique la equivalencia y laigualdad de ambas El resultado puede sorprenderlo pero explica por queacute elalias no es un problema para un objeto inmutable

DepuracioacutenAl comenzar a trabajar con objetos es probable que encuentre algunasexcepciones nuevas Si intenta acceder a un campo que no existe obtendraacute

juliagt p = Punto(30 40)Punto(30 40)juliagt pz = 10ERROR type Punto has no field z

Si no estaacute seguro del tipo de un objeto puede saberlo de la siguiente manera

Copiado 205

juliagt typeof(p)Punto

Tambieacuten puede usar isa para verificar si un objeto es una instancia de un tipoespeciacutefico

juliagt p isa Puntotrue

Si no estaacute seguro de si un objeto tiene un atributo particular puede usar lafuncioacuten fieldnames

juliagt fieldnames(Punto)(x y)

o la funcioacuten isdefined

juliagt isdefined(p x)truejuliagt isdefined(p z)false

El primer argumento puede ser cualquier objeto y el segundo argumento es elsiacutembolo seguido del nombre del atributo

Glosarioestructura

Un tipo compuesto

constructorUna funcioacuten con el mismo nombre que un tipo que crea instancias de estetipo

instanciaUn objeto que pertenece a un tipo

instanciarCrear un nuevo objeto

atributo o campoUn valor con nombre asociado un objeto

206 Capiacutetulo 15 Estructuras y Objetos

objeto embebidoUn objeto que se almacena como atributo de otro objeto

deep copy o copia profundaCopiar el contenido de un objeto y cualquier objeto embebido en eacutel y a suvez cualquier objeto embebido en ellos y asiacute sucesivamente Implementadopor la funcioacuten deepcopy

diagrama de objetoUn diagrama que muestra objetos sus atributos y valores de atributos

Ejercicios

Ejercicio 15-3

1 Escriba una definicioacuten de un tipo llamado Circulo que tenga atributos centroy radio y doacutende centro sea un objeto Punto y radio un nuacutemero

2 Cree una instancia de un objeto Circulo que represente a un ciacuterculo concentro en y radio 75

3 Escriba una funcioacuten llamada puntoencirculo que tome un objeto Circulo y unobjeto Punto y devuelva true si el punto se encuentra dentro o en el liacutemitedel ciacuterculo

4 Escriba una funcioacuten llamada rectencirculo que tome un objeto Circulo y unobjeto Rectangulo y devuelva true si el rectaacutengulo se encuentracompletamente dentro o en el liacutemite del ciacuterculo

5 Escriba una funcioacuten llamada sobreposicionrectcirc que tome un objetoCirculo y un objeto Rectangulo y devuelva true si alguna de las esquinas delrectaacutengulo cae dentro del ciacuterculo Una versioacuten maacutes desafiante es escribiruna funcioacuten que devuelva true si alguna parte del rectaacutengulo (nonecesariamente una esquina) cae dentro del ciacuterculo

Ejercicio 15-4

1 Escriba una funcioacuten llamada dibujarrect que tome como argumentos unobjeto turtle y un objeto Rectaacutengulo y use turtle para dibujar el rectaacutenguloConsulte el Capiacutetulo 4 para ver ejemplos que usen objetos Turtle

2 Escriba una funcioacuten llamada dibujarcirculo que tome como argumentos unobjeto Turtle y un objeto Circulo y dibuje el ciacuterculo

Ejercicios 207

Capiacutetulo 16 Estructuras y FuncionesAhora que se ha tratado coacutemo crear tipos compuestos el siguiente paso esescribir funciones que tomen objetos definidos por el programador comoparaacutemetros y que devuelvan otros como resultados En este capiacutetulo tambieacuten sepresenta el estilo de programacioacuten funcional y dos nuevas formas dedesarrollar programas

TiempoComo otro ejemplo de tipo compuesto se define una estructura llamada Horaque registra la hora del diacutea La definicioacuten de esta estructura se muestra acontinuacioacuten

Representa la hora del diacutea

atributos hora minuto segundostruct Hora hora minuto segundoend

Observacioacuten Time es una palabra reservada de Julia

juliagt tiempo = Hora(11 59 30)Hora(11 59 30)

El diagrama de objeto para el objeto Hora luce asiacute Figura 22

Figura 22 Diagrama de objeto

Ejercicio 16-1

Escriba una funcioacuten llamada imprimirhora que tome un objeto Hora y lo imprimacon el formato horaminutosegundo Printf de la macro printf del moacuteduloStdLib permite imprimir un nuacutemero entero con el formato 02d es decirutilizando al menos dos diacutegitos incluido un cero inicial si es necesario

208 Capiacutetulo 16 Estructuras y Funciones

Ejercicio 16-2

Escriba una funcioacuten booleana llamada estadespues que tome dos objetos Horat1 y t2 y devuelva true si la hora t1 estaacute despueacutes que t2 y false de lo contrarioDesafiacuteo no use sentencias if

Funciones PurasEn las siguientes secciones se escriben dos versiones de una funcioacuten que calculala suma de horas La primera versioacuten muestra un tipo de funcioacuten llamado funcioacutenpura y la segunda un tipo llamado modificador Ademaacutes estas versionespermitiraacuten mostrar un nuevo plan de desarrollo de programas llamado desarrollode prototipos una forma de abordar un problema complejo comenzando con unprototipo simple y lidiando gradualmente con las complicaciones

Este es un primer prototipo de la funcioacuten sumahora

function sumahora(t1 t2) Hora(t1hora + t2hora t1minuto + t2minuto t1segundo +t2segundo)end

La funcioacuten crea un nuevo objeto Hora inicializa sus atributos y devuelve unareferencia al nuevo objeto A esto se le llama funcioacuten pura porque no modificaninguno de los objetos que se le pasan como argumento y no tiene efectos (comomostrar un valor o tomar una entrada del usuario) maacutes que devolver un valor

Para probar esta funcioacuten se crean dos objetos Hora inicio que contiene la horade inicio de una peliacutecula como Roma y duracion que contiene la duracioacuten de lapeliacutecula que es dos horas y 15 minutos

sumahora calcula cuaacutendo se terminaraacute la peliacutecula

imprimirhora (generic function with 1 method)

juliagt inicio = Hora(9 50 0)

juliagt duracion = Hora(2 15 0)

juliagt finaliza = sumahora(inicio duracion)

juliagt imprimirhora(finaliza)116500

El resultado 116500 no es lo que se buscaba El problema es que esta funcioacuten

Funciones Puras 209

no considera los casos en los que el nuacutemero de segundos o minutos suma maacutesque sesenta Cuando esto ocurre debemos acarrear (como en una suma) lossegundos sobrantes a la columna de los minutos o los minutos extras a lacolumna de las horas He aquiacute una versioacuten corregida de la funcioacuten

function sumahora(t1 t2) segundo = t1segundo + t2segundo minuto = t1minuto + t2minuto hora = t1hora + t2hora if segundo gt= 60 segundo -= 60 minuto += 1 end if minuto gt= 60 minuto -= 60 hora += 1 end Hora(hora minuto segundo)end

Aunque esta funcioacuten es correcta es muy larga Maacutes adelante se exploraraacute unaalternativa maacutes corta

ModificadoresHay veces en las que es uacutetil que una funcioacuten modifique uno o maacutes de los objetosque recibe como paraacutemetros En ese caso los cambios son visibles en el nivel endonde se ubica la sentencia de llamada Estas funciones se llaman modificadores

La funcioacuten incrementar que agrega un nuacutemero dado de segundos a un objetoHora puede escribirse naturalmente como un modificador Aquiacute se muestra unprototipo de la funcioacuten

function incrementar(tiempo segundos) tiemposegundo += segundos if tiemposegundo gt= 60 tiemposegundo -= 60 tiempominute += 1 end if tiempominuto gt= 60 tiempominuto -= 60 tiempohora += 1 endend

La primera liacutenea realiza la suma de los segundos y las restantes se ocupan de los

210 Capiacutetulo 16 Estructuras y Funciones

casos especiales vistos anteriormente

iquestEs correcta esta funcioacuten iquestQueacute ocurre si el paraacutemetro segundos es muchomayor que sesenta

En tal caso no es suficiente con acarrear una vez debemos seguir hacieacutendolohasta que tiemposegundo sea menor que sesenta Una solucioacuten es sustituir lassentencias if por sentencias while Esta funcioacuten seriacutea correcta pero no es lasolucioacuten maacutes eficiente

Ejercicio 16-3

Escriba una versioacuten correcta de incrementar sin bucles

Todo lo que se pueda hacer con modificadores tambieacuten puede lograrse confunciones puras De hecho algunos lenguajes de programacioacuten solo permitenfunciones puras Hay ciertas evidencias de que los programas que usanfunciones puras son maacutes raacutepidos de desarrollar y menos propensos a errores quelos programas que usan modificadores Sin embargo a veces los modificadoresson uacutetiles y en algunos casos los programas funcionales (es decir con funcionespuras) tienden a ser menos eficientes

En general recomendamos que escriba funciones puras siempre que searazonable y recurra a los modificadores soacutelo si hay una ventaja convincente Esteenfoque podriacutea llamarse estilo de programacioacuten funcional

Ejercicio 16-4

Escriba una versioacuten pura de incrementar que cree y devuelva un nuevo objetoHora en vez de modificar el paraacutemetro

Desarrollo de prototipos frente a la planificacioacutenEl desarrollo de programas que veremos ahora se llama ldquodesarrollo deprototiposrdquo En cada una de las funciones anteriores escribimos un prototipoque realizaba el caacutelculo baacutesico y luego lo probamos sobre unos cuantos casoscorrigiendo los errores a medida que iban apareciendo

Este enfoque puede ser efectivo especialmente si auacuten no tiene un conocimientoprofundo del problema No obstante las correcciones incrementales puedengenerar coacutedigo innecesariamente complicado (que considere muchos casosespeciales) y poco confiable (es difiacutecil saber si ha encontrado todos los errores)

Una alternativa es el desarrollo planificado en el que la comprensioacuten delproblema en profundidad puede facilitar en gran medida la programacioacuten En elcaso de sumahora se puede ver un objeto Hora como iexclun nuacutemero de tres diacutegitosen base 60 (vea httpsenwikipediaorgwikiSexagesimal ) El atributo segundoes la ldquocolumna de unidadesrdquo el atributo minuto es la ldquocolumna de los sesentasrdquo y

Desarrollo de prototipos frente a la planificacioacuten 211

el atributo hora es la ldquocolumna de los tres mil seiscientosrdquo

Cuando se escribiacutea sumahora e incrementar efectivamente se estaba sumandoen base 60 por eso se tuvo que acarrear de una columna a la siguiente

Esta observacioacuten sugiere otro enfoque para el problema se pueden convertir losobjetos Hora en enteros y aprovechar el hecho de que la computadora saberealizar aritmeacutetica con enteros

La siguiente funcioacuten convierte un objeto Hora en un entero

function horaaentero(tiempo) minutos = tiempohora 60 + tiempominuto segundos = minutos 60 + tiemposegundoend

Ahora para convertir un entero en un objeto Hora (recuerde que divrem divideel primer argumento por el segundo y devuelve el cociente y el resto como unatupla)

function enteroahora(segundos) (minutos segundo) = divrem(segundos 60) hora minuto = divrem(minutos 60) Hora(hora minuto segundo)end

Puede que tenga que pensar un poco y realizar algunas pruebas paraconvencerse de que estas funciones son correctas Una forma de probarlas esverificar que horaaentero((enteroahora(x)) == x para muchos valores de x Estees un ejemplo de prueba de consistencia

Una vez que esteacute convencido puede usar estas funciones para reescribirsumahora

function sumahora(t1 t2) segundos = horaaentero(t1) + horaaentero(t2) enteroahora(segundos)end

Esta versioacuten es maacutes corta que la original y maacutes faacutecil de verificar

Ejercicio 16-5

Reescriba incrementar usando horaaentero y enteroahora

Convertir de base 60 a base 10 y viceversa es maacutes difiacutecil que solo trabajar con

212 Capiacutetulo 16 Estructuras y Funciones

los tiempos El cambio de base es maacutes abstracto pero la intuicioacuten humana paratratar con las horas es mejor

Si al usuario se le ocurre tratar los tiempos como nuacutemeros de base 60 e invierteun poco de tiempo en escribir las funciones de conversioacuten (horaaentero yenteroahora) obtiene un programa maacutes corto faacutecil de leer y depurar y confiable

El cambio de base tambieacuten hace que sea maacutes faacutecil antildeadir funcionalidadesposteriormente Por ejemplo imagine restar dos Horas para hallar el intervaloentre ellas El enfoque simple seriacutea implementar una resta con preacutestamo perousar funciones de conversioacuten seriacutea maacutes faacutecil y con mayor probabilidad correcto

Iroacutenicamente a veces hacer un poblema maacutes complejo (o maacutes general) lo hacemaacutes faacutecil porque hay menos casos especiales y por lo tanto el margen de errores menor

DepuracioacutenUn objeto Hora estaacute bien definido si los valores de minuto y segundo estaacuten entre0 y 60 (incluido 0 pero no 60) y si hora es positivo hora y minuto deben servalores enteros pero se podriacutea permitir que segundo sea fraccional

Los requisitos como estos se denominan invariantes porque siempre deben serverdaderos Dicho de otra manera si no son ciertos algo estaacute mal

Escribir coacutedigo para verificar invariantes puede ayudar a detectar errores yencontrar sus causas Por ejemplo podriacutea tener una funcioacuten como eshoravalidaque tome un objeto Hora y devuelva false si viola una invariante

function eshoravalida(tiempo) if tiempohora lt 0 || tiempominuto lt 0 || tiemposegundo lt 0 return false end if tiempominuto gt= 60 || tiemposegundo gt= 60 return false end trueend

Al comienzo de cada funcioacuten puede verificar los argumentos para asegurarse deque sean vaacutelidos

Depuracioacuten 213

function sumahora(t1 t2) if eshoravalida(t1) || eshoravalida(t2) error(objeto Hora en sumahora es invaacutelido) end segundos = horaaentero(t1) + horaaentero(t2) enteroahora(segundos)end

O podriacutea usar una macro assert que verifica un invariante dado y genera unaexcepcioacuten si falla

function sumahora(t1 t2) assert(eshoravalida(t1) ampamp eshoravalida(t2) objeto Hora en sumahoraes invaacutelido) segundos = horaaentero(t1) + horaaentero(t2) enteroahora(segundos)end

Las macros assert son uacutetiles porque permiten distinguir el coacutedigo que tratacondiciones normales del coacutedigo que verifica los errores

Glosariodesarrollo de prototipos

Una forma de desarrollar programas que involucra generar un prototipo delprograma hacer pruebas y corregir errores a medida que son encontrados

desarrollo planificadoUna forma de desarrollar programas que implica una profunda comprensioacutendel problema y maacutes planificacioacuten que desarrollo incremental o desarrollo deprototipos

funcioacuten puraUna funcioacuten que no modifica los objetos que recibe como paraacutemetros Lamayoriacutea de las funciones puras son productivas

modificadorUna funcioacuten que modifica uno o maacutes de los objetos que recibe comoparaacutemetros La mayoriacutea de los modificadores son nulos es decir entreganresultado nothing

estilo funcional de programacioacutenUn estilo de programacioacuten en el que la mayoriacutea de las funciones son puras

214 Capiacutetulo 16 Estructuras y Funciones

invarianteUna condicioacuten que nunca deberiacutea cambiar durante la ejecucioacuten de unprograma

Ejercicios

Ejercicio 16-6

Escriba una funcioacuten llamada multhora que tome un objeto Hora y un nuacutemero ydevuelva un nuevo objeto Hora que contenga el producto entre Hora original y elnuacutemero

Luego use multhora para escribir una funcioacuten que tome un objeto Hora querepresente el tiempo de duracioacuten de una carrera y un nuacutemero que represente ladistancia y devuelva un objeto Hora que represente el ritmo promedio (minutospor kiloacutemetro)

Ejercicio 16-7

Julia proporciona objetos de tiempo similares a los objetos Hora de este capiacutetulopero que tienen un amplio conjunto de funciones y operadores Lea ladocumentacioacuten en httpsdocsjulialangorgenv1stdlibDates

1 Escriba un programa que tome la fecha actual e imprima el diacutea de lasemana

2 Escriba un programa que tome como entrada una fecha de cumpleantildeos eimprima la edad del usuario y la cantidad de diacuteas horas minutos ysegundos hasta su proacuteximo cumpleantildeos

3 Para dos personas nacidas en diacuteas diferentes hay un diacutea en que una tiene eldoble de edad que la otra Ese es su Diacutea Doble Escriba un programa quetome dos cumpleantildeos y calcule su Diacutea doble

4 Desafiacuteo Escriba una versioacuten maacutes general que calcule el diacutea en que unapersona es veces mayor que la otra

Ejercicios 215

Capiacutetulo 17 Dispatch MuacuteltipleJulia permite escribir coacutedigo que puede funcionar con diferentes tipos Esto sellama programacioacuten geneacuterica

En este capiacutetulo se discutiraacute sobre las declaraciones de tipo en Julia Ademaacutes sepresentan los meacutetodos que son formas de implementar diferentescomportamientos en una funcioacuten dependiendo del tipo de sus argumentos Estoes conocido como dispatch muacuteltiple

Declaraciones de Tipo

El operador asocia anotaciones de tipo con expresiones y variables

juliagt (1 + 2) Float64ERROR TypeError in typeassert expected Float64 got a value of typeInt64juliagt (1 + 2) Int643

Esto ayuda a verificar que el programa funciona de la manera esperada

El operador tambieacuten se puede agregar al lado izquierdo de una asignacioacuten ocomo parte de una declaracioacuten

juliagt function devolverfloat() xFloat64 = 100 x enddevolverfloat (generic function with 1 method)juliagt x = devolverfloat()1000juliagt typeof(x)Float64

La variable x siempre es de tipo Float64 y su valor se convierte en un puntoflotante si es necesario

Tambieacuten se puede antildeadir una anotacioacuten de tipo al encabezado de una definicioacutende funcioacuten

216 Capiacutetulo 17 Dispatch Muacuteltiple

function sinc(x)Float64 if x == 0 return 1 end sin(x)(x)end

El valor de retorno de sinc siempre se convierte al tipo Float64

En Julia cuando se omiten los tipos los valores pueden ser de cualquier tipo(Any)

MeacutetodosEn Capiacutetulo 16 definimos una estructura llamada Hora y en Seccioacuten 161escribimos una funcioacuten llamada imprimirhora

using Printf

struct Hora hora Int64 minuto Int64 segundo Int64end

function imprimirhora(tiempo) printf(02d02d02d tiempohora tiempominuto tiemposegundo)end

Para mejorar el rendimiento se pueden (y deben) agregar las declaraciones detipo a los atributos en una definicioacuten de estructura

Para llamar a esta funcioacuten debe pasarle un objeto Hora como argumento

juliagt inicio = Hora(9 45 0)Hora(9 45 0)juliagt imprimirhora(inicio)094500

Para agregar un meacutetodo a la funcioacuten imprimirhora con el fin de que esta soloacepte como argumento un objeto Hora todo lo que hay que hacer es agregar seguido de Hora al argumento tiempo en la definicioacuten de funcioacuten

Meacutetodos 217

function imprimirhora(tiempoHora) printf(02d02d02d tiempohora tiempominuto tiemposegundo)end

Un meacutetodo es una definicioacuten de funcioacuten con una especificacioacuten imprimirhoratiene un argumento de tipo Hora

Llamar a la funcioacuten imprimirhora con un objeto Hora produce el mismo resultadoque antes

juliagt imprimirhora(inicio)094500

Se redefine el primer meacutetodo sin la anotacioacuten de tipo lo cual permite unargumento de cualquier tipo

function imprimirhora(tiempo) println(No seacute coacutemo imprimir el tiempo del argumento)end

Si se llama a la funcioacuten imprimirhora con un objeto diferente de Hora seobtendraacute

juliagt imprimirhora(150)No seacute coacutemo imprimir el tiempo del argumento

Ejercicio 17-1

Reescriba horaaentero y enteroahora (de Seccioacuten 164) especificando el tipo delos argumentos

enteroahora (generic function with 1 method)

Ejemplos AdicionalesAquiacute hay una versioacuten de la funcioacuten incrementar (Ejercicio 16-5 de Seccioacuten 163)reescrita especificando el tipo de los argumentos

function incrementar(tiempoHora segundosInt64) segundos += horaaentero(tiempo) enteroahora(segundos)end

218 Capiacutetulo 17 Dispatch Muacuteltiple

Tenga en cuenta que ahora incrementar es una funcioacuten pura no un modificador

Asiacute es como se llama a la funcioacuten incrementar

juliagt inicio = Hora(9 45 0)Hora(9 45 0)juliagt incrementar(inicio 1337)Hora(10 7 17)

Si se colocan los argumentos en el orden incorrecto se obtiene un error

juliagt incrementar(1337 inicio)ERROR MethodError no method matching incrementar(Int64 Hora)

La especificacioacuten del meacutetodo es incrementar(tiempoHora segundosInt64) noincrementar(segundosInt64 tiempoHora)

Al reescribir estadespues (Ejercicio 16-2 de Seccioacuten 163) para que solo acepteobjetos Hora se tiene

function estadespues(t1Hora t2Hora) (t1hora t1minuto t1segundo) gt (t2hora t2minuto t2segundo)end

Hace falta destacar que los argumentos opcionales permiten definir muacuteltiplesmeacutetodos Por ejemplo esta definicioacuten

function f(a=1 b=2) a + 2bend

se traduce en los siguientes tres meacutetodos

f(a b) = a + 2bf(a) = f(a 2)f() = f(1 2)

Estas expresiones son definiciones vaacutelidas de meacutetodos de Julia Esta es unanotacioacuten abreviada para definir funcionesmeacutetodos

ConstructoresUn constructor es una funcioacuten especial que se llama para crear un objeto Losmeacutetodos por defecto del constructor Hora tienen las siguientes especificaciones

Constructores 219

Hora(hora minuto segundo)Hora(horaInt64 minutoInt64 segundoInt64)

Tambieacuten se pueden agregar meacutetodos propios de constructores externos

function Hora(tiempoHora) Hora(tiempohora tiempominuto tiemposegundo)end

Este meacutetodo se llama constructor de copia porque el nuevo objeto Hora es unacopia de su argumento

Para imponer invariantes se necesitan meacutetodos de constructor interno

struct Hora hora Int64 minuto Int64 segundo Int64 function Hora(horaInt64=0 minutoInt64=0 segundoInt64=0) assert(0 le minuto lt 60 Minuto no estaacute entre 0 y 60) assert(0 le segundo lt 60 Segundo no estaacute entre 0 y 60) new(hora minuto segundo) endend

La estructura Hora tiene ahora 4 meacutetodos de constructor interno

Hora()Hora(horaInt64)Hora(horaInt64 minutoInt64)Hora(horaInt64 minutoInt64 segundoInt64)

Un meacutetodo de constructor interno siempre se define dentro del bloque de unadeclaracioacuten de tipo y tiene acceso a una funcioacuten especial llamada new que creaobjetos del tipo recieacuten declarado

AVISOSi se define alguacuten constructor interno el constructor por defectoya no estaacute disponible Se tienen que escribir expliacutecitamente todoslos constructores internos necesarios

Tambieacuten existe un meacutetodo sin argumentos de la funcioacuten local new

220 Capiacutetulo 17 Dispatch Muacuteltiple

mutable struct Hora hora Int64 minuto Int64 segundo Int64 function Hora(horaInt64=0 minutoInt64=0 segundoInt64=0) assert(0 le minuto lt 60 Minuto estaacute entre 0 y 60) assert(0 le segundo lt 60 Segundo estaacute entre 0 y 60) tiempo = new() tiempohora = hora tiempominuto = minuto tiemposegundo = segundo tiempo endend

Esto permite construir estructuras de datos recursivas es decir una estructuradonde uno de los atributos es la estructura misma En este caso la estructuradebe ser mutable ya que sus atributos se modifican despueacutes de la creacioacuten deinstancias

showshow es una funcioacuten especial que devuelve la representacioacuten de cadena de unobjeto A continuacioacuten se muestra el meacutetodo show para objetos Hora

using Printf

function Baseshow(ioIO tiempoHora) printf(io 02d02d02d tiempohora tiempominutotiemposegundo)end

Esta funcioacuten guarda como cadena de texto una hora dada en el archivo al que iohace referencia

El prefijo Base es necesario si se quiere agregar un nuevo meacutetodo a la funcioacutenBaseshow

Cuando se imprime un objeto Julia llama a la funcioacuten show (esto ocurre siemprey como agregamos un nuevo meacutetodo a la funcioacuten Baseshow entonces se muestraHora con el formato que queremos)

juliagt tiempo = Hora(9 45 0)094500

Al escribir un nuevo tipo compuesto casi siempre es preferible empezar

show 221

escribiendo un constructor externo puesto que facilita la creacioacuten de instanciasde objetos y show que es uacutetil para la depuracioacuten

Ejercicio 17-2

Escriba un meacutetodo de constructor externo para la clase Punto que tome x e ycomo paraacutemetros opcionales y los asigne a los atributos correspondientes

incrementar (generic function with 1 method)

Sobrecarga de OperadoresEs posible cambiar la definicioacuten de los operadores cuando se aplican a tiposdefinidos por el usuario Esto se hace definiendo meacutetodos del operador Porejemplo si se define un meacutetodo llamado + con dos argumentos Hora se puedeusar el operador + en los objetos Hora

Asiacute es como se veriacutea la definicioacuten

import Base+

function +(t1Hora t2Hora) segundos = horaaentero(t1) + horaaentero(t2) enteroahora(segundos)end

La sentencia import agrega el operador + al aacutembito local (local scope) para quese puedan agregar meacutetodos

A continuacioacuten se muestra coacutemo usar este operador para objetos Hora

juliagt inicio = Hora(9 45)094500juliagt duracion = Hora(1 35 0)013500juliagt inicio + duracion112000

Al aplicar el operador + a objetos Hora Julia invoca el meacutetodo recieacuten agregadoCuando REPL muestra el resultado Julia invoca a show iexclHay muchas cosasocurriendo pero que no se observan

Ampliar el comportamiento de los operadores de modo que funcionen con tiposdefinidos por el usuarioprogramador se denomina sobrecarga del operador

222 Capiacutetulo 17 Dispatch Muacuteltiple

Dispatch MuacuteltipleEn la seccioacuten anterior se sumaron dos objetos Hora Imagine que ahora se quieresumar un nuacutemero entero a un objeto Hora

function +(tiempoHora segundosInt64) incrementar(tiempo segundos)end

He aquiacute un ejemplo que usa el operador + con un objeto Hora y un entero

juliagt inicio = Hora(9 45)094500juliagt inicio + 1337100717

La suma es un operador conmutativo por lo que se debe agregar otro meacutetodo

function +(segundosInt64 tiempoHora) tiempo + segundosend

Y se obtiene el mismo resultado

juliagt 1337 + inicio100717

La eleccioacuten del meacutetodo a ejecutar cuando se aplica una funcioacuten se llamadispatch Julia permite que el proceso de dispatch elija a cuaacutel de los meacutetodos deuna funcioacuten llamar en funcioacuten del nuacutemero y tipo de los argumentos dados El usode todos los argumentos de una funcioacuten para elegir el meacutetodo que se debeinvocar se conoce como dispatch muacuteltiple

Ejercicio 17-3

Escriba los siguientes meacutetodos + para objetos Punto

bull Si ambos operandos son objetos Punto el meacutetodo deberiacutea devolver un nuevoobjeto Punto cuya coordenada x sea la suma de las coordenadas x de losoperandos De manera anaacuteloga haga lo mismo para la coordenada y

bull Si el primer o el segundo operando es una tupla el meacutetodo debe agregar elprimer elemento de la tupla a la coordenada x y el segundo elemento a lacoordenada y y devolver un nuevo objeto Punto con el resultado

Dispatch Muacuteltiple 223

Programacioacuten GeneacutericaEl dispatch muacuteltiple es uacutetil cuando es necesario pero (afortunadamente) nosiempre lo es A menudo puede evitarse escribiendo funciones que funcionencorrectamente para argumentos de diferentes tipos

Muchas de las funciones que se han visto para cadenas tambieacuten funcionan paraotros tipos de secuencia Por ejemplo en Seccioacuten 112 se usa histograma paracontar la cantidad de veces que cada letra aparece en una palabra

function histograma(s) d = Dict() for c in s if c notin keys(d) d[c] = 1 else d[c] += 1 end end dend

Esta funcioacuten tambieacuten funciona para listas tuplas e incluso diccionarios siemprey cuando los elementos de s sean hashables ya que asiacute pueden usarse comoclaves de d

juliagt t = (spam huevo spam spam tocino spam)(spam huevo spam spam tocino spam)juliagt histograma(t)DictAnyAny with 3 entries spam =gt 4 huevo =gt 1 tocino =gt 1

Las funciones que pueden tomar paraacutemetros de diferentes tipos se llamanpolimoacuterficas El polimorfismo puede facilitar la reutilizacioacuten del coacutedigo

Por ejemplo la funcioacuten integrada sum que suma los elementos de una secuenciafunciona siempre que los elementos de la secuencia permitan la suma

Como se antildeadioacute el meacutetodo + para los objetos Hora entonces se puede usar sumpara Hora

224 Capiacutetulo 17 Dispatch Muacuteltiple

juliagt t1 = Hora(1 7 2)010702juliagt t2 = Hora(1 5 8)010508juliagt t3 = Hora(1 5 0)010500juliagt sum((t1 t2 t3))031710

Si todas las operaciones realizadas dentro de la funcioacuten se pueden aplicar al tipola funcioacuten se puede aplicar al tipo

El mejor tipo de polimorfismo es el que no se busca cuando usted descubre queuna funcioacuten que habiacutea escrito se puede aplicar a un tipo para el que nunca lahabiacutea planeado

Interfaz e implementacioacutenUno de los objetivos del dispatch muacuteltiple es hacer que el software sea maacutes faacutecilde mantener lo que significa poder mantener el programa funcionando cuandootras partes del sistema cambian y modificar el programa para cumplir con losnuevos requisitos

Una teacutecnica de disentildeo que ayuda a lograr ese objetivo es mantener las interfacesseparadas de las implementaciones Esto significa que los meacutetodos que tienen unargumento con anotacioacuten de tipo no deberiacutean depender de coacutemo se representanlos atributos de ese tipo

Por ejemplo en este capiacutetulo se desarrolla una estructura que representa unahora del diacutea Los meacutetodos que tienen un argumento con anotacioacuten de este tipoincluyen horaaentero estadespues y +

Se pueden implementar esos meacutetodos de varias maneras Los detalles de laimplementacioacuten dependen de coacutemo se represente Hora En este capiacutetulo losatributos de un objeto Hora son hora minuto y segundo

Otra opcioacuten seriacutea reemplazar estos atributos con un solo entero que representeel nuacutemero de segundos desde la medianoche Esta implementacioacuten hariacutea quealgunas funciones como estadespues sean maacutes faacuteciles de escribir pero hace queotras sean maacutes difiacuteciles

Despueacutes de implementar un tipo puede descubrir una mejor implementacioacuten Siotras partes del programa estaacuten usando su tipo cambiar la interfaz puede llevarmucho tiempo y ser propenso a errores No obstante si hizo un buen disentildeoacute deinterfaz puede cambiar la implementacioacuten sin cambiar la interfaz lo quesignifica que otras partes del programa no tienen que cambiar

Interfaz e implementacioacuten 225

DepuracioacutenLlamar a una funcioacuten con los argumentos correctos puede ser difiacutecil cuando seespecifica maacutes de un meacutetodo para la funcioacuten Julia permite examinar lasespecificaciones de los meacutetodos de una funcioacuten

Para saber queacute meacutetodos estaacuten disponibles para una funcioacuten determinada puedeusar la funcioacuten methods

juliagt methods(imprimirhora) 2 methods for generic function imprimirhora[1] printtime(timeMyTime) in Main at REPL[3]2[2] printtime(time) in Main at REPL[4]2

En este ejemplo la funcioacuten imprimirhora tiene 2 meacutetodos uno con un argumentoHora y otro con un argumento Any

Glosarioanotacioacuten de tipo

El operador seguido de un tipo que indica que una expresioacuten o unavariable es de ese tipo

meacutetodoUna definicioacuten de un posible comportamiento de una funcioacuten

dispatchLa eleccioacuten de queacute meacutetodo ejecutar cuando se ejecuta una funcioacuten

especificacioacutenEl nuacutemero y tipo de argumentos de un meacutetodo que permite al dispatchseleccionar el meacutetodo maacutes especiacutefico de una funcioacuten durante la llamada afuncioacuten

constructor externoConstructor definido fuera de la definicioacuten de tipo para definir meacutetodosuacutetiles para crear un objeto

constructor internoConstructor definido dentro de la definicioacuten de tipo para imponerinvariantes o para construir objetos recursivos

constructor por defectoConstructor interno que estaacute disponible cuando el usuario no defineconstructores internos

226 Capiacutetulo 17 Dispatch Muacuteltiple

constructor de copiaMeacutetodo de constructor externo de un tipo que tiene como uacutenico argumentoun objeto del tipo Crea un nuevo objeto que es una copia del argumento

sobrecarga de operadoresAmpliar el comportamiento de los operadores como ++ de modo quetrabajen con tipos definidos por el usuario

dispatch muacuteltipleDispatch basado en todos los argumentos de una funcioacuten

programacioacuten geneacutericaEscribir coacutedigo que pueda funcionar con maacutes de un tipo

Ejercicios

Ejercicio 17-4

Cambie los atributos de Hora para que sea un solo nuacutemero entero querepresente los segundos desde la medianoche Luego modifique los meacutetodosdefinidos en este capiacutetulo para que funcionen con la nueva implementacioacuten

Ejercicio 17-5

Escriba una definicioacuten para un tipo llamado Canguro con un atributo llamadocontenidodemarsupio de tipo Arreglo y los siguientes meacutetodos

bull Un constructor que inicialice contenidodemarsupio a un arreglo vaciacuteo

bull Un meacutetodo llamado ponerenmarsupio que tome un objeto Canguro y unobjeto de cualquier tipo y lo agregue a contenidodemarsupio

bull Un meacutetodo show que devuelva una representacioacuten de cadena del objetoCanguro y el contenido del marsupio

Pruebe su coacutedigo creando dos objetos Canguro asignaacutendolos a variablesllamadas cangu y ro y luego agregando ro al contenido del marsupio de cangu

Ejercicios 227

Capiacutetulo 18 SubtiposEn el capiacutetulo anterior se presentoacute el dispatch muacuteltiple y los meacutetodospolimoacuterficos Al no especificar el tipo de los argumentos de un meacutetodo este sepuede invocar con argumentos de cualquier tipo Ahora se veraacute coacutemo especificarun subconjunto de tipos permitidos en las especificaciones de un meacutetodo

En este capiacutetulo se explica el concepto de subtipo usando tipos que representannaipes mazos de naipes y manos de poacuteker

Si usted nunca ha jugado poacuteker puede leer sobre eacutel en httpseswikipediaorgwikiPC3B3quer aunque no es necesario ya que se explicaraacute todo lonecesario para los ejercicios

NaipesHay cincuenta y dos naipes en una baraja inglesa cada uno de los cualespertenece a uno de los cuatro palos y tiene un valor Los palos son Picas (spades)Corazones (hearts) Diamantes (diams) y Treacuteboles (clubs) Los valores son As (A) 2 3 4 5 67 8 9 10 Jota (J) Reina (Q) y Rey (K) Dependiendo del tipo de juego el valordel As puede ser mayor que al Rey o inferior al 2

Si queremos definir un nuevo objeto para representar un naipe son obvios losatributos que deberiacutea tener valor y palo Lo que no es tan obvio es el tipo que sedebe dar a estos atributos Una opcioacuten es usar cadenas de caracteres quecontengan palabras como Picas para los palos y Reina para los valores Unproblema de esta implementacioacuten es que no seriacutea faacutecil comparar naipes para vercuaacutel tiene mayor valor o palo

Una alternativa es usar nuacutemeros enteros para codificar los valores y palos Eneste contexto codificar significa definir una asociacioacuten entre nuacutemeros y paloso entre nuacutemeros y valores Este tipo de codificacioacuten no estaacute relacionada concifrar o traducir a un coacutedigo secreto (eso seriacutea cifrado)

Por ejemplo esta tabla muestra una correspondencia entre palos y coacutedigos(nuacutemeros) enteros

bull spades 4

bull hearts 3

bull diams 2

bull clubs 1

Este coacutedigo facilita la comparacioacuten de naipes los palos maacutes altos se asignan a losnuacutemeros maacutes altos por lo tanto podemos comparar los palos al comparar suscoacutedigos

228 Capiacutetulo 18 Subtipos

Estamos usando el siacutembolo para dejar en claro que estas asignaciones no sonparte de Julia Forman parte del disentildeo del programa pero no aparecenexpliacutecitamente en el coacutedigo

La definicioacuten de estructura de Naipe se ve asiacute

struct Naipe palo Int64 valor Int64 function Naipe(paloInt64 valorInt64) assert(1 le palo le 4 el palo no estaacute entre 1 y 4) assert(1 le valor le 13 el valor no estaacute entre 1 y 13) new(palo valor) endend

Para crear un Naipe se debe llamar a Naipe con el palo y el valor del naipedeseado

juliagt reina_de_diamantes = Naipe(2 12)Naipe(2 12)

Variables GlobalesPara poder imprimir los objetos Naipe de una manera que sea faacutecil de leer senecesita establecer una correspondencia entre los coacutedigos enteros y suscorrespondientes palos y valores Una manera natural de hacer esto es conarreglos de cadenas

const nombres_palo = [clubs diams hearts spades]const nombres_valor = [A 2 3 4 5 6 7 8 9 10J Q K]

Las variables nombres_palo y nombres_valor son variables globales Ladeclaracioacuten const significa que la variable solo se puede asignar una vez Estoresuelve el problema de rendimiento de las variables globales

Ahora se puede implementar un meacutetodo show apropiado

function Baseshow(ioIO naipeNaipe) print(io nombres_valor[naipevalor] nombres_palo[naipepalo])end

La expresioacuten nombres_valor[naipevalor] significa use el atributo valor delobjeto naipe como iacutendice en el arreglo nombres_valor y seleccione la cadena

Variables Globales 229

correspondiente

Con los meacutetodos que se tienen hasta ahora se pueden crear e imprimir naipes

juliagt Naipe(3 11)Jhearts

Comparacioacuten de naipesPara los tipos integrados existen operadores relacionales (lt gt == etc) quecomparan valores y determinan cuaacutendo uno es mayor menor o igual a otro Paralos tipos definidos por el usuario se puede sustituir el comportamiento de estosoperadores si se proporciona un meacutetodo llamado lt

El orden correcto de los naipes no es obvio Por ejemplo iquestcuaacutel es mejor el 3 deTreacuteboles o el 2 de Diamantes Uno tiene un valor mayor pero el otro tiene unpalo mayor Para hacer que los naipes sean comparables se debe decidir queacute esmaacutes importante valor o palo

La respuesta puede depender del tipo de juego pero para simplificar las cosasse establece la eleccioacuten arbitraria de que el palo es maacutes importante por lo quetodas los treacuteboles superan a todos los diamantes y asiacute sucesivamente

Con esa decisioacuten tomada se puede escribir lt

import Baselt

function lt(c1Naipe c2Naipe) (c1palo c1valor) lt (c2palo c2valor)end

Ejercicio 18-1

Escriba un meacutetodo lt para objetos Hora Puede usar comparacioacuten de tuplas ocomparacioacuten de enteros

Prueba unitariaUna prueba unitaria permite verificar el correcto funcionamiento de su coacutedigocomparando los resultados obtenidos con los esperados Esto puede ser uacutetil paraverificar que su coacutedigo funciona correctamente despueacutes de haberlo modificado ytambieacuten es una forma de predefinir el comportamiento correcto de su coacutedigodurante el desarrollo

Se pueden realizar pruebas unitarias simples con las macros test

230 Capiacutetulo 18 Subtipos

juliagt using Test

juliagt test Naipe(1 4) lt Naipe(2 4)Test Passedjuliagt test Naipe(1 3) lt Naipe(1 4)Test Passed

test devuelve Test Passed (Prueba aprobada) si la expresioacuten que sigue estrue Test Failed (Prueba fallida) si es false y Error Result (Resultado deerror) si no se pudo evaluar

MazosAhora que ya tenemos Naipes el proacuteximo paso es definir Mazos Como un mazoestaacute compuesto de naipes naturalmente cada Mazo contendraacute un arreglo denaipes como atributo

A continuacioacuten se muestra una definicioacuten para Mazo El constructor crea elatributo naipes y genera la baraja estaacutendar de cincuenta y dos naipes

struct Mazo naipes ArrayNaipe 1end

function Mazo() mazo = Mazo(Naipe[]) for palo in 14 for valor in 113 push(mazonaipes Naipe(palo valor)) end end mazoend

La forma maacutes faacutecil de poblar el mazo es mediante un bucle anidado El bucleexterior enumera los palos desde 1 hasta 4 El bucle interior enumera los valoresdesde 1 hasta 13 Cada iteracioacuten crea un nuevo Naipe con el palo y valor actualy lo agrega a mazonaipes

Este es un meacutetodo show para Mazo

Mazos 231

function Baseshow(ioIO mazoMazo) for naipe in mazonaipes print(io naipe ) end println()end

Asiacute es como se ve el resultado

juliagt Mazo()Aclubs 2clubs 3clubs 4clubs 5clubs 6clubs 7clubs 8clubs 9clubs 10clubs Jclubs Qclubs Kclubs Adiams 2diams 3diams 4diams 5diams 6diams 7diams 8diams 9diams 10diams JdiamsQdiams Kdiams Ahearts 2hearts 3hearts 4hearts 5hearts 6hearts 7hearts 8hearts 9hearts 10hearts Jhearts Qhearts Khearts Aspades 2spades 3spades 4spades 5spades 6spades 7spades 8spades 9spades10spades Jspades Qspades Kspades

Antildeadir Eliminar Barajar y OrdenarPara repartir los naipes se debe tener una funcioacuten que elimine un naipe delmazo y lo devuelva La funcioacuten pop proporciona una forma conveniente derealizar esto

function Basepop(mazoMazo) pop(mazonaipes)end

Como pop elimina el uacuteltimo naipe en el arreglo se estaacute repartiendo desde elextremo inferior del mazo

Para antildeadir un naipe se puede usar la funcioacuten push

function Basepush(mazoMazo naipeNaipe) push(mazonaipes naipe) mazoend

Un meacutetodo como este que usa otro meacutetodo sin hacer mucho maacutes se llamaenchapado La metaacutefora proviene de la carpinteriacutea donde un enchapado es unacapa fina de madera de alta calidad que se pega a la superficie de una pieza demadera de baja calidad para mejorar su apariencia

En este caso push es un meacutetodo fino que expresa una operacioacuten de arreglosadecuada para los mazos Mejora la apariencia o interfaz de la implementacioacuten

Tambieacuten podemos escribir un meacutetodo llamado shuffle (barajar en ingleacutes) usandola funcioacuten Randomshuffle

232 Capiacutetulo 18 Subtipos

using Random

function Randomshuffle(mazoMazo) shuffle(mazonaipes) mazoend

Ejercicio 18-2

Escriba una funcioacuten llamada sort (ordenar en ingleacutes) que use la funcioacuten sortpara ordenar las cartas en un Mazo sort usa el meacutetodo isless que definimospara determinar el orden

Tipos Abstractos y SubtiposSe busca que un tipo represente una mano es decir los naipes que tiene unjugador Una mano es similar a un mazo ambos estaacuten compuestos de unconjunto de naipes y ambos requieren de operaciones tales como agregar yeliminar una carta

Una mano es diferente de un mazo en ciertos aspectos ya que existen ciertasoperaciones sobre una mano que no tendriacutean sentido sobre un mazo Porejemplo en el poker se debe comparar una mano con otra para ver quieacuten ganaEn bridge se necesita calcular el puntaje de la mano para asiacute poder hacer lasubasta

Por lo tanto hace falta una forma de agrupar los tipos concretos que estaacutenrelacionados En Julia esto se hace definiendo un abstract type (tipo abstracto eningleacutes) que sea padre de Mazo y Mano A esto se le llama crear subtipos

Se llama al tipo abstracto ConjuntoDeCartas

abstract type ConjuntoDeCartas end

Se puede crear un nuevo tipo abstracto con la palabra reservada abstract typeDe manera opcional se puede especificar un tipo padre de una estructuracolocando despueacutes del nombre de esta el siacutembolo lt seguido del nombre de untipo abstracto existente

Cuando no se proporciona un supertipo el supertipo por defecto es Any es decirun tipo abstracto predefinido del que todos los objetos son instancias y del quetodos los tipos son subtipos

Ahora se puede expresar que Mazo es un hijo de ConjuntoDeCartas

Tipos Abstractos y Subtipos 233

struct Mazo lt ConjuntoDeCartas naipes ArrayNaipe 1end

function Mazo() mazo = Mazo(Naipe[]) for palo in 14 for valor in 113 push(mazonaipes Naipe(palo valor)) end end mazoend

El operador isa comprueba si un objeto es de un tipo dado

juliagt mazo = Mazo()

juliagt mazo isa ConjuntoDeCartastrue

Una mano tambieacuten es un ConjuntoDeCartas

struct Mano lt ConjuntoDeCartas naipes ArrayNaipe 1 etiqueta Stringend

function Mano(etiquetaString=) Mano(Naipe[] etiqueta)end

En lugar de llenar la mano con 52 naipes nuevos el constructor de Manoinicializa naipes a un arreglo vaciacuteo Se puede etiquetar a la Mano pasando unargumento opcional al constructor

juliagt mano = Mano(nueva mano)Mano(Naipe[] nueva mano)

Tipos Abstractos y FuncionesAhora podemos expresar las operaciones que tienen en comuacuten Mazo y Mano alser funciones que tienen como argumento a ConjuntoDeCartas

234 Capiacutetulo 18 Subtipos

function Baseshow(ioIO cdcConjuntoDeCartas) for naipe in cdcnaipes print(io naipe ) endend

function Basepop(cdcConjuntoDeCartas) pop(cdcnaipes)end

function Basepush(cdcConjuntoDeCartas naipeNaipe) push(cdcnaipes naipe) nothingend

Se puede usar pop y push para repartir una carta

juliagt mazo = Mazo()Aclubs 2clubs 3clubs 4clubs 5clubs 6clubs 7clubs 8clubs 9clubs 10clubs Jclubs Qclubs Kclubs Adiams 2diams 3diams 4diams 5diams 6diams 7diams 8diams 9diams 10diams JdiamsQdiams Kdiams Ahearts 2hearts 3hearts 4hearts 5hearts 6hearts 7hearts 8hearts 9hearts 10hearts Jhearts Qhearts Khearts Aspades 2spades 3spades 4spades 5spades 6spades 7spades 8spades 9spades10spades Jspades Qspades Kspadesjuliagt shuffle(mazo)10clubs 9hearts 7spades 2spades Ahearts 4clubs Jhearts 2diams 6clubs Qclubs 8diams 8hearts 3hearts 7clubs 3diams 2clubs Jclubs 8clubs 9diams 6spades 3spades 5spades Adiams Aclubs10hearts 4spades Qhearts Jdiams Kspades 10diams Khearts Kclubs 5clubs 5hearts 5diams 10spades 7diams 3clubs 9spades Aspades 2hearts 7hearts 9clubs Qdiams 6hearts 8spades Jspades 4diamsQspades 6diams Kdiams 4heartsjuliagt naipe = pop(mazo)4heartsjuliagt push(mano naipe)

A continuacioacuten se encapsula este coacutedigo en una funcioacuten llamada mover

function mover(cdc1ConjuntoDeCartas cdc2ConjuntoDeCartas nInt) assert 1 le n le length(cs1naipes) for i in 1n naipe = pop(cdc1) push(cdc2 naipe) end nothingend

mover toma tres argumentos dos objetos ConjuntoDeCartas y el nuacutemero decartas a repartir Modifica ambos objetos ConjuntoDeCartas y devuelve nothing

En algunos juegos las cartas se mueven de una mano a otra o de una mano almazo Puede usar mover para cualquiera de estas operaciones cdc1 y cdc2pueden ser un Mazo o una Mano

Tipos Abstractos y Funciones 235

Diagramas de tiposHasta ahora se han visto diagramas de pila que muestran el estado de unprograma y diagramas de objetos que muestran los atributos de un objeto y susvalores Estos diagramas son como una foto sacada durante la ejecucioacuten de unprograma por lo que cambian a medida que se ejecuta el programa

Tambieacuten son muy detallados en algunos casos demasiado detallados Undiagrama de tipos es una representacioacuten maacutes abstracta de la estructura de unprograma En vez de mostrar objetos individuales muestra los tipos y lasrelaciones entre ellos

Hay varias formas de relacioacuten entre tipos

bull Los objetos de un tipo concreto pueden contener referencias a objetos deotro tipo Por ejemplo cada Rectaacutengulo contiene una referencia a un Puntoy cada Mazo contiene referencias a un conjunto de Naipes Este tipo derelacioacuten se llama TIENE-UN como por ejemplo un Rectaacutengulo tiene unPunto

bull Un tipo concreto puede tener un tipo abstracto como supertipo Estarelacioacuten se llama ES-UN como por ejemplo una Mano es unConjuntoDeCartas

bull Un tipo puede depender de otro si los objetos de un tipo toman objetos delsegundo tipo como paraacutemetros o usan objetos del segundo tipo como partede un caacutelculo Este tipo de relacioacuten se llama dependencia

Figura 23 Diagrama de tipo

Cada una de las flechas superiores representa una relacioacuten ES-UN En este casoindica que Mano tiene como supertipo a ConjuntoDeCartas

Cada una de las flechas inferiores representa una relacioacuten TIENE-UN en estecaso un Mazo tiene referencias a objetos Naipe

El asterisco () cerca de la flecha es una multiplicidad e indica cuaacutentos Naipestiene un Mazo Una multiplicidad puede ser un nuacutemero simple como 52 unrango como 57 o un asterisco lo cual indica que un Mazo puede tener cualquiernuacutemero de Naipes

236 Capiacutetulo 18 Subtipos

No hay dependencias en este diagrama Normalmente se mostrariacutean con unaflecha achurada Si hay muchas dependencias a veces se omiten

Un diagrama maacutes detallado podriacutea mostrar que un Mazo en realidad contiene unarreglo de Naipes pero los tipos integrados como arreglos y diccionariosgeneralmente no se incluyen en los diagramas de tipos

DepuracioacutenUtilizar subtipos puede dificultar la depuracioacuten ya que al llamar a una funcioacutencon un objeto como argumento puede ser complicado determinar queacute meacutetodo seinvocaraacute

Al escribir una funcioacuten que funciona con objetos Mano se busca que funcionecon todo tipo de Manos como ManoDePoker ManoDeBridge etc Si el usuarioinvoca un meacutetodo como sort podriacutea obtener el meacutetodo definido para un tipoabstracto Mano pero si existiera un meacutetodo sort que tuviera como argumentocualquiera de estos subtipos de Mano obtendriacutea esa versioacuten Estecomportamiento suele ser algo bueno pero puede ser confuso

function Basesort(manoMano) sort(manonaipes)end

Si usted no estaacute seguro del flujo de ejecucioacuten de un programa la solucioacuten maacutessimple es agregar sentencias de impresioacuten al inicio de sus meacutetodos maacutesrelevantes Si shuffle imprimiera un mensaje como Ejecutando shuffle en Mazodurante la ejecucioacuten del programa seriacutea posible rastrear el flujo de ejecucioacuten

Una mejor alternativa es la macro which

juliagt which sort(mano)sort(manoMano) in Main at REPL[5]1

Entonces el meacutetodo sort de mano es el que tiene como argumento un objeto detipo Mano

Una sugerencia para el disentildeo del programa cuando anula un meacutetodo lainterfaz del nuevo meacutetodo deberiacutea ser la misma que la anterior Deberiacutea tomarlos mismos paraacutemetros devolver el mismo tipo y obedecer las mismascondiciones previas y posteriores Si sigue esta regla cualquier funcioacuten disentildeadapara funcionar con una instancia de un supertipo como un ConjuntoDeCartastambieacuten funcionaraacute con instancias de sus subtipos Mazo y Mano

Si viola esta regla llamada principio de sustitucioacuten de Liskov su coacutedigocolapsaraacute como un castillo de naipes (jeje)

Depuracioacuten 237

La funcioacuten supertype permite encontrar el supertipo directo de un tipo

juliagt supertype(Mazo)ConjuntoDeCartas

Encapsulado de DatosLos capiacutetulos anteriores muestran un plan de desarrollo que podriacuteamos llamardisentildeo orientado a tipos Se identifican los objetos necesarios como PuntoRectaacutengulo y Hora y se definen estructuras para representarlos En cada casohay una correspondencia obvia entre el objeto y alguna entidad en el mundo real(o al menos en el mundo matemaacutetico)

A veces no es tan obvio saber queacute objetos se necesitan y coacutemo estos debeninteractuar En ese caso se necesita un plan de desarrollo diferente Lo mismoque ocurre con interfaces de funciones por encapsulado y generalizacioacuten ocurrecon interfaces de tipo por encapsulado de datos

El anaacutelisis de Markov de Seccioacuten 138 es un buen ejemplo Si descarga el coacutedigodesde httpsgithubcomBenLauwensThinkJuliajlblobmastersrcsolutionschap13jl veraacute que se usan dos variables globales sufijos y prefijo las cuales seleen y escriben desde varias funciones

sufijos = Dict()prefijos = []

Debido a que estas variables son globales solo se puede ejecutar un anaacutelisis a lavez Si se leen dos textos sus prefijos y sufijos se agregariacutean a las mismasestructuras de datos (lo que generariacutea un texto interesante)

Para ejecutar muacuteltiples anaacutelisis y mantenerlos separados se puede encapsular elestado de cada anaacutelisis en un objeto Asiacute es como se veriacutea

struct Markov orden Int64 sufijos DictTupleStringVarargString ArrayString 1 prefijo ArrayString 1end

function Markov(ordenInt64=2) new(orden DictTupleStringVarargString ArrayString 1()ArrayString 1())end

A continuacioacuten se transforman las funciones en meacutetodos Por ejemplo para

238 Capiacutetulo 18 Subtipos

procesarpalabra

function procesarpalabra(markovMarkov palabraString) if length(markovprefijo) lt markovorden push(markovprefijo palabra) return end get(markovsufijos (markovprefijo) ArrayString 1()) push(markovsufijos[(markovprefijo)] palabra) popfirst(markovprefijo) push(markovprefijo palabra)end

Transformar un programa asiacute (cambiando el disentildeo sin cambiar elcomportamiento) es otro ejemplo de refactorizacioacuten (vea Seccioacuten 47)

Este ejemplo sugiere el siguiente plan de desarrollo para disentildear tipos

bull Comience escribiendo funciones que lean y escriban variables globales(cuando sea necesario)

bull Una vez que el programa esteacute funcionando busque asociaciones entre lasvariables globales y las funciones que las usan

bull Encapsule variables relacionadas como atributos de una estructura

bull Transforme las funciones asociadas en meacutetodos que tengan comoargumentos objetos del nuevo tipo

Exercise 18-3

Descargue el coacutedigo de Markov de httpsgithubcomBenLauwensThinkJuliajlblobmastersrcsolutionschap13jl y siga los pasos descritos anteriormente paraencapsular las variables globales como atributos de una nueva estructurallamada Markov

Glosariocodificar

Representar un conjunto de valores utilizando otro conjunto de valoresgenerando una asociacioacuten entre ellos

prueba unitariaManera estandarizada de probar que el coacutedigo estaacute correcto

enchapadoUn meacutetodo o funcioacuten que mejora la interfaz de otra funcioacuten sin hacermuchos caacutelculos

Glosario 239

crear subtiposLa capacidad de definir una jerarquiacutea de tipos relacionados

tipo abstractoUn tipo que puede ser padre de otro tipo

tipo concretoUn tipo que se puede construir

subtipoUn tipo que tiene como padre un tipo abstracto

supertipoUn tipo abstracto que es el padre de otro tipo

relacioacuten ES-UNUna relacioacuten entre un subtipo y su supertipo

relacioacuten TIENE-UNUna relacioacuten entre dos tipos donde las instancias de un tipo contienenreferencias a instancias del otro

dependenciaUna relacioacuten entre dos tipos donde las instancias de un tipo usan instanciasdel otro tipo pero no las almacenan como atributos

diagrama de tiposUn diagrama que muestra los tipos en un programa y las relaciones entreellos

multiplicidadUna notacioacuten en un diagrama de tipo que muestra para una relacioacutenTIENE-UN cuaacutentas referencias hay a instancias de otra clase

encapsulado de datosUn plan de desarrollo de programas que implica hacer un prototipo que usevariables globales y una versioacuten final que convierta las variables globales enatributos de instancia

Ejercicios

Ejercicio 18-4

Para el siguiente programa dibuje un diagrama de tipos que muestre estos tiposy las relaciones entre ellos

240 Capiacutetulo 18 Subtipos

abstract type PadrePingPong end

struct Ping lt PadrePingPong pong PadrePingPongend

struct Pong lt PadrePingPong pings ArrayPing 1 function Pong(pings=ArrayPing 1()) new(pings) endend

function agregarping(pongPong pingPing) push(pongpings ping) nothingend

pong = Pong()ping = Ping(pong)agregarping(pong ping)

Ejercicio 18-5

Escriba un meacutetodo llamado repartir que tome tres paraacutemetros un Mazo elnuacutemero de manos y el nuacutemero de naipes por mano Deberiacutea crear el nuacutemeroapropiado de objetos Mano repartir el nuacutemero apropiado de naipes por mano ydevolver un arreglo de Manos

Ejercicio 18-6

Las siguientes son las posibles manos en el poacuteker en orden de valor creciente yprobabilidad decreciente

parejaDos cartas del mismo nuacutemero

doble parejaDos pares de cartas del mismo nuacutemero

triacuteoTres cartas del mismo nuacutemero

escaleraCinco cartas consecutivas (los ases pueden ser considerados altos o bajospor lo tanto As-2-3-4-5 es escalera 10-Jota-Reina-Rey-As tambieacuten pero

Ejercicios 241

Reina-Rey-As-2-3 no)

colorCinco cartas del mismo palo

fullTres cartas iguales en su valor maacutes otras dos iguales en su valor

poacutekerCuatro cartas iguales en su valor

escalera de colorCinco cartas consecutivas del mismo palo

El objetivo de este ejercicio es estimar la probabilidad de tener cada una de estasmanos

1 Agregue meacutetodos llamados tienepareja tienedoblepareja etc quedevuelvan true o false seguacuten si la mano cumple o no con los criteriosrelevantes Su coacutedigo deberiacutea funcionar correctamente para manos quecontengan cualquier nuacutemero de naipes (aunque 5 y 7 son los tamantildeos maacutescomunes)

2 Escriba un meacutetodo llamado clasificar que descubra la clasificacioacuten de mayorvalor para una mano y defina el atributo etiqueta con esta clasificacioacuten Porejemplo una mano de 7 cartas que contiene un color y una pareja debeetiquetarse como color

3 Cuando esteacute convencido de que sus meacutetodos de clasificacioacuten estaacutenfuncionando correctamente estime las probabilidades de las distintasmanos Escriba una funcioacuten que baraje un mazo de naipes la divida endiferentes manos clasifique las manos y cuente la cantidad de veces queaparecen varias clasificaciones

4 Imprima una tabla de las clasificaciones y sus probabilidades Ejecute suprograma con un nuacutemero cada vez mayor de manos hasta que los valores desalida converjan con un grado razonable de precisioacuten Compare susresultados con los valores en httpsenwikipediaorgwikiHand_rankings

242 Capiacutetulo 18 Subtipos

Capiacutetulo 19 Extra SintaxisUno de los objetivos de este libro es ensentildearle lo justo y necesario de Julia Seexplica una sola forma de hacer las cosas y en ocasiones se deja como ejercicioal lector una segunda manera

Ahora se veraacuten algunos temas que se han dejado de lado pero que son uacutetilesJulia proporciona una serie de caracteriacutesticas que no son realmente necesarias(se puede escribir un buen coacutedigo sin ellas) pero a veces permiten escribir uncoacutedigo maacutes conciso legible yo eficiente

En este capiacutetulo y el siguiente se discute aquello que se ha omitido en loscapiacutetulos anteriores

bull maacutes sintaxis

bull funciones tipos y macros disponibles directamente de Base

bull funciones tipos y macros de la Biblioteca Estaacutendar (Standard Library)

Tuplas con nombreEs posible colocarle nombre a los componentes de una tupla creando una tuplacon nombre

juliagt x = (a=1 b=1+1)(a = 1 b = 2)juliagt xa1

En las tuplas con nombre se puede acceder a los atributos con su nombreutilizando la sintaxis de punto (xa)

FuncionesLas funciones en Julia tambieacuten se pueden definir mediante una sintaxiscompacta de la siguiente forma

juliagt f(xy) = x + yf (generic function with 1 method)

Funciones Anonimas

Podemos definir una funcioacuten sin especificar su nombre

Tuplas con nombre 243

juliagt x -gt x^2 + 2x - 11 (generic function with 1 method)juliagt function (x) x^2 + 2x - 1 end3 (generic function with 1 method)

Estos son ejemplos de funciones anoacutenimas Las funciones anoacutenimasgeneralmente se usan como argumento de otra funcioacuten

juliagt using Plots

juliagt plot(x -gt x^2 + 2x - 1 0 10 xlabel=x ylabel=y)

Figura 24 muestra el resultado del comando plot (graficar en ingleacutes)

Figura 24 Plot

Argumentos con nombre

Tambieacuten se puede poner nombre a los argumentos de una funcioacuten

juliagt function migrafico(x y style=continua width=1 color=negro) endmigrafico (generic function with 1 method)juliagt migrafico(010 010 style=dotted color=blue)

Los argumentos con nombre en una funcioacuten se especifican despueacutes de un punto ycoma en la especificacioacuten pero al llamar a la funcioacuten se pueden utilizar solocomas

244 Capiacutetulo 19 Extra Sintaxis

Clausuras

Una clausura es una teacutecnica que permite que una funcioacuten capture una variabledefinida fuera del aacutembito de la funcioacuten

juliagt foo(x) = ()-gtxfoo (generic function with 1 method)

juliagt bar = foo(1)1 (generic function with 1 method)

juliagt bar()1

En este ejemplo la funcioacuten foo devuelve una funcioacuten anoacutenima que tiene acceso alargumento x de la funcioacuten foo bar apunta a la funcioacuten anoacutenima y devuelve elvalor del argumento de foo

BloquesUn bloque es una forma de agrupar varias sentencias Un bloque comienza con lapalabra reservada begin y termina con end

En Capiacutetulo 4 se presentoacute la macro svg

ὂ = Turtle()svg begin forward(ὂ 100) turn(ὂ -90) forward(ὂ 100)end

En este ejemplo la macro svg tiene un uacutenico argumento un bloque queagrupa 3 llamadas a funciones

Bloques let

Un bloque let es uacutetil para crear nuevas ligaduras (o bindings) es decir variableslocales que pueden apuntar a valores

Bloques 245

juliagt x y z = -1 -1 -1

juliagt let x = 1 z show x y z endx = 1y = -1ERROR UndefVarError z not definedjuliagt show x y zx = -1y = -1z = -1

En el ejemplo la primera macro show muestra la variable local x la variableglobal y y la variable local indefinida z Las variables globales se mantienenintactas

Bloques do

En Seccioacuten 142 se cierra el archivo despueacutes de terminar de escribir en eacutel Estose puede hacer automaacuteticamente usando un Bloque do

juliagt datos = El Cid convoca a sus vasallosneacutestos se destierran coneacutelnEl Cid convoca a sus vasallosneacutestos se destierran con eacutelnjuliagt open(salidatxt w) do fout write(fout datos) end61

En este ejemplo fout es el archivo stream utilizado para la salida

Esto es equivalente a

juliagt f = fout -gt begin write(fout datos) end3 (generic function with 1 method)juliagt open(f salidatxt w)61

La funcioacuten anoacutenima se utiliza como primer argumento de la funcioacuten open

246 Capiacutetulo 19 Extra Sintaxis

function open(fFunction args) io = open(args) try f(io) finally close(io) endend

Un bloque do puede capturar variables de su aacutembito envolvente (enclosedscope) Por ejemplo la variable datos en el ejemplo anterior de open do escapturada desde el aacutembito externo

Estructuras de control

Operador ternario

El operador ternario puede utilizarse en vez de una sentencia if-elseif Estasentencia se usa cuando se necesita elegir entre diferentes expresiones con valoruacutenico

juliagt a = 150150juliagt a 2 == 0 println(par) println(impar)par

La expresioacuten que va antes de es una expresioacuten de condicioacuten Si la condicioacuten estrue se evaluacutea la expresioacuten que va antes de De lo contrario se evaluacutea laexpresioacuten que va despueacutes de

Evaluacioacuten de cortocircuito

Los operadores ampamp y || realizan una evaluacioacuten de cortocircuito es decir seevaluacutea el siguiente argumento solo cuando es necesario para determinar el valorfinal

Por ejemplo una funcioacuten factorial recursiva podriacutea definirse asiacute

function fact(nInteger) n gt= 0 || error(n debe ser no negativo) n == 0 ampamp return 1 n fact(n-1)end

Estructuras de control 247

Tarea (o Corrutina)

Una tarea es una estructura de control que puede ceder el control de formacooperativa sin hacer return En Julia una tarea puede implementarse como unafuncioacuten con un objeto Channel como primer argumento Se usa un channel parapasar valores de la funcioacuten a la sentencia que la llama

El teacutermino cooperativo alude a que los programas deben cooperar para quetodo el esquema de programacioacuten funcione

La secuencia de Fibonnaci se puede generar mediante una tarea

function fib(cChannel) a = 0 b = 1 put(c a) while true put(c b) (a b) = (b a+b) endend

put almacena valores en un objeto channel y take lee valores desde eacutel

juliagt fib_gen = Channel(fib)

juliagt take(fib_gen)0juliagt take(fib_gen)1juliagt take(fib_gen)1juliagt take(fib_gen)2juliagt take(fib_gen)3

El constructor Channel crea la tarea La funcioacuten fib se suspende despueacutes de cadallamada a put y se reanuda al llamar a take Por razones de rendimiento sealmacenan varios valores de la secuencia en el objeto channel durante un ciclode reanudacioacutensuspensioacuten

Un objeto channel tambieacuten se puede usar como iterador

248 Capiacutetulo 19 Extra Sintaxis

juliagt for val in Channel(fib) print(val ) val gt 20 ampamp break end0 1 1 2 3 5 8 13 21

Tipos

Tipos Primitivos

Un tipo concreto compuesto por bits se llama tipo primitivo A diferencia de lamayoriacutea de los lenguajes en Julia se puede declarar nuestros propios tiposprimitivos Los tipos primitivos estaacutendar se definen de la misma manera

primitive type Float64 lt AbstractFloat 64 endprimitive type Bool lt Integer 8 endprimitive type Char lt AbstractChar 32 endprimitive type Int64 lt Signed 64 end

El nuacutemero en las sentencias especifica cuaacutentos bits son necesarios

El siguiente ejemplo crea un tipo primitivo Byte y un constructor

juliagt primitive type Byte 8 end

juliagt Byte(valUInt8) = reinterpret(Byte val)Bytejuliagt b = Byte(0x01)Byte(0x01)

La funcioacuten reinterpret se usa para almacenar los bits de un entero sin signo con8 bits (UInt8) en el byte

Tipos Parameacutetricos

El sistema de tipos de Julia es parameacutetrico lo que significa que los tipos puedentener paraacutemetros

Los paraacutemetros de un tipo se colocan despueacutes del nombre del tipo entre llaves

struct PuntoTltReal xT yTend

Tipos 249

Con esto se define un nuevo tipo parameacutetrico PuntoTltReal que contiene doscoordenadas de tipo T que puede ser cualquier tipo que tenga Real comosupertipo

juliagt Punto(00 00)PuntoFloat64(00 00)

Ademaacutes de los tipos compuestos los tipos abstractos y los tipos primitivostambieacuten pueden tener paraacutemetros

OBSERVACIOacuteN

Para mejorar el rendimiento es totalmenterecomendable tener tipos concretos como atributos deuna estructura por lo que esta es una buena manera dehacer que Punto sea raacutepido y flexible

Union de Tipo

Una union de tipo es un tipo parameacutetrico abstracto que puede actuar comocualquiera de los tipos de sus argumentos

juliagt EnteroOCadena = UnionInt64 StringUnionInt64 Stringjuliagt 150 EnteroOCadena150juliagt Julia EnteroOCadenaJulia

Una unioacuten de tipos es en la mayoriacutea de los lenguajes informaacuteticos unaconstruccioacuten interna para trabajar con tipos Sin embargo Julia pone adisposicioacuten esta caracteriacutestica para sus usuarios ya que permite generar uncoacutedigo eficiente (cuando la unioacuten es entre pocos tipos) Esta caracteriacutestica otorgauna gran flexibilidad para controlar el dispatch

Meacutetodos

Meacutetodos Parameacutetricos

Las definiciones de meacutetodos tambieacuten pueden tener paraacutemetros de tipo quelimiten su especificacioacuten

250 Capiacutetulo 19 Extra Sintaxis

juliagt espuntoentero(pPuntoT) where T = (T === Int64)espuntoentero (generic function with 1 method)juliagt p = Punto(1 2)PuntoInt64(1 2)juliagt espuntoentero(p)true

Objetos Similares a Funciones

Cualquier objeto arbitrario de Julia puede hacerse invocable Tales objetosinvocables a veces se denominan funtores

struct PolinomioR coefVectorRend

function (pPolinomio)(x) val = pcoef[end] for coef in pcoef[end-1-11] val = val x + coef end valend

Para evaluar el polinomio simplemente debemos llamarlo

juliagt p = Polinomio([110100])PolinomioInt64([1 10 100])juliagt p(3)931

ConstructoresLos tipos parameacutetricos se pueden construir expliacutecita o impliacutecitamente

juliagt Punto(12) T implicitoPuntoInt64(1 2)juliagt PuntoInt64(1 2) T explicitoPuntoInt64(1 2)juliagt Punto(125) T implicitoERROR MethodError no method matching Punto(Int64 Float64)

Se generan constructores internos y externos por defecto para cada T

Constructores 251

struct PuntoTltReal xT yT PuntoT(xy) where TltReal = new(xy)end

Punto(xT yT) where TltReal = PuntoT(xy)

y tanto x como y deben ser del mismo tipo

Cuando x e y son de tipos diferentes se puede definir el siguiente constructorexterno

Punto(xReal yReal) = Punto(promote(xy))

La funcioacuten promote se detalla en Seccioacuten 1982

Conversioacuten y PromocioacutenJulia tiene un sistema para convertir argumentos de diferentes tipos a un tipocomuacuten Esto es llamado promocioacuten y aunque no es automaacutetico se puede realizarfaacutecilmente

Conversioacuten

Un valor se puede convertir de un tipo a otro

juliagt x = 1212juliagt typeof(x)Int64juliagt convert(UInt8 x)0x0cjuliagt typeof(ans)UInt8

Se pueden agregar nuestros propios meacutetodos convert

juliagt Baseconvert(TypePuntoT xArrayT 1) where TltReal =Punto(x)

juliagt convert(PuntoInt64 [1 2])PuntoInt64(1 2)

252 Capiacutetulo 19 Extra Sintaxis

Promocioacuten

Promocioacuten es la conversioacuten de valores de diferentes tipos a un solo tipo comuacuten

juliagt promote(1 25 3)(10 25 30)

Generalmente los meacutetodos para la funcioacuten promote no se definen directamentesino que se usa la funcioacuten auxiliar promot_rule para especificar las reglas de lapromocioacuten

promote_rule(TypeFloat64 TypeInt32) = Float64

MetaprogramacioacutenUn coacutedigo de Julia se puede representar como una estructura de datos del mismolenguaje Esto permite que un programa escriba y manipule su propio coacutedigo

Expresiones

Cada programa de Julia comienza como una cadena

juliagt prog = 1 + 21 + 2

El siguiente paso es analizar cada cadena en un objeto llamado expresioacutenrepresentado por el tipo de Julia Expr

juliagt ex = Metaparse(prog)(1 + 2)juliagt typeof(ex)Exprjuliagt dump(ex)Expr head Symbol call args ArrayAny((3)) 1 Symbol + 2 Int64 1 3 Int64 2

La funcioacuten dump muestra objetos expr con anotaciones

Las expresiones se pueden construir directamente con el prefijo entrepareacutentesis o usando un bloque quote

Metaprogramacioacuten 253

juliagt ex = quote 1 + 2 end

eval

Julia puede evaluar un objeto de expresioacuten usando la funcioacuten eval

juliagt eval(ex)3

Cada moacutedulo tiene su propia funcioacuten eval que evaluacutea las expresiones de suaacutembito

AVISO Generalmente si un coacutedigo tiene muchas llamadas a eval significaque algo estaacute mal eval se considera malo

Macros

Las macros pueden incluir coacutedigo generado en un programa Una macro asociauna tupla de objetos Expr directamente con una expresioacuten compilada

Aquiacute hay una macro simple

macro contenedorvariable(contenedor elemento) return esc(($(Symbol(contenedorelemento)) = $contenedor[$elemento]))end

Las macros se llaman anteponiendo (arroba) a su nombre La llamada a lamacro contenedorvariable letras 1 se reemplaza por

(letras1 = letras[1])

macroexpand contenedorvariable letras 1 returns this expression which isextremely useful for debugging

Este ejemplo ilustra coacutemo una macro puede acceder al nombre de susargumentos algo que una funcioacuten no puede hacer Se debe escapar de laexpresioacuten de retorno con esc porque debe resolverse en el entorno de la macrollamada

254 Capiacutetulo 19 Extra Sintaxis

NOTA

iquestPor queacute usar Macros

Las macros generan e incluyen fragmentos de coacutedigopersonalizado durante el tiempo de anaacutelisis es decir antes deejecutar el programa completo

Funciones Generadas

La macro generated crea coacutedigo especializado para meacutetodos dependiendo deltipo de los argumentos

generated function cuadrado(x) println(x) (x x)end

El cuerpo devuelve una expresioacuten citada como una macro

Para la sentencia que llama la funcioacuten generada se comporta como una funcioacutennormal

juliagt x = cuadrado(2) nota la salida es de la instruccioacuten println ()que estaacute en el cuerpoInt64juliagt x ahora imprimimos x4juliagt y = cuadrado(spam)Stringjuliagt yspamspam

Datos FaltantesLos datos faltantes se pueden representar a traveacutes del objeto missing que es lainstancia uacutenica del tipo Missing

Los arreglos pueden contener datos que faltan missing values en ingleacutes

juliagt a = [1 missing]2-element ArrayUnionMissing Int641 1 missing

El tipo de dicho arreglo es UnionMissing T doacutende T es el tipo de los valoresque realmente tenemos en el arreglo

Datos Faltantes 255

Las funciones de reduccioacuten devuelven missing cuando se invocan con arreglosque contienen valores que faltan

juliagt sum(a)missing

En este caso se puede usar la funcioacuten skipmissing para omitir los valores quefaltan

juliagt sum(skipmissing([1 missing]))1

Llamar a Coacutedigo de C y FortranSe escribe mucho coacutedigo en C o Fortran Reutilizar un coacutedigo que ya ha sidoprobado generalmente es mejor que escribir su propia versioacuten en otro lenguajeJulia puede llamar directamente a las bibliotecas C o Fortran existentesutilizando la sintaxis ccall

En Seccioacuten 146 se presentoacute una interfaz de Julia de la biblioteca GDBM defunciones de base de datos La biblioteca estaacute escrita en C Para cerrar la base dedatos se debe hacer una llamada a la funcioacuten close(db)

Baseclose(dbmDBM) = gdbm_close(dbmhandle)

function gdbm_close(handlePtrCvoid) ccall((gdbm_close libgdbm) Cvoid (PtrCvoid) handle)end

Un objeto dbm tiene un atributo handle de tipo PtrCvoid Este atributocontiene un puntero de C que apunta a la base de datos Para cerrar la base dedatos debe llamarse a la funcioacuten de C gdbm_close teniendo como uacutenicoargumento el puntero C apuntando a la base de datos sin valor de retorno Juliahace esto directamente con la funcioacuten ccall que tiene como argumentos

bull una tupla que consiste en un siacutembolo que contiene el nombre de la funcioacutenque queremos llamar gdbm_close y la libreriacutea compartida especificadacomo una cadena +libgdm

bull el tipo de retorno Cvoid

bull una tupla de tipos de argumentos (PtrCvoid)

bull los valores del argumento handle

Una visioacuten completa de la libreriacutea GDBM se puede encontrar como ejemplo enlas fuentes de ThinkJulia

256 Capiacutetulo 19 Extra Sintaxis

Glossaryclausura

Funcioacuten que captura variables del aacutembito en doacutende estaacute definida

bloque letBloque de asignacioacuten de nuevas ligaduras variables

funcioacuten anoacutenimaFuncioacuten definida sin nombre

tupla con nombreTupla con componentes con nombre

argumentos con nombreArgumentos identificados por su nombre en vez de solo por la posicioacuten queocupan

bloque doConstruccioacuten usada para definir y llamar a una funcioacuten anoacutenima parecida aun bloque de coacutedigo normal

operador ternarioOperador de estructura de control que toma tres operandos una condicioacutenuna expresioacuten que se ejecutaraacute si la condicioacuten devuelve true y una expresioacutenque se ejecutaraacute si la condicioacuten devuelve false

evaluacioacuten de cortocircuitoEvaluacioacuten de un operador booleano para el que se ejecuta o evaluacutea elsegundo argumento solo si el primero no es suficiente para determinar elvalor de la expresioacuten

tareas (corrutina)Caracteriacutestica de las estructuras de control que permite suspender yreanudar caacutelculos de manera flexible

tipo primitivoTipo concreto cuyos datos estaacuten compuestos de bits

unioacuten de tiposTipo que incluye todas las instancias de cualquiera de sus tipos deparaacutemetros como objetos

Glossary 257

tipo parameacutetricoTipo que tiene paraacutemetros

funtorObjeto con un meacutetodo asociado para que sea invocable

conversioacutenPermite convertir un valor de un tipo a otro

promocioacutenConversioacuten de valores de diferentes tipos a un solo tipo comuacuten

expresioacutenTipo de Julia que contiene una construccioacuten de lenguaje

macroForma de incluir el coacutedigo generado en el cuerpo final de un programa

funciones generadasFunciones capaces de generar coacutedigo especializado seguacuten el tipo de losargumentos

datos faltantesInstancias que representan datos sin valor

258 Capiacutetulo 19 Extra Sintaxis

Capiacutetulo 20 Extra Base y Libreriacutea EstaacutendarJulia tiene todo lo necesario El moacutedulo Base contiene las funciones tipos ymacros maacutes uacutetiles los cuales estaacuten disponibles directamente en Julia

Julia tambieacuten posee una gran cantidad de moacutedulos especializados en suBiblioteca Estaacutendar (moacutedulos para fechas computacioacuten distribuida aacutelgebralineal perfiles nuacutemeros aleatorios entre otros) Las funciones los tipos y lasmacros definidos en la Biblioteca Estaacutendar deben importarse antes de poderusarse

bull import _Module_ importa el modulo y _Modulefn_(x) llama a la funcioacuten _fn_

bull using _Module_ importa todas las funciones tipos y macros exportadas de_Module_

Ademaacutes es posible agregar maacutes funciones a una gran cantidad de paquetes(httpsjuliaobservercom)

Este capiacutetulo no es un reemplazo de la documentacioacuten oficial de Julia Soacutelo sedan algunos ejemplos para ilustrar lo que es posible hacer sin ser exhaustivoLas funciones ya vistas no estaacuten incluidas Se puede encontrar una explicacioacutenmaacutes completa en httpsdocsjulialangorg

Midiendo el RendimientoHemos visto que algunos algoritmos funcionan mejor que otros fibonnaci enSeccioacuten 116 es mucho maacutes raacutepido que fib en Seccioacuten 67 La macro timepermite cuantificar la diferencia

juliagt fib(1)1juliagt fibonacci(1)1juliagt time fib(40) 0567546 seconds (5 allocations 176 bytes)102334155juliagt time fibonacci(40) 0000012 seconds (8 allocations 1547 KiB)102334155

time imprime el tiempo que tardoacute en ejecutarse la funcioacuten el nuacutemero deasignaciones (allocations) y la memoria asignada antes de devolver el resultadoLa funcioacuten fibonacci que guarda resultados previos es mucho maacutes raacutepida peronecesita maacutes memoria

Midiendo el Rendimiento 259

El teorema No free lunch dice que no existe un uacutenico modelo que funcionemejor en todos los casos

OBSERVACIOacuteN

Para comparar dos algoritmos estos debenimplementarse como funciones Una funcioacuten en Julia secompila la primera vez que se ejecuta por lo tanto sedebe excluir la primera vez que se llama a estasfunciones al medir el rendimiento De lo contrariotambieacuten se mediriacutea el tiempo de compilacioacuten

El paquete BenchmarkTools (httpsgithubcomJuliaCIBenchmarkToolsjl) proporciona la macro btime querealiza una evaluacioacuten comparativa de la maneracorrecta iexclAsiacute que uacutesela

Colecciones y Estructuras de DatosEn Seccioacuten 136 se usan diccionarios para encontrar las palabras que apareciacuteanen un documento y que no apareciacutean en un arreglo de palabras La funcioacuten quese escribioacute tomaba d1 que conteniacutea las palabras del documento como claves yd2 que conteniacutea el arreglo de palabras Y devolviacutea un diccionario que conteniacutealas claves de d1 que no estaban en d2

function resta(d1 d2) res = Dict() for clave in keys(d1) if clave notin keys(d2) res[clave] = nothing end end resend

En todos estos diccionarios los valores son nothing porque nunca son usadosCon esto se estaacute desperdiciando espacio de almacenamiento

Julia ofrece otro tipo integrado llamado conjunto que se comporta como unacoleccioacuten de claves de diccionario sin valores Agregar elementos a un conjuntoes raacutepido y tambieacuten lo es verificar si un elemento forma parte de eacutel Ademaacutes losconjuntos proporcionan funciones y operadores para calcular operaciones deconjuntos

Por ejemplo la resta de conjuntos estaacute disponible como una funcioacuten llamadasetdiff Entonces reescribiendo resta

260 Capiacutetulo 20 Extra Base y Libreriacutea Estaacutendar

function resta(d1 d2) setdiff(d1 d2)end

El resultado es un conjunto en vez de un diccionario

Algunos de los ejercicios en este libro se pueden hacer de manera eficiente yconcisa con conjuntos Por ejemplo a continuacioacuten se muestra una solucioacuten pararepetido de Seccioacuten 10157 que usa un diccionario

function repetido(t) d = Dict() for x in t if x isin d return true end d[x] = nothing end falseend

Cuando un elemento aparece por primera vez se agrega al diccionario Si elmismo elemento aparece nuevamente la funcioacuten devuelve true

Usando conjuntos podemos escribir la misma funcioacuten

function repetido(t) length(Set(t)) lt length(t)end

Un elemento solo puede aparecer en un conjunto una vez por lo que si unelemento en t aparece maacutes de una vez el conjunto seraacute maacutes pequentildeo que t Si nohay elementos repetidos el conjunto tendraacute el mismo tamantildeo que t

Tambieacuten podemos usar conjuntos para hacer algunos de los ejercicios deCapiacutetulo 9 Por ejemplo aquiacute hay una versioacuten de usasolo con un bucle

function usasolo(palabra disponibles) for letra in palabra if letra notin disponibles return false end end trueend

Colecciones y Estructuras de Datos 261

usasolo comprueba si todas las letras en palabra estaacuten en disponibles Podemosreescribir esta funcioacuten

function usasolo(palabra disponibles) Set(palabra) sube Set(disponibles)end

El operador sube (subseteq TAB) verifica si un conjunto es un subconjunto deotro incluida la posibilidad de que sean iguales lo cual es cierto si todas lasletras en palabra aparecen en disponibles

Exercise 20-1

Reescriba la funcioacuten evita de Capiacutetulo 9 usando conjuntos

MatemaacuteticasTambieacuten se pueden usar nuacutemeros complejos en Julia La constante global im estaacuteasociada al nuacutemero complejo que representa la raiacutez cuadrada principal de

Ahora se puede verificar la identidad de Euler

juliagt ℯ^(imπ)+100 + 12246467991473532e-16im

El siacutembolo ℯ (euler TAB) es la base de los logaritmos naturales

Se puede analizar la naturaleza compleja de las funciones trigonomeacutetricas

Se puede probar esta foacutermula para diferentes valores de

juliagt x = 0012π000162juliagt cos(x) == 05(ℯ^(imx)+ℯ^(-imx))true

Aquiacute se muestra otro ejemplo del operador punto Julia tambieacuten permite usarvalores numeacutericos con identificadores (siacutembolos leacutexicos que nombran entidadescomo π) como en 2π

262 Capiacutetulo 20 Extra Base y Libreriacutea Estaacutendar

CadenasEn Capiacutetulo 8 y Capiacutetulo 9 se realizan algunas buacutesquedas en cadenas AdemaacutesJulia puede usar expresiones regulares (o regexes) compatibles con Perl lo quefacilita la tarea de encontrar patrones complejos en cadenas

La funcioacuten usasolo se puede implementar como una expresioacuten regular

function usasolo(palabra disponibles) r = Regex([^$(disponibles)]) occursin(r palabra)end

La expresioacuten regular busca un caraacutecter que no estaacute en la cadena disponible yoccursin devuelve true si el patroacuten se encuentra en palabra

juliagt usasolo(banana abn)truejuliagt usasolo(bananas abn)false

Las expresiones regulares tambieacuten se pueden construir como literales de cadenano estaacutendar con el prefijo r

juliagt match(r[^abn] banana)

juliagt m = match(r[^abn] bananas)RegexMatch(s)

En este caso la interpolacioacuten de cadenas no estaacute permitida La funcioacuten matchdevuelve nothing si no se encuentra el patroacuten de lo contrario devuelve un objetoregexmatch

Podemos extraer la siguiente informacioacuten de un objeto regexmatch

bull La subcadena que coincide mmatch

bull Las subcadenas que coinciden en forma de arreglo de cadenas mcaptures

bull La primera posicioacuten en la que se encuentra el patroacuten moffset

bull Las posiciones de las subcadenas que coinciden en forma de arreglomoffsets

Cadenas 263

juliagt mmatchsjuliagt moffset7

Las expresiones regulares son extremadamente poderosas y el manual de PERLhttpperldocperlorgperlrehtml explica coacutemo realizar hasta las buacutesquedas maacutesextrantildeas

ArreglosEn el Capiacutetulo 10 se usa un objeto de arreglo unidimensional con un iacutendice paraacceder a sus elementos Sin embargo en Julia las matrices sonmultidimensionales

Se puede crear una matriz de ceros de 2 por 3

juliagt z = zeros(Float64 2 3)2times3 ArrayFloat642 00 00 00 00 00 00juliagt typeof(z)ArrayFloat642

El tipo de esta matriz es un arreglo que contiene nuacutemeros de punto flotante Estamatriz es de 2 dimensiones

La funcioacuten size devuelve una tupla con el nuacutemero de elementos en cadadimensioacuten

juliagt size(z)(2 3)

La funcioacuten ones construye una matriz con elementos de valor unitario

juliagt s = ones(String 1 3)1times3 ArrayString2

El elemento de valor unitario de una cadena es una cadena vaciacutea

264 Capiacutetulo 20 Extra Base y Libreriacutea Estaacutendar

AVISO

s no es un arreglo unidimensional

juliagt s == [ ]false

s es un vector fila y [ ] es un vector columna

Se puede crear una matriz usando espacios para separar elementos en una fila ypunto y coma para separar filas

juliagt a = [1 2 3 4 5 6]2times3 ArrayInt642 1 2 3 4 5 6

Se pueden usar corchetes para modificar elementos de una matriz

juliagt z[12] = 11juliagt z[23] = 11juliagt z2times3 ArrayFloat642 00 10 00 00 00 10

Se pueden usar porciones en cada dimensioacuten para seleccionar un subgrupo deelementos

juliagt u = z[2end]2times2 ArrayFloat642 10 00 00 10

El operador aplica una operacioacuten en todas las dimensiones

juliagt ℯ^(imu)2times2 ArrayComplexFloat642 0540302+0841471im 10+00im 10+00im 0540302+0841471im

Arreglos 265

InterfacesJulia especifica algunas interfaces informales para definir comportamientos esdecir meacutetodos con un objetivo especiacutefico Cuando se extienden estos meacutetodospara un tipo los objetos de ese tipo se pueden usar para construir estoscomportamientos

Si parece un pato nada como un pato y grazna como un pato entoncesprobablemente sea un pato

En Seccioacuten 67 implementamos la funcioacuten fib que devuelve el elemento -eacutesimode la secuencia de Fibonnaci

Recorrer los valores de una coleccioacuten lo cual recibe el nombre de iteracioacuten esuna interfaz de este tipo Se puede crear un iterador que devuelva la secuenciade Fibonacci

struct FibonacciTltReal endFibonacci(dDataType) = dltReal Fibonaccid() error(No Real type)

Baseiterate(FibonacciT) where TltReal = (zero(T) (one(T) one(T)))Baseiterate(FibonacciT stateTupleT T) where TltReal =(state[1] (state[2] state[1] + state[2]))

Se implementa un tipo parameacutetrico Fibonacci sin atributos un constructorexterno y dos meacutetodos iterate Se llama al primer meacutetodo iterate para inicializarel iterador y este devuelve una tupla que consta de un primer valor 0 y unestado El estado en este caso es una tupla que contiene el segundo y el tercervalor 1 y 1

Se llama al segundo meacutetodo iterate para obtener el siguiente valor de lasecuencia de Fibonacci y devuelve una tupla que tiene como primer elemento elsiguiente valor y como segundo elemento el estado que es una tupla con los dosvalores siguientes

Ahora se puede usar Fibonacci en un bucle for

juliagt for e in Fibonacci(Int64) e gt 100 ampamp break print(e ) end0 1 1 2 3 5 8 13 21 34 55 89

Parece sacado debajo de la manga pero la explicacioacuten es simple Un bucle for enJulia

266 Capiacutetulo 20 Extra Base y Libreriacutea Estaacutendar

for i in iter bodyend

se traduce en

next = iterate(iter)while next == nothing (i state) = next body next = iterate(iter state)end

Este es un ejemplo de coacutemo una interfaz bien definida permite que unaimplementacioacuten use todas las funciones disponibles en esta interfaz

Moacutedulo Interactive UtilitiesYa se ha visto el moacutedulo InteractiveUtils en Seccioacuten 1810 La macro which essolo una de las tantas opciones

La biblioteca LLVM transforma el coacutedigo de Julia en coacutedigo de maacutequina envarios pasos Podemos visualizar la salida de cada etapa

Aquiacute se muestra un ejemplo simple

function sumacuadrada(aFloat64 bFloat64) a^2 + b^2end

El primer paso es mirar el coacutedigo de bajo nivel (lowered code)

juliagt using InteractiveUtils

juliagt code_lowered sumacuadrada(30 40)CodeInfo(1 1 = Coreapply_type(BaseVal 2) 2 = (1)() 3 = Baseliteral_pow(^ a 2) 4 = Coreapply_type(BaseVal 2) 5 = (4)() 6 = Baseliteral_pow(^ b 5) 7 = 3 + 6 return 7)

Moacutedulo Interactive Utilities 267

La macro code_lowered devuelve un arreglo de una representacioacuten intermediadel coacutedigo que utiliza el compilador para generar coacutedigo optimizado

El siguiente paso antildeade informacioacuten del tipo

juliagt code_typed sumacuadrada(30 40)CodeInfo(1 1 = Basemul_float(a a)Float64 2 = Basemul_float(b b)Float64 3 = Baseadd_float(1 2)Float64 return 3) =gt Float64

El tipo de resultados intermedios y el valor de retorno se infiere correctamente

Esta representacioacuten del coacutedigo se transforma en coacutedigo LLVM

juliagt code_llvm sumacuadrada(30 40) none1 within `sumacuadradadefine double julia_sumacuadrada_6080(double double) top none2 within `sumacuadrada intfuncsjl296 within `literal_pow floatjl405 within ` 2 = fmul double 0 0 3 = fmul double 1 1 floatjl401 within `+ 4 = fadd double 2 3 ret double 4

Y finalmente se genera el coacutedigo de maacutequina

268 Capiacutetulo 20 Extra Base y Libreriacutea Estaacutendar

juliagt code_native sumacuadrada(30 40) text none2 within `sumacuadrada intfuncsjl296 within `literal_pow floatjl405 within ` vmulsd xmm0 xmm0 xmm0 vmulsd xmm1 xmm1 xmm1 floatjl401 within `+ vaddsd xmm1 xmm0 xmm0 retq nopl (rax)

DepuracioacutenLas macros Logging son una alternativa al andamiaje con sentencias deimpresioacuten

juliagt warn iexclOh vosotros los que entraacuteis abandonad la depuracioacuten conprintf Warning iexclOh vosotros los que entraacuteis abandonad la depuracioacuten conprintf Main REPL[1]1

Las sentencias de depuracioacuten (debug) no tienen que eliminarse del coacutedigo Porejemplo en contraste con el warn anterior

juliagt debug La suma de algunos valores $(sum(rand(100)))

debug por defecto no produce salida En este caso sum(rand(100)) nunca seevaluaraacute a menos que debug logging esteacute habilitado

El nivel de logging puede seleccionarse mediante la variable de entornoJULIA_DEBUG

$ JULIA_DEBUG=all julia -e debug La suma de algunos valores$(sum(rand(100))) Debug La suma de algunos valores 47116520814555024 Main none1

Aquiacute hemos utilizado all para obtener toda la informacioacuten de depuracioacuten perotambieacuten se puede optar por generar salida solo para un archivo o moacuteduloespeciacutefico

Depuracioacuten 269

Glosarioregex

Expresioacuten regular una secuencia de caracteres que definen un patroacuten debuacutesqueda

matrizArreglo bidimensional

representacioacuten intermediaEstructura de datos utilizada internamente por un compilador pararepresentar el coacutedigo fuente

coacutedigo de maacutequinaInstrucciones que pueden ser ejecutadas directamente por la unidad centralde procesamiento de una computadora

debug loggingAlmacenar mensajes de depuracioacuten en un registro (log)

270 Capiacutetulo 20 Extra Base y Libreriacutea Estaacutendar

Capiacutetulo 21 DepuracioacutenAl depurar es necesario distinguir entre los diferentes tipos de errores pararastrearlos maacutes raacutepidamente

bull Los errores de sintaxis se descubren cuando el inteacuterprete traduce el coacutedigofuente a coacutedigo de bytes Estos errores indican que hay una falla en laestructura del programa Por ejemplo omitir la palabra reservada end alfinal de un bloque de funciones genera el mensaje ERROR LoadErrorsyntax incomplete function requires end

bull Los errores en tiempo de ejecucioacuten se presentan si algo falla mientras seejecuta el programa La mayoriacutea de los mensajes de error en tiempo deejecucioacuten indican doacutende ocurrioacute el error y queacute funciones se estabanejecutando Ejemplo Una recursioacuten infinita eventualmente causa el error entiempo de ejecucioacuten ERROR StackOverflowError

bull Los errores semaacutenticos ocurren cuando un programa se ejecuta sin generarmensajes de error pero no hace lo que deberiacutea Por ejemplo una expresioacutenpuede no evaluarse en el orden esperado generando un resultadoincorrecto

El primer paso en la depuracioacuten es averiguar el tipo de error al que se enfrentaAunque las siguientes secciones estaacuten organizadas por tipo de error algunasteacutecnicas son aplicables en maacutes de una situacioacuten

Errores de SintaxisLos errores de sintaxis suelen ser faacuteciles de corregir una vez se descubre cuaacutelesson Desafortunadamente muchas veces los mensajes de error no son uacutetiles Losmensajes maacutes comunes son

ERROR LoadError syntax incomplete premature end of input

y

ERROR LoadError syntax unexpected =

los cuales no son muy informativos

Por otro lado el mensaje indica en queacute parte del programa se produjo elproblema En realidad indica doacutende Julia notoacute que habiacutea un problema que no esnecesariamente doacutende estaacute el error A veces el error es anterior a la ubicacioacutendel mensaje de error generalmente en la liacutenea anterior

Si estaacute programando incrementalmente el usuario deberiacutea tener casi localizadoel error ya que estaraacute en la uacuteltima liacutenea que agregoacute

Si estaacute copiando coacutedigo de un libro comience comparando su coacutedigo con el

Errores de Sintaxis 271

coacutedigo del libro y verifique cada letra Al mismo tiempo recuerde que el libropuede contener errores por lo que si ve algo que parece un error de sintaxis esposible que lo sea

Aquiacute hay algunas formas de evitar los errores de sintaxis maacutes comunes

1 Aseguacuterese de no estar usando una palabra reservada de Julia en un nombrede variable

2 Compruebe que tiene la palabra reservada end al final de cada sentenciacompuesta incluyendo los bloques for while if y function

3 Aseguacuterese de que las cadenas tengan su par de comillas de apertura ycierre Aseguacuterese de que todas las comillas sean comillas rectas y no otrotipo de comillas

4 Si tiene cadenas que ocupan varias liacuteneas con triples comillas aseguacuterese deque ha terminado la cadena correctamente Una cadena sin terminar puedeprovocar un error invalid token al final de su programa o puede hacer quela siguiente parte del programa sea tratada como una cadena hasta llegar ala siguiente cadena iexclEl segundo caso podriacutea no presentar mensaje de error

5 Un pareacutentesis sin cerrar mdash( or [mdash hace que Julia continuacutee con la liacuteneasiguiente como parte de la sentencia actual Generalmente se produce unerror casi inmediatamente en la siguiente liacutenea

6 Verifique el claacutesico error que se produce al ocupar = en lugar de == dentrode un condicional

7 Si tiene caracteres que no son ASCII en el coacutedigo (incluidas cadenas ycomentarios) esto podriacutea causar un problema aunque Julia generalmentemaneja caracteres no ASCII Tenga cuidado si pega texto de una paacutegina webu otra fuente

Si nada funciona pase a la siguiente seccioacuten hellip

Sigo haciendo cambios y no hay diferencia

Si el REPL dice que hay un error y usted no lo ve podriacutea deberse a que usted y elREPL no estaacuten viendo el mismo coacutedigo Verifique su entorno de programacioacutenpara asegurarse de que el programa que estaacute editando es el que Julia estaacutetratando de ejecutar

Si no estaacute seguro intente poner un error de sintaxis obvio y deliberado alcomienzo del programa Ahora ejecuacutetelo de nuevo Si REPL no encuentra elnuevo error no estaacute ejecutando el nuevo coacutedigo

Estas son algunas de las posibles razones

bull Editoacute el archivo y olvidoacute guardar los cambios antes de ejecutarlonuevamente Algunos entornos de programacioacuten hacen esto por usted pero

272 Capiacutetulo 21 Depuracioacuten

otros no

bull Cambioacute el nombre del archivo pero auacuten estaacute ejecutando el archivo con elnombre anterior

bull Algo en su entorno de desarrollo estaacute configurado incorrectamente

bull Si estaacute escribiendo un moacutedulo y estaacute usando using aseguacuterese de no darle asu moacutedulo el mismo nombre que uno de los moacutedulos estaacutendar de Julia

bull Si estaacute usando using para importar un moacutedulo recuerde que debe reiniciarREPL cuando modifique el coacutedigo en el moacutedulo Si vuelve a importar elmoacutedulo no ocurre nada

Si se queda atascado y no puede darse cuenta de lo que estaacute sucediendo unenfoque es comenzar de nuevo con un nuevo programa como iexclHola Mundo yasegurarse de que puede ejecutar este programa ya conocido Luego puedeagregar gradualmente las piezas del programa original al nuevo

Errores en Tiempo de EjecucioacutenUna vez que su programa es sintaacutecticamente correcto Julia puede leerlo y almenos comenzar a ejecutarlo iquestQueacute podriacutea salir mal

Mi programa no hace absolutamente nada

Este problema es comuacuten cuando su archivo consta de funciones y clases pero enrealidad no llama a ninguna funcioacuten para iniciar la ejecucioacuten Esto puede serintencional si soacutelo se busca importar este moacutedulo para suministrar clases yfunciones

Si no es intencional aseguacuterese de que haya una llamada a la funcioacuten en elprograma y aseguacuterese de que el flujo de ejecucioacuten pase por esta llamada (veaSeccioacuten 21223)

Mi programa se congela

Si un programa se detiene y parece no estar haciendo nada estaacute congeladoGeneralmente eso significa que estaacute atrapado en un bucle infinito o en unarecursioacuten infinita

bull Si hay un bucle en particular que le resulta sospechoso de poder provocar elproblema agregue una sentencia de impresioacuten justo antes del bucle quediga entrando al bucle y otra inmediatamente posterior que diga saliendodel bucle

Ejecute el programa Si recibe el primer mensaje y no el segundo tiene unbucle infinito Vea Seccioacuten 21221

bull La mayoriacutea de las veces una recursioacuten infinita haraacute que el programa se

Errores en Tiempo de Ejecucioacuten 273

ejecute por un rato y luego produzca un error ERROR LoadErrorStackOverflowError Si eso sucede vea Seccioacuten 21222

Si no obtiene este error pero sospecha que hay un problema con un meacutetodoo funcioacuten recursiva igual puede utilizar las teacutecnicas de Seccioacuten 21222

bull Si ninguno de esos pasos funciona comience a probar otros bucles y otrasfunciones y meacutetodos recursivos

bull Si esto no funciona quizaacutes es porque usted no entiende el flujo de ejecucioacutende su programa Vea Seccioacuten 21223

Bucle Infinito

Si cree tener un bucle infinito y cree saber cuaacutel es antildeada una sentencia deimpresioacuten que imprima los valores de las variables de la condicioacuten al final delbucle junto con el valor de la condicioacuten

Por ejemplo

while x gt 0 ampamp y lt 0 hacer algo con x hacer algo con y debug variables x y debug condicion x gt 0 ampamp y lt 0end

Ahora cuando ejecute el programa en modo de depuracioacuten veraacute el valor de lasvariables y la condicioacuten en cada iteracioacuten En la uacuteltima iteracioacuten la condicioacutendebe ser false Si el ciclo continuacutea podraacute ver los valores de x e y y podraacuteaveriguar por queacute no se actualizan correctamente

Recursioacuten Infinita

La mayoriacutea de las veces una recursioacuten infinita hace que el programa se ejecutedurante un tiempo y luego produzca un error

ERROR LoadError StackOverflowError

Si sospecha que una funcioacuten o un meacutetodo estaacute causando una recursioacuten infinitacomience por asegurarse de que hay un caso base En otras palabras deberiacuteahaber una condicioacuten que haga que la funcioacuten devuelva un valor sin hacer otrallamada recursiva Si no necesita revisar el algoritmo y encontrar ese caso base

Si hay un caso base pero el programa no parece llegar hasta eacutel antildeada unasentencia de impresioacuten al inicio de la funcioacuten que imprima los paraacutemetrosAhora cuando ejecute el programa veraacute el valor de los paraacutemetros cada vez quese llame la funcioacuten Si los paraacutemetros no se acercan al caso base eso le daraacute

274 Capiacutetulo 21 Depuracioacuten

alguna idea de por queacute no lo hace

Flujo de Ejecucioacuten

Si no estaacute seguro del flujo de ejecucioacuten en su programa antildeada sentencias deimpresioacuten al principio de cada funcioacuten con mensajes como ldquoentrando a la funcioacutenfunrdquo donde fun sea el nombre de la funcioacuten

Ahora cuando ejecute el programa se imprimiraacute una mensaje en cada funcioacuten amedida que estas sean llamadas

Cuando ejecuto el programa recibo una excepcioacuten

Si algo sale mal durante la ejecucioacuten Julia imprime un mensaje que incluye elnombre de la excepcioacuten la liacutenea del programa donde sucedioacute el problema y untrazado inverso

El trazado inverso identifica la funcioacuten que se estaacute ejecutando y la funcioacuten que lallamoacute y luego la funcioacuten que llamoacute a esa y asiacute sucesivamente En otras palabrastraza la ruta de las llamadas a las funciones que le llevaron a donde seencuentra Tambieacuten incluye los nuacutemeros de las liacuteneas de su archivo doacutendesuceden todas esas llamadas

El primer paso es examinar el lugar del programa donde ocurrioacute el error y ver sipuede adivinar lo que sucedioacute Estos son algunos de los errores en tiempo deejecucioacuten maacutes comunes

ArgumentErrorUno de los argumentos para llamar a una funcioacuten no tiene la formaesperada

BoundsErrorSe estaacute tratando de acceder a un elemento de un arreglo fuera de los liacutemitesde indexacioacuten

DomainErrorEl argumento de una funcioacuten o constructor no pertenece al dominio vaacutelido

DivideErrorSe intentoacute dividir un entero por 0

EOFErrorNo habiacutea maacutes datos disponibles para leer desde un archivo o stream

InexactErrorNo se puede convertir a un tipo

Errores en Tiempo de Ejecucioacuten 275

KeyErrorSe estaacute tratando de acceder o eliminar un elemento inexistente de un objetoAbstractDict (Dict) o Set

MethodErrorNo existe un meacutetodo con la especificacioacuten de tipo requerida en la funcioacutengeneacuterica dada Alternativamente no existe un meacutetodo uacutenico maacutes especiacutefico

OutOfMemoryErrorUna operacioacuten asignoacute demasiada memoria para que el sistema o elrecolector de basura opere correctamente

OverflowErrorEl resultado de una expresioacuten es demasiado grande para el tipo especificadoy se produce un desbordamiento

StackOverflowErrorUna llamada a funcioacuten trata de usar maacutes espacio que el que estaacute disponibleen la pila de llamadas Esto generalmente ocurre cuando una llamada serepite infinitamente

StringIndexErrorSe produjo un error al intentar acceder a un iacutendice invaacutelido de una cadena

SystemErrorFalloacute una llamada al sistema y se muestra un mensaje de error

TypeErrorError de asercioacuten de tipo o error producido al llamar a una funcioacutenintegrada con un tipo de argumento incorrecto

UndefVarErrorUn siacutembolo en el entorno (o aacutembito) actual no estaacute definido

Puse tantas sentencias de impresioacuten que me ahogo eninformacioacuten

Uno de los problemas de usar sentencias print en la depuracioacuten es que puedeterminar ahogado por tanta informacioacuten Hay dos formas de resolver estosimplificar la salida o simplificar el programa

Para simplificar la salida puede eliminar o comentar (convertir en comentariosno evaluados coacutemo oacuterdenes del programa) las sentencias print que no sean uacutetileso combinarlas Tambieacuten puede dar a la salida un formato que la haga maacutescomprensible

276 Capiacutetulo 21 Depuracioacuten

Para simplificar el programa puede hacer varias cosas Primero puede reducir laescala del problema en el que estaacute trabajando el programa Por ejemplo si estaacutebuscando algo en una lista buacutesquelo en una lista pequentildea Si el programa aceptaentradas del usuario ingrese la entrada maacutes simple que provoque el problema

Segundo puede limpiar el programa Elimine el coacutedigo muerto y reorganice elprograma para hacerlo tan legible como sea posible Por ejemplo si sospechaque el problema estaacute en una parte del programa con un anidamiento (nesting)muy profundo pruebe a reescribir esa parte con una estructura maacutes simple Sisospecha de una funcioacuten muy larga trate de dividirla en funciones maacutes pequentildeasy prueacutebelas separadamente

Generalmente el proceso de encontrar el caso de prueba miacutenimo lleva el usuarioa encontrar el error Si encuentra que un programa funciona en una situacioacutenpero no en otra eso le daraacute una pista sobre lo que estaacute sucediendo

De forma parecida reescribir una porcioacuten de coacutedigo puede ayudarle a encontrarerrores sutiles Si realiza un cambio que cree que no deberiacutea afectar elprograma pero lo hace entonces eso puede darle una pista

Errores SemaacutenticosEn cierto modo los errores semaacutenticos son los maacutes difiacuteciles de corregir ya que elinteacuterprete no entrega informacioacuten sobre lo que estaacute mal Soacutelo usted sabe lo quese supone que debe hacer el programa

El primer paso es hacer una conexioacuten entre el coacutedigo y el comportamiento queestaacute viendo Necesita una hipoacutetesis sobre lo que realmente estaacute haciendo elprograma Una de las dificultades que nos encontramos es la alta velocidad delos computadores

A menudo seriacutea deseable ralentizar el programa a una velocidad humana Eltiempo que lleva colocar unas sentencias print en los lugares adecuados sueleser menor que el que lleva configurar un depurador poner y quitar puntos deinterrupcioacuten y ldquohacer avanzarrdquo al programa hasta donde se produce el error

Mi programa no funciona

Deberiacutea hacerse estas preguntas

bull iquestHay algo que se supone que deberiacutea hacer el programa pero que nosucede Busque la seccioacuten del coacutedigo que realiza esa funcioacuten y aseguacuterese deque se ejecuta cuando deberiacutea

bull iquestOcurre algo que no deberiacutea Busque el coacutedigo en su programa que realizaesa funcioacuten y vea si se ejecuta cuando no debe

bull iquestHay alguna seccioacuten del coacutedigo que cause un efecto que no esperabaAseguacuterese de que entiende el coacutedigo en cuestioacuten especialmente si incluye

Errores Semaacutenticos 277

funciones o meacutetodos de otros moacutedulos de Julia Lea la documentacioacuten de lasfunciones a las que llama Prueacutebelas escribiendo casos de prueba simples ycomprobando sus resultados

Para programar necesitaraacute tener un modelo mental de coacutemo funcionan losprogramas Si escribe un programa que no hace lo que esperaba de eacutel muchasveces el problema no estaraacute en el programa sino en su modelo mental

La mejor manera de corregir su modelo mental es dividiendo el programa en suscomponentes (normalmente en funciones y meacutetodos) y probando cadacomponente de forma independiente Una vez que encuentre la discrepanciaentre su modelo y la realidad podraacute solucionar el problema

Por supuesto deberiacutea ir haciendo y probando componentes a medida quedesarrolla el programa Si encuentra un problema soacutelo habriacutea que revisar unapequentildea cantidad de coacutedigo nuevo

Tengo una expresioacuten grande y peliaguda y no hace lo queespero

Estaacute bien escribir expresiones complejas mientras sean legibles pero pueden serdifiacuteciles de depurar Suele ser una buena idea dividir una expresioacuten compleja enuna serie de asignaciones de variables temporales

Por ejamplo

agregarcarta(juegomanos[i] sacarcarta(juegomanos[encontrarvecino(juegoi)]))

Puede reescribirse como

vecino = encontrarvecino(juego i)cartaseleccionada = sacarcarta(juegomanos[vecino])agregarcarta(juegomanos[i] cartaseleccionada)

La versioacuten expliacutecita es maacutes faacutecil de leer porque los nombres de variables nosentregan documentacioacuten adicional y es maacutes faacutecil de depurar porque se puedencomprobar los tipos de las variables intermedias y mostrar sus valores

Otro problema que puede suceder con las expresiones grandes es que el ordende evaluacioacuten puede no ser el que usted esperaba Por ejemplo si estaacutetraduciendo la expresioacuten a Julia podriacutea escribir

y = x 2 π

Esto no es correcto ya que la multiplicacioacuten y la divisioacuten tienen la misma

278 Capiacutetulo 21 Depuracioacuten

precedencia y se evaluacutean de izquierda a derecha De este modo la anteriorexpresioacuten calcula

Una buena forma de depurar expresiones es antildeadir pareacutentesis para que seaexpliacutecito el orden de evaluacioacuten

y = x (2 π)

Siempre que no esteacute seguro del orden de evaluacioacuten utilice pareacutentesis Elprograma no soacutelo seraacute correcto (en el sentido de que hace lo que usted quiere)sino que ademaacutes seraacute maacutes legible para otras personas que no hayan memorizadolas reglas de precedencia y que lean el coacutedigo

Tengo una funcioacuten que no devuelve lo que esperaba

Si tiene una sentencia return con una expresioacuten compleja no tendraacute laoportunidad de imprimir el valor de retorno antes de retornar De nuevo puedeusar una variable temporal Por ejemplo en lugar de

return sacarpares(juegomanos[i])

podriacutea escribir

contar = sacarpares(juegomanos[i])return contar

Ahora ya tiene la oportunidad de mostrar el valor de count antes de retornar

Estoy atascado de verdad y necesito ayuda

Primero intente alejarse del computador durante unos minutos Trabajar con uncomputador puede provocar estos efectos

bull Frustracioacuten yo furia

bull Creencias supersticiosas (ldquoel computador me odiardquo) y pensamiento maacutegico(ldquoel programa soacutelo funciona cuando me pongo la gorra hacia atraacutesrdquo)

bull Programar dando palos de ciego (el empentildeo de programar escribiendo todoslos programas posibles y eligiendo el que hace lo correcto)

Si se encuentra afectado por alguno de estos siacutentomas levaacutentese y deacute un paseoCuando esteacute calmado piense en el programa iquestQueacute es lo que hace iquestCuaacutelespueden ser las causas de tal comportamiento iquestCuaacutendo fue la uacuteltima vez que suprograma funcionaba y queacute fue lo siguiente que hizo

A veces lleva tiempo encontrar un error Muchas veces encontramos errores

Errores Semaacutenticos 279

cuando estamos lejos del computador y divagamos Algunos de los mejoreslugares para encontrar errores son los trenes las duchas y la cama justo antesde quedarse dormido

No de verdad necesito ayuda

Sucede Incluso los mejores programadores se atascan de vez en cuando A vecestrabaja durante tanto tiempo en un programa que no puede ver el error Lo quenecesita es un par de ojos nuevos

Antes de llamar a alguien aseguacuterese de estar preparado Su programa deberiacuteaser tan simple como sea posible y usted deberiacutea estar trabajando con la entradamiacutenima que provoca el error Deberiacutea tener sentencias print en los lugaresadecuados (y lo que dicen deberiacutea ser comprensible) y deberiacutea tambieacuten entenderel problema lo bastante bien como para describirlo de manera concisa

Cuando llame a alguien para que le ayude aseguacuterese de darle la informacioacuten quenecesitan

bull Si hay un mensaje de error iquestcuaacutel es y queacute parte del programa sentildeala

bull iquestQueacute fue lo uacuteltimo que hizo antes de que apareciera el error iquestCuaacuteles sonlas uacuteltimas liacuteneas de coacutedigo que escribioacute o cuaacutel es el nuevo caso de pruebaque falla

bull iquestQueacute ha intentado hasta ahora y queacute ha averiguado

Cuando encuentre el error toacutemese un momento para pensar acerca de lo quepodriacutea haber hecho para encontrarlo maacutes raacutepido La siguiente vez que vea algoparecido seraacute capaz de encontrar el error antes

Recuerde el objetivo no es solo hacer que el programa funcione El objetivo esaprender coacutemo hacer funcionar el programa

280 Capiacutetulo 21 Depuracioacuten

Apeacutendice A Entrada de UnicodeLa siguiente tabla muestra algunos de los muchos caraacutecteres Unicode quepueden ingresarse mediante abreviaciones similares a aquellas utilizadas enLatex en el REPL de Julia (y en muchos otros entornos de edicioacuten)

Caraacutecter Tab completionsequence

representacioacuten ASCII

sup2 ^2₁ _1₂ _2ἴ appleἴ bananaὂ camelἵ pearὂ turtlecap capequiv equiv ===

ℯ eulerisin in in

ge ge gt=

le le lt=

ne ne =

notin notinπ pi pi

sube subseteqε varepsilon

Apeacutendice A Entrada de Unicode 281

Apeacutendice B JuliaBoxJuliaBox permite ejecutar Julia en su navegador Ingrese a la paacuteginahttpswwwjuliaboxcom inicie sesioacuten y comience a usar el entorno Jupyter

La pantalla inicial se muestra en Figura 25 El botoacuten new (nuevo) permite lacreacioacuten de un notebook de Julia un archivo de texto (text file) una carpeta(folder) o una sesioacuten de terminal (terminal session)

En una sesioacuten de terminal el comando julia inicia REPL como se muestra enFigura 26

La interfaz del notebook permite mezclar texto (en modo Markdown) y coacutedigocon su respectiva salida Figura 27 muestra un ejemplo

Puedes encontrar maacutes documentacioacuten en el sitio web de Jupyterhttpjupyterorgdocumentation

Figura 25 Pantalla inicial

282 Apeacutendice B JuliaBox

Figura 26 Sesioacuten de terminal

Apeacutendice B JuliaBox 283

Figura 27 Notebook

284 Apeacutendice B JuliaBox

Apeacutendice C Cambios de ThinkJuliaEste libro es una traduccioacuten de ThinkJulia que estaacute disponible bajo la LicenciaCreative Commons Atribucioacuten-NoComercial 30 No portada Esta licenciarequiere que los trabajos derivados (como este libro) enumeren los cambiosrealizados en relacioacuten a la fuente

Las diferencias de este libro respecto a ThinkJulia incluyen lo siguiente

bull Traduccioacuten del ingleacutes al espantildeol

bull Se cambiaron muchas frases idiomaacuteticas que no seriacutean familiares para loshispanohablantes (Se cayoacute el centavo)

bull En vez de usar el texto de la novela Emma en el Capiacutetulo 13 se usa eltexto de Don Quijote

bull Debido a que OrsquoReilly no financioacute la traduccioacuten algunas de las referencias aOrsquoReilly en el prefacio fueron eliminadas

Apeacutendice C Cambios de ThinkJulia 285

Index 126 57=

veacutease ne 57

veacutease cadena vaciacutea 101

veacutease comillas triples 51hellip (comillas)

veacutease comillas 11

veacutease comentario 22$

veacutease interpolacioacuten de cadenas102

161veacutease operador moacutedulo 56

ampamp 247 57 21 21 (asterisco)

operador de multiplicacioacutenveacutease asterisco 9

+ 21+ (operador de suma)

veacutease suma 9+= 127 (coma)

no usar en enterosveacutease coma 11

- 21- (operador de resta)

veacutease subtraction 9 200 201 265

veacutease operador punto 128 21 (operador de divisioacuten)

veacutease division 10 206 253 244 25 265 64lt 57lt=

veacutease le 57=

veacutease sentencia de asignacioacuten 17== 105 205 57 75===

veacutease equiv 131=gt 142gt 57gt=

veacutease ge 57

veacutease help 51 247 254assert 214code_llvm 268code_lowered 267code_native 268code_typed 268contenedorvariable 254debug 269generated 255macroexpand 254printf 187show 73svg 43test 230time 259warn 269which 237 267[]

veacutease slice operator 125[]

veacutease operador corchete 97n 196r 196t 175 196] 42^ 21 21^ (circunflejo)

operador de exponenciacioacutenveacutease circunflejo 10

_ (guioacuten bajo)en enteros

veacutease guioacuten bajo (_) 11``

286 Index

veacutease comillas invertidas 193

veacutease llaves 142|| 247 57divide 161

veacutease operador divisioacuten entera 56hellip 161isin

veacutease in 104notin 115cap 177ne 57equiv 131 205le 57ge 57sube 262

Aabreviaturas tipo LaTeX 18abs 71 92abspath 188abstract type 233 233 240ack 83actualizacioacuten 94acumulador 127 137 174algoritmo 93 95alias 133 138 167 203 205ambas 105analizar 32andamiaje 154 73 83anidado 122anotacioacuten de tipo 226anular 177 184Any 123 142 217anaacutelisis de Markov 179anaacutelisis de sintaxis 12 15append 126arc 49archivo de texto 196arco 49 53areacirculo 74ArgumentError 27 275 64argumento 27 30 32 33 38argumento opcional 131 176argumentos con nombre 244 257argumentos opcionales 138

Arreglo 123arreglo 122 137 166arreglo vaciacuteo 122 124asignacioacuten 160 191 24asignacioacuten aumentada 137asignacioacuten de tupla 160 164asignacioacuten en tupla 168asignacioacuten muacuteltiple 86 94asterisco ()

operador de multiplicacioacuten 9atributo 199 206

Bbandera 151 155Base 243 259base de datos 191 197begin 245benchmarking 182 184Biblioteca Estaacutendar 243bloque 245bloque do 257bloque let 257Bool 57borrarprimero 133BoundsError 107 160 275break 89bucle 44 52 88bucle infinito 273 88 95bugs

veacutease errores 15Byte 249buacutesqueda 102 103 109 109 115 155buacutesqueda de biseccioacuten 178buacutesqueda inversa 155

Ccadena 166 97 97

concatenacioacutenveacutease concatenar 21

repeticioacutenveacutease repeticioacuten 22

cadena vaciacutea 101 108cadenas 10 14calculadora 26campo

veacutease atributo 199

Index 287

Canguro 227capturar 197capturar una excepcion 190Car Talk 120 157 169carpeta

veacutease directorio actual 188caraacutecter guioacuten bajo 18Caraacutecter Unicode 17caraacutecter Unicode 30 72caso base 63 66caso especial 119 120catch 190ccall 256cd 193Channel 248Char 112 97cifrado Ceacutesar 112Circulo 207circunflejo (^)

operador de exponenciacioacuten 10clasificar 242clausura 257clave 142 154close 113 187 192codificacioacuten UTF-8 108 99codificar 228 239coinciden 164cola 135collect 130 146 163coma ()

no usar en enteros 11coma final 158comentario 22 25comillas 30comillas (hellip)

entre 11comillas invertidas 193comillas triples 51comparacioacuten de cadenas 105componentes leacutexicos 11 15composicioacuten 29 33 39 74concatenacioacuten de cadenas 25concatenar 21 34concatenar_dos 34condicional alternativa 71condicional anidada 59 66

condicional encadenada 59 66condicioacuten 58 66conjetura de Collatz 89conjuntoanagramas 198ConjuntoDeCartas 233const 153 229constructor 199 206 219 251

copiaveacutease constructor de copia

220externo

veacutease constructor externo220

internoveacutease constructor interno

220constructor de copia 220 227constructor externo 220 226constructor interno 220 226constructor por defecto 226contador 104 109ContarLineas 195contarlineas 194conteo 109continue 90conversioacuten 252 258conversioacuten de tipo 27convert 252copia 125copiar 193 205copodenieve 69corchetes 142 265cos 33cuadrado 46cuatroveces 40cuenta regresiva 61cuentaregresiva 88cuerpo 30 38curva de Koch 69ciacuterculo 47 50coacutedigo ASCII 108 97coacutedigo de maacutequina 268coacutedigo muerto 277 71 82

Ddatos faltantes 255 258

288 Index

DBM 191de Cervantes

Miguel 174debug logging 269 270declaracioacuten 151 156decremento 88 94deepcopy 205 206 207definicioacuten circular 76definicioacuten de funcioacuten 29 38definicioacuten recursiva 76deleteat 130delimitador 131 138dependencia 236 240depuracioacuten 106 119 135 153 154

167 182 196 205 213 22623 269 37 52 65 72 81 93

emociones de la manejando las13

veacutease errores (bugs) probando15

depuracioacuten del pato de goma 183 184depuracioacuten experimental 37depuracioacuten por biseccioacuten 93desarrollo de prototipos 209 211 214desarrollo incremental 72 82desarrollo planificado 212 214deserialize 192desplazarpalabra 112 156determiniacutestico 172 183devolverfloat 216diaframa de estado 123diagrama

estadoveacutease diagrama de estado 17

graacutefico de llamadasveacutease graacutefico de llamadas

149objeto

veacutease diagrama de objeto200

pilaveacutease diagrama de pila 34

tiposveacutease diagrama de tipos 236

diagrama de estado 131 132 149166 166 17 24 86

diagrama de objeto 200 202 207diagrama de pila 134 34 39 62 68

78diagrama de tipos 236 240dibujarcirculo 207dibujarrect 207diccionario 142 154Dict 142Dijkstra

Edsger W 119dimensioacuten 264directorio 188 196disentildeo orientado a tipos 238dispatch 223 226dispatch muacuteltiple 223 227dispersar 168dispersioacuten 162distancia 72distanciaentrepuntos 203DivideError 275divisioacuten

operador de divisioacuten () 10divisioacuten entera 65divrem 161do 246docstring 202 51 53DomainError 275dosveces 40Doyle

Arthur Conan 37dump 196 253

Eeachindex 124eachline 114 194ejecucioacuten alternativa 58ejecutar 19 24elemento 122 137else 58elseif 59embebido 202emoji 97 99enbiseccion 141encabezado 30 38encapsulacioacuten 47encapsulado 53

Index 289

encapsulado de dato 238encapsulado de datos 240enchapado 232 239encontrarcentro 204end 101 124 190 195 199 245 30

44 58 98enteroahora 212 218entrelazan 141enumerate 164EOFError 275equivalente 132 138error 147 213

BaseEOFError 275KeyError 143StringIndexError 99SystemError 189

CoreArgumentError 27BoundsError 107DivideError 275DomainError 275InexactError 275MethodError 98OutOfMemoryError 276OverflowError 276StackOverflowError 63TypeError 216UndefVarError 34

semaacutenticoveacutease error semaacutentico 23

sintaxisveacutease error de sintaxis 18

tiempo de ejecucioacutenveacutease error de tiempo de

ejecucioacuten 23error de forma 168error de sintaxis 18 23 25 271 29error de tiempo de ejecucioacuten 23 25error en tiempo de ejecucioacuten 271 34error semaacutentico 23 25 271errores (bugs) 13

veacutease depuracioacuten 15errores de forma 167ES-UN 236esabecedaria 115 117

esanagrama 140esc 254escogerdelhistograma 173esdivisible 75eshoravalida 213espalindromo 110 118 84especificacioacuten 218 226 250espotencia 84esreverso 106 119estadespues 209 219estaordenada 140estilo de programacioacuten funcional 211estilo funcional de programacioacuten 214estimarpi 96estriangulo 68estructura 11 15estructura de dato 168estructuras de datos 167estructuras de datos recursivas 221eval 254 95evalbucle 96evaluacioacuten de cortocircuito 247 257evaluar 19 24evita 115 262evitar 114excepcioacuten

veacutease error de tiempo deejecucioacuten 23

exp 29export 195Expr 253expresioacuten 18 24 253 258expresioacuten booleana 57 66extension

jl 19extrema 161

Ffact 247 77 80 81factorial 78false 57faltantes 255fib 79Fibonacci 266fibonnaci 149 79file stream 113 119

290 Index

filter 174filtro 128 138finally 190findall 148findfirst 104findnext 104firstindex 99float 27flujo de ejecucioacuten 273 32 39 71 77

81 88for 44formateando 187formatting 154forward 42fractal 69funccioacuten

definida por el programadorconjuntoanagramas 198

funciondefinida por el programador

aacuterea 70funciones generadas 255 258funcioacuten 27 29 38

Baseabs 71abspath 188append 126buacutesqueda 109ccall 256coinciden 164collect 130conteo 109convert 252cos 33deepcopy 205 206deleteat 130divrem 161dump 196eachindex 124eachline 114enumerate 164error 147esc 254exp 29extrema 161factorial 78

filter 174findall 148firstindex 99float 27get 145get 156include 194insert 130isdefined 206isdir 188isequal 148isfile 189isletter 171ispath 188iterate 266join 131joinpath 189keys 143length 40log 28log10 28lpad 121match 263max 162maximum 161min 162minimum 161new 220nextind 99occursin 263ones 264open 113parse 27pop 129popfirst 129print 41promote 252promote_rule 253push 125pushfirst 130put 248pwd 188rand 140readdir 189readline 113 64reinterpret 249

Index 291

repr 196reverse 167reverse 167run 193setdiff 260show 36sin 28size 264sizeof 99skipmissing 256sort 126sort 126splice 129split 130sqrt 28string 28sum 127supertype 238take 192 248time 67trunc 27tupla 158uppercase 104values 144vcat 134walkdir 189write 186zeros 264zip 163

ContarLineascontarlineas 195

Coreeval 254 95

definida por el programadorack 83ambas 105areacirculo 74borrarprimero 133buacutesqueda 102clasificar 242cola 135concatenar_dos 34contarlineas 194copodenieve 69cuadrado 46cuatroveces 40

cuenta regresiva 61ciacuterculo 47desplazarpalabra 112devolverfloat 216dibujarcirculo 207dibujarrect 207distancia 72distanciaentrepuntos 203dosveces 40enbiseccion 141encontrarcentro 204enteroahora 212esabecedaria 115esanagrama 140escogerdelhistograma 173esdivisible 75eshoravalida 213espalindromo 84espotencia 84esreverso 106estadespues 209estaordenada 140estimarpi 96estriangulo 68evalbucle 96evita 114fact 77fib 79findfirst 104findnext 104histograma 145horaaentero 212imprimircuadricula 41imprimirdosveces 32imprimirhist 146imprimirhora 208imprimirmascomun 176imprimirpalabra 40imprimirpunto 202imprimirtodo 161incrementar 210interior 139interior 139invertirdic 148justificar_a_la_derecha 39koch 69

292 Index

leeranagramas 198mascomun 175masfrecuente 168mcd 85medio 84minmax 161miraiz 95mover 235moverpunto 203multhora 215noborrarprimero 135notiene_e 114palabraalazar 178palabrasdiferentes 175palabrastotales 174par inverso 141polyline 49poliacutegono 47ponerenmarsupio 227primera 84printn 62probarraiz 95procesararchivo 173procesarlinea 173procesarpalabra 239puntoencirculo 207recorrer 189rectencirculo 207recursioacuten 63repartir 241repetido 140repetirletras 30resta 177sed 197seq 89sinc 216sobreposicionrectcirc 207solomayusculas 128sumaacumulada 139sumaanidada 139sumacuadrada 267sumahora 209sumartodo 162tienedoblepareja 242tienepareja 242todoenmayusculas 127

ultima 84usasolo 115usatodo 115valorabsoluto 70verificarfermat 67

definido por el programadorimprimirletras 29

IntroAJuliaforward 42pendown 43penup 43turn 43

Metaparse 253 95

Plotsgraficar 185 244

programmer-definedarco 49

Randomshuffle 232

Serializacioacutendeserialize 192serialize 192

funcioacuten Ackermann 83funcioacuten anoacutenima 244 257funcioacuten booleana 75funcioacuten de Ackermann 156funcioacuten definida por el programador

29 33funcioacuten exponencial

veacutease exp 29funcioacuten factorial 77funcioacuten gamma 80funcioacuten hash 155funcioacuten logaritmo

veacutease log 28funcioacuten matemaacutetica 28funcioacuten nula 35 39funcioacuten productiva 35 39 70funcioacuten pura 209 214funcioacuten raiacutez

veacutease sqrt 28funcioacuten recursiva 61funcioacuten trigonomeacutetrica 28funcioacuten typeof 10function 29

Index 293

funtor 251 258

GGDBM 191generalizacioacuten 47 53get 145get 156 174global 151 99graficar 185graacutefico de llamada 155graacutefico de llamadas 149guardian 81guardiaacuten 83guioacuten bajo (_)

en enteros 11

Hhash 149hash table 144hashable 149 155help 51histograma 145 224Holmes

Sherlock 37Hora 208 217horaaentero 212 218

Iidentidad de Euler 262ideacutentico 132 138if 58im 262immutable 102 108 158 167 200implementacioacuten 144 155 225import 195 259imprimircuadricula 41imprimirdosveces 32imprimirhist 146imprimirhora 208 217imprimirletras 29imprimirmascomun 176imprimirpalabra 40imprimirpunto 202imprimirtodo 161in 100 124 143 156 44include 194

incrementar 218incrementar 210incremento 88 94indentacioacuten 46indicador 64

en REPL 14 9indice 98InexactError 275informaacuteticos habilidades de

veacutease programacioacuten 7inicializacioacuten 94initializacioacuten 87input 113insert 130 136instancia 200 206instanciacioacuten 200instanciar 206instrucciones

veacutease sentencias 7Int 112InteractiveUtils 237 267interfaz 225 266 48 53interior 139interior 139intermediate representation 270interpolacioacuten de cadenas 102 109

187 263IntroAJulia 42invariante 213 215invertirdic 148IOBuffer 192isa 206 234 80isdefined 206isdir 188isequal 148isfile 189isletter 171 174ispath 188item 122 142 154iteracioacuten 191 86 88 94iterador 163 168 266iterate 266

Jjoin 131joinpath 189

294 Index

Juliaejecutando 8

JuliaBox 19 8notebook graacutefico 42

justificar_a_la_derecha 39

KKeyError 143 276keys 143keyword

elseveacutease else 58

importveacutease import 259

koch 69

LLaTeX-like abbreviations 281leeranagramas 198lemario 113length 143 40 84 98lenguaje de programacioacuten 11 15lenguaje de programacioacuten completo 76lenguaje formal 11 15lenguaje natural 11 14ley de Zipf 184Linux 38lista anidada 137Llamada a funcioacuten 27 38llaves 142 249LLVM code 268log 28log10 28lookup 147lowercase 174lpad 121

Mmachine code 270macro 254 258 43

Baseassert 214debug 269generated 255macroexpand 254show 73

time 259warn 269

definida por el programadorcontenedorvariable 254

InteractiveUtilscode_llvm 268code_lowered 267code_native 268code_typed 268which 237

Luxorsvg 43

Printfprintf 187

Testtest 230

Mano 234map 128mapeo 138 142 154marco 34 39 62Markov 238mascomun 175masfrecuente 168match 263matemaacuteticas

operadores aritmeacuteticos 9matrix 264 270max 162maximum 161mayuacutescula 127Mazo 231mcd 85md5 194md5sum 194medio 84mensaje de error 23MethodError 101 159 162 219 276

98min 162minimum 161minmax 161miraiz 95Missing 255modelo mental 278modificador 210 214modo interactivo 19 24 36

Index 295

modo script 19 24 36module 195

ContarLineasveacutease ContarLineas 195

InteractiveUtilsveacutease InteractiveUtils 237

Randomveacutease Random 232

Testveacutease Test 230

modulo 42 52veacutease IntroAJulia 42

mover 235moverpunto 203MPunto 201multhora 215multiplicidad 236 240mutable 123 133 167mutable struct 201meacutetodo 217 226meacutetodo de Newton 91meacutetodos 226moacutedulo

Plotsveacutease Plots 184 244

Serializacioacutenveacutease Serializacioacuten 192

Nnada 39Naipe 229new 220nextind 99noborrarprimero 135norma Unicode 108 97notacioacuten de punto

veacutease 200nothing 177 36 36 70notiene_e 114 115nuacutemeros complejos 262

Oobjeto 131 138objeto de comando 193 197objeto de funcioacuten 38 40objeto embebido 207

objeto zip 163 168occursin 263ones 264open 113 186 246operacioacuten con cadenas 21operacioacuten de reduccioacuten 127 138operador

Base= 57 56+= 127 128lt 57lt= 57== 57gt 57gt= 57 247[] 125[] 97in 104isa 206 234divide 56isin 104notin 115cap 177ne 57equiv 131le 57ge 57sube 262

cadenas 21operador corchete 101 101 122 123

159 191 97operador de divisioacuten entera 56operador de exponenciacioacuten (^) 10operador de multiplicacioacuten () 9operador de resta (-) 9operador de suma (+) 9operador loacutegico 57 66operador moacutedulo 56 65operador porcioacuten 125 135 159operador punto 128 137operador relacional 159 57 66operador ternario 257

veacutease 247

296 Index

operadores 14 9aritmeacuteticos 9

operadores aritmeacuteticos 9operando 24orden alfabeacutetico 105orden de operaciones 21OutOfMemoryError 276output

sentencia de impresioacuten 14 9OverflowError 276

Ppalabra clave 18 24palabra reservada

abstract type 233begin 245break 89catch 190const 153 229continue 90do 246elseif 59export 195final 30finally 190for 44function 30global 151if 58import 195in 44module 195mutable struct 201quote 253return 62struct 199tipo primitivo 249try 190using 42while 88

palabraalazar 178palabrasdiferentes 175palabrastotales 174paliacutendromo 84PAPOMUDAS 21paquete 42 52

par clave-valor 142 154 165par inverso 141Paradoja del cumpleantildeos 140pares de metaacutetesis 169parse 253 64 95paraacutemetro 32 34 38pareacutentesis 158 164 21 27

vaciacuteos 30pendown 43penup 43persistente 186 196pi 17 28pista 150 155 156 170plan de desarrollo de programa 117

211 239 50 53 82plot 244Plots 184 244polimorfismo 225polimoacuterfica 224polygon 49polyline 49poliacutegono 47Poncela

Enrique Jardiel 114ponerenmarsupio 227pop 129 232 234popfirst 129 133porcioacuten 108 109 265postcondicioacuten 52 53 81precedencia del operador 25precondicioacuten 52 53 81prefijo 179primera 84Principal 35principio de sustitucioacuten de Liskov 237print 187 41println 187 41printn 62probarraiz 95procesararchivo 173procesarlinea 173procesarpalabra 239programacioacuten de caminata aleatoria

183programacioacuten geneacuterica 227programas 14 7

Index 297

promocioacuten 253 258promote 252 253promote_rule 253Proyecto Gutenberg 171prueba de consistencia 154prueba de cordura 154prueba unitaria 230 239pseudoaleatorio 172 184Ptr 256Punto 199 222puntoencirculo 207push 125 130 134 136 141 232

234pushfirst 130 136put 248pwd 188

Qquote 253

Rrama 59 66rand 140 172Random 232read 194readdir 189readline 113 64 90reasignacioacuten 151 204recopila 161recorrer 189recorrido 106 108 124 99Rectangulo 202rectencirculo 207recursividad 61recursioacuten 117 63 66 68 76 86 88recursioacuten infinita 274 63 67 80recursos en liacutenea

JuliaBox 8reduccioacuten a un problema previamente

resuelto 120reduccioacuten a un problema resuelto

previamente 117reducible 170reducir el tamantildeo 153refactorizacioacuten 239 50 53referencia 133 138 200

Regex 263regex 263 270RegexMatch 263reinterpret 249relacioacuten ES-UN 240relacioacuten TIENE-UN 240repartir 241repeticioacuten 22 34

veacutease iteracioacuten 8repetido 140 156 261repetirletras 30repetition 43REPL 281REPL (Read-Eval-Print Loop) 14 8replace 174repr 196representacioacuten intermedia 268resolucioacuten de problemas 14 7resta 177 260return 62reunir 168reverse 167 175reverse lookup 147reverse 167run 193ruta 188 197ruta absoluta 188 197ruta relativa 188 197

Ssangriacutea 30 60script 19 24secuencia 108 97 97secuencias de secuencias 166sed 197semaacutentica 25sentencia 19 24sentencia break 89 94sentencia compuesta 58 66sentencia condicional 58 66 76sentencia continue 90 95sentencia de asignacioacuten 123 17 86sentencia de asignacioacuten aumentada

127sentencia de depuracioacuten 269sentencia de impresioacuten 14

298 Index

funcioacuten println 9sentencia for 100 114 117 124 163

165 191 266 44 86 88sentencia global 152 155sentencia if 58sentencia print 81 94sentencia return 62 66 70sentencia try 190sentencia using 42 52sentencia while 117 88 94 99separador 175seq 89Serializacioacuten 192serialize 192Set 260setdiff 260shell 193 197show 221 227 229 234 36shuffle 232sin 28 32sinc 216singleton 148 155sintaxis 11 15sintaxis de punto 129 138 243size 264sizeof 99skipmissing 256slice 101sobrecarga de operadores 227sobrecarga del operador 222sobreposicionrectcirc 207solomayusculas 128sort 126 137 146 167 175sort 126 136 136 167 233splice 129split 130 160 174sqrt 28 73square 47StackOverflowError 274 276 63 80stacktrace 63String 97string 187 263 28StringIndexError 276 99strip 136struct 199 206subtipo 233 233 240 240

sufijo 179sum 127 162 224suma de verificacioacuten 194sumaacumulada 139sumaanidada 139sumacuadrada 267sumahora 209 213sumartodo 162supertipo 233 240supertype 238SVG picture 43Symbol 206SystemError 189 276

Ttabla hash 155take 192 248tarea 248 257teorema de Pitaacutegoras 72tesis de Turing 76Test 230TIENE-UN 236tienedoblepareja 242tienepareja 242Time 208time 67tipo 199 233

BaseAny 123 142Array 123Bool 57Channel 248Char 97Dict 142Expr 253IOBuffer 192Missing 255nothing 36Ptr 256Regex 263RegexMatch 263Set 260Symbol 206Tuple 158UInt8 249Union 250

Index 299

DatesTime 208

definida por el programadorByte 249Canguro 227Circulo 207ConjuntoDeCartas 233Fibonacci 266Hora 208Mano 234Markov 238Mazo 231MPunto 201Naipe 229Punto 199Rectangulo 202

IntroAJuliaDBM 191

LuxorTurtle 42

tipo compuesto 199tipo compuesto mutable 201tipo concreto 233 240tipo de punto flotante (Float64) 10 14tipo entero (Int64) 10 14tipo parameacutetrico 258tipo primitivo 249 257tipos 10 14

Float64veacutease tipo de punto flotante

10Int64

veacutease tipo entero 10String

veacutease cadenas 10tipos de datos

veacutease tipos 10todoenmayusculas 127 129Torvalds

Linus 38transitorio 186trazado inverso 35 39true 57trunc 27try 190tupla 158 158 166 167

tupla con nombre 243 257Tuple 158Turing

Alan 76turn 43Turtle 42TypeError 216 276typeof 122 158 205

UUInt8 249ultima 84UndefVarError 152 276 34 35 87Unicode character 281Union 250union de tipo 250unioacuten de tipos 257update 87uppercase 104usasolo 115 116 261 263usatodo 115 116using 259 42

Vvalor 131 142 154 17valor de retorno 27 39valor por defecto 184valor predeterminado 176valorabsoluto 70valores 10 14values 144variable 131 17 24

local 34variable de entorno 269variable global 151 155 229variable global constante 153 156variable local 34 38variable temporal 279 70 75 82vcat 134 136verificar 154verificar automaacuteticamente 154verificarfermat 67voto de confianza 78

Wwalkdir 189

300 Index

while 88write 186

Zzeros 264zip 163 165 167 167

Aacuteaacutembito 195aacuterea 70

Iacuteiacutendice 108 123

Uacuteuacuteltimo teorema de Fermat 67

Ππ

veacutease pi 17

ℯ 262

Index 301

  • Introduccioacuten a la Programacioacuten en Julia
  • Tabla de Contenido
  • Licencia
  • Dedicatoria
  • Prefacio
  • Capiacutetulo 1 El camino de la programacioacuten
  • Capiacutetulo 2 Variables expresiones y sentencias
  • Capiacutetulo 3 Funciones
  • Capiacutetulo 4 Estudio de Caso Disentildeo de Interfaz
  • Capiacutetulo 5 Condicionales y recursividad
  • Capiacutetulo 6 Funciones productivas
  • Capiacutetulo 7 Iteracioacuten
  • Capiacutetulo 8 Cadenas
  • Capiacutetulo 9 Estudio de Caso Juego de Palabras
  • Capiacutetulo 10 Arreglos
  • Capiacutetulo 11 Diccionarios
  • Capiacutetulo 12 Tuplas
  • Capiacutetulo 13 Estudio de Caso Seleccioacuten de Estructura de Datos
  • Capiacutetulo 14 Archivos
  • Capiacutetulo 15 Estructuras y Objetos
  • Capiacutetulo 16 Estructuras y Funciones
  • Capiacutetulo 17 Dispatch Muacuteltiple
  • Capiacutetulo 18 Subtipos
  • Capiacutetulo 19 Extra Sintaxis
  • Capiacutetulo 20 Extra Base y Libreriacutea Estaacutendar
  • Capiacutetulo 21 Depuracioacuten
  • Apeacutendice A Entrada de Unicode
  • Apeacutendice B JuliaBox
  • Apeacutendice C Cambios de ThinkJulia
  • Index
Page 2: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar

Tabla de ContenidoLicencia 1Dedicatoria 2Prefacio 31 El camino de la programacioacuten 72 Variables expresiones y sentencias 173 Funciones 274 Estudio de Caso Disentildeo de Interfaz 425 Condicionales y recursividad 566 Funciones productivas 707 Iteracioacuten 868 Cadenas 979 Estudio de Caso Juego de Palabras 11310 Arreglos 12211 Diccionarios 14212 Tuplas 15813 Estudio de Caso Seleccioacuten de Estructura de Datos 17114 Archivos 18615 Estructuras y Objetos 19916 Estructuras y Funciones 20817 Dispatch Muacuteltiple 21618 Subtipos 22819 Extra Sintaxis 24320 Extra Base y Libreriacutea Estaacutendar 25921 Depuracioacuten 271Apeacutendice A Entrada de Unicode 281Apeacutendice B JuliaBox 282Apeacutendice C Cambios de ThinkJulia 285Index 286

LicenciaCopyright copy 2018 Allen Downey Ben Lauwens Todos los derechos reservados

Este libro estaacute disponible bajo la Licencia Creative Commons Atribucioacuten-NoComercial 30 No portada Es una traduccioacuten de ThinkJulia el cual tiene lamisma licencia Una lista de las diferencias entre ThinkJulia y este libro estaacutedisponible en el Apeacutendice C

Un PDF de este libro estaacute disponible aquiacute

Ben Lauwens es profesor de matemaacuteticas en Royal Military Academy (RMABeacutelgica) Tiene un doctorado en ingenieriacutea y maestriacuteas de KU Leuven y RMAademaacutes de una licenciatura de RMA

Allen Downey es profesor de informaacutetica en Olin College of Engineering Hadado clases en Wellesley College Colby College y UC Berkeley Tiene undoctorado en informaacutetica de UC Berkeley y maestriacuteas y licenciaturas del MIT

Licencia 1

DedicatoriaPara Emeline Arnaud y Tibo

2 Dedicatoria

PrefacioEn enero de 2018 comenceacute a preparar un curso de programacioacuten pensado paraestudiantes que no tuvieran experiencia previa en programacioacuten Queriacutea usarJulia como lenguaje de programacioacuten y descubriacute que no existiacutea ninguacuten libro paraaprender a programar que usara Julia como primer lenguaje de programacioacutenHay tutoriales maravillosos que explican los conceptos clave de Julia peroninguno de ellos se dedicaba lo suficiente a ensentildear a pensar como programador

Conociacutea el libro Think Python de Allen Downey el cual contiene todos loselementos clave para aprender a programar correctamente Sin embargo estelibro se basa en el lenguaje de programacioacuten Python Mi primer borrador delcurso fue una mezcla de muchas referencias pero a medida que trabajaba eneste el contenido comenzoacute a parecerse cada vez maacutes a los capiacutetulos de ThinkPython Pronto la idea de desarrollar mi curso como base para trasladar eselibro a Julia se hizo realidad

Todo el material estaba disponible en un repositorio de GitHub en forma denotebooks de Jupyter Despueacutes de publicar un mensaje en el sitio Discourse deJulia sobre el progreso de mi curso los comentarios fueron abrumadoresAparentemente un libro sobre conceptos baacutesicos de programacioacuten con Juliacomo primer lenguaje de programacioacuten era algo que faltaba en el universo deJulia Contacteacute a Allen para ver si podiacutea iniciar oficialmente la versioacuten de ThinkPython para Julia y su respuesta fue inmediata ldquoiexcladelanterdquo me puso encontacto con su editor de OrsquoReilly Media y ahora un antildeo despueacutes estoy haciendolos retoques finales a este libro

Fue un camino difiacutecil En Agosto de 2018 se lanzoacute Julia v10 y como todos miscolegas programadores de Julia tuve que hacer una migracioacuten del coacutedigo Todoslos ejemplos en el libro se prueban durante la conversioacuten de los archivos fuente aarchivos ASCIIDoc compatibles con OrsquoReilly Tanto la cadena de herramientascomo el coacutedigo de los ejemplos teniacutean que ser compatibles con Julia v10Afortunadamente no hay cursos en Agostohellip

Espero que disfrutes al trabajar con este libro y que te ayude a aprender aprogramar y pensar como informaacutetico al menos un poco

Ben Lauwens

iquestPor queacute JuliaJulia fue lanzado originalmente en 2012 por Alan Edelman Stefan Karpinski JeffBezanson y Viral Shah Es un lenguaje de programacioacuten gratuito y de coacutedigoabierto

La eleccioacuten de un lenguaje de programacioacuten es siempre subjetiva Para miacute lassiguientes caracteriacutesticas de Julia son decisivas

iquestPor queacute Julia 3

bull Julia estaacute desarrollado como un lenguaje de programacioacuten de altorendimiento

bull Julia usa enviacuteo muacuteltiple (ldquomultiple dispatchrdquo en ingleacutes) que le permite alprogramador elegir entre diferentes patrones de programacioacuten de acuerdoa la aplicacioacuten

bull Julia es un lenguaje de tipo dinaacutemico que se puede usar faacutecilmente de formainteractiva

bull Julia tiene una sintaxis de alto nivel que es faacutecil de aprender

bull Julia es un lenguaje de programacioacuten con tipos opcionales cuyos tipos dedatos (definidos por el usuario) hacen que el coacutedigo sea claro y robusto

bull Julia tiene una biblioteca estaacutendar extendida ademaacutes estaacuten disponiblesnumerosos paquetes de terceros

Julia es un lenguaje de programacioacuten uacutenico ya que resuelve el problema de losdos idiomas No se necesita de ninguacuten otro lenguaje de programacioacuten paraescribir coacutedigo de alto rendimiento Esto no significa que ocurraautomaacuteticamente Es responsabilidad del programador optimizar el coacutedigo quegenere cuellos de botella aunque esto puede hacerse directamente en Julia

iquestA quieacuten estaacute dirigido este libroEste libro es para cualquier persona que quiera aprender a programar No serequieren conocimientos formales previos

Los nuevos conceptos se introducen gradualmente y los temas maacutes avanzados sedescriben en capiacutetulos posteriores

Introduccioacuten a Julia puede ser usado como un curso de un semestre de nivelsecundario o universitario

Convenciones utilizadas en este libroEn este libro se siguen las siguientes convenciones tipograacuteficas

CursivaIndica nuevos teacuterminos URL direcciones de correo electroacutenico nombres dearchivo y extensiones de archivo

Ancho constanteSe utiliza para mostrar coacutedigo de programas asiacute como dentro de lospaacuterrafos para referirse a elementos del programa como nombres devariables o funciones bases de datos tipos de datos variables de entornosentencias y palabras reservadas

4 Prefacio

Ancho constante en negrita

Muestra comandos u otro texto que el usuario debe escribir

Ancho constante en cursivaMuestra el texto que debe reemplazarse con valores proporcionados por elusuario o por valores determinados por el contexto

OBSERVACIOacuteN Esto indica consejo o sugerencia

NOTA Esto es una nota general

AVISO Esto indica una advertencia o precaucioacuten

Usando los coacutedigos de ejemploTodo el coacutedigo utilizado en este libro estaacute disponible en un repositorio de Git enGitHub httpsgithubcomJuliaIntroIntroAJuliajl Si no estaacute familiarizado conGit es un sistema de control de versiones que le permite realizar seguimiento alos archivos que componen un proyecto Una coleccioacuten de archivos controladospor Git se denomina ldquorepositoriordquo GitHub es un servicio de hosting queproporciona almacenamiento para repositorios de Git y una interfaz webconveniente

El siguiente paquete puede ser de utilidad y se puede agregar directamente aJulia Simplemente escriba add httpsgithubcomJuliaIntroIntroAJuliajlen el REPL en modo Pkg

La forma maacutes faacutecil de ejecutar un coacutedigo de Julia es yendo a httpsjuliaboxcome iniciar una sesioacuten de prueba gratuita Es posible utilizar tanto las interfacesREPL como de notebooks Si desea tener Julia instalada localmente en sucomputadora puede descargar JuliaPro de Julia Computing gratuitamenteConsiste en una versioacuten reciente de Julia el IDE de Juno basado en Atom y variospaquetes de Julia preinstalados Si es maacutes aventurero puede descargar Juliadesde httpsjulialangorg instale el editor que prefiera por ejemplo Atom oVisual Studio Code activando los complementos para su integracioacuten de Julia Enel caso de una instalacioacuten local tambieacuten puede agregar el paquete IJulia que lepermite ejecutar un notebook de Jupyter en su computadora

AgradecimientosRealmente quiero agradecer a Allen por escribir Think Python y permitirmetrasladar este libro a Julia iexclTu entusiasmo es contagioso

Tambieacuten me gustariacutea agradecer a los revisores teacutecnicos de este libro quehicieron muchas sugerencias uacutetiles Tim Besard Bart Janssens y David P

Usando los coacutedigos de ejemplo 5

Sanders

Gracias a Melissa Potter de OrsquoReilly Media por hacer de este un mejor libro Meobligaste a hacer las cosas bien y hacer que este libro sea lo maacutes originalposible

Gracias a Matt Hacker de OrsquoReilly Media que me ayudoacute con la cadena deherramientas Atlas y algunos problemas al destacar la sintaxis

Gracias a todos los estudiantes que trabajaron con una versioacuten temprana de estelibro y a todos los colaboradores (enumerados a continuacioacuten) que enviaroncorrecciones y sugerencias

Lista de ColaboradoresSi tiene una sugerencia o correccioacuten abra un issue en GitHub Si se realiza uncambio basado en sus comentarios seraacute agregado a la lista de contribuyentes (amenos que solicite ser omitido)

Aviacutesenos con queacute versioacuten del libro estaacute trabajando y en queacute formato Si incluyeal menos parte de la oracioacuten en la que aparece el error eso facilita la buacutesquedaLos nuacutemeros de paacutegina y seccioacuten tambieacuten son uacutetiles pero no es tan faacutecil trabajarcon ellos iexclGracias

bull Scott Jones sentildealoacute el cambio de nombre de Void a Nothing y con esto secomenzoacute la migracioacuten a Julia v10

bull Robin Deits encontroacute algunos errores tipograacuteficos en el Capiacutetulo 2

bull Mark Schmitz sugirioacute destacar la sintaxis

bull Zigu Zhao encontroacute algunos errores en el Capiacutetulo 8

bull Oleg Soloviev detectoacute un error en la url al agregar el paquete ThinkJulia

bull Aaron Ang encontroacute algunos problemas de representacioacuten y nomenclatura

bull Sergey Volkov encontroacute un enlace caiacutedo en el Capiacutetulo 7

bull Sean McAllister sugirioacute mencionar el excelente paquete BenchmarkTools

bull Carlos Bolech envioacute una larga lista de correcciones y sugerencias

bull Krishna Kumar corrigioacute el ejemplo de Markov en el Capiacutetulo 18

6 Prefacio

Capiacutetulo 1 El camino de la programacioacutenEl objetivo de este libro es ensentildearle a pensar como un informaacutetico Esta manerade pensar combina las mejores caracteriacutesticas de las matemaacuteticas la ingenieriacutea ylas ciencias naturales Los informaacuteticos al igual que los matemaacuteticos usanlenguajes formales para expresar ideas (especiacuteficamente caacutelculos) De manerasimilar a los ingenieros disentildean estructuras ensamblan componentes paraformar sistemas evaluando los costos y beneficios entre las alternativasAdemaacutes observan el comportamiento de sistemas complejos elaboran hipoacutetesisy prueban predicciones como los cientiacuteficos

La habilidad maacutes importante para un informaacutetico es la resolucioacuten de problemasEsto implica ser capaz de formular problemas encontrar soluciones creativasexpresando una solucioacuten de forma clara y precisa Como resultado el proceso deaprender a programar es una excelente oportunidad para practicar habilidadesde resolucioacuten de problemas Es por ello que este capiacutetulo se llama El camino dela programacioacuten

Por una parte aprenderaacute a programar que es una habilidad muy uacutetil por siacutemisma Pero ademaacutes la programacioacuten se constituiraacute como un medio para un finA medida que avancemos este fin seraacute maacutes claro

iquestQueacute es un programa

Un programa es una secuencia de instrucciones que especifica coacutemo hacer uncaacutelculo El caacutelculo puede ser de naturaleza matemaacutetica tal como resolver unsistema de ecuaciones o encontrar las raiacuteces de un polinomio pero tambieacutenpuede ser un caacutelculo simboacutelico como buscar y reemplazar texto en undocumento o bien algo graacutefico tal como procesar una imagen o reproducir unvideo

Los detalles difieren para cada lenguaje pero algunas instrucciones baacutesicasaparecen en casi todos los lenguajes

EntradaInputSe obtienen datos a traveacutes del teclado un archivo una red u otrodispositivo

SalidaOutputLos datos se muestran por pantalla se guardan en un archivo se enviacutean atraveacutes de la red etc

MatemaacuteticasSe realizan operaciones matemaacuteticas baacutesicas como la suma y lamultiplicacioacuten

iquestQueacute es un programa 7

Ejecucioacuten condicionalSe verifican ciertas condiciones y se ejecuta el coacutedigo apropiado

RepeticioacutenSe realiza alguna accioacuten repetidamente generalmente con alguna variacioacuten

Aunque no lo crea eso es todo lo que se debe hacer Cada programa que hausado sin importar su complejidad estaacute construido basaacutendose en instruccionesque se asemejan a estas De esta manera la programacioacuten puede entendersecomo el proceso de dividir una tarea compleja y larga en pequentildeas subtareas losuficientemente simples como para realizarse con una de estas instruccionesbaacutesicas

Ejecutando Julia

Uno de los desafiacuteos al comenzar a utilizar Julia es su instalacioacuten ademaacutes delsoftware relacionado Si estaacute familiarizado con su sistema operativo y se sientecoacutemodo con la interfaz de liacutenea de comandos no tendraacute problemas No obstantepara los principiantes puede ser difiacutecil aprender sobre administracioacuten de sistemay programacioacuten al mismo tiempo

Para evitar ese problema se recomienda que comience ejecutando Julia en unnavegador Maacutes tarde cuando se sienta coacutemodo con Julia se haraacuten sugerenciaspara instalar Julia en su ordenador

En el navegador puede ejecutar Julia en JuliaBox No se requiere instalacioacutensimplemente abra su navegador y entre a la paacutegina de JuliaBox inicie sesioacuten ycomience a programar (consulte Apeacutendice B)

Julia REPL (de ReadndashEvalndashPrint Loop que se traduce en Bucle de Leer-Evaluar-Imprimir) es un programa que lee y ejecuta coacutedigo de Julia Puede iniciar REPLabriendo un terminal en JuliaBox y escribiendo julia en la liacutenea de comandoCuando comienza deberiacutea ver una salida como esta

_ _ _ _(_)_ | Documentation httpsdocsjulialangorg (_) | (_) (_) | _ _ _| |_ __ _ | Type for help ] for Pkg help | | | | | | | _` | | | | |_| | | | (_| | | Version 152 (2020-09-23) _ |___|_|_|___| | Official httpsjulialangorg release|__ |

juliagt

Las primeras liacuteneas contienen informacioacuten sobre el REPL por lo que esto puede

8 Capiacutetulo 1 El camino de la programacioacuten

mostrarse diferente en su computadora Debe verificar que la versioacuten sea almenos 100

El uacuteltima liacutenea es un indicador sentildealando que el REPL estaacute listo para que seingrese una instruccioacuten Si escribe una liacutenea de coacutedigo y presiona Enter la REPLmuestra el resultado

juliagt 1 + 12

Los fragmentos de coacutedigo se pueden copiar y pegar textualmente incluido elindicador juliagt y cualquier salida

Ahora ya estaacute listo para comenzar De aquiacute en adelante ya sabraacute coacutemo iniciar laREPL de Julia y ejecutar su coacutedigo

El primer programaTradicionalmente el primer programa que se escribe en un nuevo lenguaje sellama ldquoiexclHola mundordquo porque todo lo que hace es mostrar las palabras ldquoiexclHolamundordquo En Julia se ve asiacute

juliagt println(iexclHola mundo)iexclHola mundo

Este es un ejemplo de una sentencia de impresioacuten aunque en realidad noimprime nada en papel Muestra un resultado en la pantalla

Las comillas en el programa marcan el principio y el final del texto que semostraraacute y no apareceraacuten en el resultado

Los pareacutentesis indican que println es una funcioacuten Se estudiaraacuten funciones enCapiacutetulo 3

Operadores aritmeacuteticos

Despueacutes de nuestro programa ldquoiexclHola mundordquo el siguiente paso es laaritmeacutetica Julia tiene operadores los cuales son siacutembolos que representancaacutelculos como la suma y la multiplicacioacuten

Los operadores + - y realizan las operaciones de suma resta y multiplicacioacutenrespectivamente como se muestra en los siguientes ejemplos

El primer programa 9

juliagt 40 + 242juliagt 43 - 142juliagt 6 742

El operador realiza la divisioacuten

juliagt 842420

Quizaacutes se pregunte por queacute el resultado es 420 en vez de 42 Esto seraacuteexplicado en la siguiente seccioacuten

Finalmente el operador ^ realiza la potencicioacuten es decir eleva un nuacutemero a unapotencia

juliagt 6^2 + 642

Valores y tipos

Un valor es uno de los elementos baacutesicos con los que trabaja un programa talcomo una letra o un nuacutemero Algunos de los valores que hemos visto hasta ahorason 2 420 y Hola Mundo

Estos valores pertenecen a diferentes tipos 2 es un entero (integer en ingleacutes)420 es un nuacutemero de punto flotante (floating-point number en ingleacutes) y HolaMundo es una cadena de caracteres (string en ingleacutes) llamada asiacute porque lasletras que contiene estaacuten unidas

Si no estaacute seguro del tipo de un valor el REPL puede ayudarle

juliagt typeof(2)Int64juliagt typeof(420)Float64juliagt typeof(iexclHola mundo)String

Los enteros pertenecen al tipo Int64 las cadenas pertenecen a String y losnuacutemeros de punto flotante pertenecen a Float64

10 Capiacutetulo 1 El camino de la programacioacuten

iquestQueacute pasa con los valores 2 y 420 Parecen nuacutemeros pero estaacuten entrecomillas como si fueran cadenas Estos valores tambieacuten son cadenas

juliagt typeof(2)Stringjuliagt typeof(420)String

Si se quiere escribir un nuacutemero de grandes dimensiones se podriacutea caer en lacostumbre de usar comas para separar sus cifras como por ejemplo 1000000Este no es un entero vaacutelido en Julia aunque siacute es vaacutelido

juliagt 1000000(1 0 0)

iexclEsto no es lo que se podriacutea esperar Julia entiende 1000000 como unasecuencia de enteros separados por comas Maacutes adelante aprenderemos maacutessobre este tipo de secuencias

Sin embargo puede obtener el resultado esperado usando 1_000_000

Lenguajes formales y naturales

Los lenguajes naturales son los lenguajes hablados como el espantildeol el ingleacutes oel franceacutes no fueron disentildeados por personas (aunque las personas intentanimponerles un orden) sino que evolucionaron naturalmente

Los lenguajes formales son lenguajes disentildeados por personas para propoacutesitosespeciacuteficos Por ejemplo la notacioacuten que usan los matemaacuteticos es un lenguajeformal particularmente uacutetil para denotar relaciones entre nuacutemeros y siacutembolosLos quiacutemicos usan un lenguaje formal para representar la estructura quiacutemica delas moleacuteculas Los lenguajes de programacioacuten tambieacuten son lenguajes formales yhan sido disentildeados para expresar caacutelculos

Los lenguajes formales tienden a dictar reglas estrictas de sintaxis quegobiernan la estructura de las sentencias Por ejemplo en matemaacuteticas lasentencia tiene la sintaxis correcta pero no En quiacutemica esuna foacutermula sintaacutecticamente correcta pero no lo es

Las reglas de sintaxis pueden ser de dos tipos correspondientes a componentesleacutexicos y a estructura Los componentes leacutexicos son los elementos baacutesicos dellenguaje como palabras nuacutemeros y elementos quiacutemicos Uno de los problemascon es que no es un componente leacutexico vaacutelido en matemaacuteticas (al menos

Lenguajes formales y naturales 11

hasta donde conocemos) Del mismo modo no es vaacutelido porque no existeninguacuten elemento con la abreviatura

El segundo tipo de reglas de sintaxis se refiere a la forma en que se combinan loscomponentes leacutexicos La ecuacioacuten no es vaacutelida porque aunque y soncomponentes leacutexicos vaacutelidos no se puede tener uno justo despueacutes el otro Delmismo modo en una foacutermula quiacutemica el subiacutendice se coloca despueacutes del nombredel elemento no antes

Esta es un oracioacuten en espa$ol bien estructurada con cmponentes leacutexicos novaacutelidos Esta oracioacuten leacutexicos todos componentes los tiene pero estructura una novaacutelida con

Cuando se lee una oracioacuten en espantildeol o en un lenguaje formal se tiene quedescubrir la estructura (aunque en un lenguaje natural se haceinconscientemente) Este proceso se llama parsing o anaacutelisis de sintaxis

Aunque los lenguajes formales y naturales tienen muchas caracteriacutesticas encomuacutenmdashcomponentes leacutexicos estructura y sintaxismdashexisten algunas diferencias

AmbiguumledadLos lenguajes naturales estaacuten llenos de ambiguumledades este problema esabordado mediante el uso del contexto y otra informacioacuten Los lenguajesformales estaacuten disentildeados para ser casi completamente precisos lo quesignifica que cualquier declaracioacuten tiene exactamente un significadoindependientemente del contexto

RedundanciaPara compensar la ambiguumledad y reducir los malentendidos los lenguajesnaturales emplean mucha redundancia Como resultado a menudo sonverbosos Los lenguajes formales son menos redundantes y maacutes concisos

MetaacuteforaLos lenguajes naturales estaacuten llenos de modismos y metaacuteforas Si se diceldquoCaiacute en la cuentardquo probablemente no haya una cuenta y nada que se caiga(este modismo significa que alguien entendioacute algo despueacutes de un periacuteodo deconfusioacuten) Por otro lado los lenguajes formales significan exactamente loque expresan

Debido a que todo el mundo crece hablando lenguajes naturales a veces esdifiacutecil adaptarse a los lenguajes formales La diferencia entre lenguaje formal ynatural es como la diferencia entre la poesiacutea y la prosa

PoesiacuteaLas palabras se usan por sus sonidos y significados El poema en conjuntocrea un efecto o una respuesta emocional La ambiguumledad no soacutelo es comuacutensino a menudo deliberada

12 Capiacutetulo 1 El camino de la programacioacuten

ProsaEl significado literal de las palabras es maacutes importante y la estructuraaporta significado La prosa es maacutes faacutecil de analizar que la poesiacutea pero amenudo sigue siendo ambigua

ProgramasEl significado de un programa computacional es inequiacutevoco y literal ypuede entenderse por completo mediante el anaacutelisis de los componentesleacutexicos y de estructura

Los lenguajes formales son maacutes densos que los naturales por lo que lleva maacutestiempo leerlos Ademaacutes la estructura es importante por lo que no siempre esmejor leer de arriba a abajo y de izquierda a derecha En cambio aprenderaacute aanalizar el programa mentalmente identificando los componentes leacutexicos einterpretando la estructura Finalmente los detalles son importantes Pequentildeoserrores de ortografiacutea y puntuacioacuten que pueden pasar desapercibidos en loslenguajes naturales pueden hacer una gran diferencia en un lenguaje formal

Depuracioacuten

Los programadores cometen errores Los errores de programacioacuten se denominanbugs y el proceso para rastrearlos se denomina debugging o depuracioacuten

La programacioacuten y especialmente la depuracioacuten pueden provocar emocionesnegativas Frente a un error difiacutecil de solucionar puede sentir enojo verguumlenzaoacute cansancio

Existe evidencia de que las personas responden naturalmente a lascomputadoras como si fueran personas Cuando trabajan bien se los consideracompantildeeros de equipo y cuando son obstinados o groseros se los trata de lamisma manera que a personas groseras y obstinadas [1]

Prepararse para estas reacciones puede ayudarlo a lidiar con ellas Un enfoquees pensar en la computadora como un empleado con ciertas fortalezas como lavelocidad y la precisioacuten y debilidades particulares como la falta de empatiacutea y laincapacidad para comprender el panorama general

Su trabajo es ser un buen gerente debe encontrar formas de aprovechar lasfortalezas y mitigar las debilidades Ademaacutes debe encontrar formas de usar susemociones para involucrarse con el problema sin dejar que sus reaccionesinterfieran con su capacidad para trabajar de manera efectiva

Aprender a depurar puede ser frustrante pero es una habilidad valiosa que esuacutetil para muchas actividades maacutes allaacute de la programacioacuten Al final de cadacapiacutetulo hay una seccioacuten como esta con algunas sugerencias para ladepuracioacuten iexclEspero que le sean de ayuda

Depuracioacuten 13

Glosarioresolucioacuten de problemas

El proceso de formular un problema encontrar una solucioacuten y expresarla

programaUna secuencia de instrucciones que especifica un caacutelculo

REPLUn programa que de manera reiterada lee una entrada la ejecuta y generaresultados

indicadorCaracteres mostrados por el REPL para indicar que estaacute listo para recibirinformacioacuten de entrada de parte del usuario

sentencia de impresioacuten (print)Una instruccioacuten que hace que el REPL de Julia muestre un valor en lapantalla

operadorUn siacutembolo que representa un caacutelculo simple como la suma lamultiplicacioacuten o la concatenacioacuten de cadenas

valorUna de las unidades baacutesicas de datos como un nuacutemero o cadena quemanipula un programa

tipoUna categoriacutea de valores Los tipos que se han visto hasta ahora sonenteros (Int64) nuacutemeros de punto flotante (Float64) y cadenas (String)

enteroUn tipo que representa nuacutemeros enteros

punto flotanteUn tipo que representa nuacutemeros con un punto decimal

cadenaUn tipo que representa secuencias de caracteres

lenguaje naturalCualquier lenguaje hablado que evoluciona naturalmente

14 Capiacutetulo 1 El camino de la programacioacuten

lenguaje formalCualquier lenguaje disentildeado para fines especiacuteficos como la representacioacutende ideas matemaacuteticas o programas de computadora Todos los lenguajes deprogramacioacuten son lenguajes formales

sintaxisLas reglas que gobiernan la estructura de un programa

componente leacutexicoUno de los elementos baacutesicos de la estructura de un programa anaacutelogo auna palabra en un lenguaje natural

estructuraLa manera en que los componentes leacutexicos se combinan

anaacutelisis de sintaxisExaminar un programa y analizar la estructura sintaacutectica

bugUn error en un programa

depuracioacutendebuggingEl proceso de buacutesqueda y correccioacuten de errores

Ejercicios

OBSERVACIOacuteNEs una buena idea leer este libro frente a unacomputadora para hacer los ejemplos y ejerciciosconforme avance

Ejercicio 1-1

Siempre que esteacute experimentando con algo nuevo debe intentar cometererrores Por ejemplo en el programa ldquoiexclHola mundordquo iquestQueacute sucede si omite unade las comillas iquestQueacute pasa si omite ambas iquestQueacute ocurre si escribe mal println

Este tipo de ejercicios le ayuda a recordar lo que leyoacute tambieacuten le ayuda aprogramar porque puede saber queacute significan los mensajes de error Es mejorcometer errores ahora y a propoacutesito en lugar de despueacutes y accidentalmente

1 En un comando print iquestQueacute sucede si omite uno de los pareacutentesis o ambos

2 Si estaacute intentando imprimir un string iquestQueacute sucede si omite una de lascomillas o ambas

3 Se puede usar un signo menos para escribir un nuacutemero negativo como -2

Ejercicios 15

iquestQueacute sucede si pone un signo + antes de un nuacutemero iquestQueacute pasa con 2++2

4 En notacioacuten matemaacutetica los ceros a la izquierda son correctos como en 02iquestQueacute pasa si intenta esto en Julia

5 iquestQueacute sucede si tiene dos valores sin operador entre ellos

Ejercicio 1-2

Inicie el REPL de Julia y uacuteselo como una calculadora

1 iquestCuaacutentos segundos hay en 42 minutos y 42 segundos

2 iquestCuaacutentas millas hay en 10 kiloacutemetros

OBSERVACIOacuteN Hay 161 kiloacutemetros en una milla

3 Si corre una carrera de 10 kiloacutemetros en 37 minutos y 48 segundos iquestCuaacuteles su ritmo promedio (tiempo por milla en minutos y segundos) iquestCuaacutel es suvelocidad promedio en millas por hora

[1] Reeves Byron and Clifford Ivar Nass 1996 ldquoThe Media Equation How People Treat ComputersTelevision and New Media Like Real People and Placesrdquo Chicago IL Center for the Study of Language andInformation New York Cambridge University Press

16 Capiacutetulo 1 El camino de la programacioacuten

Capiacutetulo 2 Variables expresiones y sentenciasUna de las caracteriacutesticas maacutes poderosas de un lenguaje de programacioacuten es lacapacidad de manipular variables Una variable es un nombre que hacereferencia a un valor

Sentencias de asignacioacuten

Una sentencia de asignacioacuten crea una nueva variable y le asigna un valor

juliagt mensaje = Y ahora algo completamente diferenteY ahora algo completamente diferentejuliagt n = 1717juliagt π_val = 31415926535897933141592653589793

Este ejemplo realiza tres asignaciones La primera asigna una cadena a unanueva variable llamada mensaje la segunda le asigna el entero 17 a la variable nla tercera asigna el valor (aproximado) de π (pi TAB) a la variable π_val

Una forma comuacuten de representar variables en papel es escribir el nombre de lavariable con una flecha apuntando a su valor Este tipo de figura se llamaldquodiagrama de estadordquo porque muestra en queacute estado se encuentra cada una delas variables La Figura 1 Figura 1 muestra el resultado del ejemplo anterior

Figura 1 Diagrama de estado

Nombres de variablesLos programadores generalmente eligen nombres representativos para susvariables es decir nombres que explican para queacute se usa o queacute contiene lavariable

Los nombres de las variables pueden ser tan largos como se desee Puedencontener casi todos los caracteres Unicode (consulte Seccioacuten 81) pero nopueden comenzar con un nuacutemero Es vaacutelido usar letras mayuacutesculas pero locomuacuten es usar solo minuacutesculas para nombres de variables

Los caracteres Unicode se pueden ingresar mediante autocompletado portabulacioacuten de las abreviaturas tipo LaTeX en el REPL de Julia

El caraacutecter guioacuten bajo _ puede formar parte del nombre de una variable

Sentencias de asignacioacuten 17

Generalmente se usa como separador en nombres con varias palabras como porejemplo en tu_nombre ovelocidad_aerodinamica_de_una_golondrina_sin_cargamento

Si se le da un nombre invaacutelido a una variable aparece un error de sintaxis

juliagt 76trombones = un gran desfileERROR syntax 76 is not a valid function argument name (ERRORsintaxis 76 no es un nombre de argumento de funcioacuten vaacutelido)juliagt mas = 1000000ERROR syntax extra token after end of expression (ERROR sintaxiscomponente leacutexico adicional despueacutes del final de la expresioacuten)juliagt struct = Quiacutemica avanzadaERROR syntax unexpected = (ERROR sintaxis = inesperado)

76trombones es un nombre de variable invaacutelido porque comienza con un nuacutemeroTambieacuten es invaacutelido mas porque contiene el caraacutecter invaacutelido Pero iquestCuaacutel esel error en struct

Resulta que struct es una de las palabras reservadas de Julia Julia usa laspalabras reservadas para reconocer la estructura del programa por ello nopueden usarse como nombres de variables

Julia tiene las siguientes palabras reservadas

abstract type baremodule begin break catchconst continue do else elseifend export finally for functionglobal if import importall inlet local macro module mutable structprimitive type quote return try usingstruct where while

No es necesario memorizar esta lista En la mayoriacutea de los entornos dedesarrollo las palabras reservadas se muestran en un color diferente por lotanto si intenta usar una como nombre de variable lo sabraacute

Expresiones y sentenciasUna expresioacuten es una combinacioacuten de valores variables y operadores Un valor ouna variable por siacute solos se consideran una expresioacuten por lo que las siguientesexpresiones son vaacutelidas

18 Capiacutetulo 2 Variables expresiones y sentencias

juliagt 4242juliagt n17juliagt n + 2542

Cuando escribe una expresioacuten en el indicador el REPL la evaluacutea lo que significaque encuentra el valor de la expresioacuten En este ejemplo n tiene el valor 17previamente asignado y n+25 retorna el valor 42

Una sentencia es una unidad de coacutedigo que tiene un efecto tal como crear unavariable o mostrar un valor

juliagt n = 1717juliagt println(n)17

La primera liacutenea es una sentencia de asignacioacuten ya que asigna un valor a n Lasegunda liacutenea es una sentencia de impresioacuten que muestra el valor de n

Cuando escribe una sentencia REPL la ejecuta es decir hace lo que dice lasentencia

Modo scriptHasta ahora se ha ejecutado Julia en modo interactivo lo que significa que se hainteractuado directamente con el REPL Este modo es una buena manera decomenzar pero si estaacute trabajando con varias liacuteneas de coacutedigo puede resultarincoacutemodo

Una alternativa es guardar el coacutedigo en un archivo de oacuterdenes o script y luegoutilizar Julia en modo script para ejecutarlo Por convencioacuten los scripts de Juliatienen nombres que terminan con la extensioacuten jl

Si sabe coacutemo crear y ejecutar un script en su computadora estaacute listo paracomenzar De lo contrario es recomendable usar JuliaBox nuevamente Abra unarchivo de texto escriba el script y guaacuterdelo con la extensioacuten jl El script sepuede ejecutar en una terminal con el comando julia nombre_del_scriptjl

Debido a que Julia proporciona ambos modos puede probar liacuteneas de coacutedigo enmodo interactivo antes de colocarlos en un script Auacuten asiacute tenga enconsideracioacuten que existen diferencias entre el modo interactivo y el modo scriptque pueden generar confusioacuten

Por ejemplo si estaacute utilizando Julia como una calculadora puede escribir

Modo script 19

juliagt millas = 262262juliagt millas 16142182

La primera liacutenea asigna un valor a millas y muestra el valor La segunda liacutenea esuna expresioacuten por lo que el REPL la evaluacutea y muestra el resultado Gracias alcoacutedigo anterior sabemos que una maratoacuten tiene unos 42 kiloacutemetros

Pero si escribe el mismo coacutedigo en un script y lo ejecuta no obtendraacute ninguacutenresultado En el modo script una expresioacuten por siacute sola no tiene ninguacuten efectovisible Julia evaluacutea la expresioacuten pero no muestra el valor a menos que se loindique

millas = 262println(millas 161)

Al principio este comportamiento puede ser confuso

Un script generalmente contiene una secuencia de sentencias Si hay maacutes de unasentencia los resultados aparecen de uno a la vez a medida que se ejecutan lassentencias

Por ejemplo el script

println(1)x = 2println(x)

produce la salida

12

Notar que la sentencia de asignacioacuten x = 2 no tiene salida

Ejercicio 2-1

Para comprobar que ha comprendido lo recientemente explicado escriba lassiguientes sentencias en el REPL de Julia y vea lo que hace cada una

5x = 5x + 1

20 Capiacutetulo 2 Variables expresiones y sentencias

Ahora coloque las mismas sentencias en un script y ejecuacutetelo iquestCuaacutel es elresultado Modifique el script transformando cada expresioacuten en una sentencia deimpresioacuten y luego ejecuacutetelo de nuevo

Orden de operacionesCuando una expresioacuten contiene maacutes de un operador el orden de evaluacioacutendepende de las reglas de precedencia Julia sigue la convencioacuten matemaacutetica parael orden de evaluacioacuten de los operadores matemaacuteticos El acroacutenimo PAPOMUDASes una forma uacutetil de recordar estas reglas

bull PAreacutentesis tienen la mayor precedencia y se pueden utilizar para forzar laevaluacioacuten de una expresioacuten en el orden que se desee Dado que lasexpresiones entre pareacutentesis se evaluacutean primero 2(3-1) es 4 y (1+1)^(5-2) es 8 Tambieacuten puede usar pareacutentesis para hacer una expresioacuten maacutes faacutecilde leer como en (minuto100)60 incluso si no cambia el resultado

bull POtenciacioacuten tiene la siguiente precedencia maacutes alta por lo que 1+2^3 es9 no 27 y 23^2 es 18 no 36

bull MUltiplicacioacuten y Divisioacuten tienen mayor precedencia que la Adicioacuten ySustraccioacuten Entonces 23-1 es 5 no 4 y 6+42 es 8 no 5

bull Los operadores con la misma precedencia se evaluacutean de izquierda a derecha(excepto potencias) Entonces en la expresioacuten grados2π la divisioacuten ocurreprimero y el resultado se multiplica por π Para dividir entre puede usarpareacutentesis escribir grados2π o grados2π

OBSERVACIOacuteNNo se esfuerce demasiado en recordar el orden de lasoperaciones Si el orden no es evidente mirando laexpresioacuten use pareacutentesis para que siacute lo sea

Operaciones con cadenasEn general no se pueden realizar operaciones matemaacuteticas con cadenas aunquelas cadenas puedan parecer nuacutemeros por lo que lo siguiente es invaacutelido

2 - 1huevos faacuteciltercero + talismaacuten

No obstante hay dos excepciones y ^

El operador realiza concatenacioacuten de cadenas lo que significa que une lascadenas de extremo a extremo Por ejemplo

Orden de operaciones 21

juliagt primer_str = autoautojuliagt segundo_str = moacutevilmoacuteviljuliagt primer_str segundo_strautomoacutevil

El operador ^ tambieacuten funciona con cadenas generando repeticiones Porejemplo Spam^3 es SpamSpamSpam Si uno de los valores es una cadena elotro tiene que ser un nuacutemero entero

De manera anaacuteloga este uso de y ^ tambieacuten tiene sentido en la multiplicacioacuten ypotencia Asiacute como 4^3 es equivalente a 444 esperamos que el Spam^3 sea lomismo que el SpamSpamSpam y lo es

ComentariosA medida que los programas se hacen maacutes largos y complejos se vuelven maacutesdifiacuteciles de leer Los lenguajes formales son densos y a menudo es difiacutecil leer elcoacutedigo y entender queacute estaacute haciendo o por queacute

Por esta razoacuten es una buena idea agregar notas a sus programas para explicaren lenguaje natural lo que estaacute haciendo el programa Estas notas se llamancomentarios y comienzan con el siacutembolo

calcula el porcentaje de hora que ha transcurridoporcentaje = (minuto 100) 60

En este caso el comentario aparece soacutelo en una liacutenea Tambieacuten puede ponercomentarios al final de una liacutenea

porcentaje = (minuto 100) 60 porcentaje de una hora

Todo desde el hasta el final de la liacutenea se ignora y no tiene ninguacuten efecto en laejecucioacuten del programa

Los comentarios son maacutes uacutetiles cuando documentan caracteriacutesticas no obvias delcoacutedigo Es razonable suponer que el lector puede averiguar queacute hace el coacutedigopor lo tanto es maacutes uacutetil explicar por queacute

Este comentario es inuacutetil porque es redundante con el coacutedigo

v = 5 asigna 5 a v

Este comentario contiene informacioacuten uacutetil que no estaacute presente en el coacutedigo

22 Capiacutetulo 2 Variables expresiones y sentencias

v = 5 velocidad en metrossegundo

OBSERVACIOacuteNLos nombres de las variables tienen que ser descriptivospara asiacute reducir la necesidad de comentarios pero notan largos como para dificultar la lectura del coacutedigo

DepuracioacutenSe pueden producir tres tipos de errores en un programa errores de sintaxiserrores en tiempo de ejecucioacuten y errores semaacutenticos Es uacutetil distinguirlos pararastrearlos maacutes raacutepidamente

Error de sintaxisldquoSintaxisrdquo se refiere a la estructura de un programa y las reglas sobre esaestructura Por ejemplo los pareacutentesis deben presentarse de a pares por loque (1+2) es vaacutelido pero 8) es un error de sintaxis

Si hay un error de sintaxis en cualquier parte de su programa Julia muestraun mensaje de error y se cierra no pudiendo ejecutar el programa Durantesus primeras semanas como programador puede pasar mucho tiemporastreando errores de sintaxis A medida que gane experiencia cometeraacutemenos errores y los encontraraacute maacutes raacutepido

Error en tiempo de ejecucioacutenEl segundo tipo de error es el error en tiempo de ejecucioacuten llamado asiacuteporque aparece durante la ejecucioacuten del programa Estos errores tambieacutense denominan excepciones porque generalmente indican que ha sucedidoalgo excepcional (y malo)

Los errores en tiempo de ejecucioacuten son raros en los programas simples queveraacute en los primeros capiacutetulos por lo que puede pasar un tiempo antes deque encuentre uno

Error semaacutenticoEl tercer tipo de error es ldquosemaacutenticordquo es decir relacionado con elsignificado Si hay un error semaacutentico en su programa este se ejecutaraacute singenerar mensajes de error pero no haraacute lo que se desea sino que haraacute otracosa Especiacuteficamente haraacute lo que usted le dijo que hiciera (y no lo queusted desea que realice)

Identificar errores semaacutenticos puede ser complicado porque requiere que setrabaje a la inversa analizando la salida del programa para intentar descubrirqueacute estaacute haciendo

Depuracioacuten 23

Glosariovariable

Un nombre que hace referencia a un valor

asignacioacutenUna sentencia que asigna un valor a una variable

diagrama de estadoUna representacioacuten graacutefica de un conjunto de variables y los valores a losque hace referencia

palabra claveUna palabra reservada que se utiliza para definir la sintaxis y estructura deun programa no puede usar palabras reservadas como if function ywhile como nombres de variables

operandoUno de los valores sobre los que opera un operador

expresioacutenUna combinacioacuten de variables operadores y valores que representa un solovalor como resultado

evaluarSimplificar una expresioacuten realizando operaciones para obtener un solo valor

sentenciaUna seccioacuten de coacutedigo que representa un comando o accioacuten Hasta ahoralas sentencias que hemos visto son asignaciones e impresiones

ejecutarEjecutar una sentencia y hacer lo que eacutesta dice

modo interactivoUna forma de utilizar el REPL de Julia escribiendo coacutedigo en el indicador

modo scriptUna forma de usar Julia para leer coacutedigo desde un script y ejecutarlo

scriptUn programa almacenado en un archivo

24 Capiacutetulo 2 Variables expresiones y sentencias

precedencia del operadorReglas que rigen el orden en que se evaluacutean las expresiones que involucranmuacuteltiples operadores matemaacuteticos y operandos

concatenarUnir dos cadenas de extremo a extremo

comentarioInformacioacuten en un programa que estaacute destinada a otros programadores (ocualquier persona que lea el coacutedigo fuente) y que no tiene efecto en laejecucioacuten del programa

error de sintaxisUn error en un programa que hace que sea imposible de analizar (y por lotanto imposible de ejecutar)

error en tiempo de ejecucioacuten o excepcioacutenUn error que se detecta mientras se ejecuta el programa

semaacutenticaEl significado de un programa

error semaacutenticoEs un error en un programa que provoca que se haga algo diferente a loque el programador pretendiacutea

Ejercicios

Ejercicio 2-2

Repitiendo el consejo del capiacutetulo anterior cada vez que aprenda algo nuevodebe probarlo en el modo interactivo y cometer errores a propoacutesito para ver elresultado

1 Hemos visto que n=42 es vaacutelido iquestQueacute pasa con 42=n

2 iquestY con x=y=1

3 En algunos lenguajes cada sentencia termina con un punto y coma iquestQueacutesucede si pone un punto y coma al final de una sentencia en Julia

4 iquestQueacute pasa si pone un punto al final de una sentencia

5 En notacioacuten matemaacutetica puede multiplicar x e y de esta manera x y iquestQueacutepasa si intenta eso en Julia iquestY queacute sucede con 5x

Ejercicios 25

Ejercicio 2-3

Practique usando el REPL de Julia como una calculadora

1 El volumen de una esfera con radio es iquestCuaacutel es el volumen de unaesfera con radio 5

2 Supongamos que el precio de venta de un libro es de $2495 pero laslibreriacuteas obtienen un descuento del 40 El enviacuteo cuesta $3 por la primeracopia y 75 centavos por cada copia adicional iquestCuaacutel es el costo total al pormayor de 60 copias

3 Si una persona sale de casa a las 652 am y corre 1 milla a un ritmorelajado (815 minutos por milla) luego 3 millas maacutes raacutepido (712 minutospor milla) y 1 milla a ritmo relajado nuevamente iquestA queacute hora llega a casapara desayunar

26 Capiacutetulo 2 Variables expresiones y sentencias

Capiacutetulo 3 FuncionesEn el contexto de la programacioacuten una funcioacuten es una secuencia de sentenciasque ejecuta una operacioacuten deseada y tiene un nombre Cuando se define unafuncioacuten se especifica su nombre y secuencia de sentencias Una vez hecho estose puede llamar a la funcioacuten por su nombre

Llamada a funcioacuten

Ya se ha visto un ejemplo de una llamada a funcioacuten

juliagt println(iexclHola Mundo)iexclHola Mundo

El nombre de esta funcioacuten es println La expresioacuten entre pareacutentesis se llamaargumento de la funcioacuten

Es comuacuten decir que una funcioacuten toma un argumento y devuelve un resultadoEl resultado tambieacuten se llama valor de retorno

Julia tiene funciones integradas que convierten valores de un tipo a otro Lafuncioacuten parse toma una cadena y si es posible la convierte en cualquier tipo denuacutemero en caso contrario arroja error

juliagt parse(Int64 32)32juliagt parse(Float64 314159)314159juliagt parse(Int64 Hola)ERROR ArgumentError invalid base 10 digit H in Hola

(ERROR ArgumentError base invaacutelida de 10 diacutegitos H en Hola)

trunc puede convertir valores de punto flotante a enteros pero no redondea sinoque trunca

juliagt trunc(Int64 399999)3juliagt trunc(Int64 -23)-2

float convierte nuacutemeros enteros en nuacutemeros de punto flotante

Llamada a funcioacuten 27

juliagt float(32)320

Finalmente string convierte el argumento en una cadena

juliagt string(32)32juliagt string(314159)314159

Funciones matemaacuteticasEn Julia la mayoriacutea de las funciones matemaacuteticas conocidas estaacuten disponiblesdirectamente

proporcioacuten = potencia_de_sentildealpotencia_de_ruidodecibelios = 10log10(proporcioacuten)

Este primer ejemplo utiliza la funcioacuten log10 para calcular la proporcioacuten entresentildeal y ruido en decibelios (suponiendo que potencia_de_sentildeal ypotencia_de_ruido estaacuten definidos) Tambieacuten existe la funcioacuten log que calcula ellogaritmo natural

radianes = 07altura = sin(radianes)

Este segundo ejemplo encuentra la razoacuten seno (en ingleacutes sine) de la variableradianes El nombre de esta variable es una pista de que la funcioacuten sin y las otrasfunciones trigonomeacutetricas (cos tan etc) toman argumentos en radianes Paraconvertir grados a radianes se debe dividir por 180 y multiplicar por

juliagt grados=4545juliagt radianes=grados180π07853981633974483juliagt sin(radianes)07071067811865475

El valor de la variable π es una aproximacioacuten de punto flotante de con unaprecisioacuten de aproximadamente 16 diacutegitos

Si sabe de trigonometriacutea puede verificar el resultado anterior comparaacutendolo conla raiacutez cuadrada de dos dividido por dos

28 Capiacutetulo 3 Funciones

juliagt sqrt(2) 207071067811865476

ComposicioacutenHasta ahora hemos analizado los elementos de un programa (variablesexpresiones y sentencias) de forma aislada sin mencionar coacutemo se combinan

Una de las caracteriacutesticas maacutes uacutetiles de los lenguajes de programacioacuten es sucapacidad para combinar pequentildeos bloques de coacutedigo Por ejemplo elargumento de una funcioacuten puede ser cualquier tipo de expresioacuten incluidosoperadores aritmeacuteticos

x = sin(grados3602π)

E incluso llamadas a funciones

x = exp(log(x + 1))

Casi en cualquier lugar donde se pueda colocar un valor se puede colocar unaexpresioacuten arbitraria con una excepcioacuten el lado izquierdo de una sentencia deasignacioacuten debe ser un nombre de variable Cualquier otra expresioacuten en el ladoizquierdo genera un error de sintaxis (se veraacuten excepciones a esta regla maacutesadelante)

2

juliagt minutos = horas 60 bien120juliagt horas 60 = minutos malERROR syntax 60 is not a valid function argument name

(ERROR sintaxis 60 no es un nombre de argumento de funcioacuten vaacutelido)

Agregar nuevas funcionesHasta ahora solo hemos usado las funciones integradas en Julia pero tambieacuten esposible agregar nuevas funciones Una definicioacuten de funcioacuten especifica el nombrede una nueva funcioacuten y la secuencia de sentencias que se ejecutan cuando sellama a la funcioacuten A continuacioacuten se muestra un ejemplo

Composicioacuten 29

function imprimirletras() println(Juguemos en el bosque) println(mientras el lobo no estaacute)end

function es una palabra reservada que indica que esta es una definicioacuten defuncioacuten El nombre de la funcioacuten es imprimirletras Las reglas para losnombres de funciones son las mismas que para los nombres de variables puedencontener casi todos los caracteres Unicode (consulte Seccioacuten 81) pero el primercaraacutecter no puede ser un nuacutemero No puede usar una palabra reservada comonombre de una funcioacuten y debe evitar tener una variable y una funcioacuten con elmismo nombre

Los pareacutentesis vaciacuteos despueacutes del nombre indican que esta funcioacuten no tieneargumentos

La primera liacutenea de una definicioacuten de funcioacuten se llama encabezado el resto sellama cuerpo El cuerpo termina con la palabra reservada end y puede contenertodas las sentencias que desee Para facilitar la lectura el cuerpo de la funcioacutendeberiacutea tener sangriacutea

Las comillas deben ser comillas rectas () generalmente ubicadas junto a latecla Enter en el teclado Las comillas inglesas (ldquordquo)no son vaacutelidas en Julia

Si escribe una definicioacuten de funcioacuten en modo interactivo Julia REPL inserta unasangriacutea para informarle que la definicioacuten no estaacute completa

juliagt function imprimirletras() println(Juguemos en el bosque)

Para finalizar la funcioacuten debe escribir end

La sintaxis para llamar a la nueva funcioacuten es la misma que para las funcionesintegradas en Julia

juliagt imprimirletras()Juguemos en el bosquemientras el lobo no estaacute

Una vez definida una funcioacuten puede usarla dentro de otra funcioacuten Por ejemplopara repetir el estribillo anterior se podriacutea escribir una funcioacuten llamadarepetirletras

30 Capiacutetulo 3 Funciones

function repetirletras() imprimirletras() imprimirletras()end

Y luego llamar a repetirletras

juliagt repetirletras()Juguemos en el bosquemientras el lobo no estaacuteJuguemos en el bosquemientras el lobo no estaacute

Definiciones y usosAl unir los fragmentos de coacutedigo de la seccioacuten anterior todo el programa se veasiacute

function imprimirletras() println(Jueguemos en el bosque) println(mientras el lobo no estaacute)end

funcioacuten repetirletras() imprimirletras() imprimirletras()end

repetirletras()

Este programa contiene dos definiciones de funcioacuten imprimirletras yrepetirletras Las definiciones de funcioacuten se ejecutan al igual que otrassentencias pero su ejecucioacuten crea nuevas funciones Las sentencias dentro de lafuncioacuten no se ejecutan hasta que se llama a la funcioacuten y la definicioacuten de lafuncioacuten no genera salida

Como es de esperar debe crear una funcioacuten antes de poder ejecutarla En otraspalabras la definicioacuten de la funcioacuten tiene que ejecutarse antes de que se llame ala funcioacuten

Ejercicio 3-1

Mueva la uacuteltima liacutenea de este programa a la parte superior de modo que lallamada a funcioacuten aparezca antes de las definiciones Ejecute el programa y veaqueacute mensaje de error obtiene

Definiciones y usos 31

Ahora mueva la llamada a funcioacuten hacia abajo y coloque la definicioacuten deimprimirletras despueacutes de la definicioacuten de repetirletras iquestQueacute sucede cuandoejecuta este programa

Flujo de ejecucioacutenPara asegurarse de que una funcioacuten sea definida antes de su primer uso debeconocer el orden en que se ejecutan las instrucciones lo que se denomina flujode ejecucioacuten

La ejecucioacuten siempre comienza con la primera sentencia del programa Lassentencias se ejecutan una a la vez en orden descendente

Las definiciones de funcioacuten no alteran el flujo de ejecucioacuten del programa pero sedebe recordar que las sentencias dentro de la funcioacuten no se ejecutan hasta quese llama a la funcioacuten

Una llamada a funcioacuten es como un desviacuteo en el flujo de ejecucioacuten En lugar depasar a la siguiente sentencia el flujo salta al cuerpo de la funcioacuten ejecuta lassentencias que estaacuten alliacute y luego regresa para continuar el coacutedigo donde lo dejoacute

Esto suena bastante simple hasta que se tiene en cuenta que una funcioacuten puedellamar a otra Mientras se estaacute ejecutando una funcioacuten el programa podriacutea tenerque ejecutar las sentencias de otra funcioacuten Luego mientras ejecuta esa nuevafuncioacuten iexclel programa podriacutea tener que ejecutar otra funcioacuten maacutes

Afortunadamente Julia es capaz de hacer el seguimiento de sus movimientos asiacuteque cada vez que una funcioacuten termina el programa retoma la funcioacuten que lallamoacute justo donde la dejoacute Cuando llega al final del programa la ejecucioacutentermina

En resumen cuando lee un programa no siempre debe leer de arriba haciaabajo A veces tiene maacutes sentido seguir el flujo de ejecucioacuten

Paraacutemetros y argumentosAlgunas de las funciones que se han visto requieren argumentos Por ejemplo lafuncioacuten cos necesita un nuacutemero como argumento Algunas funciones toman maacutesde un argumento por ejemplo parse toma dos un nuacutemero y una cadena

Dentro de la funcioacuten los argumentos se asignan a variables llamadasparaacutemetros A continuacioacuten se muestra un ejemplo de definicioacuten de funcioacuten quetoma un argumento

32 Capiacutetulo 3 Funciones

function imprimirdosveces(juan) println(juan) println(juan)end

Esta funcioacuten asigna el argumento a un paraacutemetro llamado juan Cuando se llamaa la funcioacuten esta imprime el valor del paraacutemetro (cualquiera que sea) dos veces

Esta funcioacuten funciona con cualquier valor que se pueda imprimir

juliagt imprimirdosveces(Correo no deseado)Correo no deseadoCorreo no deseadojuliagt imprimirdosveces(42)4242juliagt imprimirdosveces(π)π = 31415926535897 π = 31415926535897

Las mismas reglas de composicioacuten que se aplican a las funciones integradastambieacuten se aplican a las funciones definidas por el programador por lo quepodemos usar cualquier tipo de expresioacuten como argumento paraimprimirdosveces

juliagt imprimirdosveces(Correo no deseado ^4)Correo no deseado Correo no deseado Correo no deseado Correo no deseadoCorreo no deseado Correo no deseado Correo no deseado Correo no deseadojuliagt imprimirdosveces(cos(π))-10-10

El argumento se evaluacutea antes de llamar a la funcioacuten por lo que en los ejemploslas expresiones Correo no deseado ^4 y cos(π) solo se evaluacutean una vez

Tambieacuten puede usar una variable como argumento

juliagt michael = La vida es bellaLa vida es bellajuliagt imprimirdosveces(michael)La vida es bellaLa vida es bella

El nombre de la variable que pasamos como argumento (michael) no tiene nadaque ver con el nombre del paraacutemetro (juan) Para la funcioacuten imprimirdosveces

Paraacutemetros y argumentos 33

todos los paraacutemetros se llaman juan sin importar el nombre de la variable quepasemos como argumento (en este caso michael)

Las variables y los paraacutemetros son localesCuando se crea una variable dentro de una funcioacuten esta es local es decir soloexiste dentro de la funcioacuten Por ejemplo

function concatenar_dos(parte1 parte2) concat = parte1 parte2 imprimirdosveces(concat)end

Esta funcioacuten toma dos argumentos los concatena e imprime el resultado dosveces Aquiacute hay un ejemplo

juliagt linea1 = Hola holaHola holajuliagt linea2 = adioacutes adioacutesadioacutes adioacutesjuliagt concatenar_dos(liacutenea1 liacutenea2)Hola hola adioacutes adioacutesHola hola adioacutes adioacutes

Cuando concatenar_dos termina la variable concat es destruida Si intentamosimprimirla obtendremos un error

juliagt println(concat)ERROR UndefVarError concat not defined

Los paraacutemetros tambieacuten son locales Por ejemplo fuera de la funcioacutenimprimirdosveces no existe juan

Diagramas de pilaPara seguir la pista de queacute variables se usan en queacute lugares es uacutetil dibujar undiagrama de pila Al igual que los diagramas de estado los diagramas de pilamuestran el valor de cada variable pero tambieacuten muestran la funcioacuten a la quepertenece cada una

Cada funcioacuten se representa por un marco Un marco es un recuadro con elnombre de una funcioacuten a un costado y los paraacutemetros y variables de la funcioacutendentro El diagrama de pila para el ejemplo anterior se muestra en Figura 2

34 Capiacutetulo 3 Funciones

Figura 2 Diagrama de pila

Los marcos se ordenan de tal manera que cada funcioacuten llama a la funcioacuteninmediatamente inferior En este ejemplo imprimirdosveces fue llamado porconcatenar_dos y concatenar_dos fue llamado por Main que es un nombreespecial para la funcioacuten de maacutes alto nivel Cuando se crea una variable afuera decualquier funcioacuten pertenece a Main

Cada paraacutemetro se refiere al mismo valor que su argumento correspondienteEntonces parte1 tiene el mismo valor que linea1 parte2 tiene el mismo valorque linea2 y juan tiene el mismo valor que concat

Si se produce un error durante una llamada a funcioacuten Julia imprime el nombrede la funcioacuten el nombre de la funcioacuten que la llamoacute el nombre de la funcioacuten que asu vez llamoacute a esta otra y asiacute sucesivamente hasta llegar a la funcioacuten de maacutes altonivel Main

Por ejemplo si intenta acceder a concat desde imprimirdosveces obtendraacute unUndefVarError

ERROR UndefVarError concat not definedStacktrace [1] imprimirdosveces at REPL[1]gt2 [inlined] [2] concatenar_dos(String String) at REPL[2]gt3

Esta lista de funciones se llama trazado inverso Indica en queacute archivo deprograma se produjo el error en queacute liacutenea y queacute funciones se estaban ejecutandoen ese momento Tambieacuten muestra la liacutenea de coacutedigo que causoacute el error

El orden de las funciones en el trazado inverso es el opuesto del orden de losrecuadros en el diagrama de pila La funcioacuten que se estaacute ejecutando actualmenteestaacute en la parte superior

Funciones productivas y funciones nulasAlgunas de las funciones que hemos utilizado como las funciones matemaacuteticasdevuelven resultados A este tipo de funciones se les llamaraacute funcionesproductivas a falta de un nombre mejor Otras funciones comoimprimirdosveces realizan una accioacuten pero no devuelven un valor Estas sellaman funciones nulas

Funciones productivas y funciones nulas 35

Cuando se llama a una funcioacuten productiva casi siempre se quiere hacer algo conel resultado por ejemplo asignarlo a una variable o usarlo como parte de unaexpresioacuten

x = cos(radianes)aurea = (sqrt(5)+1)2

Cuando se llama a una funcioacuten en modo interactivo Julia muestra el resultado

juliagt sqrt(5)223606797749979

Pero en un script si se llama a una funcioacuten productiva iexclel valor de retorno sepierde para siempre

sqrt(5)

Output

223606797749979

Este script calcula la raiacutez cuadrada de 5 pero como no almacena ni muestra elresultado no es muy uacutetil

Las funciones nulas pueden mostrar algo en la pantalla o tener alguacuten otro efectopero no tienen un valor de retorno Si asigna el resultado a una variableobtendraacute un valor especial llamado nothing (nada en ingleacutes)

juliagt resultado = imprimirdosveces(Bing)BingBingjuliagt show(resultado)nothing

Para imprimir el valor nothing debe usar la funcioacuten show que es como la funcioacutenprint pero permite el valor nothing

El valor nothing no es lo mismo que la cadena nothing Es un valor especial quetiene su propio tipo

juliagt typeof (nothing)Nothing

Las funciones que hemos escrito hasta ahora son nulas Comenzaremos a escribir

36 Capiacutetulo 3 Funciones

funciones productivas en unos pocos capiacutetulos

iquestPor queacute se necesitan funcionesPuede que no esteacute claro por queacute vale la pena dividir un programa en funcionesHay varias razones

bull Crear una nueva funcioacuten le brinda la oportunidad de darle nombre a ungrupo de sentencias lo que hace que su programa sea maacutes faacutecil de leer ydepurar

bull Las funciones pueden hacer que un programa sea maacutes corto al eliminarcoacutedigo repetitivo Ademaacutes si realiza un cambio solo tiene que hacerlo en unsolo lugar

bull Dividir un programa largo en funciones le permite depurar las partes de unaen una y luego unirlas

bull Las funciones bien disentildeadas pueden ser uacutetiles para muchos programasUna vez que escribe y depura una puede reutilizarla

bull En Julia las funciones pueden mejorar mucho el rendimiento

DepuracioacutenUna de las habilidades maacutes importantes que adquiriraacute es la depuracioacuten Aunquepuede ser frustrante la depuracioacuten es una de las partes maacutes intelectualmentegratificantes desafiantes e interesantes de la programacioacuten

La depuracioacuten puede ser vista como un trabajo de detective El programador seenfrenta a pistas y tiene que inferir los procesos y eventos que generaron losresultados que ve

La depuracioacuten tambieacuten es como una ciencia experimental Una vez que se tieneuna idea de lo que estaacute mal se modifica el programa y se intenta nuevamente Sila hipoacutetesis era correcta se puede predecir el resultado de la modificacioacuten y asiacuteestar un paso maacutes cerca de un programa totalmente funcional Si la hipoacutetesis eraincorrecta se tiene que encontrar una nueva Como Sherlock Holmes sentildealoacute

Cuando todo aquello que es imposible ha sido eliminado lo que quede pormuy improbable que parezca es la verdad

mdash A Conan Doyle El signo de los cuatro

Para algunas personas la programacioacuten y la depuracioacuten son lo mismo Es decirla programacioacuten es el proceso de depurar gradualmente un programa hasta quehaga lo que desea Lo ideal es comenzar con un programa que funcione y hacer

iquestPor queacute se necesitan funciones 37

pequentildeas modificaciones depuraacutendolas a medida que avanza

Por ejemplo Linux es un sistema operativo que contiene millones de liacuteneas decoacutedigo pero comenzoacute como un programa simple que Linus Torvalds usoacute paraexplorar el chip Intel 80386 Seguacuten Larry Greenfield Uno de los proyectosanteriores de Linus fue un programa que cambiariacutea entre imprimir AAAA yBBBB Esto luego evolucionoacute a Linux (The Linux Usersrsquo Guide Beta Version1)

Glosariofuncioacuten

secuencia de sentencias que ejecuta una operacioacuten deseada y tiene unnombre Las funciones pueden tomar o no argumentos y pueden producir ono un resultado

definicioacuten de funcioacutenUna sentencia que crea una nueva funcioacuten especificando su nombreparaacutemetros y las sentencias que contiene

objeto de funcioacutenUn valor creado por una definicioacuten de funcioacuten El nombre de la funcioacuten esuna variable que se refiere a un objeto de funcioacuten

encabezadoLa primera liacutenea de una definicioacuten de funcioacuten

cuerpoSecuencia de sentencias dentro de una definicioacuten de funcioacuten

paraacutemetroUn nombre usado dentro de una funcioacuten para referirse al valor pasado comoargumento

Llamada a funcioacutenUna sentencia que ejecuta una funcioacuten Compuesta por el nombre de lafuncioacuten seguido por la lista de argumentos que usa entre pareacutentesis

argumentoValor que se le pasa a una funcioacuten cuando se la llama Este valor se asignaal paraacutemetro correspondiente en la funcioacuten

variable localUna variable definida dentro de una funcioacuten Una variable local solo puedeusarse dentro de su funcioacuten

38 Capiacutetulo 3 Funciones

valor de retornoEl resultado de una funcioacuten Si se utiliza una llamada a funcioacuten como unaexpresioacuten el valor de retorno es el valor de la expresioacuten

funcioacuten productivaUna funcioacuten que devuelve un valor

funcioacuten vaciacuteaUna funcioacuten que siempre devuelve nothing

nothingUn valor especial devuelto por las funciones nulas

composicioacutenUsar una expresioacuten como parte de una expresioacuten maacutes grande o unasentencia como parte de una sentencia maacutes grande

flujo de ejecucioacutenEl orden en que las sentencias se ejecutan

diagrama de pilaUna representacioacuten graacutefica de una pila de funciones sus variables y losvalores a los que se refieren

marcoUn recuadro que en un diagrama de pila representa una llamada de funcioacutenContiene las variables locales y los paraacutemetros de la funcioacuten

trazado inversoUna lista de las funciones que se estaacuten ejecutando las cuales son impresascuando ocurre una excepcioacuten

Ejercicios

OBSERVACIOacuteN Estos ejercicios deben realizarse utilizando soacutelo lo quese ha tratado hasta ahora

Ejercicio 3-2

Escriba una funcioacuten llamada justificar_a_la_derecha que tome una cadena s comoparaacutemetro y que imprima la cadena con suficientes espacios en blanco para quela uacuteltima letra de la cadena se encuentre en la columna 70 de la pantalla

using IntroAJulia

Ejercicios 39

justificar_a_la_derecha(Celia)

OBSERVACIOacuteN

Use concatenacioacuten de cadenas y repeticioacuten AdemaacutesJulia tiene integrada una funcioacuten llamada length quedevuelve la longitud de una cadena por lo que el valorde length(Celia) es 5

Ejercicio 3-3

Un objeto de funcioacuten es un valor que se puede asignar a una variable o serpasado como argumento Por ejemplo dosveces es una funcioacuten que toma unobjeto de funcioacuten como argumento y lo llama dos veces

function dosveces(f) f() f()end

A continuacioacuten se muestra un ejemplo que usa dosveces para llamar a unafuncioacuten llamada imprimirgato dos veces

function imprimirpalabra() println(palabra)end

dosveces(imprimirpalabra)

1 Escriba este ejemplo en un script y prueacutebelo

2 Modifique dosveces para que tome dos argumentos un objeto de funcioacuten yun valor y que llame a la funcioacuten dos veces pasando el valor comoargumento

3 Copie la definicioacuten de imprimirdosveces mencionada antes en este capiacutetuloa su secuencia de comandos

4 Use la versioacuten modificada de dosveces para llamar a imprimirdosveces dosveces pasando palabra como argumento

5 Defina una nueva funcioacuten llamada cuatroveces que tome un objeto defuncioacuten y un valor y que llame a la funcioacuten cuatro veces pasando el valorcomo paraacutemetro Debe haber solo dos sentencias en el cuerpo de estafuncioacuten no cuatro

40 Capiacutetulo 3 Funciones

Ejercicio 3-4

1 Escriba la funcioacuten imprimircuadricula que dibuje una cuadriacutecula como lasiguiente

juliagt imprimircuadricula()+ - - - - + - - - - +| | || | || | || | |+ - - - - + - - - - +| | || | || | || | |+ - - - - + - - - - +

1 Escriba una funcioacuten que dibuje una cuadriacutecula similar con cuatro filas ycuatro columnas

Creacuteditos Este ejercicio se basa en un ejercicio en Oualline Practical CProgramming Third Edition OrsquoReilly Media 1997

OBSERVACIOacuteN

Para imprimir maacutes de un valor por liacutenea se puedeimprimir una secuencia de valores separados por comas

println (+ -)

La funcioacuten print no avanza a la siguiente liacutenea

print(+)println(-)

El resultado de estas sentencias es + - en la mismaliacutenea El resultado de una siguiente sentencia deimpresioacuten comenzariacutea en la siguiente liacutenea

Ejercicios 41

Capiacutetulo 4 Estudio de Caso Disentildeo de InterfazEste capiacutetulo presenta un segundo estudio de caso que muestra el proceso dedisentildear funciones que trabajen en conjunto

Se presentan graacuteficos turtle que es una forma de crear dibujos a traveacutes de laprogramacioacuten Los graacuteficos turtle no estaacuten incluidos en la Biblioteca Estaacutendarpor lo que se debe agregar el moacutedulo IntroAJulia a su configuracioacuten de Julia

Los ejemplos de este capiacutetulo se pueden ejecutar en un notebook graacutefico enJuliaBox el cual combina coacutedigo texto formateado matemaacuteticas y multimedia enun solo documento (vea Apeacutendice B)

TurtlesUn modulo es un archivo que contiene una coleccioacuten de funciones relacionadasJulia proporciona algunos moacutedulos en su Biblioteca Estaacutendar Ademaacutes es posibleagregar maacutes funciones a una gran cantidad de paquetes(httpsjuliaobservercom)

Los paquetes se pueden instalar en REPL ingresando al modo Pkg REPL con latecla ]

(v12) pkggt add httpsgithubcomJuliaIntroIntroAJuliajl

Esto puede demorar un poco

Antes de que podamos usar las funciones de un moacutedulo tenemos que importarlocon una sentencia using

juliagt using IntroAJulia

juliagt ὂ = Turtle()LuxorTurtle(00 00 true 00 (00 00 00))

El moacutedulo IntroAJulia proporciona una funcioacuten llamada Turtle (tortuga enespantildeol) que crea un objeto LuxorTurtle el cual es asignado a una variablellamada ὂ (turtle TAB)

Una vez que crea una tortuga puede llamar a una funcioacuten para moverla y asiacutehacer un dibujo con ella Por ejemplo para mover la tortuga hacia adelante(forward en ingleacutes)

42 Capiacutetulo 4 Estudio de Caso Disentildeo de Interfaz

svg begin forward(ὂ 100)end

Figura 3 Haciendo avanzar a la tortuga

La palabra reservada svg ejecuta una macro que dibuja una imagen SVG Lasmacros son una caracteriacutestica importante pero avanzada de Julia

Los argumentos de forward son la tortuga y una distancia en piacutexeles por lo queel tamantildeo real depende de su pantalla

Tambieacuten es posible hacer girar a la tortuga con la funcioacuten turn Los argumentosde esta funcioacuten son la tortuga y un aacutengulo en grados

Ademaacutes cada tortuga estaacute sosteniendo un laacutepiz que puede estar hacia arriba ohacia abajo si el laacutepiz estaacute hacia abajo la tortuga deja un rastro cuando semueve Figura 3 muestra el rastro dejado por la tortuga Las funciones penup ypendown significan laacutepiz hacia arriba y laacutepiz hacia abajo

Para dibujar un aacutengulo recto modifique la llamada a la macro

ὂ = Turtle()svg begin forward(ὂ 100) turn(ὂ -90) forward(ὂ 100)end

Ejercicio 4-1

Ahora modifique la macro para que dibuje un cuadrado iexclNo sigas hasta haberloterminado

Repeticioacuten Simple

Es probable que haya escrito algo como esto

Repeticioacuten Simple 43

ὂ = Turtle()svg begin forward(ὂ 100) turn(ὂ -90) forward(ὂ 100) turn(ὂ -90) forward(ὂ 100) turn(ὂ -90) forward(ὂ 100)end

Se puede hacer lo mismo de manera maacutes concisa con una sentencia for

juliagt for i in 14 println(iexclHola) endiexclHolaiexclHolaiexclHolaiexclHola

Este es el uso maacutes simple de la sentencia for aunque se veraacuten maacutes usos despueacutesEacutesto deberiacutea ser suficiente para reescribir su programa que dibuja un cuadradoNo continuacutee hasta que lo haga

Aquiacute hay una sentencia for que dibuja un cuadrado

ὂ = Turtle()svg begin for i in 14 forward(ὂ 100) turn(ὂ -90) endend

La sintaxis de una sentencia for es similar a la definicioacuten de una funcioacuten Tieneun encabezado y un cuerpo que termina con la palabra reservada end El cuerpopuede contener el nuacutemero de sentencias que desee

Una sentencia for tambieacuten es llamada bucle porque el flujo de ejecucioacuten recorreel cuerpo y luego vuelve a la parte superior En este caso ejecuta el cuerpocuatro veces

Esta versioacuten es en realidad un poco diferente del coacutedigo anterior que dibujaba uncuadrado porque hace otro giro despueacutes de dibujar el uacuteltimo lado del cuadradoEl giro adicional lleva maacutes tiempo pero simplifica el coacutedigo si se hace lo mismo

44 Capiacutetulo 4 Estudio de Caso Disentildeo de Interfaz

en cada iteracioacuten del ciclo Esta versioacuten tambieacuten tiene el efecto de dejar a latortuga nuevamente en la posicioacuten inicial mirando hacia la direccioacuten inicial

EjerciciosLos siguientes ejercicios usan tortugas Son divertidos pero tambieacuten tienen untrasfondo Mientras trabaja en ellos piense cuaacutel es ese trasfondo

OBSERVACIOacuteNLas siguientes secciones muestran las soluciones paraestos ejercicios asiacute que no mire hasta que hayaterminado (o al menos lo haya intentado)

Ejercicio 4-2

Escriba una funcioacuten llamada cuadrado que tome como paraacutemetro a un turtle tDeberiacutea usar este turtle para dibujar un cuadrado

Ejercicio 4-3

Escriba una llamada a funcioacuten que pase t como argumento a cuadrado y luegovuelva a ejecutar la macro

Ejercicio 4-4

Agregue otro paraacutemetro llamado lon a cuadrado Modifique el cuerpo para quela longitud de los lados sea lon y luego modifique la llamada a funcioacutenagregando este segundo argumento Ejecute la macro nuevamente Pruebe conun rango de valores para lon

Ejercicio 4-5

Haga una copia de cuadrado y cambie su nombre a poliacutegono Agregue otroparaacutemetro llamado n y modifique el cuerpo para que dibuje un poliacutegono regularde -lados

OBSERVACIOacuteN Los aacutengulos exteriores de un poliacutegono regular de -ladosson grados

Ejercicio 4-6

Escriba una funcioacuten llamada ciacuterculo que tome un turtle t y un radio r comoparaacutemetros y que dibuje un ciacuterculo aproximado llamando a poliacutegono con unalongitud y nuacutemero de lados apropiados Pruebe su funcioacuten con un rango devalores de r

Ejercicios 45

OBSERVACIOacuteN Calcule la circunferencia del ciacuterculo y aseguacuterese de quelen n == circunferencia

Ejercicio 4-7

Haga una versioacuten maacutes general de circulo llamada arco que tome un paraacutemetroadicional angulo y que determine queacute fraccioacuten de un ciacuterculo dibujar angulo estaacuteen grados entonces cuando angulo= 360 arco deberiacutea dibujar un ciacuterculocompleto

EncapsulacioacutenEl primer ejercicio le pide que coloque el coacutedigo que permite dibujar uncuadrado en una definicioacuten de funcioacuten y que luego llame a la funcioacuten pasando aturtle como paraacutemetro Aquiacute hay una solucioacuten

function cuadrado(t) for i in 14 forward(t 100) turn(t -90) endendὂ = Turtle()svg begin cuadrado(ὂ)end

Las sentencias maacutes internas forward y turn tienen doble sangriacutea para mostrarque estaacuten dentro del bucle for que a su vez estaacute dentro de la definicioacuten defuncioacuten

Dentro de la funcioacuten t se refiere a la misma tortuga ὂ entonces turn(t -90)tiene el mismo efecto que turn(ὂ -90) En ese caso iquestpor queacute no llamar alparaacutemetro ὂ La razoacuten es que t puede ser cualquier tortuga no solo ὂ por loque podriacuteamos crear una segunda tortuga y pasarla como argumento a cuadrado

ὂ = Turtle()svg begin cuadrado(ὂ)end

Colocar una porcioacuten de coacutedigo en una funcioacuten se denomina encapsulacioacuten Unode los beneficios de la encapsulacioacuten es que al ponerle un nombre al coacutedigo estosirve como una especie de documentacioacuten Otra ventaja es que si reutiliza elcoacutedigo iexcles maacutes conciso llamar a una funcioacuten dos veces que copiar y pegar el

46 Capiacutetulo 4 Estudio de Caso Disentildeo de Interfaz

cuerpo

GeneralizacioacutenEl siguiente paso es agregar un paraacutemetro lon a cuadrado Aquiacute hay unasolucioacuten

function cuadrado(t lon) for i in 14 forward(t lon) turn(t -90) endendὂ = Turtle()svg begin cuadrado(ὂ 100)end

Agregar un paraacutemetro a una funcioacuten se llama generalizacioacuten porque hace que lafuncioacuten sea maacutes general en la versioacuten anterior el cuadrado siempre teniacutea elmismo tamantildeo en esta versioacuten puede ser de cualquier tamantildeo

El siguiente paso tambieacuten es una generalizacioacuten En vez de dibujar cuadradospoligono dibuja poliacutegonos regulares con cualquier nuacutemero de lados Aquiacute hay unasolucioacuten

function poligono(t n lon) angulo = 360 n for i in 1n forward(t lon) turn(t -angulo) endendὂ = Turtle()svg begin poligono(ὂ 7 70)end

Este ejemplo dibuja un poliacutegono de 7 lados con una longitud de 70 por lado

Disentildeo de InterfazEl siguiente paso es escribir circulo que toma un radio r como paraacutemetro Aquiacutehay una solucioacuten simple que usa poligono para dibujar un poliacutegono de 50 lados

Generalizacioacuten 47

function circulo(t r) circunferencia = 2 π r n = 50 lon = circunferencia n poligono(t n lon)end

La primera liacutenea calcula la circunferencia de un ciacuterculo con radio usando lafoacutermula n es el nuacutemero de segmentos de liacutenea de nuestra aproximacioacuten a unciacuterculo y lon es la longitud de cada segmento Por lo tanto poliacutegono dibuja unpoliacutegono de 50 lados que se aproxima a un ciacuterculo de radio r

Una limitante de esta solucioacuten es que n es constante lo que significa que paraciacuterculos muy grandes los segmentos de liacutenea son demasiado largos y paraciacuterculos pequentildeos perdemos tiempo dibujando segmentos muy pequentildeos Unasolucioacuten seriacutea generalizar la funcioacuten tomando n como paraacutemetro Esto le dariacutea alusuario (quien llama a ciacuterculo) maacutes control pero la interfaz seriacutea menos pulcra

La interfaz de una funcioacuten es un resumen de coacutemo se usa iquestcuaacuteles son losparaacutemetros iquestQueacute hace la funcioacuten iquestY cuaacutel es el valor de retorno Una interfazes pulcra si le permite al usuario que la llama hacer lo que quiera sin tener quelidiar con detalles innecesarios

En este ejemplo r pertenece a la interfaz porque especifica el ciacuterculo a dibujar nes menos apropiado porque se refiere a los detalles de coacutemo se debe representarel ciacuterculo

En lugar de saturar la interfaz es mejor elegir un valor apropiado de ndependiendo de la circunferencia

function circulo(t r) circunferencia = 2 π r n = trunc(circunferencia 3) + 3 lon = circunferencia n poligono(t n lon)end

Ahora el nuacutemero de segmentos es un nuacutemero entero cercano a circunferencia3por lo que la longitud de cada segmento es aproximadamente 3 que es losuficientemente pequentildeo como para que los ciacuterculos se vean bien pero losuficientemente grandes como para ser eficientes y aceptables para cualquierciacuterculo

Agregar 3 a n garantiza que el poliacutegono tenga al menos 3 lados

48 Capiacutetulo 4 Estudio de Caso Disentildeo de Interfaz

RefactorizacioacutenCuando se escribioacute circulo se pudo reutilizar poligono ya que un poliacutegono demuchos lados es una buena aproximacioacuten de un ciacuterculo Pero arco no es tanversaacutetil no se puede usar poligono o circulo para dibujar un arco

Una alternativa es comenzar con una copia de poligono y transformarla en arcoEl resultado podriacutea verse asiacute

function arco(t r angulo) arco_lon = 2 π r angulo 360 n = trunc(arco_lon 3) + 1 paso_lon = arco_lon n paso_angulo = angulo n for i in 1n forward(t paso_lon) turn(t -paso_angulo) endend

La segunda mitad de esta funcioacuten se parece a poligono pero no se puedereutilizar poligono sin cambiar la interfaz Se podriacutea generalizar poligono paratomar un angulo como tercer argumento iexclpero entonces poligono ya no seriacutea unnombre apropiado En su lugar se puede llamar a esta funcioacuten maacutes generalpolilinea

function polilinea(t n lon angulo) for i in 1n forward(t lon) turn(t -angulo) endend

Ahora se puede reescribir poligono y arco usando polilinea

Refactorizacioacuten 49

function poligono(t n lon) angulo = 360 n polilinea(t n lon angulo)end

function arco(t r angulo) arco_lon = 2 π r angulo 360 n = trunc(arco_lon 3) + 1 paso_lon = arco_lon n paso_angulo = angulo n polilinea(t n paso_lon paso_angulo)end

Finalmente se puede reescribir circulo usando arco

function circulo(t r) arco(t r 360)end

Este proceso que reorganiza un programa para mejorar las interfaces y facilitarla reutilizacioacuten del coacutedigo se denomina refactorizacioacuten En este caso se observaque habiacutea un coacutedigo similar en arco y poligono por lo que lo factorizamos enpolilinea

Si se hubiese planeado con anticipacioacuten se podriacutea haber escrito polilineaprimero y haber evitado la refactorizacioacuten pero a menudo no se sabe losuficiente al comienzo de un proyecto para disentildear todas las interfaces Una vezque se comienza a programar se comprende mejor el problema A vecesrefactorizar es una sentildeal de que se ha aprendido algo

Un Plan de DesarrolloUn plan de desarrollo de programa es un proceso para escribir programas Elproceso que se utiliza en este estudio de caso es encapsulacioacuten ygeneralizacioacuten Los pasos de este proceso son

1 Comience escribiendo un pequentildeo programa sin definiciones de funciones

2 Una vez que el programa funcione identifique una porcioacuten de coacutedigo quetenga un objetivo especiacutefico encapsule esta porcioacuten en una funcioacuten yasiacutegnele un nombre

3 Generalice la funcioacuten agregando los paraacutemetros apropiados

4 Repita los pasos 1ndash3 hasta que tenga un conjunto de funciones De serposible copie y pegue coacutedigo para evitar volver a escribir (y volver adepurar)

50 Capiacutetulo 4 Estudio de Caso Disentildeo de Interfaz

5 Busque oportunidades para mejorar el programa refactorizando Porejemplo si tiene un coacutedigo similar en varios lugares considere factorizarloen una funcioacuten general apropiada

Este proceso tiene algunos inconvenientes se exploraraacuten alternativas maacutesadelante pero puede ser uacutetil si no sabe de antemano coacutemo dividir el programaen funciones Este enfoque permite disentildear conforme se avanza

DocstringUn docstring es una cadena que va antes de una funcioacuten y que explica la interfaz(doc es la abreviatura de documentacioacuten) Aquiacute hay un ejemplo

polilinea(t n lon angulo)

Dibuja n segmentos de liacutenea de la longitud dada y conaacutengulo entre ellos (en grados) dado t es una tortugafunction polilinea(t n lon angulo) for i in 1n forward(t lon) turn(t -angulo) endend

Se puede acceder a la documentacioacuten en REPL o en un notebook escribiendo seguido del nombre de una funcioacuten o macro y presionando ENTER

helpgt polilineasearch

polilinea(t n lon angulo)

Dibuja n segmentos de liacutenea de la longitud dada y con aacutengulo entre ellos(en grados) dado t es una tortuga

Los docstring generalmente son cadenas de comillas triples tambieacuten conocidascomo cadenas de liacuteneas muacuteltiples ya que las comillas triples permiten que lacadena abarque maacutes de una liacutenea

Un docstring contiene la informacioacuten esencial que alguien necesitariacutea para usaresta funcioacuten Explica de manera concisa lo que hace la funcioacuten (sin entrar endetalles sobre coacutemo lo hace) Explica queacute efecto tiene cada paraacutemetro en elcomportamiento de la funcioacuten y de queacute tipo debe ser cada paraacutemetro (si no esobvio)

Docstring 51

OBSERVACIOacuteN

Escribir este tipo de documentacioacuten es una parteimportante del disentildeo de la interfaz Una interfaz biendisentildeada debe ser simple de explicar si tienedificultades para explicar una de sus funciones tal vez lainterfaz podriacutea mejorarse

DepuracioacutenUna interfaz es como un contrato entre una funcioacuten y el usuario El usuarioacepta proporcionar ciertos paraacutemetros y la funcioacuten acepta hacer cierto trabajo

Por ejemplo polilinea requiere cuatro argumentos t tiene que ser una tortuga ntiene que ser un nuacutemero entero lon deberiacutea ser un nuacutemero positivo y angulotiene que ser un nuacutemero en grados

Estos requisitos se llaman precondiciones porque se supone que son verdaderosantes de que la funcioacuten comience a ejecutarse Por el contrario las condicionesal final de la funcioacuten son postcondiciones Las postcondiciones incluyen el efectodeseado de la funcioacuten (como dibujar segmentos de liacutenea) y cualquier efectosecundario (como mover la tortuga o hacer otros cambios)

Las condiciones previas son responsabilidad del usuario Si el usuario viola unaprecondicioacuten (iexcldebidamente documentada) y la funcioacuten no funcionacorrectamente el error estaacute en el usuario no en la funcioacuten

Si se cumplen las precondiciones pero no las postcondiciones el error estaacute en lafuncioacuten Si sus pre y postcondiciones son claras pueden ayudar con ladepuracioacuten

Glosariomodulo

Un archivo que contiene una coleccioacuten de funciones relacionadas y otrasdefiniciones

paqueteUna biblioteca externa con maacutes funcionalidades

sentencia usingUna sentencia que lee un archivo de moacutedulo y crea un objeto de moacutedulo

bucleUna parte de un programa que puede ejecutarse repetidamente

52 Capiacutetulo 4 Estudio de Caso Disentildeo de Interfaz

encapsulacioacutenEl proceso de transformar una secuencia de sentencias en una definicioacuten defuncioacuten

generalizacioacutenEl proceso de reemplazar algo innecesariamente especiacutefico (como unnuacutemero) con algo maacutes general (como una variable o paraacutemetro)

interfazUna descripcioacuten de coacutemo usar una funcioacuten incluido el nombre y lasdescripciones de los argumentos y el valor de retorno

refactorizacioacutenEl proceso de modificar un programa para mejorar las interfaces de lasfunciones y otras cualidades del coacutedigo

plan de desarrollo de programaUn proceso para escribir programas

docstringUna cadena que aparece en la parte superior de una definicioacuten de funcioacutenpara documentar la interfaz de la funcioacuten

precondicioacutenUn requisito que debe cumplir el usuario antes de que comience unafuncioacuten

postcondicioacutenUn requisito que debe cumplir la funcioacuten antes de que finalice

Ejercicios

Ejercicio 4-8

Copie y pegue el coacutedigo de este capiacutetulo en un notebook

1 Dibuje un diagrama de pila que muestre el estado del programa mientrasejecuta circulo(ὂ radio) Puede hacer la aritmeacutetica a mano o agregarsentencias de impresioacuten al coacutedigo

2 La versioacuten de arco en Seccioacuten 47 no es muy precisa ya que la aproximacioacutenlineal del ciacuterculo siempre queda por afuera del ciacuterculo verdadero Comoresultado la tortuga termina a unos pocos piacutexeles del destino correcto Lasiguiente solucioacuten muestra una forma de reducir el efecto de este error Leael coacutedigo y vea si tiene sentido Si dibuja un diagrama es posible queentienda mejor coacutemo funciona

Ejercicios 53

arco(t r angulo)

Dibuja un arco con el radio y el aacutengulo dados

t tortuga r radio angulo aacutengulo subtendido por el arco en gradosfunction arco(t r angulo) arco_lon = 2 π r abs(angulo) 360 n = trunc(arco_lon 4) + 3 paso_lon = arco_lon n paso_angulo = angulo n

haciendo un ligero giro a la izquierda antes de comenzar se reduce el error causado por la aproximacioacuten lineal del arco turn(t -paso_angulo2) polilinea(t n paso_lon paso_angulo) turn(t paso_angulo2)end

Ejercicio 4-9

Escriba un conjunto de funciones generales que permitan dibujar flores como enFigura 4

Figura 4 Flores con Turtle

Ejercicio 4-10

Escriba un conjunto de funciones generales que puedan dibujar formas como enFigura 5

Figura 5 Poliacutegonos con Turtle

54 Capiacutetulo 4 Estudio de Caso Disentildeo de Interfaz

Ejercicio 4-11

Las letras del alfabeto se pueden construir a partir de un nuacutemero pequentildeo deelementos baacutesicos como liacuteneas verticales y horizontales y algunas curvasDisentildee un alfabeto que se pueda dibujar con un nuacutemero miacutenimo de elementosbaacutesicos y luego escriba funciones que dibujen las letras

Deberiacutea escribir una funcioacuten para cada letra con nombres dibujar_a dibujar_betc y colocar sus funciones en un archivo llamado letrasjl

Ejercicio 4-12

Lea sobre espirales en httpseswikipediaorgwikiEspiral luego escriba unprograma que dibuje una espiral de Arquiacutemedes como en Figura 6

Figura 6 Espiral de Arquiacutemedes

Ejercicios 55

Capiacutetulo 5 Condicionales y recursividadEl tema principal de este capiacutetulo es la sentencia if la cual permite ejecutardiferentes acciones dependiendo del estado del programa Inicialmente sepresentan dos nuevos operadores divisioacuten entera y moacutedulo

Divisioacuten entera y MoacuteduloEl operador divisioacuten entera divide (div TAB) divide dos nuacutemeros y redondea haciaabajo el resultado Por ejemplo suponga que la duracioacuten de una peliacutecula es de105 minutos Es posible que desee saber la duracioacuten en horas La divisioacutenconvencional devuelve un nuacutemero de punto flotante

juliagt minutos = 105105juliagt minutos 60175

No obstante las horas no se suelen escribir con decimales La divisioacuten enteradevuelve el nuacutemero entero de horas redondeado hacia abajo

juliagt horas = minutos divide 601

Para obtener el resto de la divisioacuten se puede restar una hora (en minutos) a laduracioacuten total de la peliacutecula

juliagt resto = minutos - horas 6045

Otra alternativa es usar el operador moacutedulo que divide dos nuacutemeros ydevuelve el resto

juliagt resto = minutos 6045

OBSERVACIOacuteN

El operador moacutedulo es maacutes uacutetil de lo que parecePermite verificar por ejemplo si un nuacutemero es divisiblepor otro si xy es cero entonces x es divisible por y

Ademaacutes puede extraer el (o los) diacutegito(s) maacutes a laderecha de un nuacutemero Por ejemplo x10 devuelve eldiacutegito maacutes a la derecha de un entero x (en base 10) Delmismo modo x100 devuelve los dos uacuteltimos diacutegitos

56 Capiacutetulo 5 Condicionales y recursividad

Expresiones booleanasUna expresioacuten booleana es una expresioacuten que es verdadera o falsa Lossiguientes ejemplos usan el operador == que compara dos operandos ydevuelve el valor true (verdadero en espantildeol) si son iguales y el valor false(falso) de lo contrario

juliagt 5 == 5truejuliagt 5 == 6false

true y false son valores especiales que pertenecen al tipo Bool no son cadenas

juliagt typeof(true)Booljuliagt typeof(false)Bool

El operador == es un operador relacional El resto de operadores relacionalesson

x = y x no es igual a y x ne y (ne TAB) x gt y x es mayor que y x lt y x es menor que y x gt= y x es mayor o igual que y x ge y (ge TAB) x lt= y x es menor o igual que y x le y (le TAB)

AVISO

Aunque estas operaciones probablemente le sean familiares lossiacutembolos de Julia son diferentes de los siacutembolos matemaacuteticos Unerror comuacuten es usar un solo signo igual (=) en vez de un doblesigno igual (== Recuerde que = es un operador de asignacioacuten y== es un operador relacional No existe =lt o =gt

Operadores LoacutegicosHay tres operadores loacutegicos ampamp (y) || (o) y (no) La semaacutentica (significado) deestos operadores es similar a su significado en espantildeol Por ejemplo xgt0 ampampxlt10 es verdadero solo si x es mayor que 0 y menor que 10

n2==0 || n3 == 0 es verdadero si una o ambas condiciones son verdaderases decir si el nuacutemero es divisible por 2 o por 3

Expresiones booleanas 57

Tanto ampamp como || se asocian en primer lugar con el objeto a su derecha pero ampamptiene preferencia por sobre ||

Finalmente el operador niega una expresioacuten booleana entonces (xgty) esverdadero si xgty es falso es decir si x es menor o igual que y

Ejecucioacuten CondicionalPara escribir programas uacutetiles generalmente se necesita verificar condiciones ycambiar el comportamiento del programa acorde a ellas Las sentenciascondicionales permiten llevar esto a cabo La forma maacutes simple es la sentencia if(si en ingleacutes)

if x gt 0 println(x es positivo)end

La expresioacuten booleana despueacutes de if se llama condicioacuten Si es verdadera seejecuta la instruccioacuten con sangriacutea Si no nada ocurre

Las sentencias if tienen la misma estructura que las definiciones de funcioacuten unencabezado seguido del cuerpo terminado con la palabra reservada end (enespantildeol fin) Las sentencias como esta se denominan sentencias compuestas

No hay liacutemite en el nuacutemero de sentencias que pueden aparecer en el cuerpo Aveces es uacutetil tener un cuerpo sin sentencias (por lo general como un marcadorde posicioacuten para el coacutedigo que auacuten no se ha escrito)

if x lt 0 TODO se necesita realizar alguna accioacuten con los valores negativosend

Ejecucioacuten alternativaUna segunda forma de la sentencia if es la ejecucioacuten alternativa en la que haydos posibilidades y la condicioacuten determina cuaacutel se ejecuta La sintaxis se ve asiacute

if x 2 == 0 println(x es par)else println(x es impar)end

Si el resto de x dividido por 2 es 0 entonces x es par y el programa muestra unmensaje acorde Si la condicioacuten es falsa se ejecuta el segundo conjunto de

58 Capiacutetulo 5 Condicionales y recursividad

sentencias Como la condicioacuten debe ser verdadera o falsa se ejecutaraacuteexactamente una de las alternativas Las alternativas se llaman ramas porqueson ramas en el flujo de ejecucioacuten

Condicionales encadenadasA veces hay maacutes de dos posibilidades y se necesitan maacutes de dos ramas Unamanera de expresar este coacutemputo es a traveacutes de una condicional encadenada

if x lt y println(x es menor que y)elseif x gt y println(x es mayor que y)else println(x e y son iguales)end

De nuevo soacutelo se ejecutaraacute una rama No hay liacutemite al nuacutemero de sentenciaselseif Si hay una sentencia else debe estar al final (aunque no es necesario queesteacute)

if alternativa == a dibujar_a()elseif alternativa == b dibujar_b()elseif alternativa == c dibujar_c()end

Cada condicioacuten se comprueba en orden Si la primera es falsa se comprueba lasiguiente y asiacute se sigue con las demaacutes Si una de ellas es verdadera se ejecuta larama correspondiente y la sentencia se termina Si es verdadera maacutes de unacondicioacuten soacutelo se ejecuta la primera rama verdadera

Condicionales anidadasUna condicional puede estar anidada (nested en ingleacutes) dentro de otraPodriacuteamos haber escrito el ejemplo de la seccioacuten anterior de la siguiente manera

Condicionales encadenadas 59

if x == y println(x e y son iguales)else if x lt y println(x es menor a y) else println(x es mayor a y) endend

La condicional externa contiene dos ramas La primera rama contiene unasentencia simple La segunda rama contiene otra sentencia if que tiene dosramas propias Estas dos ramas son ambas sentencias simples aunque podriacuteanser sentencias condicionales

Aunque la sangriacutea no obligatoria de las sentencias hace evidente su estructuralas condicionales anidadas muy pronto se vuelven difiacuteciles de leer Se recomiendaevitarlas cuando pueda

Los operadores loacutegicos a menudo proporcionan una forma de simplificar lassentencias condicionales anidadas Por ejemplo es posible reescribir el siguientecoacutedigo usando un solo condicional

if 0 lt x if x lt 10 println(x es un nuacutemero positivo de un solo diacutegito) endend

La sentencia print soacutelo se ejecuta si conseguimos superar ambas condicionalesde modo que se puede obtener el mismo efecto con el operador ampamp

if 0 lt x ampamp x lt 10 println(x es un nuacutemero positivo de un solo diacutegito)end

Para este tipo de condicioacuten Julia proporciona una sintaxis maacutes concisa

if 0 lt x lt 10 println(x es un nuacutemero positivo de un solo diacutegito)end

60 Capiacutetulo 5 Condicionales y recursividad

RecursividadEstaacute permitido que una funcioacuten llame a otra y tambieacuten que una funcioacuten se llamea siacute misma Puede no parecer uacutetil pero siacute lo es como puede verse en la siguientefuncioacuten

function cuentaregresiva(n) if n le 0 println(Despegue) else print(n ) cuentaregresiva(n-1) endend

Si n es 0 o negativo muestra la palabra Despegue En otro caso muestra elvalor n y luego llama a la funcioacuten cuentaregresiva pasaacutendole n-1 comoargumento

iquestQueacute sucede si llamamos a una funcioacuten como esta

juliagt cuentaregresiva(3)3 2 1 Despegue

La ejecucioacuten de cuentaregresiva empieza con n = 3 y como n es mayor que 0muestra el valor 3 y luego se llama a siacute mismahellip

 La ejecucioacuten de cuentaregresiva empieza con n = 2 y como n es mayor que 0   muestra el valor 2 y luego se llama a siacute mismahellip

  La ejecucioacuten de cuentaregresiva empieza con n = 1 y como n es mayor que0    muestra el valor 1 y luego se llama a siacute mismahellip

   La ejecucioacuten de cuentaregresiva empieza con n = 0 y como n no es mayorque 0     muestra la palabra Despegue y luego termina

  La cuentaregresiva cuyo argumento es n = 1 termina

 La cuentaregresiva cuyo argumento es n = 2 termina

La cuentaregresiva cuyo argumento es n = 3 termina

Y volvemos a Main

Una funcioacuten que se llama a siacute misma es una funcioacuten recursiva y el proceso deejecucioacuten se llama recursividad

Recursividad 61

Como otro ejemplo se puede escribir una funcioacuten que imprima una cadena veces

function printn(s n) if n le 0 return end println(s) printn(s n-1)end

Si n lt= 0 se usa la sentencia return para salir de la funcioacuten El flujo de laejecucioacuten vuelve inmediatamente a la sentencia de llamada a funcioacuten y no seejecutan las liacuteneas restantes de la funcioacuten

El resto de la funcioacuten es similar a cuenta regresiva muestra s y luego se llama asiacute misma para mostrar s veces maacutes de modo que el nuacutemero de lineasmostradas es es decir

Para ejemplos simples como este es maacutes faacutecil usar un ciclo for Se mostraraacutenejemplos que son difiacuteciles de escribir con un ciclo for y faacuteciles de escribir conrecursividad

Diagramas de pila para funciones recursivasEn Seccioacuten 39 se usoacute un diagrama de pila para representar el estado de unprograma durante una llamada de funcioacuten El mismo tipo de diagrama puede serde utilidad para interpretar una funcioacuten recursiva

Cada vez que se llama a una funcioacuten Julia crea un marco que contiene lasvariables locales de la funcioacuten y los paraacutemetros En una funcioacuten recursiva puedehaber maacutes de un marco en el diagrama de pila al mismo tiempo

Figura 7 Diagrama de pila

Figura 7 muestra un diagrama de pila para cuentaregresiva utilizando n=3

Como siempre la parte superior de la pila es el marco para Main Estaacute vaciacuteopues no se crearon variables en Main ni tampoco se pasaron argumentos

62 Capiacutetulo 5 Condicionales y recursividad

Los cuatro marcos de cuentaregresiva tienen diferentes valores del paraacutemetro nLa parte inferior del diagrama de pila donde n = 0 es llamado caso base Nohace una llamada recursiva asiacute que no hay maacutes marcos

Ejercicio 5-1

Como ejercicio dibuje un diagrama de pila para printn llamada con s = Hola yn = 2 Luego escriba una funcioacuten llamada hacer_n que tome como argumentosuna funcioacuten y un nuacutemero n y que luego llame a la funcioacuten dada veces

Recursioacuten infinitaSi una recursioacuten nunca alcanza un caso base continuacutea haciendo llamadasrecursivas para siempre y el programa nunca termina Esto se conoce comorecursioacuten infinita y generalmente no es una buena idea Aquiacute hay un coacutedigo conuna recursioacuten infinita

function recursion() recursion()end

En la mayoriacutea de los entornos de programacioacuten un programa con recursioacuteninfinita realmente no se ejecuta para siempre Julia entrega un mensaje de errorcuando se alcanza la profundidad de recursioacuten maacutexima

juliagt recursion()ERROR StackOverflowErrorStacktrace [1] recursion() at REPL[1]2 (repeats 80000 times)

Este stacktrace es un poco maacutes grande que el que vimos en el capiacutetulo anteriorCuando se produce el error iexclhay 80000 marcos de recursion en el diagrama depila

Si por accidente encuentra una recursioacuten infinita en su coacutedigo revise su funcioacutenpara confirmar que hay un caso base que no realiza una llamada recursiva Sihay un caso base verifique si realmente puede ocurrir

Entrada por tecladoLos programas que se han escrito hasta ahora no aceptan entradas del usuarioSimplemente hacen lo mismo cada vez

Julia tiene una funcioacuten incorporada llamada readline que detiene el programa yespera a que el usuario escriba algo Cuando el usuario presiona RETURN oENTER el programa se reanuda y readline devuelve lo que el usuario escribioacute

Recursioacuten infinita 63

como una cadena

juliagt text = readline()iquestQueacute estaacute esperandoiquestQueacute estaacute esperando

Antes de recibir una entrada por teclado del usuario es una buena idea imprimirun mensaje que le diga al usuario queacute escribir

juliagt print(iquestCuaacutel es su nombre ) readline()iquestCuaacutel es su nombre iexclArturo Rey de los BretonesiexclArturo Rey de los Bretones

Un punto y coma permite colocar varias sentencias en la misma liacutenea En elREPL solo la uacuteltima sentencia devuelve su valor

Si espera que el usuario escriba un nuacutemero entero puede intentar convertir elvalor de retorno a Int64

juliagt println(iquestCuaacutentos dejaron su casa su tierra o su posesioacuten)numero = readline()iquestCuaacutentos dejaron su casa su tierra o su posesioacuten115115juliagt parse(Int64 numero)115

Pero si el usuario no escribe una cadena de diacutegitos obtendraacute un error

juliagt println(iquestCuaacutentos dejaron su casa su tierra o su posesioacuten)numero = readline()iquestCuaacutentos dejaron su casa su tierra o su posesioacutenMaacutes de ciento quince sonMaacutes de ciento quince sonjuliagt parse(Int64 speed)ERROR ArgumentError invalid base 10 digit M in Maacutes de ciento quinceson[]

Veremos queacute hacer con este tipo de error maacutes adelante

DepuracioacutenCuando se produce un error de sintaxis o de tiempo de ejecucioacuten el mensaje deerror contiene mucha informacioacuten lo cual puede ser abrumador Las partes maacutes

64 Capiacutetulo 5 Condicionales y recursividad

uacutetiles suelen ser

bull Queacute tipo de error fue

bull Doacutende ocurrioacute tal error

Los errores de sintaxis suelen ser faacuteciles de encontrar y hay algunos trucos Engeneral los mensajes de error indican doacutende se descubrioacute el problema pero elerror real podriacutea estar antes en el coacutedigo a veces en una liacutenea anterior

Lo mismo aplica para los errores de tiempo de ejecucioacuten Suponga que estaacutetratando de calcular una relacioacuten sentildealruido en decibelios La foacutermula es

En Julia se podriacutea escribir algo como esto

intensidad_sentildeal = 9intensidad_ruido = 10relacion = intensidad_sentildeal divide intensidad_ruidodecibeles = 10 log10(relacion)print(decibeles)

Obteniendo

-Inf

Este no es el resultado que esperaacutebamos

Para encontrar el error puede ser uacutetil imprimir el valor de la variable relacionque resulta ser 0 El problema estaacute en la liacutenea 3 que usa la divisioacuten entera enlugar de la divisioacuten de punto flotante

AVISOEl usuario debe tomarse el tiempo de leer los mensajes de errorcuidadosamente pero no se debe asumir que todo lo que dicen escorrecto

GlosarioDivisioacuten entera

Un operador denotado por divide que divide dos nuacutemeros y redondea haciaabajo (hacia el infinito negativo) a un entero

operador moacuteduloUn operador denotado con el signo de porcentaje () que se utiliza conenteros y devuelve el resto cuando un nuacutemero se divide por otro

Glosario 65

expresioacuten booleanaUna expresioacuten cuyo valor es verdadero o falso

operador relacionalUno de los operadores que compara sus operandos == ne (=) gt lt ge(gt=) and le (lt=)

operador loacutegicoUno de los operadores que combina expresiones booleanas ampamp (and) ||(or) and (not)

sentencia condicionalUna sentencia que controla el flujo de ejecucioacuten dependiendo de algunacondicioacuten

condicioacutenLa expresioacuten booleana en una sentencia condicional que determina queacuterama se ejecuta

sentencia compuestaUna sentencia que consta de un encabezado y un cuerpo El cuerpo terminacon la palabra reservada end

ramaUna de las secuencias alternativas de sentencias en una sentenciacondicional

condicional encadenadaUna sentencia condicional con una serie de ramas alternativas

condicional anidadaUna sentencia condicional que aparece en una de las ramas de otrasentencia condicional

sentencia returnUna sentencia que hace que una funcioacuten finalice de inmediato y que vuelvaa la sentencia de llamada a funcioacuten

recursividad o recursioacutenEl proceso de llamar a la funcioacuten que se estaacute ejecutando actualmente

caso baseUna rama condicional en una funcioacuten recursiva que no realiza una llamadarecursiva

66 Capiacutetulo 5 Condicionales y recursividad

recursioacuten infinitaUna recursioacuten que no tiene un caso base o que nunca llega a eacutelEventualmente una recursioacuten infinita provoca un error de tiempo deejecucioacuten

Ejercicios

Ejercicio 5-2

La funcioacuten time devuelve el tiempo medio de Greenwich actual en segundosdesde la eacutepoca que es un tiempo arbitrario utilizado como punto de referenciaEn sistemas UNIX la eacutepoca es el 1 de enero de 1970

juliagt time()1603600382165353e9

Escriba un script que lea la hora actual y la convierta a una hora del diacutea enhoras minutos y segundos maacutes el nuacutemero de diacuteas transcurridos desde la eacutepoca

Ejercicio 5-3

El uacuteltimo teorema de Fermat dice que no hay enteros positivos and tal que

para cualquier valor de mayor que 2

1 Escriba una funcioacuten llamada verificarfermat que tome cuatroparaacutemetrosmdasha b c y nmdash y que verifique si el teorema de Fermat es vaacutelidoSi n es mayor que 2 y a^n + b^n == c^n el programa deberiacutea imprimiriexclSanto cielo Fermat estaba equivocado De lo contrario el programadeberiacutea imprimir No eso no funciona

2 Escriba una funcioacuten que solicite al usuario ingresar valores para a b c y nque los convierta en enteros y que use verificarfermat para verificar siviolan el teorema de Fermat

Ejercicio 5-4

Si tiene tres barras estas podriacutean o no formar un triaacutengulo Por ejemplo si unade las barras tiene 12 centiacutemetros de largo y las otras dos tienen un centiacutemetrode largo no es posible que las barras pequentildeas puedan juntarse al medio Paracualquier triacuteo de longitudes hay una prueba simple para ver si es posible formarun triaacutengulo

Ejercicios 67

OBSERVACIOacuteN

Si cualquiera de las tres longitudes es mayor que lasuma de las otras dos entonces no se puede formar untriaacutengulo De lo contrario se puede (Si la suma de doslongitudes es igual a la tercera forman lo que se llamaun triaacutengulo degenerado)

1 Escriba una funcioacuten llamada estriangulo que tome tres enteros comoargumentos y que imprima ldquoSiacuterdquo o ldquoNordquo dependiendo de si se puede o noformar un triaacutengulo a partir de barras de las longitudes dadas

2 Escriba una funcioacuten que solicite al usuario ingresar tres longitudes debarras las convierta en enteros y use estriangulo para verificar si las barrascon las longitudes dadas pueden formar un triaacutengulo

Ejercicio 5-5

iquestCuaacutel es el resultado del siguiente programa Dibuje un diagrama de pila quemuestre el estado del programa cuando imprima el resultado

function recursion(n s) if n == 0 println(s) else recursion(n-1 n+s) endend

recursion(3 0)

1 iquestQueacute pasariacutea si se llamara a esta funcioacuten asiacute recursion(-1 0)

2 Escriba un documento que explique todo lo que alguien necesitariacutea saberpara usar esta funcioacuten (y nada maacutes)

Los siguientes ejercicios utilizan el moacutedulo IntroAJulia descrito en Capiacutetulo 4

Ejercicio 5-6

Lea la siguiente funcioacuten y vea si puede averiguar queacute hace (vea los ejemplos enCapiacutetulo 4) Luego ejecuacutetelo y vea si lo hizo bien

68 Capiacutetulo 5 Condicionales y recursividad

function dibujar(t distancia n) if n == 0 return end angulo = 50 adelante(t distancian) girar(t -angulo) dibujar(t distancia n-1) girar(t 2angulo) dibujar(t distancia n-1) girar(t -angulo) adelante(t -distancian)end

Ejercicio 5-7

Figura 8 Una curva de Koch

La curva de Koch es un fractal que luce como Figura 8 Para dibujar una curva deKoch con longitud todo lo que tiene que hacer es

1 Dibuje una curva de Koch con longitud

2 Gire a la izquierda 60 grados

3 Dibuje una curva de Koch con longitud

4 Gire a la derecha 120 grados

5 Dibuje una curva de Koch con longitud

6 Gire a la izquierda 60 grados

7 Dibuje una curva de Koch con longitud

La excepcioacuten es cuando es menor que 3 en ese caso puede dibujar una liacutenearecta con una longitud

1 Escribe una funcioacuten llamada koch que tome una tortuga y una longitudcomo paraacutemetros y que use la tortuga para dibujar una curva de Koch con lalongitud dada

2 Escriba una funcioacuten llamada copodenieve que dibuje tres curvas de Kochpara hacer el contorno de un copo de nieve

3 La curva de Koch se puede generalizar de varias maneras ConsultehttpsenwikipediaorgwikiKoch_snowflake para ver ejemplos eimplementar su favorito

Ejercicios 69

Capiacutetulo 6 Funciones productivasMuchas de las funciones de Julia que se han utilizado como las funcionesmatemaacuteticas producen valores de retorno Todas las funciones que se hanescrito hasta ahora son nulas es decir tienen un efecto (como imprimir un valor)pero devuelven el valor nothing En este capiacutetulo se ensentildea a escribir funcionesproductivas

Valores de retornoLlamar a una funcioacuten genera un valor de retorno que generalmente se asigna auna variable o se usa como parte de una expresioacuten

e = exp(10)altura = radio sin(radio)

Las funciones que se han escrito hasta ahora son nulas Coloquialmentehablando no tienen valor de retorno de manera formal su valor de retorno esnothing En este capiacutetulo (finalmente) se van a escribir funciones productivas Elprimer ejemplo es area que devuelve el aacuterea de un ciacuterculo dado un radio

function area(radio) a = π radio^2 return aend

Se ha visto la sentencia return antes pero en una funcioacuten productiva la sentenciareturn incluye una expresioacuten Esta sentencia significa Retorne inmediatamentede esta funcioacuten y use la siguiente expresioacuten como valor de retorno La expresioacutendada puede ser arbitrariamente complicada Asiacute pues se podriacutea haber escritoesta funcioacuten maacutes concisamente

function area(radio) π radio^2end

El valor devuelto por una funcioacuten es el valor de la uacuteltima expresioacuten evaluadaque por defecto es la uacuteltima expresioacuten en el cuerpo de la definicioacuten de lafuncioacuten

Por otro lado las variables temporales como a y las sentencias return expliacutecitaspueden facilitar la depuracioacuten

A veces es uacutetil tener muacuteltiples sentencias return una en cada rama de unasentencia condicional

70 Capiacutetulo 6 Funciones productivas

function valorabsoluto(x) if x lt 0 return -x else return x endend

Dado que estas sentencias return estaacuten en una condicional alternativa solo seejecuta una

En cuanto se ejecuta una sentencia return la funcioacuten termina sin ejecutarninguna de las sentencias siguientes El coacutedigo que aparece despueacutes de lasentencia return o en cualquier otro lugar al que el flujo de ejecucioacuten nuncallegaraacute se llama coacutedigo muerto

En una funcioacuten productiva es una buena idea asegurarse que cualquier posiblerecorrido del programa llegue a una sentencia return Por ejemplo

function valorabsoluto(x) if x lt 0 return -x end if x gt 0 return x endend

Esta versioacuten no es correcta porque si x es igual a 0 ninguna de las condicioneses verdadera y la funcioacuten termina sin alcanzar una sentencia return Si el flujo deejecucioacuten llega al final de la funcioacuten el valor de retorno es nothing queclaramente no es el valor absoluto de 0

juliagt show(valorabsoluto(0))nothing

OBSERVACIOacuteN Julia tiene una funcioacuten incorporada llamada abs quecalcula los valores absolutos

Ejercicio 6-1

Escriba la funcioacuten comparar que tome dos valores x y y y que devuelva 1 si x gty 0 si x == y y -1 si x lt y

Valores de retorno 71

Desarrollo incrementalConforme vaya escribiendo funciones maacutes extensas puede empezar a dedicarmaacutes tiempo a la depuracioacuten

Para lidiar con programas de complejidad creciente se sugiere una teacutecnicallamada desarrollo incremental El objetivo del desarrollo incremental es evitarlargas sesiones de depuracioacuten antildeadiendo y probando solamente pequentildeasporciones de coacutedigo cada vez

Por ejemplo suponga que desea encontrar la distancia entre dos puntos dadospor las coordenadas y Por el teorema de Pitaacutegoras la distancia es

El primer paso es considerar queacute aspecto tendriacutea la funcioacuten distancia en Julia Enotras palabras iquestcuaacuteles son las entradas (paraacutemetros) y cuaacutel es la salida (valor deretorno)

En este caso las entradas son los dos puntos que se pueden representar usandocuatro nuacutemeros El valor devuelto es la distancia que es un nuacutemero de puntoflotante

He aquiacute una primera versioacuten de la funcioacuten

function distancia(x₁ y₁ x₂ y₂) 00end

Obviamente esta versioacuten de la funcioacuten no calcula distancias sino que siempredevuelve cero Aun asiacute es correcta sintaacutecticamente hablando y se ejecutaraacute loque implica que se puede probar antes de hacerla maacutes compleja Los nuacutemeros desubiacutendice estaacuten disponibles en la codificacioacuten de caracteres Unicode (_1 TAB_2 TAB etc)

Para probar la nueva funcioacuten se llama con una muestra de valores

distance(1 2 4 6)

Se eligen estos valores de tal forma que la distancia horizontal sea igual a 3 y ladistancia vertical sea igual a 4 y de esa manera el resultado es 5 (la hipotenusadel triaacutengulo 3-4-5) Cuando se comprueba una funcioacuten es uacutetil conocer larespuesta correcta

Hasta el momento se ha podido confirmar que la funcioacuten es sintaacutecticamentecorrecta por lo que se puede empezar a agregar liacuteneas de coacutedigo El paso loacutegico

72 Capiacutetulo 6 Funciones productivas

siguiente es encontrar las diferencias y En la siguiente versioacuten de lafuncioacuten se almacenaraacuten estos valores en variables temporales y se mostraraacuten conel macro show

function distancia(x₁ y₁ x₂ y₂) dx = x₂ - x₁ dy = y₂ - y₁ show dx dy 00end

Si la funcioacuten trabaja bien las salidas deben ser dx = 3 y dy = 4 Si es asiacute se sabeque la funcioacuten estaacute obteniendo los paraacutemetros correctos y realizando el primercaacutelculo correctamente Si no entonces soacutelo hay unas pocas liacuteneas que revisar

A continuacioacuten se calcula la suma de los cuadrados de dx y dy

function distancia(x₁ y₁ x₂ y₂) dx = x₂ - x₁ dy = y₂ - y₁ dsup2 = dx^2 + dy^2 show dsup2 00end

De nuevo se quiere ejecutar el programa en esta etapa y comprobar la salida(que deberiacutea ser 25) Los nuacutemeros en superiacutendice tambieacuten estaacuten disponibles (^2TAB) Finalmente se puede usar sqrt para calcular y devolver el resultado

function distancia(x₁ y₁ x₂ y₂) dx = x₂ - x₁ dy = y₂ - y₁ dsup2 = dx^2 + dy^2 sqrt(dsup2)end

Si esto funciona correctamente ya se habriacutea terminado Si no se podriacutea mostrarel valor de la variable resultado antes de la sentencia de retorno

La versioacuten final de la funcioacuten no muestra nada cuando se ejecuta soacutelo retorna unvalor Las sentencias print son uacutetiles para la depuracioacuten pero una vez que elprograma esteacute funcionando correctamente se deben eliminar El coacutedigoeliminado se llama andamiaje porque es uacutetil para construir el programa pero noes parte del producto final

Al principio deberiacutea antildeadir solamente una o dos liacuteneas de coacutedigo cada vez

Desarrollo incremental 73

Conforme vaya ganando experiencia puede que se encuentre escribiendo ydepurando fragmentos mayores de coacutedigo Sin embargo el proceso de desarrolloincremental puede ahorrarle mucho tiempo de depuracioacuten

Los aspectos clave del proceso son

1 Iniciar con un programa que funcione y hacerle pequentildeos cambiosincrementales En cualquier momento si hay un error sabraacute exactamentedoacutende estaacute

2 Usar variables temporales para guardar valores intermedios para que puedamostrarlos y verificarlos

3 Una vez que el programa esteacute funcionando tal vez prefiera eliminar partedel andamiaje o consolidar muacuteltiples sentencias en expresiones compuestaspero soacutelo si eso no hace que el programa sea difiacutecil de leer

Ejercicio 6-2

Use la teacutecnica de desarrollo incremental para escribir una funcioacuten llamadahipotenusa que retorne el largo de la hipotenusa de un triaacutengulo rectaacutengulo dadoel largo de las otras dos aristas Registre cada etapa del proceso de desarrollo

ComposicioacutenAhora como usted esperariacutea se puede llamar a una funcioacuten desde otra Comoejemplo se escribe una funcioacuten que tome dos puntos el centro del ciacuterculo y unpunto del periacutemetro y calcule el aacuterea del ciacuterculo

Suponga que el punto central estaacute almacenado en las variables xc y yc y que elpunto del periacutemetro lo estaacute en xp y yp El primer paso es hallar el radio delciacuterculo que es la distancia entre los dos puntos La funcioacuten distancia que realizaesta tarea seriacutea

radio = distancia(xc yc xp yp)

El siguiente paso es encontrar el aacuterea del ciacuterculo usando este radio De nuevo seusa una de las funciones definidas previamente

resultado = area(radio)

Envolviendo todo en una funcioacuten se obtiene

74 Capiacutetulo 6 Funciones productivas

function areacirculo(xc yc xp yp) radio = distancia(xc yc xp yp) resultado = area(radio) return resultadoend

Las variables temporales radio y resultado son uacutetiles para el desarrollo y ladepuracioacuten pero una vez que el programa estaacute funcionando se puede hacer maacutesconciso componiendo las llamadas a funcioacuten

function areacirculo(xc yc xp yp) area(distancia(xc yc xp yp))end

Funciones BooleanasLas funciones pueden devolver valores booleanos lo que a menudo esconveniente para ocultar complicadas comprobaciones dentro de funciones Porejemplo

function esdivisible(x y) if x y == 0 return true else return false endend

Es comuacuten dar a las funciones booleanas nombres que suenan como preguntasque tienen como respuesta un si oacute un no esdivisible devuelve true o false paraindicar si x es o no divisible por y

Por ejemplo

juliagt esdivisible(6 4)falsejuliagt esdivisible(6 3)true

El resultado del operador == es booleano por lo tanto se puede escribir lafuncioacuten de una manera maacutes concisa devolviendo el resultado directamente

Funciones Booleanas 75

function esdivisible(x y) x y == 0end

Las funciones booleanas se usan a menudo en las sentencias condicionales

if esdivisible(x y) println(x es divisible por y)end

Puede parecer tentador escribir algo como

if esdivisible(x y) == true println(x es divisible por y)end

pero la comparacioacuten extra con true es innecesaria

Ejercicio 6-3

Escriba la funcioacuten entremedio(xyz) que devuelva true si x le y le z o false enotro caso

Maacutes recursividadSolo se ha cubierto una pequentildea parte de Julia pero le puede interesar saber queesta parte ya es un lenguaje de programacioacuten completo lo que significa quecualquier coacutemputo puede expresarse en este lenguaje Cualquier programa quese haya escrito podriacutea reescribirse usando solo lo que ha aprendido hasta ahora(en realidad necesitariacutea algunos comandos para controlar dispositivos como elmouse discos etc pero eso es todo)

Probar esta afirmacioacuten es un ejercicio no trivial realizado por primera vez porAlan Turing uno de los primeros cientiacuteficos de la computacioacuten (algunosargumentariacutean que era matemaacutetico pero muchos de los primeros cientiacuteficosinformaacuteticos comenzaron como matemaacuteticos) En consecuencia esto se conocecomo la Tesis de Turing Para una discusioacuten maacutes completa (y precisa) de la Tesisde Turing se recomienda el libro de Michael Sipser Introduccioacuten a la Teoriacutea de laComputacioacuten

Para darle una idea de lo que puede hacer con las herramientas que haaprendido hasta ahora se evaluacutean algunas funciones matemaacuteticas definidasrecursivamente Una definicioacuten recursiva es similar a una definicioacuten circular enel sentido de que la definicioacuten contiene una referencia a lo que estaacute siendodefinido Una definicioacuten verdaderamente circular no es muy uacutetil

76 Capiacutetulo 6 Funciones productivas

vorpalUn adjetivo usado para describir algo que es vorpal

Si esta definicioacuten apareciese en el diccionario la persona que la leyera podriacuteamolestarse Por otro lado si se busca la definicioacuten de la funcioacuten factorialdenotada con el siacutembolo se encuentra encontrar algo como esto

Esta definicioacuten dice que el factorial de 0 es 1 y el factorial de cualquier otrovalor es multiplicado por el factorial de

Entonces es 3 veces que es 2 veces que es 1 vez Es decir es igual a3 por 2 por 1 por 1 que es 6

Si se puede escribir una definicioacuten recursiva se puede escribir un programa deJulia para evaluarlo El primer paso es decidir cuaacuteles deberiacutean ser losparaacutemetros En este caso debe quedar claro que factorial toma valores enteros

function fact(n) end

Si el argumento es 0 la funcioacuten debe devolver 1

function fact(n) if n == 0 return 1 endend

De lo contrario y esto es lo interesante se tiene que hacer una llamada recursivapara encontrar el factorial de n-1 y luego multiplicarlo por n

function fact(n) if n == 0 return 1 else recursion = fact(n-1) resultado = n recursion return resultado endend

El flujo de ejecucioacuten de este programa es similar al flujo de cuentaregresiva enSeccioacuten 58 Si llamamos a fact con el valor 3

Maacutes recursividad 77

Como 3 no es 0 se toma la segunda rama y se calcula el factorial de n-1 hellip

 Como 2 no es 0 se toma la segunda rama y se calcula el factorial de n-1 hellip

  Como 1 no es 0 se toma la segunda rama y se calcula el factorial de + n-1 +hellip

   Como 0 es igual a 0 se toma la primera rama y devuelve 1 sin realizar      maacutes llamadas recursivas

  El valor de retorno 1 se multiplica por n que es 1 y se devuelve elresultado

 El valor de retorno 1 se multiplica por n que es 2 y se devuelve el resultado

El valor de retorno 2 se multiplica por n que es 3 y el resultado 6 se convierteen el valor de retorno de la llamada a funcioacuten que inicioacute todo el proceso

Figura 9 Diagrama de pila

Figura 9 muestra coacutemo se ve el diagrama de pila para esta secuencia dellamadas a funciones

Los valores de retorno se pasan de nuevo a la pila En cada marco el valor deretorno es el valor de resultado que es el producto de n y recursion

En el uacuteltimo marco las variables locales recursion y resultado no existen porquela rama que las crea no se ejecuta

OBSERVACIOacuteN Julia tiene la funcioacuten factorial para calcular el factorialde un nuacutemero entero

Voto de confianzaSeguir el flujo de ejecucioacuten es una forma de leer programas pero puede llegar aser abrumador Una alternativa es lo que se conoce como el voto deconfianza(en ingleacutes leap of faith) Cuando llega a una llamada de funcioacuten enlugar de seguir el flujo de ejecucioacuten asume que la funcioacuten funcionacorrectamente y devuelve el resultado correcto

De hecho ya se estaacute dando este voto de confianza cuando se usan funciones

78 Capiacutetulo 6 Funciones productivas

integradas de Julia Cuando se llaman a cos o exp no se examinan los cuerpos deesas funciones Simplemente se asume que funcionan porque las personas quelas escribieron eran buenos programadores

Lo mismo ocurre cuando el usuario llama a una de sus propias funciones Porejemplo en Seccioacuten 64 se escribe una funcioacuten llamada esdivisible quedetermina si un nuacutemero es divisible por otro Una vez que se confirme que estafuncioacuten es correcta mdashal examinar y probar el coacutedigomdash se puede usar la funcioacutensin mirar nuevamente el cuerpo

Lo mismo aplica a los programas recursivos Cuando llegue a la llamadarecursiva en lugar de seguir el flujo de ejecucioacuten debe suponer que la llamadarecursiva funciona (devuelve el resultado correcto) y luego preguntarseSuponiendo que pueda encontrar el factorial de iquestse puede calcular elfactorial de Estaacute claro que es posible multiplicando por

Por supuesto es un poco extrantildeo suponer que la funcioacuten funciona correctamentecuando no ha terminado de escribirla iexclpero por eso se llama voto de confianza

Un Ejemplo MaacutesDespueacutes de los factoriales el ejemplo maacutes comuacuten de una funcioacuten matemaacuteticadefinida de manera recursiva es fibonacci que tiene la siguiente definicioacuten (verhttpsenwikipediaorgwikiFibonacci_number)

Traducido a Julia se ve asiacute

function fib(n) if n == 0 return 0 elseif n == 1 return 1 else return fib(n-1) + fib(n-2) endend

Si intenta seguir el flujo de ejecucioacuten en esta funcioacuten incluso para valoresbastante pequentildeos de n su cabeza podriacutea estallar Dando un voto de confianzaes decir asumiendo que las dos llamadas recursivas funcionan correctamenteentonces estaacute claro que se obtiene el resultado correcto al sumarlas

Un Ejemplo Maacutes 79

Tipos de Comprobacioacuten

iquestQueacute pasa si se llama a fact con 15 como argumento

juliagt fact(15)ERROR StackOverflowErrorStacktrace [1] fact(Float64) at REPL[3]2

Parece una recursioacuten infinita iquestComo es esto posible La funcioacuten tiene un casobase (cuando n == 0) Pero si n no es un nuacutemero entero es posible perderse elcaso base y hacer recursioacuten para siempre

En la primera llamada recursiva el valor de n es 05 En la siguiente es -05 Apartir de ahiacute se vuelve maacutes pequentildeo (maacutes negativo) pero nunca seraacute 0

Existen dos opciones Se puede intentar generalizar la funcioacuten factorial paratrabajar con nuacutemeros de punto flotante o se puede hacer que fact verifique eltipo del argumento La primera opcioacuten se llama funcioacuten gamma y estaacute un pocomaacutes allaacute del alcance de este libro En este libro se proseguiraacute con la segunda

Se puede usar el operador integrado isa para verificar el tipo de argumentoTambieacuten podemos asegurarnos de que el argumento sea positivo

function fact(n) if (n isa Int64) error(El factorial uacutenicamente estaacute definido para nuacutemerosenteros) elseif n lt 0 error(El factorial no estaacute definido para enteros negativos) elseif n == 0 return 1 else return n fact(n-1) endend

El primer caso base se hace cargo de nuacutemeros no enteros y el segundo deenteros negativos En ambos casos el programa imprime un mensaje de error ydevuelve nothing para indicar que algo salioacute mal

juliagt fact(fred)ERROR El factorial uacutenicamente estaacute definido para nuacutemeros enterosjuliagt fact(-2)ERROR El factorial no estaacute definido para enteros negativos

80 Capiacutetulo 6 Funciones productivas

Si se superan ambas verificaciones se sabe que n es positivo o cero por lo quees posible probar que la recursioacuten termina

Este programa muestra un patroacuten a veces llamado guardian Los dos primeroscondicionales actuacutean como guardianes protegiendo el coacutedigo que sigue de losvalores que pueden causar un error Los guardianes hacen posible demostrar queel coacutedigo es correcto

En Seccioacuten 145 se exploraraacute una alternativa maacutes flexible para imprimir unmensaje de error generar una excepcioacuten

DepuracioacutenDividir un coacutedigo extenso en pequentildeas funciones crea naturalmente puntos decontrol para la depuracioacuten Si un programa no estaacute funcionando existen tresposibilidades a considerar

bull Hay algo incorrecto en los argumentos de la funcioacuten se viola una condicioacutenprevia

bull Hay algo incorrecto en la funcioacuten se viola una condicioacuten posterior

bull Hay algo incorrecto en el valor de retorno o la forma en que se estaacuteutilizando

Para descartar la primera posibilidad puede agregar una sentencia de impresioacutenal comienzo de la funcioacuten para mostrar los valores de los paraacutemetros (y tal vezsus tipos) o bien escribir liacuteneas de coacutedigo que verifiquen las condiciones previasde manera expliacutecita

Si los paraacutemetros estaacuten bien agregue una sentencia de impresioacuten antes de cadasentencia return y muestre el valor de retorno Si es posible verifique elresultado a mano Considere tambieacuten llamar a la funcioacuten con valores quefaciliten la verificacioacuten del resultado (como en Seccioacuten 62)

Si la funcioacuten parece estar funcionando revise la llamada a la funcioacuten paraasegurarse de que el valor de retorno se estaacute utilizando correctamente (iexcloincluso si se estaacute utilizando)

Agregar sentencias de impresioacuten al principio y al final de una funcioacuten puedeayudar a que el flujo de ejecucioacuten sea maacutes transparente Por ejemplo aquiacute hayuna versioacuten de fact con sentencias de impresioacuten

Depuracioacuten 81

function fact(n) espacio = ^ (4 n) println(espacio factorial n) if n == 0 println(espacio devolviendo 1) return 1 else recursion = fact(n-1) resultado = n recursion println(espacio devolviendo resultado) return resultado endend

espacio es una cadena de caracteres de espacios que permite generar sangriacutea enla salida

juliagt fact(4) factorial 4 factorial 3 factorial 2 factorial 1factorial 0devolviendo 1 devolviendo 1 devolviendo 2 devolviendo 6 devolviendo 2424

Si estaacute confundido con el flujo de ejecucioacuten este tipo de salida puede ser uacutetilDesarrollar un buen andamiaje toma tiempo pero un poco de andamiaje puedeahorrar al usuario mucha depuracioacuten

Glosariovariable temporal

Variable usada para almacenar un valor intermedio en un caacutelculo complejo

coacutedigo muertoParte de un programa que nunca puede ser ejecutado a menudo porqueaparece despueacutes de una sentencia return

desarrollo incrementalPlan de desarrollo de un programa que intenta evitar la depuracioacutenagregando y probando solamente una pequentildea porcioacuten de coacutedigo a la vez

82 Capiacutetulo 6 Funciones productivas

andamiajeCoacutedigo que se usa durante el desarrollo de un programa pero que no esparte de la versioacuten final del mismo

guardiaacutenUn patroacuten de programacioacuten que usa una sentencia condicional paraverificar y manejar circunstancias que pueden causar un error

Ejercicios

Ejercicio 6-4

Dibuje un diagrama de pila para el siguiente programa iquestQueacute imprime elprograma

function b(z) prod = a(z z) println(z prod) prodend

function a(x y) x = x + 1 x yend

function c(x y z) total = x + y + z cuadrado = b(total)^2 cuadradoend

x = 1y = x + 1println(c(x y+3 x+y))

Ejercicio 6-5

La funcioacuten de Ackermann se define

Vea httpsenwikipediaorgwikiAckermann_function Escriba una funcioacutenllamada ack que evaluacutee la funcioacuten de Ackermann Use su funcioacuten para evaluarack(3 4) que deberiacutea ser 125 iquestQueacute sucede para valores mayores de m y n

Ejercicios 83

Ejercicio 6-6

Un paliacutendromo es una palabra que se escribe igual en un sentido que en otrocomo ana y radar De manera recursiva una palabra es un paliacutendromo si laprimera y la uacuteltima letra son iguales y lo que estaacute entre ellas es un paliacutendromo

Las siguientes funciones toman un argumento de tipo cadena y devuelven laprimera letra la uacuteltima y las intermedias

function primera(palabra) primera = firstindex(palabra) palabra[primera]end

function ultima(palabra) ultima = lastindex(palabra) palabra[ultima]end

function medio(palabra) primera = firstindex(palabra) ultima = lastindex(palabra) palabra[nextind(palabra primera) prevind(palabra ultima)]end

Se veraacute coacutemo funcionan en Capiacutetulo 8

1 Pruebe estas funciones iquestQueacute sucede si llama a la funcioacuten medio con unacadena de dos letras iquestY con una cadena de una letra iquestQueacute pasa con lacadena vaciacutea que no contiene letras

2 Escriba una funcioacuten llamada espalindromo que tome un argumento de tipocadena y devuelva true si es un paliacutendromo y false de lo contrario Recuerdeque puede usar la funcioacuten integrada length para verificar la longitud de unacadena

Ejercicio 6-7

Un nuacutemero es una potencia de si es divisible por y es una potencia de Escriba una funcioacuten llamada espotencia que tome los paraacutemetros a y b ydevuelva true si a es una potencia de b

OBSERVACIOacuteN Tendraacute que pensar en el caso base

Ejercicio 6-8

El maacuteximo comuacuten divisor (MCD) de y es el nuacutemero maacutes grande que los divide

84 Capiacutetulo 6 Funciones productivas

a ambos con resto 0

Una forma de encontrar el MCD de dos nuacutemeros se basa en la observacioacuten deque si es el resto cuando se divide por entonces mcd(a b) = mcd(b r)Como caso base podemos usar mcd(a 0) = a

Escriba una funcioacuten llamada mcd que tome los paraacutemetros a y b y devuelva sumaacuteximo divisor comuacuten

Creacuteditos Este ejercicio se basa en un ejemplo del libro Estructura einterpretacioacuten de programas informaacuteticos de Abelson y Sussman

Ejercicios 85

Capiacutetulo 7 IteracioacutenEste capiacutetulo se centra en la iteracioacuten que es la capacidad de ejecutarrepetidamente un bloque de sentencias Se han visto dos tipos de iteracioacutenusando recursioacuten en Seccioacuten 58 y usando ciclos for en Seccioacuten 42 En estecapiacutetulo veremos otro tipo maacutes usando sentencias while Primeramente seintroduciraacuten algunos teacuterminos sobre asignacioacuten de variables

Asignacioacuten muacuteltiplePuede que ya haya descubierto que estaacute permitido realizar maacutes de unaasignacioacuten a la misma variable Una nueva asignacioacuten hace que la variableexistente se refiera a un nuevo valor (y deje de referirse al viejo valor)

juliagt x = 55juliagt x = 77

La primera vez que se muestra x su valor es 5 y la segunda vez su valor es 7

Figura 10 Diagrama de estado

Figura 10 muestra el aspecto de una asignacioacuten muacuteltiple en un diagrama deestado

Es necesario aclarar algo que puede causar confusioacuten Puesto que Julia usa elsigno igual (=) para la asignacioacuten es tentador interpretar una sentencia a = bcomo una sentencia de igualdad Pero esta interpretacioacuten es incorrecta

Para empezar la igualdad es simeacutetrica y la asignacioacuten no lo es Por ejemplo enmatemaacuteticas si entonces Pero en Julia la sentencia a = 7 es vaacutelida y 7= a no lo es

Ademaacutes en matemaacuteticas una sentencia de igualdad es verdadera o falsasiempre Si ahora entonces siempre seraacute igual a En Julia una sentenciade asignacioacuten puede hacer que dos variables sean iguales pero no tienen porqueacute quedarse asiacute

86 Capiacutetulo 7 Iteracioacuten

juliagt a = 55juliagt b = a a y b son iguales5juliagt a = 3 a y b ya no son iguales3juliagt b5

La tercera liacutenea cambia el valor de a pero no cambia el valor de b por lo tanto yadejan de ser iguales

AVISO

Reasignar variables puede ser uacutetil pero se debe tener precaucioacutenSi los valores cambian frecuentemente la reasignacioacuten puedehacer que el coacutedigo sea difiacutecil de leer y depurar

Estaacute permitido definir una funcioacuten con el mismo nombre de unavariable definida anteriormente

Actualizacioacuten de variablesUna de las formas maacutes comunes de asignacioacuten muacuteltiple es la actualizacioacutendoacutende el nuevo valor de la variable depende del anterior

juliagt x = x + 18

Esto significa ldquotome el valor actual de x suacutemele uno y despueacutes actualice x con elnuevo valorrdquo

Si intenta actualizar una variable que no existe obtendraacute un error puesto queJulia evaluacutea la expresioacuten del lado derecho antes de asignar un valor a x

juliagt y = y + 1ERROR UndefVarError y not defined

Antes de actualizar una variable tiene que inicializarla usualmente con unaasignacioacuten simple

juliagt y = 00juliagt y = y + 11

Actualizar una variable sumaacutendole 1 se denomina un incremento y restaacutendole 1

Actualizacioacuten de variables 87

se llama un decremento

La Sentencia whileLas computadoras se usan a menudo para automatizar tareas repetitivasRealizar repetidamente tareas ideacutenticas o similares sin cometer errores es algoque las computadoras hacen bien y que los seres humanos hacen limitadamenteLa ejecucioacuten repetida de un conjunto de sentencias se llama iteracioacuten

Ya se han visto dos funciones cuentaregresiva y printn que iteran usandorecursividad Por ser la iteracioacuten tan comuacuten Julia proporciona variascaracteriacutesticas que la hacen maacutes faacutecil Una es la sentencia for que se vio enSeccioacuten 42 a la cual se volveraacute maacutes adelante

Otra caracteriacutestica es la sentencia while Aquiacute hay una versioacuten decuentaregresiva que muestra el uso de la sentencia while

function cuentaregresiva(n) while n gt 0 print(n ) n = n - 1 end println(iexclDespegue)end

Casi podriacutea leer la sentencia while como si fuera Espantildeol La funcioacuten anteriorsignifica ldquoMientras n sea mayor que 0 continuacutee mostrando el valor de n y luegoreduciendo el valor de n en 1 Cuando llegue a 0 muestre la palabra iexclDespegueldquo

Maacutes formalmente el flujo de ejecucioacuten de una sentencia while es el siguiente

1 Se determina si la condicioacuten es verdadera o falsa

2 Si es falsa se sale de la sentencia while y continuacutea la ejecucioacuten con lasiguiente sentencia

3 Si es verdadera ejecuta cada una de las sentencias en el cuerpo y regresa alpaso 1

Este tipo de flujo se llama bucle porque el tercer paso vuelve a la parte superior

El cuerpo del bucle deberiacutea cambiar el valor de una o maacutes variables de maneraque en alguacuten momento la condicioacuten sea falsa y el bucle termine En casocontrario el bucle se repetiraacute indefinidamente lo cual se llama bucle infinitoUna interminable fuente de diversioacuten para los informaacuteticos es la observacioacuten deque las instrucciones del champuacute ldquoEnjabone enjuague repitardquo son un bucleinfinito

88 Capiacutetulo 7 Iteracioacuten

En el caso de cuentaregresiva podemos probar que el bucle termina si n es ceroo negativo el ciclo termina En otro caso el valor de n se hace maacutes pequentildeocada vez que pasa por el bucle asiacute en cierto momento se llega a 0

En otros casos no es tan faacutecil decirlo Por ejemplo

function seq(n) while n = 1 println(n) if n 2 == 0 n is par n = n 2 else n is impar n = n3 + 1 end endend

La condicioacuten de este bucle es n = 1 de manera que el bucle continuaraacute hastaque n sea 1 que haraacute que la condicioacuten sea falsa

Cada vez que pasa por el bucle el programa muestra como salida el valor de n yluego comprueba si es par o impar Si es par el valor de n se divide por dos Si esimpar el valor de n se sustituye por n3 + 1 Por ejemplo si el argumento pasadoa la funcioacuten seq es 3 los valores resultantes n son 3 10 5 16 8 4 2 1

Puesto que n a veces aumenta y a veces disminuye no hay una prueba obvia deque n alcance alguna vez el valor 1 o de que el programa vaya a terminar Paraalgunos valores particulares de n se puede probar que siacute termina Por ejemplosi el valor de inicio es una potencia de dos entonces el valor de n seraacute par cadavez que se pasa por el bucle hasta que llegue a 1 El ejemplo anterior producedicha secuencia si se inicia con 16

Lo diacuteficil es preguntarse si se puede probar que este programa termina paratodos los valores positivos de n Hasta ahora nadie ha sido capaz de probar quelo hace o iexclque no lo hace (Vea httpseswikipediaorgwikiConjetura_de_Collatz)

Ejercicio 7-1

Reescribe la funcioacuten printn de Seccioacuten 58 utilizando iteracioacuten en vez derecursioacuten

breakA veces no se sabe que un ciclo debe terminar hasta que se llega al cuerpo Enese caso se puede usar la sentencia break para salir del bucle

break 89

Por ejemplo suponga que se desea recibir entradas del usuario hasta que esteescriba listo Podriacuteamos escribir

while true print(gt ) linea = readline() if line == listo break end println(linea)endprintln(iexclListo)

La condicioacuten del bucle es true que siempre es verdadero por lo que el bucle seejecuta hasta que llega a la sentencia break

En cada iteracioacuten se le pide al usuario (con el siacutembolo gt ) una entrada Si elusuario escribe listo la sentencia break sale del bucle De lo contrario elprograma repite lo que escriba el usuario y vuelve a la parte superior del bucleA continuacioacuten se muestra coacutemo funciona este programa

gt no listono listogt listoiexclListo

Esta forma de escribir bucles while es comuacuten porque permite verificar lacondicioacuten en cualquier parte del bucle (no solo en la parte superior) y puedeexpresar la condicioacuten de teacutermino de manera afirmativa (detenerse cuando estosuceda) en vez de negativamente (continuar hasta que esto suceda)

continueLa sentencia break permite terminar el bucle Cuando aparece una sentenciacontinue dentro de un bucle se regresa al comienzo del bucle ignorando todoslas sentencias que quedan en la iteracioacuten actual del bucle e inicia la siguienteiteracioacuten Por ejemplo

for i in 110 if i 3 == 0 continue end print(i )end

Output

90 Capiacutetulo 7 Iteracioacuten

1 2 4 5 7 8 10

Si i es divisible por 3 la sentencia continue detiene la iteracioacuten actual ycomienza la siguiente iteracioacuten Solo se imprimen los nuacutemeros en el rango de 1 a10 no divisibles por 3

Raiacuteces CuadradasLos bucles son comuacutenmente utilizados en programas que calculan resultadosnumeacutericos y que comienzan con una respuesta aproximada que es iterativamentemejorada

Por ejemplo una forma de calcular raiacuteces cuadradas es el meacutetodo de NewtonSuponga que desea conocer la raiacutez cuadrada de Si comienza con casi cualquierestimacioacuten puede calcular una mejor aproximacioacuten con la siguiente foacutermula

Por ejemplo si es 4 y es 3

juliagt a = 44juliagt x = 33juliagt y = (x + ax) 221666666666666665

El resultado estaacute maacutes cerca de la respuesta correcta ( ) Si se repite elproceso con la nueva estimacioacuten se acerca auacuten maacutes

juliagt x = y21666666666666665juliagt y = (x + ax) 220064102564102564

Despueacutes de algunas actualizaciones la estimacioacuten es casi exacta

Raiacuteces Cuadradas 91

juliagt x = y20064102564102564juliagt y = (x + ax) 220000102400262145juliagt x = y20000102400262145juliagt y = (x + ax) 220000000000262146

En general no se sabe de antemano cuaacutentos pasos se necesitan para llegar a larespuesta correcta pero se sabe que se ha llegado a ella cuando la estimacioacutendeja de cambiar

juliagt x = y20000000000262146juliagt y = (x + ax) 220juliagt x = y20juliagt y = (x + ax) 220

Cuando y == x ya se pueden detener los coacutemputos A continuacioacuten se muestraun ciclo que comienza con una estimacioacuten inicial x la cual mejora hasta que dejade cambiar

while true println(x) y = (x + ax) 2 if y == x break end x = yend

Para la mayoriacutea de los valores de a esto funciona bien aunque en general no serecomienda probar igualdad entre nuacutemeros de punto flotante Los nuacutemeros depunto flotante son aproximadamente correctos la mayoriacutea de los nuacutemerosracionales como e irracionales como no pueden ser representadosexactamente con un Float64

En lugar de verificar si x e y son exactamente iguales es maacutes seguro usar lafuncioacuten integrada abs para calcular el valor absoluto o la magnitud de ladiferencia entre ellos

92 Capiacutetulo 7 Iteracioacuten

if abs(y-x) lt ε breakend

Donde ε (varepsilon TAB) toma un valor como 00000001 que determina coacutemode cerca es suficientemente cerca

AlgoritmosEl meacutetodo de Newton es un ejemplo de un algoritmo un proceso mecaacutenico quepermite resolver una categoriacutea de problemas (en este caso el caacutelculo de raiacutecescuadradas)

Para comprender queacute es un algoritmo podriacutea ayudar empezar con algo que no esun algoritmo Cuando aprendioacute a multiplicar nuacutemeros de un solo diacutegitoprobablemente memorizoacute la tabla de multiplicar En efecto memorizoacute 100soluciones especiacuteficas Ese tipo de conocimiento no es un algoritmo

Pero si fuera perezoso podriacutea haber aprendido algunos trucos Por ejemplopara encontrar el producto de y 9 puede escribir como el primer diacutegito y

como el segundo diacutegito Este truco es una solucioacuten general para multiplicarcualquier nuacutemero de un solo diacutegito por 9 iexclEsto siacute es un algoritmo

Del mismo modo las teacutecnicas que aprendioacute para la suma con ldquollevamos tantordquo laresta con ldquopedimos prestado tantordquo y la divisioacuten ldquolarga o con galera o de casitardquoson todas ellas algoritmos Una de las caracteriacutesticas de los algoritmos es que norequieren inteligencia para realizarlos Son procesos mecaacutenicos donde cada pasose sigue de acuerdo con un conjunto simple de reglas

Ejecutar algoritmos es aburrido pero disentildearlos es interesante intelectualmentedesafiante y constituyen una parte central de la informaacutetica

Algunas de las cosas que las personas hacen naturalmente sin dificultad oconscientemente son las maacutes difiacuteciles de expresar en algoritmos Comprender ellenguaje natural es un buen ejemplo Todo el mundo lo hace pero hasta ahoranadie ha podido explicar coacutemo se hace al menos no en forma de algoritmo

DepuracioacutenA medida que comience a escribir programas maacutes extensos es posible que pasemaacutes tiempo depurando Maacutes coacutedigo significa maacutes posibilidades de cometer unerror y maacutes lugares doacutende se pueden esconder los errores

Una forma de reducir el tiempo de depuracioacuten es depurar por biseccioacuten Porejemplo si hay 100 liacuteneas en su programa y las revisa una a la vez seriacutean 100revisiones

Algoritmos 93

Es mejor tratar de dividir el problema en dos Busque en la mitad del programa oun valor intermedio que pueda verificar Agregue una sentencia de impresioacuten (oalgo que permita verificar) y ejecute el programa

Si esta verificacioacuten es incorrecta debe haber un problema en la primera mitaddel programa Si es correcta el problema estaacute en la segunda mitad

Cada vez que realiza una verificacioacuten como esta reduce a la mitad el nuacutemero deliacuteneas que debe revisar Despueacutes de seis pasos (que es mucho menos que 100) sereduciriacutea a una o dos liacuteneas de coacutedigo al menos en teoriacutea

En la praacutectica no siempre se conoce doacutende estaacute la mitad del programa y nosiempre es posible verificarlo No tiene sentido contar liacuteneas y encontrar el puntomedio exacto En su lugar piense en los lugares del programa donde puedehaber errores y en los lugares donde es faacutecil verificar Luego elija un lugar endonde usted crea que las posibilidades de encontrar un error antes o despueacutes deesta verificacioacuten son maacutes o menos las mismas

Glosarioasignacioacuten muacuteltiple

Asignar un nuevo valor a una variable que ya existe

actualizacioacutenAsignacioacuten donde el nuevo valor de la variable depende del antiguo

inicializacioacutenAsignacioacuten que le da un valor inicial a una variable que seraacute actualizada

incrementoActualizacioacuten que incrementa el valor de la variable (usualmente en 1)

decrementoActualizacioacuten que disminuye el valor de la variable (usualmente en 1)

iteracioacutenEjecucioacuten repetida de un conjunto de sentencias usando una funcioacutenrecursiva o un bucle

sentencia whileSentencia que permite iteraciones controladas por una condicioacuten

sentencia breakSentencia que permite salir de un bucle

94 Capiacutetulo 7 Iteracioacuten

sentencia continueSentencia localizada dentro de un bucle que obliga a iniciar una nuevaiteracioacuten desde el inicio del bucle

bucle infinitoUn bucle cuya condicioacuten de teacutermino no es satisfecha

algoritmoProceso general para resolver una categoriacutea de problemas

Ejercicios

Ejercicio 7-2

Copie el bucle de Seccioacuten 76 e inseacutertelo en una funcioacuten llamada miraiz que tomea como paraacutemetro elija un valor razonable de x y devuelva una estimacioacuten de laraiacutez cuadrada de a

Para probarla escriba una funcioacuten llamada probarraiz que imprima una tablacomo esta

a mysqrt sqrt diff- ------ ---- ----10 10 10 0020 1414213562373095 14142135623730951 2220446049250313e-1630 17320508075688772 17320508075688772 0040 20 20 0050 223606797749979 223606797749979 0060 2449489742783178 2449489742783178 0070 26457513110645907 26457513110645907 0080 282842712474619 28284271247461903 4440892098500626e-1690 30 30 00

La primera columna es un nuacutemero a la segunda columna es la raiacutez cuadrada dea calculada con miraiz la tercera columna es la raiacutez cuadrada calculada con lafuncioacuten integrada sqrt y la cuarta columna es el valor absoluto de la diferenciaentre las dos estimaciones

Exercise 7-3

La funcioacuten integrada Metaparse toma una cadena y la transforma en unaexpresioacuten Esta expresioacuten se puede evaluar en Julia con la funcioacuten Coreeval Porejemplo

Ejercicios 95

juliagt expr = Metaparse(1+23)(1 + 2 3)juliagt eval(expr)7juliagt expr = Metaparse(sqrt(π))(sqrt(π))juliagt eval(expr)17724538509055159

Escriba una funcioacuten llamada evalbucle que iterativamente solicite una entrada alusuario tome la entrada resultante la evaluacutee usando eval y pase posteriormentea imprimir el resultado Debe continuar hasta que el usuario ingrese listo y luegodevolver el valor de la uacuteltima expresioacuten que evaluoacute

Exercise 7-4

El matemaacutetico Srinivasa Ramanujan encontroacute una serie infinita que puede usarsepara generar una aproximacioacuten numeacuterica de

Escriba una funcioacuten llamada estimarpi que utilice esta foacutermula para calcular ydevolver una estimacioacuten de π Debe usar un ciclo while para calcular losteacuterminos de la suma hasta que el uacuteltimo teacutermino sea menor que 1e-15 (que es lanotacioacuten de Julia para ) Puede verificar el resultado comparaacutendolo con π

96 Capiacutetulo 7 Iteracioacuten

Capiacutetulo 8 CadenasLas cadenas son diferentes de los nuacutemeros enteros flotantes y booleanos Unacadena es una secuencia es decir una coleccioacuten ordenada de valores En estecapiacutetulo se veraacute coacutemo acceder a los caracteres que forman una cadena y seconoceraacuten algunas funciones integradas en Julia relacionadas con cadenas

CaracteresLos hispanohablantes estaacuten familiarizados con algunos caracteres tales como lasletras del alfabeto (A B C hellip) los nuacutemeros y los signos de puntuacioacuten comunesEstos caracteres estaacuten estandarizados en el coacutedigo ASCII (Coacutedigo EstaacutendarEstadounidense para el Intercambio de Informacioacuten)

Por supuesto hay muchos otros caracteres utilizados en idiomas distintos delespantildeol que no estaacuten en el coacutedigo ASCII tales como aquellos usados en losidiomas griego aacuterabe chino hebreo hindi japoneacutes y coreano

Definir queacute es un caraacutecter es altamente complejo La norma Unicode permiteabordar este problema y se considera como el estaacutendar definitivo para ello Estanorma funciona asignando un nuacutemero uacutenico para cada caraacutecter a nivel global

Un valor Char representa un uacutenico caraacutecter y estaacute entre comillas simples

juliagt xx ASCIIUnicode U+0078 (category Ll Letter lowercase)juliagt ἴἴ Unicode U+1F34C (category So Symbol other)juliagt typeof(x)Char

Incluso los emojis son parte del estaacutendar Unicode (banana TAB)

Una Cadena es una SecuenciaUna cadena es una secuencia de caracteres Se puede acceder a un caraacutecter conel operador corchete

juliagt fruta = bananabananajuliagt letra = fruta[1]b ASCIIUnicode U+0062 (category Ll Letter lowercase)

La segunda sentencia selecciona el caraacutecter nuacutemero 1 de fruta y la asigna a lavariable letra

Caracteres 97

La expresioacuten entre corchetes se llama indice El iacutendice indica el caraacutecter de lasecuencia a obtener (de ahiacute el nombre)

La indexacioacuten en Julia es base 1 es decir el primer elemento de cualquier objetoindexado con enteros estaacute en el iacutendice 1 y el uacuteltimo en el iacutendice end

juliagt fruta[end]a ASCIIUnicode U+0061 (category Ll Letter lowercase)

Como iacutendice se pueden usar expresiones que contengan variables y operadores

juliagt i = 11juliagt fruta[i+1]a ASCIIUnicode U+0061 (category Ll Letter lowercase)juliagt fruta[end-1]n ASCIIUnicode U+006E (category Ll Letter lowercase)

No obstante el valor del iacutendice tiene que ser un nuacutemero entero De lo contrariose obtiene

juliagt letra = fruta[15]ERROR MethodError no method matching getindex(String Float64)

lengthlength es una funcioacuten integrada que devuelve el nuacutemero de caracteres de unacadena

juliagt frutas = ἴ ἴ ἵἴ ἴ ἵjuliagt len = length(frutas)5

Para obtener la uacuteltima letra de una cadena puede sentirse tentado a probar algocomo esto

juliagt last = frutas[len] ASCIIUnicode U+0020 (category Zs Separator space)

Pero con esto no se obtiene el resultado esperado

Las cadenas se codifican usando codificacioacuten UTF-8 UTF-8 es una codificacioacutende longitud variable lo que significa que no todos los caracteres estaacuten

98 Capiacutetulo 8 Cadenas

codificados con el mismo nuacutemero de bytes

La funcioacuten sizeof devuelve el nuacutemero de bytes de una cadena

juliagt sizeof(ἴ)4

Dado que un emoji estaacute codificado en 4 bytes y la indexacioacuten de cadenas estaacutebasada en bytes el quinto elemento de frutas es un ESPACIO

Esto significa que no todos los iacutendices de byte de una cadena UTF-8 sonnecesariamente iacutendices vaacutelidos para un caraacutecter Si en una cadena se indexa conun iacutendice de bytes no vaacutelido se genera un error

juliagt frutas[2]ERROR StringIndexError(ἴ ἴ ἵ 2)

En el caso de frutas el caraacutecter ἴ es un caraacutecter de cuatro bytes por lo que losiacutendices 2 3 y 4 no son vaacutelidos y el iacutendice del siguiente caraacutecter es 5 el siguienteiacutendice vaacutelido se puede calcular con nextind(frutas 1) el subsiguiente connextind(frutas5) y asiacute sucesivamente

RecorridoMuchos caacutelculos implican procesar una cadena caraacutecter por caraacutecter A menudoempiezan por el principio seleccionan cada caraacutecter por turno hacen algo con eacutely continuacutean hasta el final Este patroacuten de proceso se llama recorrido Una formade escribir un recorrido es con una sentencia while

indice = firstindex(frutas)while indice lt= sizeof(frutas) letra = frutas[indice] println(letra) global indice = nextind(frutas indice)end

Este bucle recorre la cadena y muestra cada letra en una liacutenea distinta Lacondicioacuten del bucle es index lt= sizeof(fruta) de modo que cuando el iacutendice esmayor al nuacutemero de bytes en la cadena la condicioacuten es falsa y no se ejecuta elcuerpo del bucle

La funcioacuten firstindex devuelve el primer iacutendice de bytes vaacutelido La palabrareservada global antes de indice indica que queremos reasignar la variableindice definida en Main (ver Seccioacuten 117)

Recorrido 99

Ejercicio 8-1

Escriba una funcioacuten que tome una cadena como argumento y que muestre lasletras desde la uacuteltima a la primera una por liacutenea

Otra forma de escribir un recorrido es con un bucle for

for letra in frutas println(letra)end

Cada vez que se recorre el bucle se asigna a la variable letra el siguientecaraacutecter de la cadena El bucle continuacutea hasta que no quedan maacutes caracteres

El ejemplo siguiente muestra coacutemo usar la concatenacioacuten (multiplicacioacuten decadenas) y un bucle for para generar una serie abecedaria (es decir una seriecon elementos en orden alfabeacutetico) Por ejemplo en el libro de Robert McCloskeyMake Way for Ducklings los nombres de los patitos son Jack Kack Lack MackNack Ouack Pack y Quack Este bucle muestra esos nombres en orden

prefijos = JKLMNOPQsufijo = ack

for letra in prefijos println(letra sufijo)end

Output

JackKackLackMackNackOackPackQack

Por supuesto esto no es del todo correcto porque ldquoOuackrdquo y ldquoQuackrdquo no estaacutencorrectamente escritos

Ejercicio 8-2

Modifique este programa para solucionar este error

100 Capiacutetulo 8 Cadenas

Porciones de CadenasA la subcadena de una cadena se le llama porcioacuten La seleccioacuten de una porcioacuten essimilar a la seleccioacuten de un caraacutecter

juliagt str = Julio Cesar

juliagt str[15]Julio

El operador [nm] devuelve la parte de la cadena desde el n-eacutesimo byte hasta elm-eacutesimo Por lo tanto se siguen las mismas reglas que para la indexacioacuten simple

La palabra reservada end se puede usar para indicar al uacuteltimo byte de la cadena

juliagt str[7end]Cesar

Si el primer iacutendice es mayor que el segundo el resultado es una cadena vaciacutearepresentada por dos comillas

juliagt str[87]

Una cadena vaciacutea no contiene caracteres y tiene una longitud de 0 pero apartede eso es igual a cualquier otra cadena

Ejercicio 8-3

Continuando este ejemplo iquestqueacute cree que significa str[] Pruebe y veraacute

Las Cadenas son InmutablesEs tentador usar el operador [] en el lado izquierdo de una asignacioacuten con laintencioacuten de cambiar un caraacutecter en una cadena Por ejemplo

juliagt saludo = iexclHola mundoiexclHola mundojuliagt saludo[3] = JERROR MethodError no method matching setindex(String CharInt64)

Nota del traductor De acuerdo con la codificacioacuten de caracteres en utf-8 o latin-

Porciones de Cadenas 101

1 el caraacutecter de exclamacioacuten lsquoiexclrsquo en la variable saludo ocupa dos posiciones deahiacute que la letra lsquoHrsquo esteacute localizada en el iacutendice 3

La razoacuten del error es que las cadenas son inmutables lo que significa que no sepuede cambiar una cadena existente Lo maacuteximo que se puede hacer es crearuna nueva cadena que sea una variacioacuten de la original

juliagt saludo = iexclJ saludo[4end]iexclJola mundo

Este ejemplo concatena la apertura del signo de exclamacioacuten y una nuevaprimera letra a una porcioacuten de saludo Esta operacioacuten no tiene efecto sobre lacadena original

Interpolacioacuten de CadenasConstruir cadenas usando concatenacioacuten puede ser un poco engorroso Paradisminuir la necesidad de las llamadas a string o multiplicaciones repetidas Juliapermite la interpolacioacuten de cadenas usando $

juliagt saludo = iexclHolaiexclHolajuliagt paraquien = mundomundojuliagt $saludo $(paraquien)iexclHola mundo

Esto es maacutes entendible y conveniente que la concatenacioacuten de cadenas saludo paraquien

La expresioacuten inmediatamente siguiente a $ se toma como la expresioacuten cuyo valorse va a interpolar en la cadena Por lo tanto puede interpolar cualquierexpresioacuten en una cadena usando pareacutentesis

juliagt 1 + 2 = $(1 + 2)1 + 2 = 3

Buacutesqueda

iquestQueacute hace la siguiente funcioacuten

102 Capiacutetulo 8 Cadenas

function busqueda(palabra letra) indice = primerindice(palabra) while indice lt= sizeof(palabra) if palabra[indice] == letra return indice end indice = nextind(palabra indice) end -1end

En cierto sentido la funcioacuten buacutesqueda es lo contrario del operador [] En lugarde tomar un iacutendice y extraer el caraacutecter correspondiente toma un caraacutecter yencuentra el iacutendice donde aparece el caraacutecter Si el caraacutecter no se encuentra lafuncioacuten devuelve -1

Este es el primer ejemplo de una sentencia return dentro de un bucle Sipalabra[indice] == letra la funcioacuten devuelve inmediatamente el iacutendiceescapando del bucle prematuramente

Si el caraacutecter no aparece en la cadena entonces el programa sale del buclenormalmente y devuelve -1

Este patroacuten de computacioacuten se llama a veces un recorrido eureka porque tanpronto como encontramos lo que buscamos podemos gritar ldquoiexclEureka rdquo y dejarde buscar

Ejercicio 8-4

Modifique la funcioacuten busqueda para que tenga un tercer paraacutemetro el iacutendice depalabra donde deberiacutea comenzar a buscar

Iterando y contandoEl siguiente programa cuenta el nuacutemero de veces que aparece la letra a en unacadena

palabra = bananacontador = 0for letra in palabra if letra == a global contador = contador + 1 endendprintln(contador)

Iterando y contando 103

Este programa es otro ejemplo del patroacuten de computacioacuten llamado conteo Lavariable contador se inicializa en 0 y se incrementa cada vez que encuentra laletra a Cuando termina el bucle contador contiene el resultado (el nuacutemero totalde letras a)

Ejercicio 8-5

Coloque este coacutedigo en una funcioacuten llamada conteo y generaliacutecelo de tal maneraque tome como argumentos una cadena y una letra

Luego vuelva a escribir la funcioacuten para que en vez de revisar toda la cadenautilice la funcioacuten busqueda de tres paraacutemetros de la seccioacuten anterior

Libreriacutea con cadenasJulia tiene funciones integradas que realizan una variedad de operaciones uacutetilesen cadenas Por ejemplo la funcioacuten uppercase toma una cadena y devuelve unanueva cadena con todas las letras mayuacutesculas

juliagt uppercase(iexclHola mundo)iexclHOLA MUNDO

Existe una funcioacuten llamada findfirst que es notablemente similar a la funcioacutenbusqueda que escribimos

juliagt findfirst(a banana)22

La funcioacuten findfirst es maacutes general que la funcioacuten creada puede encontrarsubcadenas no solo caracteres

juliagt findfirst(na banana)34

Por defecto findfirst empieza la buacutesqueda al comienzo de la cadena pero lafuncioacuten findnext toma un tercer argumento el indice donde deberiacutea comenzar

juliagt findnext(na banana 4)56

El operador isinEl operador isin (in TAB) es un operador booleano que toma un caraacutecter y unacadena y devuelve true si el primero aparece en el segundo

104 Capiacutetulo 8 Cadenas

juliagt a isin banana a en bananatrue

Por ejemplo la siguiente funcioacuten imprime todas las letras de palabra1 quetambieacuten aparecen en palabra2

function ambas(palabra1 palabra2) for letra in palabra1 if letra isin palabra2 print(letra ) end endend

Una buena eleccioacuten de nombres de variables permite que Julia se pueda leercomo el espantildeol Este bucle puede leerse como para (cada) letra en (la primera)palabra si (la) letra es un elemento de (la segunda) palabra imprima (la) letra

Esto es lo que se obtiene si se compara manzanas y naranjas

juliagt ambas(manzanas naranjas)a n a n a s

Comparacioacuten de CadenasLos operadores de comparacioacuten trabajan sobre cadenas Para ver si dos cadenasson iguales

palabra = Pintildeaif palabra == banana println(iexclTenemos bananas)end

Otras operaciones de comparacioacuten son uacutetiles para ordenar alfabeacuteticamentepalabras

if palabra lt banana println(Su palabra $palabra va antes de banana)elseif word gt banana println(Su palabra $palabra va antes de banana)else println(iexclTenemos bananas)end

Comparacioacuten de Cadenas 105

Julia no maneja las letras mayuacutesculas y minuacutesculas del mismo modo que sonmanejadas en cualquier lengua hablada Todas las letras mayuacutesculas van antesde las letras minuacutesculas seguacuten el estaacutendar de codificacioacuten Por lo tanto

Su palabra Pintildea va antes de banana

OBSERVACIOacuteNUna forma comuacuten de abordar este problema es convertirlas cadenas a un formato estaacutendar como por ejemplo aminuacutesculas antes de realizar la comparacioacuten

DepuracioacutenCuando se usan iacutendices para recorrer los valores en una secuencia es difiacutecilacceder al principio y al final del recorrido Aquiacute hay una funcioacuten que comparados palabras y devuelve true si una de las palabras es el reverso de la otra perocontiene dos errores

function espalindroma(palabra1 palabra2) if length(palabra1) = length(palabra2) return false end i = firstindex(palabra1) j = lastindex(palabra2) while j gt= 0 j = prevind(palabra2 j) if palabra1[i] = palabra2[j] return false end i = nextind(palabra1 i) end trueend

La primera sentencia if verifica si las palabras tienen la misma longitud Si no sedevuelve false inmediatamente De lo contrario para el resto de la funcioacuten sepuede suponer que las palabras tienen la misma longitud Este es un ejemplo delpatroacuten guardiaacuten

i y j son iacutendices i recorre palabra1 de derecha a izquierda mientras que j recorrepalabra2 de izquierda a derecha Si dos letras no coinciden se devuelve falseinmediatamente Si el ciclo termina y todas las letras coinciden se devuelve true

La funcioacuten lastindex devuelve el uacuteltimo iacutendice de bytes vaacutelido de una cadena yprevind el iacutendice vaacutelido anterior a un caraacutecter

Si se prueba esta funcioacuten con las palabras amor y roma se espera el valor de

106 Capiacutetulo 8 Cadenas

retorno true pero se obtiene false

juliagt espalindroma(amor roma)false

Para depurar este tipo de error primeramente se imprimen los valores de losiacutendices

espalindroma (generic function with 1 method)

Ahora al ejecutar el programa se obtiene maacutes informacioacuten

juliagt espalindroma(amor roma)i = 1j = 3false

En la primera iteracioacuten del bucle el valor de j es 3 pero tendriacutea que ser 4 Estose puede solucionar trasladando la liacutenea j = prevind (palabra2 j) al final del ciclowhile

Si se soluciona ese error y se ejecuta el programa nuevamente se obtiene

espalindroma (generic function with 1 method)

juliagt espalindroma(amor roma)i = 1j = 4i = 2j = 3i = 3j = 2i = 4j = 1i = 5j = 0ERROR BoundsError attempt to access String at index [5]

Esta vez se ha producido un BoundsError El valor de i es 5 que estaacute fuera delrango de la cadena amor

Depuracioacuten 107

Ejercicio 8-6

Ejecute el programa en papel cambiando los valores de i y j durante cadaiteracioacuten Encuentre y arregle el segundo error en esta funcioacuten

Glosariosecuencia

Una coleccioacuten ordenada de valores donde cada valor se identifica medianteun iacutendice entero

coacutedigo ASCIICoacutedigo de caracteres estaacutendar para el intercambio de informacioacuten

norma UnicodeUn estaacutendar en la industria informaacutetica para la codificacioacuten representacioacuteny manejo consistentes de texto en la mayoriacutea de los sistemas de escrituradel mundo

iacutendiceUn valor entero usado para seleccionar un miembro de un conjuntoordenado como puede ser un caraacutecter de una cadena En Julia los iacutendicescomienzan en 1

codificacioacuten UTF-8Una codificacioacuten de caracteres de longitud variable capaz de codificar todoslos 1112064 puntos de coacutedigo vaacutelidos en Unicode utilizando de uno a cuatrobytes de 8 bits

recorrerIterar sobre los elementos de un conjunto realizando una operacioacuten similaren cada uno de ellos

porcioacutenUna parte de una cadena especificada mediante un rango de iacutendices

cadena vaciacuteaUna cadena sin caracteres y longitud 0 representada por dos comillas

immutableLa propiedad de una secuencia que hace que a sus elementos no se lespueda asignar nuevos valores

interpolacioacuten de cadenasEl proceso de evaluar una cadena que contiene uno o maacutes marcadores de

108 Capiacutetulo 8 Cadenas

posicioacuten produciendo un resultado en el que los marcadores de posicioacuten sereemplazan con sus valores correspondientes

buacutesquedaUn patroacuten de recorrido que se detiene cuando encuentra lo que estaacutebuscando

contadorUna variable utilizada para contar algo generalmente inicializada en cero yluego incrementada

Ejercicios

Ejercicio 8-7

Lea la documentacioacuten de las funciones relacionadas con cadenas enhttpsdocsjulialangorgenv1manualstrings Es posible que desee probaralgunas de ellas para asegurarse de comprender coacutemo funcionan strip y replaceson particularmente uacutetiles

La documentacioacuten utiliza una sintaxis que puede ser confusa Por ejemplo ensearch(cadenaAbstractString caracterChars [comienzoInteger]) loscorchetes indican argumentos opcionales Por lo tanto cadena y caracter sonobligatorios pero comienzo es opcional

Ejercicio 8-8

Hay una funcioacuten integrada llamada count que es similar a la funcioacuten en Seccioacuten89 Lea la documentacioacuten de esta funcioacuten y uacutesela para contar el nuacutemero deletras a en banana

Ejercicio 8-9

Una porcioacuten de cadena puede tomar un tercer iacutendice El primero especifica elinicio el tercero el final y el segundo el tamantildeo del paso es decir el nuacutemero deespacios entre caracteres sucesivos Un tamantildeo de paso de 2 significa cada uncaracter 3 significa cada dos etc

juliagt fruta = bananabananajuliagt fruta[126]bnn

Un tamantildeo de paso de -1 recorre la palabra hacia la izquierda por lo que laporcioacuten [end-11] genera una cadena invertida

Ejercicios 109

Use esto para escribir una versioacuten de una liacutenea de coacutedigo de espalindroma deSeccioacuten 6113

Exercise 8-10

Las siguientes funciones estaacuten destinadas a verificar si una cadena contieneletras minuacutesculas pero algunas de ellas son incorrectas Para cada funcioacutendescriba queacute hace realmente la funcioacuten (suponiendo que el paraacutemetro es unacadena)

110 Capiacutetulo 8 Cadenas

function cualquierminuscula1(s) for c in s if islowercase(c) return true else return false end endend

function cualquierminuscula2(s) for c in s if islowercase(c) return true else return false end endend

function cualquierminuscula3(s) for c in s bandera = islowercase(c) end flagend

function cualquierminuscula4(s) bandera = false for c in s bandera = bandera || islowercase(c) end flagend

function cualquierminuscula5(s) for c in s if islowercase(c) return false end end trueend

Exercise 8-11

Un cifrado Ceacutesar es una forma simple de cifrado que implica desplazar cada letraun nuacutemero fijo de lugares Desplazar una letra significa reemplazarla por otra

Ejercicios 111

letra que se encuentra un nuacutemero fijo de posiciones maacutes adelante en el alfabetoEs posible desplazarse hasta el principio del abecedario si fuera necesario Deesta manera con un desplazamiento de 3 A es D y con un desplazamiento de1 Z es A

Para desplazar una palabra desplace cada letra en la misma cantidad Porejemplo con un desplazamiento de 6 ABCDEF es GHIJKL y con undesplazamiento de -6 BCDE es VWXY En la peliacutecula 2001 Una odisea delespacio la computadora de la nave se llama HAL que es IBM desplazada por -1

Escriba una funcioacuten llamada desplazarpalabra que tome una cadena y un nuacutemeroentero como paraacutemetros y devuelva una nueva cadena que contenga las letrasde la cadena original desplazadas por la cantidad dada

OBSERVACIOacuteN

Es posible que desee utilizar la funcioacuten integrada Intque convierte un caraacutecter en un coacutedigo numeacuterico yChar que convierte los coacutedigos numeacutericos encaracteres Las letras del alfabeto estaacuten codificadas enorden alfabeacutetico por ejemplo

juliagt Int(c) - Int(a)2

Porque c es la tercera letra del alfabeto Pero cuidadolos coacutedigos numeacutericos para las letras mayuacutesculas sondiferentes

juliagt Char(Int(A) + 32)a ASCIIUnicode U+0061 (category Ll Letterlowercase)

Algunos chistes ofensivos en Internet estaacuten codificados en ROT13 que es uncifrado Ceacutesar con desplazamiento 13 Si no se ofende faacutecilmente encuentre ydecodifice algunos de ellos

112 Capiacutetulo 8 Cadenas

Capiacutetulo 9 Estudio de Caso Juego de PalabrasEste capiacutetulo presenta un segundo estudio de caso que consiste en resolverpuzzles buscando palabras que tengan ciertas propiedades Por ejemplo sebuscaraacuten palabras cuyas letras aparezcan en orden alfabeacutetico Ademaacutes sepresentaraacute otra forma de desarrollar programas la reduccioacuten a un problemapreviamente resuelto

Leer listas de palabrasPara los ejercicios de este capiacutetulo se necesita una lista de palabras en espantildeolHay muchas listas de palabras disponibles en la Web pero la maacutes adecuada paranuestro propoacutesito es una de las listas de palabras recopiladas y contribuidas aldominio puacuteblico por Ismael Olea (see httpoleaorgproyectoslemarios) Estalista de 87900 palabras se encuentra en la paacutegina de Olea con el nombre dearchivo lemario-general-del-espanoltxt Tambieacuten es posible descargar una copiadesde httpsgithubcomJuliaIntroIntroAJuliajlblobmasterdatapalabrastxt

Este archivo es un archivo de texto simple por lo que puede ser abierto con uneditor de texto o leiacutedo con Julia La funcioacuten integrada open toma el nombre delarchivo como paraacutemetro y devuelve un objeto archivo que puede ser usado parala lectura del archivo

IOStream(ltfilehometravisbuildJuliaIntroIntroAJuliajlsrcdatapalabrastxtgt)

juliagt fin = open(palabrastxt)IOStream(ltfile palabrastxtgt)

fin es un objeto archivo que puede ser utilizado como entrada y cuando se dejade utilizar debe cerrarse con close(fin)

Julia tiene integradas varias funciones de lectura entre ellas readline que lee loscaracteres del archivo hasta que llega a un salto de liacutenea devolviendo elresultado como una cadena

juliagt readline(fin)a

La primera palabra en esta lista particular es a que indica direccioacuten intervalode tiempo finalidad entre otros

El objeto archivo lleva registro de doacutende quedoacute por uacuteltima vez por lo que sillama a readline nuevamente se obtendraacute la siguiente palabra

Leer listas de palabras 113

juliagt readline(fin)a-

La siguiente palabra es a- que es un prefijo que indica privacioacuten

Tambieacuten se puede usar un archivo como parte de un bucle for El siguienteprograma lee palabrastxt e imprime cada palabra una por liacutenea

for line in eachline(palabrastxt) println(line)end

Ejercicios

Ejercicio 9-1

Escriba un programa que lea palabrastxt e imprima solo las palabras con maacutes de20 caracteres (sin contar espacios en blanco)

Ejercicio 9-2

En 1927 Enrique Jardiel Poncela publicoacute cinco historias cortas omitiendo encada una de ellas una vocal Estas historias incluyen El Chofer Nuevonarracioacuten escrita sin la letra a y Un marido sin vocacioacuten sin la letra e Dadoque la letra e es la maacutes frecuente del espantildeol esto no es faacutecil de lograr

De hecho es difiacutecil pensar oraciones que no utilicen esta letra Intentarlo escomplicado pero con la praacutectica se vuelve maacutes faacutecil

Bueno volviendo al tema importante

Escriba una funcioacuten llamada notiene_e que devuelva true si una palabra dada notiene la letra e

Modifique su programa de la seccioacuten anterior para que imprima solo las palabrasque no tienen e y que ademaacutes calcule el porcentaje de palabras en la lista queno tengan e

Ejercicio 9-3

Escriba una funcioacuten llamada evitar que tome como argumentos una palabra yuna cadena de letras prohibidas y que devuelva true si la palabra no usaninguna de las letras prohibidas

Modifique su programa de la seccioacuten anterior para solicitar al usuario queingrese una cadena de letras prohibidas y que luego imprima el nuacutemero de

114 Capiacutetulo 9 Estudio de Caso Juego de Palabras

palabras que no contengan ninguna de ellas iquestEs posible encontrar unacombinacioacuten de 5 letras prohibidas que excluya la menor cantidad de palabras

Ejercicio 9-4

Escriba una funcioacuten llamada usasolo que tome una palabra y una cadena deletras y que devuelva true si la palabra contiene solo letras de la lista iquestPuedehacer una oracioacuten usando solo las letras oneacmil Aparte de iquestEl camino

Ejercicio 9-5

Escriba una funcioacuten llamada usatodo que tome una palabra y una cadena deletras y que devuelva true si la palabra usa todas las letras requeridas al menosuna vez iquestCuaacutentas palabras usan todas las vocales aeiou

Ejercicio 9-6

Escriba una funcioacuten llamada esabecedaria que devuelva true si las letras de unapalabra aparecen en orden alfabeacutetico iquestCuaacutentas palabras de este tipo hay

BuacutesquedaTodos los ejercicios en la seccioacuten anterior tienen algo en comuacuten se puedenresolver con el patroacuten de buacutesqueda El ejemplo maacutes simple es

function notiene_e(palabra) for letra in palabra if letra == e return false end end trueend

El bucle for recorre los caracteres de palabra Si encontramos la letra e puededevolver inmediatamente false de lo contrario hay que pasar a la siguiente letraSi se sale del bucle normalmente eso significa que no se encontroacute una e por loque la funcioacuten devuelve true

Esta funcioacuten podriacutea ser escrita de manera maacutes concisa usando el operador notin(notin TAB) pero se comienza con esta versioacuten porque muestra la loacutegica delpatroacuten de buacutesqueda

evita es una versioacuten maacutes general de notiene_e pero tiene la misma estructura

Buacutesqueda 115

function evita(palabra prohibidas) for letra in palabra if letter isin prohibidas return false end end trueend

Se devuelve false tan pronto como se encuentre una letra prohibida si llegamosal final del ciclo se devuelve true

usasolo es similar excepto que el sentido de la condicioacuten se invierte

function usasolo(palabra disponibles) for letra in palabra if letra notin disponibles return false end end trueend

En vez de un conjunto de letras prohibidas se tiene un conjunto de letrasdisponibles Si se encuentra una letra en palabra que no estaacute en disponible sedevuelve false

usatodo es similar excepto que se invierte el papel de la palabra y la cadena deletras

function usatodo(palabra requeridas) for letra in requeridas if letra notin palabra return false end end trueend

En lugar de recorrer las letras de la palabra el bucle recorre las letrasrequeridas Si alguna de las letras requeridas no aparece en la palabra sedevuelve false

Si se pensara como un informaacutetico se reconoceriacutea que usatodo es una instanciade un problema previamente resuelto y se podriacutea haber escrito

116 Capiacutetulo 9 Estudio de Caso Juego de Palabras

function usatodo(palabra requeridas) usasolo(requeridas palabra)end

Este es un ejemplo de una forma de desarrollar programas llamada reduccioacuten aun problema resuelto previamente lo que significa que se reconoce el problemaen el que se estaacute trabajando como una instancia de un problema ya resuelto y seaplica la solucioacuten existente

Bucle con iacutendicesLas funciones de la seccioacuten anterior fueron escritas con ciclos for porque solo senecesitaban los caracteres en las cadenas y no hubo necesidad de trabajar conlos iacutendices

Para esabecedaria tenemos que comparar letras adyacentes lo cual es un pococomplicado con un ciclo for

function esabecedaria(palabra) i = firstindex(palabra) previa = palabra[i] j = nextind(palabra i) for c in palabra[jend] if c lt previa return false end previa = c end trueend

Otra alternativa es usar recursividad

function esabecedaria(palabra) if length(palabra) lt= 1 return true end i = firstindex(palabra) j = nextind(palabra i) if palabra[i] gt palabra[j] return false end esabecedaria(palabra[jend])end

Una tercera opcioacuten es usar un ciclo while

Bucle con iacutendices 117

function esabecedaria(palabra) i = firstindex(palabra) j = nextind(palabra 1) while j lt= sizeof(palabra) if palabra[j] lt palabra[i] return false end i = j j = nextind(palabra i) end trueend

El ciclo comienza en i=1 y j=nextind(palabra 1) y termina cuandojgtsizeof(palabra) En cada iteracioacuten se compara el caraacutecter ieacutesimo (que sepuede considerar como el caraacutecter actual) con el caraacutecter jeacutesimo (que se puedeconsiderar como el siguiente)

Si el siguiente caraacutecter es menor (va antes en el alfabeto) que el actual entoncesla palabra no tiene sus letras en orden alfabeacutetico y se devuelve false

Si se llega al final del ciclo sin encontrar letras que imposibiliten el ordenalfabeacutetico entonces la palabra pasa la prueba Para convencerse de que el ciclotermina correctamente considere como ejemplo la palabra Abel

A continuacioacuten se muestra una versioacuten de espalindromo que usa dos iacutendices unocomienza al principio de la palabra y aumenta su valor y el otro comienza al finaly disminuye su valor

function espalindromo(palabra) i = firstindex(palabra) j = lastindex(palabra) while iltj if palabra[i] = palabra[j] return false end i = nextind(palabra i) j = prevind(palabra j) end trueend

O podriacuteamos reducir este problema a uno previamente resuelto y escribir

118 Capiacutetulo 9 Estudio de Caso Juego de Palabras

function espalindromo(palabra) isreverse(palabra palabra)end

Usando esreverso de Seccioacuten 813

DepuracioacutenComprobar el correcto funcionamiento de los programas es difiacutecil Las funcionesde este capiacutetulo son relativamente faacuteciles de probar porque se pueden verificarlos resultados a mano Aun asiacute es casi imposible elegir un conjunto de palabrasque permitan evaluar todos los posibles errores

Tomando notiene_e como ejemplo hay dos casos obvios que verificar laspalabras que tienen una e deberiacutean devolver false y las palabras que nodeberiacutean devolver true No deberiacutean haber problemas para encontrar un ejemplode cada uno

Dentro de cada caso hay algunos subcasos menos obvios Entre las palabras quetienen una e se deben probar las palabras con una e al principio al final y almedio Ademaacutes se deben probar palabras largas cortas y muy cortas como unacadena vaciacutea La cadena vaciacutea es un ejemplo de un caso especial no obviodonde pueden originarse errores

Ademaacutes de las instancias de prueba generadas tambieacuten puede probar suprograma con una lista de palabras como palabrastxt Al escanear el resultadoes posible que pueda detectar errores pero tenga cuidado puede detectar untipo de error (palabras que no deberiacutean incluirse pero lo estaacuten) y no otro(palabras que deberiacutean incluirse pero no lo estaacuten)

Por lo general las pruebas pueden ayudarlo a encontrar errores pero no es faacutecilgenerar un buen conjunto de instancias de prueba e incluso si lo hace no puedeestar seguro de que su programa sea correcto Seguacuten un informaacutetico muyfamoso

Las pruebas de programa se pueden usar para mostrar la presencia deerrores iexclpero nunca para mostrar su ausencia

mdash Edsger W Dijkstra

Glosarioobjeto archivo o file stream

Un valor que representa un archivo abierto

Depuracioacuten 119

reduccioacuten a un problema previamente resueltoUna manera de resolver un problema expresaacutendolo como una instancia deun problema previamente resuelto

caso especialUna instancia de prueba que es atiacutepica o no obvia (y por lo tanto menosprobable que se maneje correctamente)

Ejercicios

Ejercicio 9-7

Esta pregunta se basa en un Puzzle que se transmitioacute en el programa de radioCar Talk (httpswwwcartalkcompuzzlerbrowse)

Se tiene una secuencia de nuacutemeros y se desea saber cuaacutel es el siguiente Losnuacutemeros son 4 6 12 18 30 42 60 y luego X

Pista 1 Todos los nuacutemeros de la secuencia son pares Pista 2 El nuacutemero queva despueacutes del que estoy buscando es 102

iquestCuaacutel es el nuacutemero

Primero piense el patroacuten que busca y luego escriba un programa que le permitaencontrar el nuacutemero que sigue este patroacuten que se encuentra entre 60 y 102

Ejercicio 9-8

A continuacioacuten se muestra otro puzzle de Car Talk (httpswwwcartalkcompuzzlerbrowse)

120 Capiacutetulo 9 Estudio de Caso Juego de Palabras

Estaba conduciendo por la autopista el otro diacutea y vi mi odoacutemetro Como lamayoriacutea de los odoacutemetros muestra seis diacutegitos y solo en kiloacutemetros enterosEntonces si mi automoacutevil tuviera un kilometraje de 300000 por ejemploseriacutea 3-0-0-0-0-0

Ahora lo que vi ese diacutea fue muy interesante Noteacute que los uacuteltimos 4 diacutegitoseran palindroacutemicos es decir se leiacutean igual hacia adelante que hacia atraacutesPor ejemplo 5-4-4-5 es un paliacutendromo por lo que mi odoacutemetro podriacuteahaberse leiacutedo 3-1-5-4-4-5

Un kiloacutemetro despueacutes los uacuteltimos 5 nuacutemeros fueron palindroacutemicos Porejemplo podriacutea haberse leiacutedo 3-6-5-4-5-6 Un kiloacutemetro despueacutes de eso los 4nuacutemeros del medio eran palindroacutemicos iquestYhellip estaacutes listo para esto iexclUnkiloacutemetro despueacutes los 6 eran palindroacutemicos

La pregunta es iquestqueacute nuacutemero estaba en el odoacutemetro cuando mireacute porprimera vez

Escriba un programa de Julia que pruebe todos los nuacutemeros de seis diacutegitos eimprima cualquier nuacutemero que satisfaga estos requisitos

Ejercicio 9-9

Aquiacute hay otro puzzle de Car Talk que puede resolver con una buacutesqueda(httpswwwcartalkcompuzzlerbrowse)

Hace poco visiteacute a mi madre y nos dimos cuenta de que los dos diacutegitos quecomponen mi edad cuando se invertiacutean daban como resultado su edad Porejemplo si tiene 73 antildeos yo tengo 37 Nos preguntamos con queacute frecuenciaesto ha sucedido a lo largo de los antildeos pero nos desviamos de otros temas ynunca obtuvimos una respuesta

Cuando llegueacute a casa descubriacute que los diacutegitos de nuestras edades han sidoreversibles seis veces hasta ahora Tambieacuten descubriacute que si teniacuteamos suertevolveriacutea a suceder en unos antildeos y si tenemos mucha suerte sucederiacutea unavez maacutes despueacutes de eso En otras palabras habriacutea sucedido 8 vecesEntonces la pregunta es iquestcuaacutentos antildeos tengo ahora

Escriba un programa de Julia que busque soluciones para este puzzle

OBSERVACIOacuteN Puede encontrar la funcioacuten lpad uacutetil

Ejercicios 121

Capiacutetulo 10 ArreglosEste capiacutetulo presenta uno de los tipos maacutes uacutetiles de Julia los arreglos Tambieacutense trataraacuten objetos y lo que puede suceder cuando se tiene maacutes de un nombrepara el mismo objeto

Un arreglo es una secuenciaAl igual que una cadena de texto un arreglo es una secuencia de valores En unacadena los valores son caracteres en un arreglo pueden ser de cualquier tipoLos valores en un arreglo se denominan elementos o a veces items

Hay varias formas de crear un nuevo arreglo la maacutes sencilla es encerrar loselementos entre corchetes ([ ])

[10 20 30 40][abadejo falsiacutea estrambote]

El primer ejemplo es un arreglo de cuatro enteros El segundo es un arreglo detres cadenas de texto Los elementos de un arreglo no tienen por queacute ser delmismo tipo El siguiente arreglo contiene una cadena un nuacutemero de puntoflotante un entero y otro arreglo

[spam 20 5 [10 20]]

Se dice que un arreglo dentro de otro arreglo estaacute anidado

Un arreglo que no contiene elementos se llama arreglo vaciacuteo y se puede crearuno con corchetes vaciacuteos []

Como es de esperar se pueden asignar valores de arreglos a variables

juliagt quesos = [Cheddar Edam Gouda]

juliagt numeros = [42 123]

juliagt vacio = []

juliagt print(quesos numeros vacio)[Cheddar Edam Gouda] [42 123] Any[]

La funcioacuten typeof se puede usar para conocer el tipo del arreglo

122 Capiacutetulo 10 Arreglos

juliagt typeof(quesos)ArrayString1juliagt typeof(numeros)ArrayInt641juliagt typeof(vacio)ArrayAny1

El tipo del arreglo se especifica entre llaves y se compone de un tipo y unnuacutemero El nuacutemero indica las dimensiones El conjunto vaciacuteo contiene valores detipo Any es decir puede contener valores de todos los tipos

Los arreglos son mutablesLa sintaxis para acceder a los elementos de un arreglo es el mismo que paraacceder a los caracteres de una cadena el operador corchete La expresioacutendentro de los corchetes especifica el iacutendice Recuerde que los iacutendices comienzanen 1

juliagt quesos[1]Cheddar

A diferencia de las cadenas los arreglos son mutables lo que significa quepodemos cambiar sus elementos Se puede modificar uno de sus elementosusando el operador corchetes en el lado izquierdo de una asignacioacuten

juliagt numeros[2] = 55juliagt print(numeros)[42 5]

El segundo elemento de numeros que era 123 ahora es 5

Figura 11 muestra los diagramas de estado para quesos numeros y vacio

Figura 11 Diagrama de estado

Los arreglos son representados mediante cuadros con elementos del arreglo en

Los arreglos son mutables 123

su interior El arreglo quesos hace referencia a un arreglo con tres elementosindexados 1 2 y 3 El arreglo numeros contiene dos elementos El diagramamuestra que el valor del segundo elemento de numeros se ha reasignado de 123a 5 Finalmente vacio hace referencia a un arreglo sin elementos

Los iacutendices de un arreglo funcionan de la misma manera que los iacutendices de unacadena (pero sin los problemas generados por la codificacioacuten UTF-8)

bull Cualquier expresioacuten entera se puede usar como iacutendice

bull Si se intenta leer o escribir un elemento que no existe se obtiene unBoundsError

bull La palabra reservada end indica el uacuteltimo iacutendice del arreglo

El operador isin tambieacuten funciona en arreglos

juliagt Edam isin quesostruejuliagt Brie in quesosfalse

Recorriendo un ArregloLa forma maacutes comuacuten de recorrer los elementos de un arreglo es con un ciclo forLa sintaxis es la misma que para las cadenas

for queso in quesos println(queso)end

Esto funciona bien si solo se necesita leer los elementos del arreglo pero si sedesea escribir o actualizar los elementos es necesario utilizar iacutendices Una formacomuacuten de hacerlo es usando la funcioacuten integrada eachindex

for i in eachindex(numeros) numeros[i] = numeros[i] 2end

Este bucle recorre el arreglo y actualiza cada elemento En cada iteracioacuten delciclo i representa el iacutendice del elemento actual La sentencia de asignacioacuten usanumeros[i] para leer el valor original del elemento y asignar el nuevo valor

Por otra parte length devuelve el nuacutemero de elementos en el arreglo

Un ciclo for sobre un arreglo vaciacuteo nunca ejecuta el cuerpo del bucle

124 Capiacutetulo 10 Arreglos

for x in [] println(Esto nunca pasa)end

Aunque un arreglo puede contener otro arreglo este arreglo anidado cuentacomo un elemento uacutenico Por ejemplo la longitud de este arreglo es cuatro

[spam 1 [Brie Roquefort Camembert] [1 2 3]]

Porciones de arreglos

El operador porcioacuten tambieacuten funciona en arreglos

juliagt t = [a b c d e f]

juliagt print(t[13])[a b c]juliagt print(t[3end])[c d e f]

El operador porcioacuten [] hace una copia de todo el arreglo

juliagt print(t[])[a b c d e f]

Como los arreglos son mutables es uacutetil hacer una copia antes de realizaroperaciones que las modifiquen

Un operador porcioacuten en el lado izquierdo de una asignacioacuten puede actualizarvarios elementos

juliagt t[23] = [x y]

juliagt print(t)[a x y d e f]

Libreriacutea de ArreglosJulia tiene funciones integradas que operan en arreglos Por ejemplo pushagrega un nuevo elemento al final de un arreglo

Porciones de arreglos 125

juliagt t = [a b c]

juliagt push(t d)

juliagt print(t)[a b c d]

append agrega elementos de un arreglo al final de otro

juliagt t1 = [a b c]

juliagt t2 = [d e]

juliagt append(t1 t2)

juliagt print(t1)[a b c d e]

En este ejemplo t2 no es modificado

sort ordena los elementos de un arreglo de menor a mayor

juliagt t = [d c e b a]

juliagt sort(t)

juliagt print(t)[a b c d e]

sort devuelve una copia ordenada de los elementos de un arreglo

juliagt t1 = [d c e b a]

juliagt t2 = sort(t1)

juliagt print(t1)[d c e b a]juliagt print(t2)[a b c d e]

NOTA Como convencioacuten en Julia se agrega a los nombres de lasfunciones que modifican sus argumentos

126 Capiacutetulo 10 Arreglos

Mapear Filtrar y ReducirPara sumar todos los nuacutemeros en un arreglo se puede usar un ciclo como este

function sumartodo(t) total = 0 for x in t total += x end totalend

total se inicializa en 0 En cada iteracioacuten con += se antildeade un elemento delarreglo a la suma total El operador += es una forma simple de actualizar estavariable Esta sentencia de asignacioacuten aumentada

total += x

es equivalente a

total = total + x

A medida que se ejecuta el ciclo total acumula la suma de los elementos A vecesse denomina acumulador a una variable utilizada de esta manera

Sumar los elementos de un arreglo es una operacioacuten tan comuacuten que Julia tieneuna funcioacuten integrada para ello sum

juliagt t = [1 2 3 4]

juliagt sum(t)10

Una operacioacuten como esta que combina una secuencia de elementos en un solovalor a veces se denomina operacioacuten de reduccioacuten

Es comuacuten querer recorrer un arreglo mientras se construye otro Por ejemplo lasiguiente funcioacuten toma un arreglo de cadenas y devuelve un nuevo arreglo quecontiene las mismas cadenas pero en mayuacutesculas

Mapear Filtrar y Reducir 127

function todoenmayusculas(t) res = [] for s in t push(res uppercase(s)) end resend

res se inicializa con un arreglo vaciacuteo y en cada iteracioacuten se le agrega un nuevoelemento De esta manera res es otro tipo de acumulador

Una operacioacuten como todoenmayusculas a veces se denomina mapeo porqueasigna una funcioacuten (en este caso uppercase) a cada uno de los elementos deuna secuencia

Otra operacioacuten comuacuten es seleccionar solo algunos de los elementos de un arregloy devolver una sub-arreglo Por ejemplo la siguiente funcioacuten toma un arreglo decadenas y devuelve un arreglo que contiene solamente las cadenas enmayuacutesculas

function solomayusculas(t) res = [] for s in t if s == uppercase(s) push(res s) end end resend

Operaciones como solomayusculas se llaman filtro porque seleccionan soloalgunos elementos filtrando otros

Las operaciones de arreglos maacutes comunes son una combinacioacuten de mapeo filtroy reduccioacuten

Sintaxis de puntoPara cada operador binario como por ejemplo ^ existe un operador puntocorrespondiente ^ que automaacuteticamente define la operacioacuten ^ para cadaelemento de un arreglo Por ejemplo [1 2 3] ^ 3 no estaacute definido pero [12 3] ^ 3 se define como el resultado de realizar la operacioacuten ^ en cadaelemento [1^3 2^3 3^3]

128 Capiacutetulo 10 Arreglos

juliagt print([1 2 3] ^ 3)[1 8 27]

Cualquier funcioacuten f de Julia puede ser aplicada a cada elemento de cualquierarreglo con la sintaxis de punto Por ejemplo para poner en mayuacutesculas unarreglo de cadenas no es necesario un bucle expliacutecito

juliagt t = uppercase([abc def ghi])

juliagt print(t)[ABC DEF GHI]

Esta es una forma elegante de crear un mapeo Siguiendo esta loacutegica la funcioacutentodoenmayusculas puede implementarse con una liacutenea

function todoenmayusculas(t) uppercase(t)end

Borrando (Insertando) ElementosHay varias formas de eliminar elementos de un arreglo Si se conoce el iacutendice delelemento que se desea eliminar se puede usar splice

juliagt t = [a b c]

juliagt splice(t 2)b ASCIIUnicode U+0062 (category Ll Letter lowercase)juliagt print(t)[a c]

splice modifica el arreglo y devuelve el elemento que se eliminoacute

pop elimina y devuelve el uacuteltimo elemento

juliagt t = [a b c]

juliagt pop(t)c ASCIIUnicode U+0063 (category Ll Letter lowercase)juliagt print(t)[a b]

popfirst elimina y devuelve el primer elemento

Borrando (Insertando) Elementos 129

juliagt t = [a b c]

juliagt popfirst(t)a ASCIIUnicode U+0061 (category Ll Letter lowercase)juliagt print(t)[b c]

Las funciones pushfirst y push insertan un elemento al principio y al final delarreglo respectivamente

Si no se necesita el valor eliminado se puede usar la funcioacuten deleteat

juliagt t = [a b c]

juliagt print(deleteat(t 2))[a c]

La funcioacuten insert inserta un elemento en un iacutendice dado

juliagt t = [a b c]

juliagt print(insert(t 2 x))[a x b c]

Arreglos y CadenasUna cadena es una secuencia de caracteres y un arreglo es una secuencia devalores pero un arreglo de caracteres no es lo mismo que una cadena Paraconvertir una cadena a un arreglo de caracteres se puede usar la funcioacutencollect

juliagt t = collect(spam)

juliagt print(t)[s p a m]

La funcioacuten collect divide una cadena u otra secuencia en elementos individuales

Si desea dividir una cadena en palabras puede usar la funcioacuten split

juliagt t = split(En un lugar de la Mancha)

juliagt print(t)SubStringString[En un lugar de la Mancha]

130 Capiacutetulo 10 Arreglos

Un argumento opcional llamado delimitador especifica queacute caracteres usar comoliacutemites de palabra El siguiente ejemplo usa un guioacuten como delimitador

juliagt t = split(hola-hola-hola -)

juliagt print(t)SubStringString[hola hola hola]

join es el inverso de split Toma un arreglo de cadenas y concatena loselementos

juliagt t = [En un lugar de la Mancha]

juliagt s = join(t )En un lugar de la Mancha

En este caso el delimitador es un caraacutecter de espacio en blanco Para concatenarcadenas sin espacios no especifique un delimitador

Objeto y ValoresUn objeto es algo a lo que una variable puede referirse Hasta ahora podriacutea usarobjeto y valor indistintamente

Si ejecutamos estas sentencias de asignacioacuten

a = bananab = banana

Se sabe que a y b apuntan a una cadena pero no se sabe si estaacuten apuntando a lamisma cadena Hay dos estados posibles los cuales se muestran en la Figura 10-2

Figura 12 Diagramas de estado

En un caso a y b se refieren a dos objetos diferentes que tienen el mismo valorEn el segundo caso se refieren al mismo objeto

Para verificar si dos variables se refieren al mismo objeto se puede usar eloperador equiv (equiv TAB)) o ===

Objeto y Valores 131

juliagt a = bananabananajuliagt b = bananabananajuliagt a equiv btrue

En este ejemplo Julia solo creoacute un objeto de cadena y ambas variables a y bapuntan a ella Pero cuando se crean dos arreglos se obtienen dos objetos

juliagt a = [1 2 3]

juliagt b = [1 2 3]

juliagt a equiv bfalse

Entonces el diagrama de estado se ve asiacute Figura 13

Figura 13 Diagrama de estado

En este caso se podriacutea decir que los dos arreglos son equivalentes porquetienen los mismos elementos pero no ideacutenticos ya que no son el mismo objetoSi dos objetos son ideacutenticos tambieacuten son equivalentes pero si son equivalentesno son necesariamente ideacutenticos

Para ser precisos un objeto tiene un valor Si se evaluacutea [1 2 3] se obtendraacute unobjeto arreglo cuyo valor es una secuencia de enteros Si otro arreglo tiene losmismos elementos se dice que tiene el mismo valor pero no es el mismo objeto

Alias (poner sobrenombres)Si a apunta a un objeto y se asigna b = a entonces ambas variables se refierenal mismo objeto

juliagt a = [1 2 3]

juliagt b = a

juliagt b equiv atrue

El diagrama de estado seriacutea como este Figura 14

132 Capiacutetulo 10 Arreglos

Figura 14 Diagrama de estado

La asociacioacuten de una variable con un objeto se llama referencia En este ejemplohay dos referencias al mismo objeto

Un objeto con maacutes de una referencia tiene maacutes de un nombre por lo quedecimos que el objeto tiene un alias

Si el objeto con alias es mutable los cambios hechos a un alias afectan al otro

juliagt b[1] = 4242juliagt print(a)[42 2 3]

AVISOAunque este comportamiento puede ser uacutetil a veces puede inducira errores En general es maacutes seguro evitar los alias cuando setrabaje con objetos mutables

No hay problema con los alias al trabajar con objetos inmutables tales comocadenas de texto En este ejemplo

a = bananab = banana

Casi nunca es relevante que a y b se refieran a la misma cadena o no

Arreglos como argumentosCuando se pasa un arreglo como argumento de una funcioacuten en realidad se pasauna referencia a ella Si la funcioacuten modifica el arreglo el que hizo la llamadaveraacute el cambio Por ejemplo la funcioacuten borrarprimero elimina el primer elementode un arreglo

function borrarprimero(t) popfirst(t)end

Aquiacute se aprecia el uso de borrarprimero

Arreglos como argumentos 133

juliagt letras = [a b c]

juliagt borrarprimero(letras)

juliagt print(letras)[b c]

El paraacutemetro t y la variable letras son alias de un mismo objeto El diagrama deestado es asiacute Figura 15

Figura 15 Diagrama de estado

Como el arreglo estaacute compartido por dos marcos se dibuja entre ambos

Es importante distinguir entre operaciones que modifiquen arreglos yoperaciones que creen nuevas arreglos Por ejemplo push modifica un arreglopero vcat crea un nuevo arreglo

Aquiacute hay un ejemplo de push

juliagt t1 = [1 2]

juliagt t2 = push(t1 3)

juliagt print(t1)[1 2 3]

t2 es un alias de t1

Aquiacute hay un ejemplo de vcat

juliagt t3 = vcat(t1 [4])

juliagt print(t1)[1 2 3]juliagt print(t3)[1 2 3 4]

El resultado de vcat es un nuevo arreglo El arreglo original no ha sufridocambios

Esta diferencia es importante al momento de escribir funciones que modificanarreglos

134 Capiacutetulo 10 Arreglos

Por ejemplo esta funcioacuten no elimina el primer elemento de un arrreglo

function noborrarprimero(t) t = t[2end] MALOend

El operador porcioacuten crea un nuevo arreglo y la asignacioacuten hace que t se refiera aella pero eso no afecta al arreglo t fuera de la funcioacuten

juliagt t4 = noborrarprimero(t3)

juliagt print(t3)[1 2 3 4]juliagt print(t4)[2 3 4]

Al comienzo de noborrarprimero t y t3 se refieren al mismo arreglo Al final t serefiere a un nuevo arreglo pero t3 todaviacutea se refiere al arreglo original nomodificado

Una alternativa es escribir una funcioacuten que cree y devuelva un nuevo arregloPor ejemplo la funcioacuten cola devuelve todos menos el primer elemento de unarreglo

function cola(t) t[2end]end

Esta funcioacuten no modifica el arreglo original y se usa de la siguiente manera

juliagt letras = [a b c]

juliagt demas = cola(letras)

juliagt print(demas)[b c]

DepuracioacutenUn uso inadecuado de los arreglos (y otros objetos mutables) puede llevar alargas horas de depuracioacuten A continuacioacuten se muestran algunos errorescomunes y coacutemo evitarlos

bull La mayoriacutea de las funciones que operan en arreglos modifican el argumentoEsto es lo opuesto a lo que ocurre en las funciones que operan en cadenas

Depuracioacuten 135

de texto que devuelven una nueva cadena y dejan la original sinmodificaciones

Si estaacute acostumbrado a escribir coacutedigo con cadenas de texto como este

nueva_palabra = strip(palabra)

Puede parecer tentador escribir coacutedigo con arreglos como este

t2 = sort(t1)

Pero como sort devuelve el arreglo original t1 modificado t2 es un alias det1

OBSERVACIOacuteN

Antes de utilizar funciones y operadores dearreglos debe leer la documentacioacutendetenidamente y luego probarla en modointeractivo

bull Escoja una expresioacuten y queacutedese con ella

Parte del problema con los arreglos es que hay demasiadas formas de hacerlas cosas Por ejemplo para eliminar un elemento de un arreglo se puedeusar pop popfirst delete_at o incluso una asignacioacuten de porcioacuten Paraagregar un elemento se puede usar push pushfirst insert or vcatSuponiendo que t es un arreglo y x es un elemento estas formas soncorrectas

insert(t 4 x)push(t x)append(t [x])

Y estas incorrectas

insert(t 4 [x]) MALOpush(t [x]) MALOvcat(t [x]) MALO

bull Haga copias para evitar usar alias

Si se desea utilizar una funcioacuten como sort que modifica el argumento perotambieacuten se necesita mantener el arreglo original es posible hacer unacopia

136 Capiacutetulo 10 Arreglos

juliagt t = [3 1 2]

juliagt t2 = t[] t2 = copy(t)

juliagt sort(t2)

juliagt print(t)[3 1 2]juliagt print(t2)[1 2 3]

En este ejemplo tambieacuten podriacutea usar la funcioacuten incorporada sort quedevuelve un nuevo arreglo ordenado y no modifica el original

juliagt t2 = sort(t)

juliagt println(t)[3 1 2]juliagt println(t2)[1 2 3]

Glosarioarreglo

Una secuencia de valores

elementoUno de los valores de un arreglo (u otra secuencia) tambieacuten llamado iacutetem

lista anidadaUn arreglo que es elemento de otro arreglo

acumuladorUna variable utilizada en un ciclo para sumar o acumular un resultado

asignacioacuten aumentadaUna sentencia que actualiza el valor de una variable usando un operadorcomo +=

operador puntoOperador binario que se aplica a cada elemento de un arreglo

Glosario 137

sintaxis de puntoSintaxis utilizada para aplicar una funcioacuten a todos los elementos decualquier arreglo

operacioacuten de reduccioacutenUn patroacuten de procesamiento que recorre una secuencia y acumula loselementos en un solo resultado

mapeoUn patroacuten de procesamiento que recorre una secuencia y realiza unaoperacioacuten en cada elemento

filtroUn patroacuten de procesamiento que recorre una secuencia y selecciona loselementos que satisfacen alguacuten criterio

objetoUna cosa a la que se puede referir una variable Un objeto tiene tipo y valor

equivalenteTener el mismo valor

ideacutenticoSer el mismo objeto (lo que implica equivalencia)

referenciaLa asociacioacuten entre una variable y su valor

aliasMuacuteltiples variables que contienen referencias al mismo objeto

argumentos opcionalesArgumentos que no son necesarios

delimitadorUn caraacutecter o cadena utilizado para indicar donde debe cortarse unacadena

Ejercicios

estaordenada (generic function with 1 method)

138 Capiacutetulo 10 Arreglos

Ejercicio 10-1

Escriba una funcioacuten llamada sumaanidada que tome un arreglo de arreglos deenteros y sume los elementos de todos los arreglos anidados Por ejemplo

juliagt t = [[1 2] [3] [4 5 6]]

juliagt sumaanidada(t)21

Ejercicio 10-2

Escriba una funcioacuten llamada sumaacumulada que tome un arreglo de nuacutemeros ydevuelva la suma acumulativa es decir un nuevo arreglo donde el eacutesimoelemento es la suma de los primeros elementos del arreglo original Porejemplo

juliagt t = [1 2 3]

juliagt print(sumaacumulada(t))Any[1 3 6]

Ejercicio 10-3

Escriba una funcioacuten llamada interior que tome un arreglo y devuelva un nuevoarreglo que contenga todos los elementos excepto el primero y el uacuteltimo Porejemplo

juliagt t = [1 2 3 4]

juliagt print(interior(t))[2 3]

Ejercicio 10-4

Escriba una funcioacuten llamada interior que tome un arreglo lo modifiqueeliminando el primer y el uacuteltimo elemento y que no devuelva un valor Porejemplo

Ejercicios 139

juliagt t = [1 2 3 4]

juliagt interior(t)

juliagt print(t)[2 3]

Ejercicio 10-5

Escriba una funcioacuten llamada estaordenada que tome un arreglo como paraacutemetroy devuelva true si el arreglo se ordena en orden ascendente y false de locontrario Por ejemplo

juliagt estaordenada([1 2 2])truejuliagt estaordenada([b a])false

Ejercicio 10-6

Dos palabras son anagramas si se pueden ordenar las letras de una para escribirla otra Escriba una funcioacuten llamada esanagrama que tome dos cadenas ydevuelva true si son anagramas

Ejercicio 10-7

Escriba una funcioacuten llamada repetido que tome un arreglo y devuelva true si hayalguacuten elemento que aparece maacutes de una vez No debe modificar el arreglooriginal

Ejercicio 10-8

Este ejercicio se relaciona con la llamada paradoja del cumpleantildeos sobre la cualpuede leer en httpseswikipediaorgwikiParadoja_del_cumpleaC3B1os

Si hay 23 estudiantes en su clase iquestcuaacuteles son las posibilidades de que dos deustedes tengan el mismo cumpleantildeos Puede estimar esta probabilidadgenerando muestras aleatorias de 23 cumpleantildeos y buscando coincidencias

OBSERVACIOacuteN Puede generar cumpleantildeos aleatorios con rand(1365)

Ejercicio 10-9

Escriba una funcioacuten que lea el archivo palabrastxt y construya un arreglo con unelemento por palabra Escriba dos versiones de esta funcioacuten una con push y la

140 Capiacutetulo 10 Arreglos

otra con la expresioacuten t = [t x] iquestCuaacutel tarda maacutes en ejecutarse iquestPor queacute

Ejercicio 10-10

Para verificar si una palabra estaacute en el arreglo de palabras se puede usar eloperador isin Esto seriacutea lento pues este operador busca las palabras en orden

Debido a que las palabras estaacuten en orden alfabeacutetico se puede acelerar laverificacioacuten con una buacutesqueda de biseccioacuten (tambieacuten conocida como buacutesquedabinaria) que es similar a lo que se hace cuando se busca una palabra en eldiccionario Se comienza en el medio y se verifica si la palabra que se estaacutebuscando va antes que la palabra localizada en el medio Si es asiacute se busca en laprimera mitad de la matriz de la misma manera De lo contrario se busca en lasegunda mitad

En ambos casos se reduce el espacio de buacutesqueda restante a la mitad Si elarreglo de palabras tiene 113809 palabras se necesitaraacuten unos 17 pasos paraencontrar la palabra o concluir que no estaacute alliacute

Escriba una funcioacuten llamada enbiseccion que tome un arreglo ordenado y unvalor objetivo y devuelva true si la palabra estaacute en el arreglo y false si no lo estaacute

Ejercicio 10-11

Dos palabras son un par inverso si cada una es la inversa de la otra Escriba unprograma llamado parinverso que encuentre todos los pares inversos en elarreglo de palabras

Ejercicio 10-12

Dos palabras se entrelazan si al tomar letras alternando entre cada palabra seforma una nueva palabra Por ejemplo pi y as se entrelazan para formarpais

Creacutedito Este ejercicio estaacute inspirado en un ejemplo de httppuzzlersorg

1 Escriba un programa que encuentre todos los pares de palabras que seentrelazan

OBSERVACIOacuteN iexclNo enumere todos los pares

2 iquestPuede encontrar tres palabras que se entrelacen es decir cada terceraletra forma una palabra empezando de la primera segunda o tercera letrade la palabra

Ejercicios 141

Capiacutetulo 11 DiccionariosEste capiacutetulo presenta otro tipo integrado llamado diccionario

Un Diccionario es un MapeoUn diccionario es como una matriz pero maacutes general En una matriz los iacutendicestienen que ser enteros en un diccionario pueden ser (casi) de cualquier tipo

Un diccionario contiene una coleccioacuten de iacutendices llamados claves y unacoleccioacuten de valores Cada clave estaacute asociada a un solo valor La asociacioacutenentre una clave y un valor se denomina par clave-valor o a veces item

En lenguaje matemaacutetico un diccionario representa un mapeo de las claves a losvalores es decir cada clave apunta a un valor A modo de ejemplo se crea undiccionario que asocia palabras en espantildeol con palabras en ingleacutes En estediccionario las claves y los valores son cadenas

La funcioacuten Dict crea un nuevo diccionario sin elementos Como Dict es el nombrede una funcioacuten integrada de Julia debe evitar usarla como nombre de variable

juliagt ing_a_esp = Dict()DictAnyAny()

El tipo de este diccionario estaacute compuesto por el tipo de las claves y de losvalores entre llaves En este caso las claves y los valores son de tipo Any

El diccionario estaacute vaciacuteo Para agregar elementos a eacutel se pueden usar corchetes

juliagt ing_a_esp[one] = uno

Esta liacutenea de coacutedigo crea un elemento con la clave one que apunta al valoruno Si se imprime el diccionario nuevamente se ve un par clave-valor con unaflecha =gt entre la clave y el valor

juliagt ing_a_espDictAnyAny with 1 entry one =gt uno

Este formato de salida tambieacuten es un formato de entrada Por ejemplo se puedecrear un nuevo diccionario con tres iacutetems de la siguiente manera

142 Capiacutetulo 11 Diccionarios

juliagt ing_a_esp = Dict(one =gt uno two =gt dos three =gt tres)DictStringString with 3 entries two =gt dos one =gt uno three =gt tres

Todas las claves y valores iniciales son cadenas por lo que se crea unDictStringString

AVISO

El orden de los pares clave-valor podriacutea no ser el mismo Siescribe el mismo ejemplo en su computadora podriacutea obtener unresultado diferente En general el orden de los elementos en undiccionario es impredecible

Esto no significa un problema ya que los elementos de un diccionario nunca seindexan con iacutendices enteros En lugar de ello se utilizan las claves para buscarlos valores correspondientes

juliagt ing_a_esp[two]dos

La clave two da el valor dos asiacute que el orden de los iacutetems no importa

Si la clave no estaacute en el diccionario se da un mensaje de error

juliagt ing_a_esp[four]ERROR KeyError key four not found

La funcioacuten length tambieacuten funciona con diccionarios y devuelve el nuacutemero depares clave-valor

juliagt length(ing_a_esp)3

La funcioacuten keys devuelve una coleccioacuten con las claves del diccionario

juliagt ks = keys(ing_a_esp)

juliagt print(ks)[two one three]

Tambieacuten se puede usar el operador isin para ver si algo es una clave en undiccionario

Un Diccionario es un Mapeo 143

juliagt one isin kstruejuliagt uno isin ksfalse

Para ver si algo es un valor en un diccionario se puede usar la funcioacuten valuesque devuelve una coleccioacuten de valores y luego usar el operador isin

juliagt vs = values(ing_a_esp)

juliagt uno isin vstrue

El operador isin utiliza diferentes algoritmos para matrices y diccionarios Para lasmatrices busca los elementos de la matriz en orden como en Seccioacuten 88 Eltiempo de buacutesqueda es directamente proporcional al largo de la matriz

Para los diccionarios Julia usa un algoritmo llamado tabla hash que tiene unapropiedad importante el operador isin toma aproximadamente la misma cantidadde tiempo sin importar cuaacutentos elementos haya en el diccionario

Diccionario como una Coleccioacuten de FrecuenciasSuponga que tiene una cadena y desea contar cuaacutentas veces aparece cada letraHay varias formas de hacerlo

bull Podriacutea crear 27 variables una para cada letra del alfabeto Luego recorrerla cadena y para cada caraacutecter incrementar el contador correspondienteprobablemente utilizando condiciones encadenadas

bull Podriacutea crear una matriz con 27 elementos Luego podriacutea convertir cadacaraacutecter en un nuacutemero (usando la funcioacuten integrada Int) usar el nuacutemerocomo iacutendice en la matriz e incrementar el contador apropiado

bull Puede crear un diccionario con caracteres como claves y contadores comolos valores correspondientes La primera vez que vea un caraacutecter agregariacuteaun elemento al diccionario Despueacutes de eso incrementariacutea el valor de unelemento existente

Cada una de estas opciones realiza el mismo caacutelculo pero la implementacioacuten esdiferente

Una implementacioacuten es una forma de realizar un caacutelculo Algunasimplementaciones son mejores que otras por ejemplo una ventaja de laimplementacioacuten del diccionario es que no hace falta saber de antemano queacuteletras aparecen en la cadena y solo hay que agregar las letras que aparecen

144 Capiacutetulo 11 Diccionarios

Asiacute es como se veriacutea el coacutedigo

function histograma(s) d = Dict() for c in s if c notin keys(d) d[c] = 1 else d[c] += 1 end end dend

La funcioacuten se llama histograma que es un teacutermino en estadiacutestica para unacoleccioacuten de frecuencias (o conteos)

La primera liacutenea de la funcioacuten crea un diccionario vaciacuteo El ciclo for recorre lacadena s En cada iteracioacuten de este ciclo si el caraacutecter c no estaacute en eldiccionario se crea un nuevo elemento con la clave c y el valor inicial 1 (ya quehemos visto esta letra una vez) Si c ya estaacute en el diccionario se incrementa d[c]

Asiacute es como funciona

juliagt h = histograma(brontosaurus)DictAnyAny with 8 entries n =gt 1 s =gt 2 a =gt 1 r =gt 2 t =gt 1 o =gt 2 u =gt 2 b =gt 1

El histograma indica que las letras a y b aparecen una vez o aparece dosveces y asiacute sucesivamente

Los diccionarios tienen una funcioacuten llamada get que toma como argumentos undiccionario una clave y un valor predeterminado Si la clave aparece en eldiccionario get devuelve el valor correspondiente de lo contrario devuelve elvalor predeterminado Por ejemplo

Diccionario como una Coleccioacuten de Frecuencias 145

juliagt h = histograma(a)DictAnyAny with 1 entry a =gt 1juliagt get(h a 0)1juliagt get(h b 0)0

Ejercicio 11-1

Use get para escribir la funcioacuten histograma de manera maacutes concisa Deberiacuteapoder eliminar la declaracioacuten if

Iteracioacuten y DiccionariosEs posible recorrer las claves del diccionario con un ciclo for Por ejemploimprimirhist imprime cada clave y su valor correspondiente

function imprimirhist(h) for c in keys(h) println(c h[c]) endend

Asiacute es como se ve la salida

juliagt h = histograma(perros)

juliagt imprimirhist(h)s 1e 1p 1r 2o 1

Nuevamente las claves no estaacuten en un orden particular Para recorrer las clavesen orden puede usar sort y collect

146 Capiacutetulo 11 Diccionarios

juliagt for c in sort(collect(keys(h))) println(c h[c]) ende 1o 1p 1r 2s 1

Buacutesqueda inversaDado un diccionario d y una clave k es faacutecil encontrar el valor correspondiente v= d[k] Esta operacioacuten se llama buacutesqueda

Pero iquestqueacute pasa si se tiene v y se quiere encontrar k Existen dos problemasprimeramente puede haber maacutes de una clave que apunta al valor v Dependiendode lo que se quiera es posible que se pueda elegir una de estas claves o que setenga que hacer una matriz que las contenga a todas En segundo lugar no hayuna sintaxis simple para hacer una buacutesqueda inversa solo se debe buscar

A continuacioacuten se muestra una funcioacuten que toma un valor y que devuelve laprimera clave que apunta a ese valor

function busquedainversa(d v) for k in keys(d) if d[k] == v return k end end error(Error de Busqueda)end

Esta funcioacuten es otro ejemplo del patroacuten de buacutesqueda pero utiliza una funcioacutenque no hemos visto antes error La funcioacuten error se usa para producir unErrorException que interrumpe el flujo normal En este caso tiene el mensajeError de Busqueda que indica que no existe una clave

Si llega al final del ciclo eso significa que v no aparece en el diccionario como unvalor por lo que se produce una excepcioacuten

A continuacioacuten se muestra un ejemplo de una buacutesqueda inversa exitosa

juliagt h = histograma(perros)

juliagt key = busquedainversa(h 2)r ASCIIUnicode U+0072 (category Ll Letter lowercase)

Buacutesqueda inversa 147

y una no exitosa

juliagt key = busquedainversa(h 3)ERROR Error de Busqueda

El efecto cuando generamos una excepcioacuten es el mismo que cuando Julia generauna se imprime un trazado inverso y un mensaje de error

Julia proporciona una forma optimizada de hacer una buacutesqueda inversafindall(isequal(3)h)

AVISO

Una buacutesqueda inversa es mucho maacutes lenta que una buacutesquedadirecta Si tiene que hacer buacutesquedas inversas con frecuencia o siel diccionario es muy grande el rendimiento de su programa severaacute afectado

Diccionarios y MatricesLas matrices pueden aparecer como valores en un diccionario Por ejemplo si setiene un diccionario que asigna frecuencias a letras y se quiere invertir es decirtener un diccionario que asigne letras a frecuencias Dado que pueden habervarias letras con la misma frecuencia cada valor en el diccionario invertidodeberiacutea ser una matriz de letras

Aquiacute hay una funcioacuten que invierte un diccionario

function invertirdic(d) inverso = Dict() for clave in keys(d) val = d[clave] if val notin keys(inverso) inverso[val] = [clave] else push(inverso[val] clave) end end inversoend

Cada vez que se recorre el bucle se asigna a la variable clave una clave de d y aval el valor correspondiente Si val no estaacute en el diccionario inverso significa queno se ha visto este valor antes por lo que se crea un nuevo item y se inicializacon un singleton (una matriz que contiene un solo elemento) De lo contrario seha visto este valor antes por lo que se agrega la clave correspondiente a lamatriz

148 Capiacutetulo 11 Diccionarios

Aquiacute hay un ejemplo

juliagt hist = histograma(perros)

juliagt inverso = invertirdic(hist)DictAnyAny with 2 entries 2 =gt [r] 1 =gt [s e p o]

Figura 16 Diagrama de estado

Figura 16 es un diagrama de estado que muestra hist e inverso Un diccionariose representa como un cuadro con los pares clave-valor dentro En este libro silos valores son enteros nuacutemeros de punto flotante o cadenas de texto se dibujandentro del cuadro y las matrices (generalmente) se dibujan fuera del cuadrosolo para mantener el diagrama simple

NOTA

Anteriormente se mencionoacute que un diccionario se implementausando una tabla hash (tambieacuten llamada matriz asociativahashing mapa hash tabla de dispersioacuten o tabla fragmentada) locual significa que las claves deben ser hashable

Un hash es una funcioacuten que toma un valor (de cualquier tipo) ydevuelve un entero Los diccionarios usan estos enteros llamadosvalores hash para almacenar y buscar pares clave-valor

PistasSi estuvo jugando con la funcioacuten fibonacci de Seccioacuten 67 es posible que hayanotado que cuanto maacutes grande el argumento que le da maacutes tiempo tarda lafuncioacuten en ejecutarse Maacutes auacuten el tiempo de ejecucioacuten aumenta muyraacutepidamente

Para entender por queacute considere Figura 17 que muestra el graacutefico de llamadaspara la funcioacuten fibonacci con n = 4

Pistas 149

Figura 17 Graacutefico de llamadas

Un graacutefico de llamadas muestra un conjunto de cuadros de funciones con liacuteneasque conectan cada cuadro con los cuadros de las funciones a las que llama En laparte superior del graacutefico fibonacci con n = 4 llama a fibonacci con n = 3 y n =2 A su vez fibonacci con n = 3 llama a fibonacci con n = 2 y n = 1 Y asiacutesucesivamente

Cuente cuaacutentas veces se llama a fibonacci(0) y fibonacci(1) Esta es una solucioacutenineficiente al problema y empeora a medida que el argumento aumenta entamantildeo

Una solucioacuten es llevar un registro de los valores que ya se han calculadoalmacenaacutendolos en un diccionario Un valor que ya ha sido calculado yalmacenado para un uso posterior se le denomina pista Aquiacute hay unaimplementacioacuten de fibonacci con pistas

anteriores = Dict(0=gt0 1=gt1)

function fibonacci(n) if n isin keys(anteriores) return anteriores[n] end res = fibonacci(n-1) + fibonacci(n-2) anteriores[n] = res resend

El diccionario llamado anteriores mantiene un registro de los valores deFibonacci que ya conocemos El programa comienza con dos pares 0corresponde a 1 y 1 corresponde a 1

Siempre que se llama a fibonacci se comprueba si el diccionario contiene elresultado ya calculado Si estaacute ahiacute la funcioacuten puede devolver el valorinmediatamente Si no tiene que calcular el nuevo valor antildeadirlo al diccionario ydevolverlo

150 Capiacutetulo 11 Diccionarios

Si ejecuta esta versioacuten de fibonacci y la compara con la original se daraacute cuentaque es mucho maacutes raacutepida

Variables GlobalesEn el ejemplo anterior el diccionario anteriores se crea fuera de la funcioacuten porlo que pertenece al marco especial llamado Main Las variables en Main a vecesson llamadas globales porque se puede acceder a ellas desde cualquier funcioacutenA diferencia de las variables locales que desaparecen cuando finaliza su funcioacutenlas variables globales existen de una llamada de funcioacuten a la siguiente

Es comuacuten usar variables globales como flags o banderas es decir variablesbooleanas que indican si una condicioacuten es verdadera Por ejemplo algunosprogramas usan una bandera llamada verbosa para controlar el nivel de detalleen la salida

verbose = true

function ejemplo1() if verbosa println(Ejecutando ejemplo1) endend

Si intenta reasignar una variable global se sorprenderaacute El siguiente ejemplotrata de llevar registro sobre si se ha llamado o no a una funcioacuten

ha_sido_llamada = false

function ejemplo2() ha_sido_llamada = true MALOend

Pero si lo ejecuta veraacute que el valor de ha_sido_llamada no cambia El problemaes que ejemplo2 + crea una nueva variable local llamada +ha_sido_llamada Lavariable local desaparece cuando finaliza la funcioacuten y no tiene efecto en lavariable global

Para reasignar una variable global dentro de una funcioacuten debe declarar lavariable global antes de usarla (reasignacioacuten

Variables Globales 151

been_called = false

function ejemplo2() global ha_sido_llamada ha_sido_llamada = trueend

La sentencia global le dice al inteacuterprete algo como esto ldquoEn esta funcioacuten cuandodigo ha_sido_llamada me refiero a la variable global asiacute que no crees unavariable local

A continuacioacuten se muestra un ejemplo que intenta actualizar una variable global

conteo = 0

function ejemplo3() conteo = conteo + 1 MALOend

Si lo ejecuta obtiene

juliagt ejemplo3()ERROR UndefVarError conteo not defined

Julia asume que conteo es local y bajo esa suposicioacuten lo estaacute leyendo antes deescribirlo La solucioacuten nuevamente es declarar conteo como global

conteo = 0

function ejemplo3() global conteo conteo += 1end

Si una variable global se refiere a un valor mutable puede modificar el valor sindeclarar la variable global

anteriores = Dict(0=gt0 1=gt1)

function ejemplo4() anteriores[2] = 1end

Por lo tanto puede agregar eliminar y reemplazar elementos de una matriz

152 Capiacutetulo 11 Diccionarios

global o diccionario pero si desea reasignar la variable debe declararla global

anteriores = Dict(0=gt0 1=gt1)

function ejemplo5() global anteriores anteriores = Dict()end

Para mejorar el rendimiento puede declarar la variable global como constanteCon esto ya no se puede reasignar la variable pero si se refiere a un valormutable siacute se puede modificar el valor

const known = Dict(0=gt0 1=gt1)

function example4() known[2] = 1end

AVISOLas variables globales pueden ser uacutetiles pero si tiene muchas deellas y las modifica con frecuencia pueden dificultar ladepuracioacuten y empeorar el desempentildeo de los programas

DepuracioacutenA medida que trabaja con conjuntos de datos maacutes grandes la depuracioacutenmediante la impresioacuten y verificacioacuten de la salida de manera manual puedetornarse difiacutecil Aquiacute hay algunas sugerencias para depurar grandes conjuntos dedatos

bull Reduzca la entrada

Si es posible reduzca el tamantildeo del conjunto de datos Por ejemplo si elprograma lee un archivo de texto comience con solo las primeras 10 liacuteneaso con el ejemplo maacutes pequentildeo que pueda encontrar que produzca erroresNo debe editar los archivos sino modificar el programa para que solo lea lasprimeras liacuteneas

Si hay un error puede reducir al valor maacutes pequentildeo que manifieste elerror y luego aumentarlo gradualmente a medida que encuentre y corrijaerrores

bull Revisar resuacutemenes y tipos

En lugar de imprimir y verificar todo el conjunto de datos considereimprimir resuacutemenes de los datos Por ejemplo el nuacutemero de elementos en

Depuracioacuten 153

un diccionario o el total de una serie de nuacutemeros

Una causa comuacuten de los errores de tiempo de ejecucioacuten son los valores detipo incorrecto Para depurar este tipo de error generalmente es suficienteimprimir el tipo de un valor

bull Escribir autocomprobaciones

Puede escribir coacutedigo que verifique errores automaacuteticamente Por ejemplosi estaacute calculando el promedio de una matriz de nuacutemeros puede verificarque el resultado no sea mayor que el elemento maacutes grande de la matriz omenor que el maacutes pequentildeo Esto se llama prueba de cordura

Otro tipo de verificacioacuten compara los resultados de dos caacutelculos diferentespara ver si son consistentes Esta se llama prueba de consistencia

bull Formatear la salida

Formatear la salida de depuracioacuten puede hacer que sea maacutes faacutecil detectarun error Vimos un ejemplo en Seccioacuten 69

Nuevamente el tiempo que dedica a construir andamiaje puede reducir eltiempo que dedica a la depuracioacuten

Glosariomapeo

Una relacioacuten en la que cada elemento de un conjunto corresponde a unelemento de otro conjunto

diccionarioUna asignacioacuten de claves a sus valores correspondientes

par clave-valorLa representacioacuten de la asociacioacuten entre una clave y un valor

itemEn un diccionario otro nombre para un par clave-valor

claveUn objeto que aparece en un diccionario como la primera parte de un parclave-valor

valorUn objeto que aparece en un diccionario como la segunda parte de un parclave-valor Este teacutermino es maacutes especiacutefico que nuestro uso previo de lapalabra valor

154 Capiacutetulo 11 Diccionarios

implementacioacutenUna forma de realizar un caacutelculo

tabla hashEl algoritmo utilizado para implementar los diccionarios de Julia

funcioacuten hashUna funcioacuten utilizada por una tabla hash para calcular la ubicacioacuten de unaclave

hashableUn tipo que tiene una funcioacuten hash

buacutesquedaUna operacioacuten sobre un diccionario que toma una clave y encuentra el valorcorrespondiente

buacutesqueda inversaUna operacioacuten sobre un diccionario que toma un valor y encuentra una omaacutes claves que se asignan a eacutel

singletonUna matriz (u otra secuencia) con un solo elemento

graacutefico de llamadaUn diagrama que muestra cada cuadro creado durante la ejecucioacuten de unprograma con una flecha entre cada funcioacuten y sus respectivas funcionesllamadas

pistaValor precalculado y almacenado temporalmente para evitar caacutelculosredundantes

variable globalUna variable definida fuera de una funcioacuten Se puede acceder a las variablesglobales desde cualquier funcioacuten

sentencia globalUna sentencia que declara un nombre de variable global

banderaUna variable booleana utilizada para indicar si una condicioacuten es verdadera

Glosario 155

declaracioacutenUna sentencia como global que le dice al inteacuterprete algo sobre una variable

variable global constanteUna variable global que no se puede reasignar

Ejercicios

Ejercicio 11-2

Escriba una funcioacuten que lea las palabras en palabrastxt y las almacene comoclaves en un diccionario No importa cuaacuteles sean los valores Luego puede usar eloperador isin como una forma raacutepida de verificar si una cadena estaacute en eldiccionario

Si hizo Seccioacuten 101510 puede comparar la velocidad de esta implementacioacutencon el operador array isin y la buacutesqueda binaria

Ejercicio 11-3

Lea la documentacioacuten de la funcioacuten que opera sobre diccionarios get y uacuteselapara escribir una versioacuten maacutes concisa de invertirdic

Ejercicio 11-4

Use pistas en la funcioacuten de Ackermann de Seccioacuten 6112 y vea si esto permiteevaluar la funcioacuten con argumentos de mayor tamantildeo

Ejercicio 11-5

Si hizo Seccioacuten 10157 ya tiene una funcioacuten llamada repetido que toma unamatriz como paraacutemetro y devuelve true si hay alguacuten objeto que aparece maacutes deuna vez en la matriz

Use un diccionario para escribir una versioacuten maacutes raacutepida y simple de repetido

Ejercicio 11-6

Dos palabras son pares desplazados si puede desplazar una de ellas y obtenerla otra (vea desplazarpalabra en Seccioacuten 8155)

Escriba un programa que lea una matriz de palabras y encuentre todos los paresdesplazados

156 Capiacutetulo 11 Diccionarios

Ejercicio 11-7

Aquiacute hay otro Puzzle de Car Talk (httpswwwcartalkcompuzzlerbrowse)

This was sent in by a fellow named Dan OrsquoLeary He came upon a commonone-syllable five-letter word recently that has the following unique propertyWhen you remove the first letter the remaining letters form a homophone ofthe original word that is a word that sounds exactly the same Replace thefirst letter that is put it back and remove the second letter and the result isyet another homophone of the original word And the question is whatrsquos theword

Now Irsquom going to give you an example that doesnrsquot work Letrsquos look at thefive-letter word lsquowrackrsquo W-R-A-C-K you know like to lsquowrack with painrsquo If Iremove the first letter I am left with a four-letter word rsquoR-A-C-Krsquo As inlsquoHoly cow did you see the rack on that buck It must have been a nine-pointerrsquo Itrsquos a perfect homophone If you put the lsquowrsquo back and remove thelsquorrsquo instead yoursquore left with the word lsquowackrsquo which is a real word itrsquos justnot a homophone of the other two words

But there is however at least one word that Dan and we know of which willyield two homophones if you remove either of the first two letters to maketwo new four-letter words The question is whatrsquos the word

You can use the dictionary from Seccioacuten 11101 to check whether a string is inthe word array

OBSERVACIOacuteNTo check whether two words are homophones you canuse the CMU Pronouncing Dictionary You can downloadit from httpwwwspeechcscmueducgi-bincmudict

Write a program that lists all the words that solve the Puzzler

Ejercicios 157

Capiacutetulo 12 TuplasEste capiacutetulo presenta otro tipo integrado las tuplas Luego muestra coacutemo losarreglos los diccionarios y las tuplas funcionan en conjunto Tambieacuten se presentauna caracteriacutestica uacutetil para los arreglos de longitud variable como argumento losoperadores de recopilacioacuten y dispersioacuten

Las Tuplas son ImmutablesUna tupla es una secuencia de valores Estos valores pueden ser de cualquiertipo y estaacuten indexados por enteros por lo que las tuplas son muy parecidas a losarreglos La diferencia maacutes importante es que las tuplas son inmutables y quecada elemento puede tener su propio tipo

Una tupla es una lista de valores separados por comas

juliagt t = a b c d e(a b c d e)

Aunque no es necesario es comuacuten encerrar las tuplas entre pareacutentesis

juliagt t = (a b c d e)(a b c d e)

Para crear una tupla con un solo elemento se debe incluir una coma final

juliagt t1 = (a)(a)juliagt typeof(t1)TupleChar

AVISO

Un valor entre pareacutentesis sin coma no es una tupla

juliagt t2 = (a)a ASCIIUnicode U+0061 (category Ll Letter lowercase)juliagt typeof(t2)Char

Otra forma de crear una tupla es la funcioacuten de tupla integrada en Julia Sinargumento esta funcioacuten crea una tupla vaciacutea

juliagt tuple()()

158 Capiacutetulo 12 Tuplas

Si se tienen muacuteltiples argumentos el resultado es una tupla con los argumentosdados

juliagt t3 = tuple(1 a pi)(1 a π)

Ya que tuple es el nombre de una funcioacuten integrada debe evitar usarla comonombre de variable

La mayoriacutea de los operadores de arreglos tambieacuten sirven en las tuplas Eloperador corchete indexa un elemento

juliagt t = (a b c d e)

juliagt t[1]a ASCIIUnicode U+0061 (category Ll Letter lowercase)

Y el operador porcioacuten selecciona un rango de elementos

juliagt t[24](b c d)

Pero si se intenta modificar uno de los elementos de la tupla se obtendraacute unerror

juliagt t[1] = AERROR MethodError no method matching setindex(NTuple5Char CharInt64)

Como las tuplas son inmutables sus elementos no se pueden modificar

Los operadores relacionales funcionan con las tuplas y otras secuencias Juliacomienza comparando el primer elemento de cada secuencia Si son igualespasa a los siguientes elementos y asiacute sucesivamente hasta que encuentraelementos que difieren Los elementos posteriores no se consideran (incluso sison realmente grandes)

juliagt (0 1 2) lt (0 3 4)truejuliagt (0 1 2000000) lt (0 3 4)true

Las Tuplas son Immutables 159

Asignacioacuten de tuplaDe vez en cuando es uacutetil intercambiar los valores de dos variables Para hacerlocon sentencias de asignacioacuten convencionales se debe usar una variable temporalPor ejemplo para intercambiar a y b

temp = aa = bb = temp

Esta solucioacuten resulta aparatosa La asignacioacuten de tuplas soluciona este problemaelegantemente

a b = b a

El lado izquierdo es una tupla de variables y el lado derecho es una tupla deexpresiones Cada valor se asigna a su respectiva variable Todas las expresionesdel lado derecho se evaluacutean antes de las asignaciones

El nuacutemero de variables de la izquierda tiene que ser menor o igual que el nuacutemerode valores a la derecha

juliagt (a b) = (1 2 3)(1 2 3)juliagt a b c = 1 2ERROR BoundsError attempt to access (1 2) at index [3]

El lado derecho puede ser cualquier tipo de secuencia (cadena arreglo o tupla)Por ejemplo para dividir una direccioacuten de correo electroacutenico en nombre deusuario y dominio se puede escribir

juliagt addr = juliocesarromajuliocesarromajuliagt unombre dominio = split(addr )

El valor de retorno de split es un arreglo con dos elementos el primer elementose asigna a unombre y el segundo a dominio

juliagt unombrejuliocesarjuliagt dominioroma

160 Capiacutetulo 12 Tuplas

Tuplas como valor de retornoEstrictamente hablando una funcioacuten solo puede devolver un valor pero si elvalor es una tupla el efecto es el mismo que devolver muacuteltiples valores Porejemplo si desea dividir dos enteros y calcular el cociente y el resto esineficiente calcular x divide y y luego x y Es mejor calcular ambos al mismotiempo

La funcioacuten integrada divrem toma dos argumentos y devuelve una tupla de dosvalores el cociente y el resto El resultado puede ser almacenado como unatupla

juliagt t = divrem(7 3)(2 1)

Tambieacuten se puede utilizar asignacioacuten de tuplas para almacenar los elementos porseparado

juliagt q r = divrem(7 3)

juliagt show q rq = 2r = 1

Aquiacute hay un ejemplo de una funcioacuten que devuelve una tupla

function minmax(t) minimum(t) maximum(t)end

maximum y minimum son funciones integradas que encuentran los elementosmaacutes grandes y maacutes pequentildeos de una secuencia respectivamente La funcioacutenminmax calcula ambos y devuelve una tupla de dos valores Otra alternativa esutilizar la funcioacuten integrada extrema lo cual es maacutes eficiente

Tupla con Argumentos de Longitud VariableLas funciones pueden tomar un nuacutemero variable de argumentos Un nombre deparaacutemetro que termina con recopila argumentos en una tupla Por ejemploimprimirtodo toma cualquier nuacutemero de argumentos y los imprime

function imprimirtodo(args) println(args)end

Tuplas como valor de retorno 161

El paraacutemetro de recopilacioacuten puede tener cualquier nombre pero la convencioacutenes llamarlo args A continuacioacuten se muestra coacutemo funciona la funcioacuten

juliagt imprimirtodo(1 20 3)(1 20 3)

El opuesto de la recopilacioacuten es la dispersioacuten Si tiene una secuencia de valores ydesea pasarla a una funcioacuten como argumento muacuteltiple puede usar el operador Por ejemplo divrem toma exactamente dos argumentos y no funciona contuplas

juliagt t = (7 3)

juliagt divrem(t)ERROR MethodError no method matching divrem(TupleInt64Int64)

No obstante si dispersamos la tupla funciona

juliagt divrem(t)(2 1)

Muchas de las funciones integradas usan tuplas con argumentos de longitudvariable Por ejemplo max y min pueden tomar cualquier nuacutemero deargumentos

juliagt max(1 2 3)3

Pero sum no

juliagt sum(1 2 3)ERROR MethodError no method matching sum(Int64 Int64 Int64)

Ejercicio 12-1

Escriba una funcioacuten llamada sumartodo que tome cualquier nuacutemero deargumentos y devuelva su suma

En el mundo de Julia generalmente se le llama ldquoslurprdquo (sorber en espantildeol) areunir y splat (plaf en espantildeol como el ruido cuando cae algo) a dispersar

162 Capiacutetulo 12 Tuplas

Arreglos y tuplaszip es una funcioacuten integrada que toma dos o maacutes secuencias y devuelve unacoleccioacuten de tuplas donde cada tupla contiene un elemento de cada secuencia Elnombre de la funcioacuten se refiere a una cremallera que une e intercala dos filas dedientes

Este ejemplo une e intercala una cadena y un arreglo

juliagt s = abc

juliagt t = [1 2 3]

juliagt zip(s t)zip(abc [1 2 3])

El resultado es un objeto zip que permite iterar a traveacutes de los pares El uso maacutescomuacuten de zip es en un bucle for

juliagt for par in zip(s t) println(par) end(a 1)(b 2)(c 3)

Un objeto zip es un tipo de iterador que es cualquier objeto que itera a traveacutes deuna secuencia Los iteradores son en cierto modo similares a los arreglos peroa diferencia de estos uacuteltimos no se puede usar un iacutendice para seleccionar unelemento de un iterador

Si desea usar operadores y funciones de arreglos puede usar un objeto zip parahacer un arreglo

juliagt collect(zip(s t))3-element ArrayTupleCharInt641 (a 1) (b 2) (c 3)

El resultado es una serie de tuplas En este ejemplo cada tupla contiene uncaraacutecter de la cadena y el elemento correspondiente del arreglo

Si las secuencias no tienen la misma longitud el resultado tiene la longitud de lamaacutes corta

Arreglos y tuplas 163

juliagt collect(zip(Juan Gabriel))4-element ArrayTupleCharChar1 (J G) (u a) (a b) (n r)

Se puede usar asignacioacuten de tuplas en un bucle for para recorrer un arreglo detuplas

juliagt t = [(a 1) (b 2) (c 3)]

juliagt for (letra numero) in t println(numero letra) end1 a2 b3 c

En cada iteracioacuten del ciclo Julia selecciona la siguiente tupla en el arreglo yasigna estos elementos a letra y nuacutemero Los pareacutentesis de (letra nuacutemero) sonobligatorios

Combinando zip for y asignacioacuten de tuplas se obtiene una forma para recorrerdos (o maacutes) secuencias al mismo tiempo Por ejemplo la funcioacuten coinciden tomados secuencias t1 y t2 y devuelve true si hay un iacutendice i tal que t1[i] == t2[i]

function coinciden(t1 t2) for (x y) in zip(t1 t2) if x == y return true end end falseend

Si se necesita recorrer los elementos de una secuencia y sus iacutendices se puedeusar la funcioacuten integrada enumerate

juliagt for (indice elemento) in enumerate(abc) println(indice elemento) end1 a2 b3 c

164 Capiacutetulo 12 Tuplas

El resultado de enumerate es un objeto enumerate el cual hace una iteracioacutensobre una secuencia de pares doacutende cada par contiene un iacutendice (a partir de 1) yun elemento de la secuencia dada

Diccionarios y TuplasLos diccionarios se pueden usar como iteradores que iteran sobre los paresclave-valor Puede usarlos en un bucle for como este

juliagt d = Dict(a=gt1 b=gt2 c=gt3)

juliagt for (key value) in d println(key value) enda 1c 3b 2

Como es de esperar en un diccionario los elementos no estaacuten en un ordenparticular

Ahora si se quiere hacer lo contrario se puede usar una serie de tuplas parainicializar un nuevo diccionario

juliagt t = [(a 1) (c 3) (b 2)]

juliagt d = Dict(t)DictCharInt64 with 3 entries a =gt 1 c =gt 3 b =gt 2

Al combinar Dict con zip podemos crear un diccionario de una manera muysimple

juliagt d = Dict(zip(abc 13))DictCharInt64 with 3 entries a =gt 1 c =gt 3 b =gt 2

Es comuacuten usar tuplas como claves en los diccionarios Por ejemplo un directoriotelefoacutenico puede asignar nuacutemeros de teleacutefono a una tupla con apellido y nombreSuponiendo que se ha definido apellido nombre y numero podriacuteamos escribir

Diccionarios y Tuplas 165

directorio[apellido nombre] = numero

La expresioacuten entre pareacutentesis es una tupla Se podriacutea usar asignacioacuten de tuplaspara recorrer este diccionario

for ((apellido nombre) numero) in directorio println(nombre apellido numero)end

Este bucle recorre los pares clave-valor en directorio los cuales son tuplasAsigna los elementos de la clave de cada tupla a apellido y nombre y el valor anumero luego imprime el nombre y el nuacutemero de teleacutefono correspondiente

Hay dos formas de representar tuplas en un diagrama de estado La versioacuten maacutesdetallada muestra los iacutendices y elementos tal como aparecen en un arreglo Porejemplo la tupla (Cortaacutezar Julio) se veriacutea como en Figura 18

Figura 18 Diagrama de estado

Pero en un diagrama maacutes grande es posible que desee omitir algunos detallesPor ejemplo un diagrama del directorio telefoacutenico puede verse como en Figura19

Figura 19 Diagrama de estado

Aquiacute las tuplas se muestran usando la sintaxis de Julia para tener un esquemamaacutes simple El nuacutemero de teleacutefono del diagrama es el nuacutemero de reclamos de laBBC asiacute que no intentes llamar

Secuencias de SecuenciasHasta ahora el capiacutetulo se ha centrado en los arreglos de tuplas pero casi todoslos ejemplos que se han visto tambieacuten funcionan con arreglos de arreglos tuplasde tuplas y tuplas de arreglos Para evitar enumerar todas las posiblescombinaciones a veces es maacutes faacutecil hablar sobre secuencias de secuencias

En muchos contextos los diferentes tipos de secuencias (cadenas arreglos ytuplas) se pueden usar indistintamente Entonces iquestcoacutemo elegir uno u otro

166 Capiacutetulo 12 Tuplas

Para comenzar con lo mas obvio las cadenas son maacutes limitadas que las demaacutessecuencias porque los elementos deben ser caracteres Ademaacutes son inmutablesSi se necesita poder cambiar los caracteres en una cadena (en vez de crear unanueva) puede que lo mas adecuado sea elegir un arreglo de caracteres

Los arreglos se usan con mas frecuencia que las tuplas principalmente porqueson mutables No obstante hay algunos casos donde es posible que seapreferible usar tuplas

bull En algunos contextos como en una sentencia return resultasintaacutecticamente maacutes simple crear una tupla que un arreglo

bull Si se pasa una secuencia como argumento de una funcioacuten el uso de tuplasreduce los comportamientos potencialmente indeseados debido a lacreacioacuten de alias

bull Por rendimiento El compilador puede especializarse en este tipo

Dado que las tuplas son inmutables no tienen funciones como sort y reverseque modifiquen arreglos ya existentes Sin embargo Julia proporciona lasfunciones integradas sort que toma un arreglo y devuelve una secuencia nuevacon los mismos elementos ordenados y reverse que toma cualquier secuencia ydevuelve una secuencia nueva del mismo tipo con los mismos elementos en elorden contrario

DepuracioacutenLos arreglos diccionarios y tuplas son ejemplos de estructuras de datos En estecapiacutetulo se empiezan a ver estructuras de datos compuestas como arreglos otuplas y diccionarios que contienen tuplas como claves y arreglos como valoresLas estructuras de datos compuestas son uacutetiles aunque tambieacuten resultanpropensas a lo que se llaman errores de forma es decir errores causados cuandouna estructura de datos tiene el tipo tamantildeo o estructura incorrecta Porejemplo si estaacute esperando una lista con un entero y se le pasa simplemente unentero (no en una lista) no funcionaraacute

Julia permite antildeadir el tipo a elementos de una secuencia Esto se detalla enCapiacutetulo 17 Especificar el tipo elimina muchos errores de forma

Glosariotupla

Una secuencia inmutable de elementos donde cada elemento puede tener supropio tipo

asignacioacuten en tuplaUna asignacioacuten con una secuencia en el lado derecho y una tupla devariables en el izquierdo Primero se evaluacutea el lado derecho y luego sus

Depuracioacuten 167

elementos son asignados a las variables de la izquierda

reunirLa operacioacuten de armar una tupla con argumentos de longitud variable

dispersarLa operacioacuten de tratar una secuencia como una lista de argumentos

objeto zipEl resultado de llamar a la funcioacuten integrada zip un objeto que itera atraveacutes de una secuencia de tuplas

iteradorUn objeto que puede iterar a traveacutes de una secuencia pero que no tiene losoperadores y funciones de arreglos

estructura de datosUna coleccion de valores relacionados a menudo organizados en arreglosdiccionarios tuplas etc

error de formaUn error causado porque un valor tiene la forma incorrecta es decir el tipoo tamantildeo incorrecto

Ejercicios

Ejercicio 12-2

Escriba una funcioacuten llamada masfrecuente que tome una cadena e imprima lasletras en orden decreciente de frecuencia Encuentre muestras de texto de variosidiomas diferentes y vea coacutemo la frecuencia de las letras variacutea entre idiomasCompare sus resultados con las tablas en httpsenwikipediaorgwikiLetter_frequencies

Ejercicio 12-3

iexclMaacutes anagramas

1 Escriba un programa que lea una lista de palabras de un archivo (veaSeccioacuten 91) e imprima todos los conjuntos de palabras que son anagramas

Aquiacute hay un ejemplo de coacutemo se veriacutea la salida

168 Capiacutetulo 12 Tuplas

[brazo zobra broza zarbo][palabra parlaba][vida diva][gato toga gota]

OBSERVACIOacuteN

Es posible que desee crear un diccionario queasigne a una coleccioacuten de letras una serie depalabras que se puedan deletrear con esas letrasLa pregunta es iquestcoacutemo representar la coleccioacuten deletras de una manera que pueda usarse comoclave

2 Modifique el programa anterior para que imprima primero el arreglo maacuteslargo de anagramas seguido del segundo maacutes larga y asiacute sucesivamente

3 En Scrabble un bingo es cuando juegas las siete fichas de tu atril juntocon una letra del tablero para formar una palabra de ocho letras iquestQueacutecoleccioacuten de 8 letras forman parte del bingo maacutes probable

Ejercicio 12-4

Dos palabras metatizan si se puede transformar una en la otra intercambiandodos letras como es el caso de conversar y conservar Escriba un programaque encuentre todos los pares de metaacutetesis en el diccionario

OBSERVACIOacuteN No pruebe con todos los pares de palabras ni tampococon todos los intercambios posibles

Creacuteditos Este ejercicio estaacute inspirado en un ejemplo de httppuzzlersorg

Ejercicio 12-5

Aquiacute hay otro Puzzle de Car Talk (httpswwwcartalkcompuzzlerbrowse)

Ejercicios 169

iquestCuaacutel es la palabra en espantildeol maacutes larga que sigue siendo una palabra enespantildeol vaacutelida a medida que se eliminan sus letras una a una

Las letras se pueden eliminar de cualquier extremo o del medio pero no sepuede reordenar ninguna de ellas Cada vez que elimina una letra se quedacon otra palabra en espantildeol Eventualmente terminaraacute con una letra la cualtambieacuten seraacute una palabra en espantildeol que puede encontrar en el diccionarioSe desea saber cuaacutel es la palabra maacutes larga y cuaacutentas letras tiene

A modo de ejemplo piense en la palabra Palote iquestDe acuerdo Comienza conpalote elimina la letra p y queda alote luego se quita la t y queda aloe setoma la e y se tiene alo quitando la o se tiene al y finalmente eliminando lal queda a

Escriba un programa que encuentre todas las palabras que se pueden reducir deesta manera y luego encuentre la maacutes larga

OBSERVACIOacuteN

Este ejercicio es un poco maacutes desafiante que el resto asiacuteque aquiacute hay algunas sugerencias

1 Es posible que quiera escribir una funcioacuten que tomeuna palabra y calcule un arreglo de todas laspalabras que se pueden formar al eliminar unaletra Estos son los hijos de la palabra

2 De manera recursiva una palabra es reducible sialguno de sus hijos es reducible Como caso basepuede considerar la cadena vaciacutea reducible

3 La lista de palabras palabrastxt no tiene la cadenavaciacutea por lo que tendraacute que agregarla

4 Para mejorar el rendimiento de su programa esposible que desee guardar las palabras que se sabeque son reducibles

170 Capiacutetulo 12 Tuplas

Capiacutetulo 13 Estudio de Caso Seleccioacuten deEstructura de DatosHasta ahora hemos aprendido sobre las principales estructuras de datos de Juliay hemos visto algunos de los algoritmos que las utilizan

Este capiacutetulo presenta un estudio de caso con ejercicios que le permitenpracticar la eleccioacuten de estructuras de datos y su uso

Anaacutelisis de Frecuencia de PalabrasComo de costumbre se recomienda intentar resolver los ejercicios antes de leerlas soluciones

Ejercicio 13-1

Escriba un programa que lea un archivo divida cada liacutenea en palabras elimine elespacio en blanco y la puntuacioacuten de las palabras y luego las convierta enminuacutesculas

OBSERVACIOacuteN La funcioacuten isletter permite saber si un caraacutecterpertenece al alfabeto

Ejercicio 13-2

Vaya a la paacutegina de Proyecto Gutenberg (httpsgutenbergorg) y descargue sulibro favorito sin derechos de autor en formato de texto plano La mayoriacutea de loslibros estaacuten en ingleacutes pero existen algunos en espantildeol

Modifique su programa del ejercicio anterior para leer el libro que descargoacuteomita la informacioacuten del encabezado al comienzo del archivo y procese el restode las palabras tal como en el ejercicio previo

Luego modifique el programa para contar la cantidad total de palabras en ellibro y la cantidad de veces que se usa cada palabra

Imprima la cantidad de palabras diferentes que se usan en el libro Comparediferentes libros de diferentes autores escritos en diferentes eacutepocas iquestQueacute autorusa un vocabulario maacutes extenso

Ejercicio 13-3

Modifique el programa del ejercicio anterior para imprimir las 20 palabras maacutesutilizadas en el libro

Anaacutelisis de Frecuencia de Palabras 171

Ejercicio 13-4

Modifique el programa anterior para que lea una lista de palabras y luegoimprima todas las palabras del libro que no esteacuten en la lista de palabrasiquestCuaacutentos de ellos son errores tipograacuteficos iquestCuaacutentos de ellos son palabrascomunes que deberiacutean estar en la lista de palabras iquest Cuaacutentos de ellos sonteacuterminos realmente macabros

Nuacutemeros aleatoriosDadas las mismas entradas la mayor parte de los programas generan la mismasalida cada vez que los ejecutamos por lo que se dice que son deterministasNormalmente el determinismo es algo bueno ya que esperamos que un caacutelculonos entregue siempre el mismo resultado Para algunas aplicaciones sinembargo queremos que el computador sea impredecible Por ejemplo en losjuegos entre otros casos

Hacer que un programa sea realmente no determinista resulta difiacutecil pero hayformas de que hacer que al menos parezca no determinista Una de ellas es usaralgoritmos para generar nuacutemeros pseudoaleatorios Los nuacutemerospseudoaleatorios no son verdaderamente aleatorios porque se generan medianteun caacutelculo determinista pero al mirar estos nuacutemeros es casi imposibledistinguirlos de lo aleatorio

La funcioacuten rand devuelve un numero de punto flotante entre 00 y 10(incluyendo 00 pero no 10) Cada vez que usted llama a rand obtiene elsiguiente numero de una larga serie Para ver un ejemplo ejecute este bucle

for i in 110 x = rand() println(x)end

La funcioacuten rand puede tomar un iterador o arreglo como argumento y devuelveun elemento aleatorio de ellos

for i in 110 x = rand(16) print(x )end

Ejercicio 13-5

Escriba una funcioacuten llamada escogerdelhistograma que tome un histogramadefinido como en Seccioacuten 112 y devuelva un valor aleatorio del histogramaelegido con probabilidad proporcional a la frecuencia Por ejemplo para este

172 Capiacutetulo 13 Estudio de Caso Seleccioacuten de Estructura de Datos

histograma

juliagt t = [a a b]

juliagt histograma(t)DictAnyAny with 2 entries a =gt 2 b =gt 1

su funcioacuten debe devolver a con probabilidad y b con probabilidad

Histograma de PalabrasDebe hacer los ejercicios anteriores antes de continuar Tambieacuten necesitaraacutehttpsgithubcomJuliaIntroIntroAJuliajlblobmasterdataDonQuijotetxt

Aquiacute hay un programa que lee un archivo y construye un histograma de laspalabras en el archivo

function procesararchivo(nombrearchivo) hist = Dict() for linea in eachline(nombrearchivo) procesarlinea(linea hist) end histend

function procesarlinea(linea hist) linea = replace(linea - =gt ) for palabra in split(linea) palabra = string(filter(isletter [palabra])) palabra = lowercase(palabra) hist[palabra] = get(hist palabra 0) + 1 endend

Histograma de Palabras 173

DictAnyAny with 23607 entries enojoacute =gt 1 angosta =gt 1 hurto =gt 10 sirviesen =gt 2 solene =gt 1 coronan =gt 1 endereacutecese =gt 2 alteza =gt 15 rescatarlos =gt 1 enderezador =gt 1 libertad =gt 81 abundante =gt 5 bajeza =gt 4 embotoacute =gt 1 estime =gt 1 renovaban =gt 1 acreciente =gt 4 debieron =gt 8 garci =gt 1 ⋮ =gt ⋮

hist = procesararchivo(DonQuijotetxt)

Este programa lee DonQuijotetxt que contiene el texto de Don Quijote deMiguel de Cervantes

procesararchivo recorre las liacuteneas del archivo pasando una liacutenea a la vez aprocesarlinea El histograma hist se estaacute utilizando como acumulador

procesarlinea usa la funcioacuten replace para reemplazar los guiones por espaciosantes de usar split para dividir la liacutenea en un arreglo de cadenas Recorre elconjunto de palabras y usa filter isletter y lowercase para eliminar los signos depuntuacioacuten y convertir las palabras a minuacutesculas (Decir que las cadenas seconvierten es incorrecto recuerde que las cadenas son inmutables por lo queuna funcioacuten como lowercase devuelve cadenas nuevas)

Finalmente procesarlinea actualiza el histograma creando un nuevo elemento oincrementando uno existente

Para contar el nuacutemero total de palabras en el archivo podemos sumar lasfrecuencias en el histograma

function palabrastotales(hist) sum(values(hist))end

174 Capiacutetulo 13 Estudio de Caso Seleccioacuten de Estructura de Datos

El nuacutemero de palabras diferentes es el nuacutemero de elementos en el diccionario

function palabrasdiferentes(hist) length(hist)end

Para imprimir los resultados se puede usar el siguiente coacutedigo

juliagt println(Nuacutemero total de palabras palabrastotales(hist))Nuacutemero total de palabras 385925

juliagt println(Nuacutemero de palabras diferentes palabrasdiferentes(hist))Nuacutemero de palabras diferentes 23607

Observacioacuten No se considera el encabezado del archivo de texto soacutelo el libro

Palabras Maacutes ComunesPara encontrar las palabras maacutes comunes podemos hacer un arreglo de tuplasdonde cada tupla contiene una palabra y su frecuencia y ordenarlas Lasiguiente funcioacuten toma un histograma y devuelve un arreglo de tuplas defrecuencia de palabras

function mascomun(hist) t = [] for (clave valor) in hist push(t (valorclave)) end reverse(sort(t))end

En cada tupla la frecuencia aparece primero por lo que el arreglo resultante seordena por frecuencia A continuacioacuten se muestra un bucle que imprime las 10palabras maacutes comunes

t = mascomun(hist)println(Las palabras maacutes comunes son)for (frec palabra) in t[110] println(palabra t frec)end

En este ejemplo utilizamos un caraacutecter de tabulacioacuten (t) como separador envez de un espacio por lo que la segunda columna estaacute alineada A continuacioacutense muestran los resultados de Don Quijote

Palabras Maacutes Comunes 175

Las palabras maacutes comunes sonque 20626de 18217y 18188la 10363a 9881en 8241el 8210no 6345los 4748se 4690

OBSERVACIOacuteN

Este coacutedigo se puede simplificar usando comoargumento la palabra reservada rev de la funcioacuten sortPuede leer sobre esto en httpsdocsjulialangorgenv1basesortBasesort

Parametros OpcionalesSe han tratado funciones integradas de Julia que toman argumentos opcionalesTambieacuten es posible escribir funciones definidas por el programador conargumentos opcionales Por ejemplo aquiacute hay una funcioacuten que imprime laspalabras maacutes comunes en un histograma

function imprimirmascomun(hist num=10) t = mascomun(hist) println(Las palabras maacutes comunes son ) for (frec palabra) in t[1num] println(palabra t frec) endend

El primer paraacutemetro es obligatorio y el segundo es opcional El valorpredeterminado de num es 10

Si solo pasas un argumento

imprimirmascomun(hist)

num toma el valor predeterminado Si pasas dos argumentos

imprimirmascomun(hist 20)

num toma el valor del argumento En otras palabras el argumento opcional

176 Capiacutetulo 13 Estudio de Caso Seleccioacuten de Estructura de Datos

anula el valor predeterminado

Si una funcioacuten tiene paraacutemetros obligatorios y opcionales los paraacutemetrosobligatorios deben ir primero seguidos de los opcionales

Resta de DiccionarioEncontrar las palabras de un libro que no estaacuten en la lista de palabras depalabrastxt es un problema similar a una resta de conjuntos es decir se quiereencontrar todas las palabras de un conjunto (las palabras en el libro) que noestaacuten en el otro (las palabras en la lista)

resta toma los diccionarios d1 y d2 y devuelve un nuevo diccionario que contienetodas las claves de d1 que no estaacuten en d2 Como realmente no importan losvalores se fijan como nothing

function resta(d1 d2) res = Dict() for clave in keys(d1) if clave notin keys(d2) res[clave] = nothing end end resend

Para encontrar las palabras en el libro que no estaacuten en palabrastxt se ouedeusar procesararchivo para construir un histograma para palabrastxt y luego lafuncioacuten resta

palabras = procesararchivo(palabrastxt)dif = resta(hist palabras)

println(Palabras en el libro que no estaacuten en la lista de palabras)for palabra in keys(dif) print(palabra )end

Estos son algunos de los resultados de Don Quijote

Palabras en el libro que no estaacuten en la lista de palabrasenojoacute angosta coronan sirviesen solene endereacutecese rescatarlos embotoacuteestime renovaban

Algunas de estas palabras son conjugaciones de verbos Otros como solene yano son de uso comuacuten iexclPero algunas son palabras comunes que deberiacutean estar en

Resta de Diccionario 177

la lista

Ejercicio 13-6

Julia proporciona una estructura de datos llamada Set que permite muchasoperaciones comunes de conjuntos Puede leer sobre ellas en Seccioacuten 202 oconsultar la documentacioacuten en httpsdocsjulialangorgenv1basecollectionsSet-Like-Collections-1

Escriba un programa que use la resta de conjuntos para encontrar palabras en ellibro que no estaacuten en la lista de palabras

Palabras al AzarPara elegir una palabra aleatoria del histograma el algoritmo maacutes simple esconstruir un arreglo con muacuteltiples copias de cada palabra de acuerdo con lafrecuencia observada y luego elegir una palabra del arreglo

function palabraalazar(h) t = [] for (palabra frec) in h for i in 1frec push(t palabra) end end rand(t)end

Este algoritmo funciona pero no es muy eficiente ya que cada vez que elige unapalabra aleatoria reconstruye el arreglo que es tan grande como el librooriginal Una mejora es construir el arreglo una vez y luego hacer muacuteltiplesselecciones pero el arreglo sigue siendo grande

Una alternativa es

1 Use las claves para obtener un arreglo de palabras del libro

2 Cree un arreglo que contenga la suma acumulada de las frecuencias depalabras (vea Seccioacuten 10152) El uacuteltimo elemento en este arreglo es elnuacutemero total de palabras en el libro

3 Elija un nuacutemero aleatorio del 1 al Use buacutesqueda binaria (vea Seccioacuten101510) para encontrar el iacutendice donde se insertaraacute el nuacutemero aleatorio enla suma acumulada

4 Use el iacutendice para encontrar la palabra correspondiente en el arreglo depalabras

178 Capiacutetulo 13 Estudio de Caso Seleccioacuten de Estructura de Datos

Ejercicio 13-7

Escriba un programa que use este algoritmo para elegir una palabra aleatoriadel libro

Anaacutelisis de MarkovSi elige palabras del libro al azar puede tener una idea del vocabulario usadopero probablemente no se va a obtener una oracioacuten

rocinante plaacuteticas sazoacuten ojos Dulcinea Dios

Una serie de palabras aleatorias rara vez tiene sentido porque no hay relacioacutenentre palabras sucesivas Por ejemplo en una oracioacuten real se esperariacutea que unartiacuteculo como el fuese seguido por un sustantivo y probablemente no un verboo un adverbio

Una forma de medir este tipo de relaciones es con el anaacutelisis de Markov quedefine para una secuencia dada de palabras la probabilidad de las palabras quepodriacutean venir despueacutes Por ejemplo en la cancioacuten La vida es un carnaval (deCeliz Cruz)

Todo aquelQue piense que la vida siempre es cruelTiene que saber que no es asiacuteQue tan solo hay momentos malosY todo pasa

Todo aquelQue piense que esto nunca va cambiarTiene que saber que no es asiacuteQue al mal tiempo buena caraY todo cambia

Ay no hay que llorar (No hay que llorar)Que la vida es un carnavalQue es maacutes bello vivir cantando

En este texto la frase que piense siempre va seguida de la palabra que perola frase piense que puede ir seguida de la o esto

El resultado del anaacutelisis de Markov es un mapeo de cada prefijo (como quepiense y piense que) a todos los sufijos posibles (como la y esto)

Dada esta asignacioacuten se puede generar un texto aleatorio comenzando concualquier prefijo y eligiendo aleatoriamente entre los posibles sufijos A

Anaacutelisis de Markov 179

continuacioacuten puede combinar el final del prefijo y el nuevo sufijo para formar elsiguiente prefijo y repetir

Por ejemplo si comienza con el prefijo Que la la siguiente palabra seraacute vidaporque el prefijo solo aparece dos veces en el texto y siempre estaacute seguido deeste sufijo El siguiente prefijo es la vida por lo que el siguiente sufijo podriacuteaser siempre o es

En este ejemplo la longitud del prefijo siempre es dos pero puede hacer anaacutelisisde Markov con un prefijo de cualquier longitud

Ejercicio 13-8

Anaacutelisis de Markov

1 Escriba un programa que lea un texto desde un archivo y realice un anaacutelisisde Markov El resultado debe ser un diccionario que asocie prefijos y unacoleccioacuten de posibles sufijos La coleccioacuten puede ser un arreglo tupla odiccionario depende de usted hacer una eleccioacuten adecuada Puede probarsu programa con una longitud de prefijo de dos pero debe escribir elprograma de manera tal que sea faacutecil probar con otras longitudes

2 Agregue una funcioacuten al programa anterior para generar un texto aleatoriobasado en anaacutelisis de Markov Aquiacute hay un ejemplo de Don Quijote conlongitud de prefijo 2

Trifaldi habiacutea de Troya ni por la majestad real Y con mis quejasDesechaacutesteme iexcloh estremo su friacuteo del agravio a la espada tenieacutendolapor aca y maacutes que soacutelo se trueca y con el cual encendiacutea el ejemplo deaquellos cazadores

Para este ejemplo se dejoacute la puntuacioacuten anexa a las palabras El resultadoes casi sintaacutecticamente correcto Semaacutenticamente casi tiene sentido perono del todo

iquestQueacute sucede si aumenta la longitud del prefijo iquestEl texto aleatorio tiene maacutessentido

3 Una vez que su programa esteacute funcionando podriacutea probar combinandotexto de dos o maacutes libros El texto aleatorio que genere combinaraacute elvocabulario y las frases de las fuentes de maneras interesantes

Creacutedito Este estudio de caso se basa en un ejemplo de Kernighan y Pike ThePractice of Programming Addison-Wesley 1999

OBSERVACIOacuteN Debe hacer este ejercicio antes de continuar

180 Capiacutetulo 13 Estudio de Caso Seleccioacuten de Estructura de Datos

Estructuras de DatosUsar anaacutelisis de Markov para generar texto aleatorio es divertido pero ademaacuteseste ejercicio tiene un trasfondo la seleccioacuten de la estructura de datos En los losejercicios anteriores teniacutea que elegir

bull Coacutemo representar los prefijos

bull Coacutemo representar la coleccioacuten de los posibles sufijos

bull Coacutemo representar la asociacioacuten de cada prefijo con la coleccioacuten de posiblessufijos

El uacuteltimo es faacutecil un diccionario es la opcioacuten obvia para una asociacioacuten entreclaves y valores correspondientes

Para los prefijos las opciones maacutes obvias son cadena arreglo de cadenas o tuplade cadenas

Para los sufijos puede ser un arreglo o un histograma (diccionario)

iquestCoacutemo se elige El primer paso es pensar en las operaciones que deberaacuteimplementar para cada estructura de datos Para los prefijos se debe ser capazde eliminar palabras del principio y agregarlas al final Por ejemplo si el prefijoactual es que piense y la siguiente palabra es que debe poder formar elsiguiente prefijo piense que

Para los prefijos podriacutea elegir un arreglo ya que en eacutel es faacutecil agregar y eliminarelementos

Para la coleccioacuten de sufijos las operaciones que se deben realizar incluyenagregar un nuevo sufijo (o aumentar la frecuencia de uno existente) y elegir unsufijo aleatorio

Agregar un nuevo sufijo es igualmente faacutecil para la implementacioacuten del arreglo odel histograma Elegir un elemento aleatorio de un arreglo es faacutecil pero elegireficientemente de un histograma es maacutes difiacutecil (ver Seccioacuten 1371)

Hasta ahora se ha hablado principalmente sobre la facilidad de implementacioacutenpero hay otros factores a considerar al elegir las estructuras de datos Uno es eltiempo de ejecucioacuten A veces hay una razoacuten teoacuterica para esperar que unaestructura de datos sea maacutes raacutepida que otra Por ejemplo anteriormente semencionoacute que el operador in es maacutes raacutepido para los diccionarios que para losarreglos al menos cuando el nuacutemero de elementos es grande

Aunque generalmente no se sabe de antemano queacute implementacioacuten seraacute maacutesraacutepida una opcioacuten es implementar ambos y ver cuaacutel es mejor Este enfoque sellama benchmarking Una alternativa praacutectica es elegir la estructura de datosque sea maacutes faacutecil de implementar y luego ver si es lo suficientemente raacutepida parala aplicacioacuten prevista Si es asiacute no hay necesidad de continuar Si no hay

Estructuras de Datos 181

herramientas como el moacutedulo Profile que pueden identificar los lugares en unprograma que toman maacutes tiempo

El otro factor a considerar es el espacio de almacenamiento Por ejemplo usar unhistograma para la coleccioacuten de sufijos puede tomar menos espacio porque solotiene que almacenar cada palabra una vez sin importar cuaacutentas veces aparezcaen el texto En algunos casos ahorrar espacio tambieacuten puede hacer que suprograma se ejecute maacutes raacutepido En el peor de los casos su programa podriacutea noejecutarse si se queda sin memoria pero para muchas aplicaciones el espacio esuna consideracioacuten secundaria despueacutes del tiempo de ejecucioacuten

Una uacuteltima reflexioacuten en esta discusioacuten se ha dado a entender que se deberiacuteausar una estructura de datos para el anaacutelisis y la generacioacuten Pero dado queestas son fases separadas tambieacuten seriacutea posible usar una estructura para elanaacutelisis y luego convertirla en otra estructura para la generacioacuten Esto seriacuteaconveniente si el tiempo ahorrado durante la generacioacuten excede el tiempodedicado a la conversioacuten

OBSERVACIOacuteNEl paquete de Julia DataStructures (verhttpsgithubcomJuliaCollectionsDataStructuresjl)implementa una variedad de estructuras de datos

DepuracioacutenCuando estaacute depurando un programa y especialmente si estaacute tratando deresolver un error difiacutecil hay cinco cosas que puede probar

LeeExamine su coacutedigo leacutealo y verifique que dice lo que queriacutea decir

EjecutaExperimente haciendo cambios y ejecutando diferentes versiones Amenudo si muestra lo correcto en el lugar correcto del programa elproblema se vuelve obvio pero para ello a veces tiene que desarrollarandamiaje

ReflexionaiexclToacutemese un tiempo para pensar iquestQueacute tipo de error es de sintaxis tiempode ejecucioacuten o semaacutentica iquestQueacute informacioacuten puede obtener de los mensajesde error o de la salida del programa iquestQueacute tipo de error podriacutea causar elproblema que estaacutes viendo iquestQueacute cambioacute antes de que apareciera elproblema

HablaSi le explica el problema a otra persona a veces puede encontrar larespuesta incluso antes de terminar de hacer la pregunta Generalmente no

182 Capiacutetulo 13 Estudio de Caso Seleccioacuten de Estructura de Datos

es necesaria otra persona incluso se podriacutea hablar con un pato de gomaEste es el origen de la conocida estrategia llamada depuracioacuten del pato degoma Esto es real vea httpsenwikipediaorgwikiRubber_duck_debugging

Vuelve atraacutesEn ocasiones lo mejor que puede hacer es retroceder deshacer los cambiosrecientes hasta regresar a un programa que funcione y que comprenda Unavez logrado esto puede comenzar a reconstruir

Los programadores principiantes a veces se atascan en una de estas actividadesy olvidan las otras Cada actividad viene con su propia forma de fallar

Por ejemplo leer su coacutedigo podriacutea ayudar si el problema es un error tipograacuteficopero no si el problema es un malentendido conceptual Si no comprende lo quehace su programa puede leerlo 100 veces y nunca ver el error porque el errorestaacute en su cabeza

Ejecutar experimentos puede ayudar especialmente si ejecuta pruebas pequentildeasy simples pero si ejecuta experimentos sin pensar o leer su coacutedigo puede caeren un patroacuten llamado programacioacuten de caminata aleatoria que es el proceso dehacer cambios aleatorios hasta que el programa haga lo correcto No hace faltadecir que la programacioacuten de caminata aleatoria puede llevar mucho tiempo

La persona que programa tiene que tomarse su tiempo para pensar Ladepuracioacuten es como una ciencia experimental Debe tener al menos una hipoacutetesissobre la causa del problema Si hay dos o maacutes opciones trate de pensar en unaprueba que elimine una de ellas

Incluso las mejores teacutecnicas de depuracioacuten fallaraacuten si hay demasiados errores osi el coacutedigo que estaacute tratando de corregir es demasiado grande y complicado Aveces la mejor opcioacuten es volver atraacutes simplificando el programa hasta quellegue a algo que funcione y que comprenda

Los programadores principiantes a menudo son reacios a volver atraacutes porque nopueden soportar eliminar una liacutenea de coacutedigo (incluso si es incorrecto) Si le hacesentir mejor copie su programa en otro archivo antes de comenzar a eliminarloLuego puede copiar las piezas una por una

Encontrar un error difiacutecil requiere leer ejecutar reflexionar y a veces volveratraacutes Si se queda atascado en una de estas actividades pruebe las otras

Glosariodeterminiacutestico

Perteneciente a un programa que hace lo mismo cada vez que se ejecuta apartir de las mismas entradas

Glosario 183

pseudoaleatorioPerteneciente a una secuencia de nuacutemeros que parecen ser aleatorios peroque son generados por un programa determinista

valor por defecto (o valor por omisioacuten)El valor dado a un paraacutemetro opcional si no se proporciona un argumento

anularReemplazar un valor por defecto con un argumento

benchmarkingEl proceso de elegir entre estructuras de datos implementando alternativasy probaacutendolas con una muestra de las posibles entradas

depuracioacuten del pato de gomaDepuracioacuten en doacutende se explica el problema a un objeto inanimado talcomo un pato de goma Articular el problema puede ayudarle a resolverloincluso si el pato de goma no sabe de Julia

Ejercicios

Ejercicio 13-9

El rango de una palabra es su posicioacuten en un arreglo de palabras ordenadaspor frecuencia la palabra maacutes comuacuten tiene rango 1 la segunda maacutes comuacuten tienerango 2 etc

La ley de Zipf describe una relacioacuten entre los rangos y las frecuencias de laspalabras en idiomas naturales (httpsenwikipediaorgwikiZipfs_law)Especiacuteficamente predice que la frecuencia de la palabra con rango es

donde y son paraacutemetros que dependen del idioma y el texto Si aplicaslogaritmo a ambos lados de esta ecuacioacuten obtienes

Entonces si se grafica versus se deberiacutea obtener una liacutenea recta conpendiente e intercepto

Escriba un programa que lea un texto de un archivo cuente las frecuencias delas palabras e imprima una liacutenea para cada palabra en orden descendente defrecuencia con y

Instale una libreriacutea para graficar

184 Capiacutetulo 13 Estudio de Caso Seleccioacuten de Estructura de Datos

(v10) pkggt add Plots

Su uso es muy sencillo

using Plotsx = 110y = x^2plot(x y)

Use la libreriacutea Plots para graficar los resultados y verificar si forman una liacutenearecta

Ejercicios 185

Capiacutetulo 14 ArchivosEste capiacutetulo presenta el concepto de persistencia que alude a los programasque mantienen los datos en almacenamiento permanente y muestra coacutemo usardiferentes tipos de almacenamiento permanente tales como archivos y bases dedatos

PersistenciaLa mayoriacutea de los programas que hemos visto hasta ahora han sido transitorioses decir se ejecutan por un tiempo corto y generan una salida pero cuandofinalizan sus datos desaparecen Si ejecuta el programa nuevamente estecomienza de cero

Otros programas en cambio son persistentes se ejecutan durante un largoperiacuteodo de tiempo (o todo el tiempo) mantienen al menos parte de sus datos enalmacenamiento permanente (en un disco duro por ejemplo) y si se apagan yvuelven a comenzar retoman donde lo dejaron

Ejemplos de programas persistentes son los sistemas operativos que se ejecutansiempre que una computadora esteacute encendida y los servidores web que seejecutan todo el tiempo esperando a que lleguen solicitudes a la red

Una de las formas maacutes simples para que los programas mantengan sus datos esleyendo y escribiendo archivos de texto Ya se han visto programas que leenarchivos de texto y en este capiacutetulo se van a ver programas que los escriben

Otra alternativa es almacenar el estado del programa en una base de datos Eneste capiacutetulo tambieacuten se presentaraacute coacutemo usar una base de datos simple

Lectura y EscrituraUn archivo de texto es una secuencia de caracteres almacenados en un mediopermanente como un disco duro o una memoria flash Ya se vio coacutemo abrir y leerun archivo en Seccioacuten 91

Para escribir un archivo debe abrirlo usando el modo w (de write) comosegundo paraacutemetro

juliagt fout = open(salidatxt w)IOStream(ltfile salidatxtgt)

Si el archivo ya existe abrirlo en modo de escritura borra los datos antiguos ycomienza de nuevo iexclasiacute que tenga cuidado Si el archivo no existe se crea unonuevo open devuelve un objeto de archivo y la funcioacuten write escribe datos en elarchivo

186 Capiacutetulo 14 Archivos

juliagt linea1 = El Cid convoca a sus vasallosn

juliagt write(fout linea1)31

El valor de retorno es el nuacutemero de caracteres que se escribieron El objeto dearchivo fout lleva el registro de doacutende se quedoacute por uacuteltima vez por lo que sillama a write nuevamente esta agrega nuevos datos al final del archivo

juliagt linea2 = eacutestos se destierran con eacuteln

juliagt write(fout linea2)30

Cuando el usuario haya terminado de escribir debe cerrar el archivo

juliagt close(fout)

Si no cierra el archivo este se cierra cuando finaliza el programa

FormateoEl argumento de write tiene que ser una cadena por lo que si queremos ponerotros valores en un archivo tenemos que convertirlos a cadenas La forma maacutesfaacutecil de hacerlo es con la funcioacuten string o con interpolacioacuten de cadenas

juliagt fout = open(salidatxt w)IOStream(ltfile salidatxtgt)juliagt write(fout string(150))3

Otra alternativa es utilizar la familia de funciones de print(ln)

juliagt camellos = 4242juliagt println(fout He visto $camellos camellos)

OBSERVACIOacuteN

Una alternativa maacutes potente es la macro printf queimprime utilizando cadenas con especificacioacuten deformato al maacutes puro estilo C Puede leer maacutes sobre estoen httpsdocsjulialangorgenv1stdlibPrintf

Formateo 187

Nombre de Archivo y RutaLos archivos estaacuten organizados en directorios (tambieacuten llamados carpetas)Cada programa en ejecucioacuten tiene su propio directorio actual que es eldirectorio que usaraacute por defecto para para la mayoriacutea de las operaciones Porejemplo cuando abre un archivo para leer Julia lo busca en el directorio actual

La funcioacuten pwd (en ingleacutes print working directory) devuelve el nombre deldirectorio actual

juliagt cwd = pwd()homeben

cwd significa directorio del trabajo actual (en ingleacutes ldquocurrent workingdirectoryrdquo) El resultado en este ejemplo es homeben que es el directorio deinicio de un usuario llamado ben

Una cadena como homeben que identifica un archivo o directorio se llamaruta o path

Un nombre de archivo simple como memotxt tambieacuten se considera una rutaaunque es una ruta relativa porque comienza en el directorio actual Si eldirectorio actual es homeben el nombre de archivo memotxt se refiere ahomebenmemotxt

Una ruta que comienza con no depende del directorio actual Este tipo de rutase llama ruta absoluta Para encontrar la ruta absoluta de un archivo puede usarabspath

juliagt abspath(memotxt)homebenmemotxt

Julia tambieacuten tiene otras funciones para trabajar con nombres de archivo y rutasPor ejemplo ispath comprueba si existe un archivo o directorio

juliagt ispath(memotxt)true

Si existe isdir comprueba si es un directorio

juliagt isdir(memotxt)falsejuliagt isdir(homeben)true

188 Capiacutetulo 14 Archivos

Del mismo modo isfile comprueba que se trate de un archivo

readdir devuelve un arreglo de los archivos (y otros directorios) en el directoriodado

juliagt readdir(cwd)3-element ArrayString1 memotxt musica fotos

Para mostrar el comportamiento de estas funciones el siguiente ejemplorecorre un directorio imprime los nombres de todos los archivos y se llama a siacutemisma de manera recursiva en todos los directorios

function recorrer(nombredir) for nombre in readdir(nombredir) ruta = joinpath(nombredir nombre) if isfile(ruta) println(ruta) else recorrer(ruta) end endend

joinpath toma un directorio y un nombre de archivo y los une en una rutacompleta

OBSERVACIOacuteN

Julia tiene una funcioacuten integrada llamada walkdir (veahttpsdocsjulialangorgenv1basefileBaseFilesystemwalkdir) que es similar a esta pero maacutesversaacutetil Como ejercicio lea la documentacioacuten y uacuteselapara imprimir los nombres de los archivos en undirectorio dado y sus subdirectorios

Captura de ExcepcionesMuchas cosas pueden salir mal al intentar leer y escribir archivos Al intentarabrir un archivo que no existe se obtiene un SystemError

juliagt fin = open(archivo_malo)ERROR SystemError opening file archivo_malo No such file or directory

Si el usuario intenta abrir un archivo pero no tiene permiso para acceder a eacutel

Captura de Excepciones 189

obtiene el error de sistema Permission denied (Permiso denegado)

Para evitar estos errores se podriacutean usar funciones como ispath e isfile perotomariacutea mucho tiempo y liacuteneas de coacutedigo verificar todas las posibilidades

Es maacutes faacutecil intentar lidiar con los problemas a medida que ocurren que esexactamente lo que hace la sentencia try La sintaxis es similar a una sentenciaif

try fin = open(archivo_malotxt)catch exc println(Algo salioacute mal $exc)end

Julia comienza ejecutando el bloque try Si nada falla se saltaraacute el bloque catch yfinalizaraacute Si ocurre una excepcioacuten Julia saltaraacute fuera del bloque try y ejecutaraacuteel bloque catch

Gestionar una excepcioacuten con try recibe el nombre de capturar una excepcioacuten Eneste ejemplo el bloque catch muestra un mensaje de error que no es muy uacutetil Engeneral capturar una excepcioacuten da la oportunidad de corregir el problemavolverlo a intentar o al menos terminar el programa con elegancia

Cuando el coacutedigo realiza cambios de estado o usa recursos como archivosgeneralmente se deben hacer ciertas cosas al finalizar la programacioacuten delcoacutedigo como por ejemplo cerrar los archivos Las excepciones pueden complicaresta tarea ya que se podriacutea salir antes de lo esperado de un bloque de coacutedigo Lapalabra reservada finally permite ejecutar un coacutedigo al salir de un bloque decoacutedigo determinado independientemente de coacutemo salga

f = open(salidatxt)try linea = readline(f) println(linea)finally close(f)end

En este ejemplo la funcioacuten close siempre se ejecutaraacute

Bases de datosUna base de datos es un archivo que estaacute organizado para almacenar datos Lamayoriacutea de las bases de datos estaacuten organizadas como diccionarios en el sentidode que realizan asociaciones entre claves y valores La diferencia maacutes importanteentre un diccionario y una base de datos es que la base de datos se encuentra en

190 Capiacutetulo 14 Archivos

el disco (u otro almacenamiento permanente) de modo que su contenido seconserva despueacutes de que el programa haya finalizado

IntroAJulia proporciona una interfaz para GDBM (GNU dbm) que permite creary actualizar archivos de base de datos A modo de ejemplo se crea una base dedatos que contiene pies de foto para archivos de imagen

Abrir una base de datos es similar a abrir otros archivos

juliagt using IntroAJulia

juliagt bd = DBM(piedefoto c)DBM(ltpiedefotogt)

El modo c significa que la base de datos debe crearse si no existe El resultadoes un objeto de base de datos que se puede usar (para la mayoriacutea de lasoperaciones) como un diccionario

Cuando se crea un nuevo elemento GDBM actualiza el archivo de base de datos

juliagt bd[luismipng] = Foto de Luis MiguelFoto de Luis Miguel

Cuando accede a uno de los elementos GDBM lee el archivo

juliagt bd[luismipng]Foto de Luis Miguel

Si realiza otra asignacioacuten a una clave existente GDBM reemplaza el valoranterior

juliagt bd[luismipng] = Foto de Luis Miguel cantandoFoto de Luis Miguel cantandojuliagt bd[luismipng]Foto de Luis Miguel cantando

Algunas funciones que tienen un diccionario como argumento con claves yvalores no funcionan con objetos de base de datos No obstante la iteracioacuten conun bucle for siacute

for (clave valor) in bd println(clave valor)end

Al igual que con otros archivos debe cerrar la base de datos cuando haya

Bases de datos 191

terminado

juliagt close(bd)

SerializacioacutenUna limitacioacuten de GDBM es que las claves y los valores deben ser cadenas oconjuntos de bytes Si intenta utilizar cualquier otro tipo se produciraacute un error

Las funciones serialize y deserialize pueden ser uacutetiles Traducen casi cualquiertipo de objeto en un arreglo de bytes (un iobuffer) adecuado para elalmacenamiento en una base de datos y luego traducen los arreglos de bytesnuevamente en objetos

juliagt using Serialization

juliagt io = IOBuffer()

juliagt t = [1 2 3]

juliagt serialize(io t)24juliagt print(take(io))UInt8[0x37 0x4a 0x4c 0x0a 0x04 0x00 0x00 0x00 0x15 0x00 0x080xe2 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x02 0x00 0x000x00 0x00 0x00 0x00 0x00 0x03 0x00 0x00 0x00 0x00 0x00 0x000x00]

El formato no es intuitivo para nosotros pero es faacutecil de interpretar para Juliadeserialize reconstituye el objeto

juliagt io = IOBuffer()

juliagt t1 = [1 2 3]

juliagt serialize(io t1)24juliagt s = take(io)

juliagt t2 = deserialize(IOBuffer(s))

juliagt print(t2)[1 2 3]

serialize y deserialize escriben y leen desde un objeto iobuffer que representa unIO stream en memoria La funcioacuten take recupera el contenido del iobuffer como

192 Capiacutetulo 14 Archivos

un arreglo de bytes y reestablece el iobuffer a su estado inicial

Aunque el nuevo objeto tiene el mismo valor que el anterior no es (en general) elmismo objeto

juliagt t1 == t2truejuliagt t1 equiv t2false

En otras palabras la serializacioacuten y luego la deserializacioacuten tienen el mismoefecto que copiar el objeto

Esto se puede usar para almacenar valores que no sean cadenas en una base dedatos

OBSERVACIOacuteN

De hecho el almacenamiento de valores que no soncadenas en una base de datos es tan comuacuten que se haencapsulado en un paquete llamado JLD2 (consultehttpsgithubcomJuliaIOJLD2jl)

Objetos de ComandoLa mayoriacutea de los sistemas operativos proporcionan una interfaz de liacutenea decomandos tambieacuten conocida como shell Las shells generalmente proporcionancomandos para navegar por el sistema de archivos y ejecutar aplicaciones Porejemplo en Unix puede cambiar los directorios con cd mostrar el contenido deun directorio con ls e iniciar un navegador web escribiendo (por ejemplo) firefox

Cualquier programa que se pueda iniciar desde la shell tambieacuten puede iniciarsedesde Julia usando un objeto de comando

juliagt cmd = `echo hola``echo hola`

Las comillas invertidas se usan para delimitar el comando

La funcioacuten run ejecuta el comando

juliagt run(cmd)hola

hola es la salida del comando echo enviado a STDOUT La funcioacuten run devuelveun objeto de proceso y genera un ErrorException si el comando externo no se

Objetos de Comando 193

ejecuta correctamente

Si se desea leer la salida del comando externo se puede usar read en su lugar

juliagt a = read(cmd String)holan

Por ejemplo la mayoriacutea de los sistemas Unix tienen un comando llamadomd5sum o md5 que lee el contenido de un archivo y calcula una suma deverificacioacuten Puede leer sobre Md5 en httpsenwikipediaorgwikiMd5 Estecomando proporciona una manera eficiente de verificar si dos archivos tienen elmismo contenido La probabilidad de que diferentes contenidos produzcan lamisma suma de comprobacioacuten es muy pequentildea

Puede usar un objeto de comando para ejecutar md5 desde Julia y obtener elresultado

juliagt nombrearchivo = salidatxtsalidatxtjuliagt cmd = `md5 $nombrearchivo``md5 salidatxt`juliagt res = read(cmd String)ERROR IOError could not spawn `md5 salidatxt` no such file ordirectory (ENOENT)

Modulos

Supongamos que tenemos un archivo llamado wcjl con el siguiente coacutedigo

function contarlineas(nombrearchivo) conteo = 0 for linea in eachline(nombrearchivo) conteo += 1 end conteoend

print(contarlineas(wcjl))

Si ejecuta este programa se leen las liacuteneas de coacutedigo y se imprime el nuacutemero deliacuteneas en el archivo que es 9 Tambieacuten puede incluirlo en REPL de esta manera

juliagt include(wcjl)9

194 Capiacutetulo 14 Archivos

Los moacutedulos permiten crear espacios de trabajo separados es decir nuevosglobal scopes (aacutembitos de tipo global) Una sentencia tiene global scope si tieneefecto en todo el programa

Un moacutedulo comienza con la palabra reservada module y termina con end Al usarmoacutedulos se evitan los conflictos de nombres entre sus propias definiciones denivel superior y las que se encuentran en el coacutedigo de otra persona importpermite controlar queacute nombres de otros moacutedulos estaacuten visibles y exportespecifica cuaacuteles de sus nombres son puacuteblicos es decir aquellos que se puedenusar fuera del moacutedulo sin tener el prefijo del nombre del moacutedulo

module ContarLineas export contarlineas

function contarlineas(nombrearchivo) conteo = 0 for linea in eachline(nombrearchivo) conteo += 1 end conteo endend

El moacutedulo ContarLineas proporciona la funcioacuten contarlineas

juliagt using ContarLineas

juliagt contarlineas(wcjl)11

Ejercicio 14-1

Escriba este ejemplo en un archivo llamado wcjl incluacuteyalo en REPL (coninclude) y escriba using ContarLineas

AVISO

Si importa un moacutedulo que ya se ha importado Julia no hace nadaNo se vuelve a leer el archivo incluso si ha sido modificado

Si desea volver a cargar un moacutedulo debe reiniciar REPL Elpaquete Revise puede ayudarlo a no reiniciar tan seguido (veahttpsgithubcomtimholyRevisejl)

DepuracioacutenAl leer y escribir archivos el usuario puede tener problemas con los espacios enblanco Estos errores pueden ser difiacuteciles de depurar porque los espacios las

Depuracioacuten 195

tabulaciones y las nuevas liacuteneas son generalmente invisibles

juliagt s = 1 2t 3n 4

juliagt println(s)1 2 3 4

Las funciones integradas repr o dump pueden ser de ayuda Toman cualquierobjeto como argumento y devuelven una representacioacuten de tipo cadena delobjeto

1 2t 3n 4

juliagt repr(s)1 2t 3n 4juliagt dump(s)String 1 2t 3n 4

Esto puede ser uacutetil para la depuracioacuten

Otro problema con el que es faacutecil encontrarse es que en diferentes sistemasoperativos se usan diferentes caracteres para indicar el final de una liacuteneaAlgunos sistemas usan una nueva liacutenea representada por n Otros usan uncaraacutecter de retorno r Algunos usan ambos Si un archivo es usado en diferentessistemas estas inconsistencias podriacutean causar problemas

Para la mayoriacutea de los sistemas hay aplicaciones para convertir de un formato aotro Puede encontrarlas (y leer maacutes sobre este tema) enhttpsenwikipediaorgwikiNewline O por supuesto podriacutea escribir una ustedmismo

Glosariopersistente

Perteneciente a un programa que se ejecuta indefinidamente y mantiene almenos algunos de sus datos en almacenamiento permanente

archivo de textoUna secuencia de caracteres almacenados en almacenamiento permanentetal como en un disco duro

directorioUna coleccioacuten de archivos con nombre tambieacuten llamada carpeta

196 Capiacutetulo 14 Archivos

rutaUna cadena que identifica a un archivo

ruta relativaUna ruta que comienza en el directorio actual

ruta absolutaUna ruta que comienza en el directorio superior del sistema de archivos

capturar (catch)Evitar que una excepcioacuten haga terminar un programa utilizando lassentencias try catch finally

base de datosUn archivo cuyo contenido estaacute organizado como un diccionario con clavesque corresponden a valores

shellUn programa que permite a los usuarios escribir comandos y luegoejecutarlos iniciando otros programas

objeto de comandoUn objeto que representa un comando de shell Esto permite que unprograma de Julia ejecute comandos y lea los resultados

Ejercicios

Ejercicio 14-2

Escriba una funcioacuten llamada sed que tome como argumentos una cadena depatrones una cadena de reemplazo y dos nombres de archivo La funcioacuten debeleer el primer archivo y escribir el contenido en el segundo archivo (creaacutendolo sies necesario) Si la cadena de patrones aparece en alguacuten lugar del archivo debereemplazarse con la cadena de reemplazo

Si se produce un error al abrir leer escribir o cerrar los archivos su programadebe detectar la excepcioacuten imprimir un mensaje de error y terminar

Ejercicio 14-3

Si hizo Seccioacuten 12102 recordaraacute que debiacutea crear un diccionario que asociabauna cadena ordenada de letras al conjunto de palabras que se podiacutea deletrearcon esas letras Por ejemplo cuaderno estaba asociado al arreglo [cuadernoeducaron encuadro]

Escriba un moacutedulo que importe conjuntoanagramas y proporcione dos nuevas

Ejercicios 197

funciones almacenaranagramas que almacena el diccionario de anagramasusando JLD2 (vea httpsgithubcomJuliaIOJLD2jl) y leeranagramas que buscauna palabra y devuelve un arreglo de sus anagramas

Ejercicio 14-4

En una gran coleccioacuten de archivos MP3 puede haber maacutes de una copia de lamisma cancioacuten almacenada en diferentes directorios o con diferentes nombresde archivo El objetivo de este ejercicio es buscar duplicados

1 Escriba un programa que busque un directorio y todos sus subdirectoriosde forma recursiva y devuelva un arreglo de rutas completas para todos losarchivos con un sufijo dado (como mp3)

2 Para reconocer duplicados puede usar md5sum o md5 para calcular unasuma de verificacioacuten para cada archivo Si dos archivos tienen la mismasuma de verificacioacuten probablemente tengan el mismo contenido

3 Para verificarlo puede usar el comando de Unix diff

198 Capiacutetulo 14 Archivos

Capiacutetulo 15 Estructuras y ObjetosA esta altura ya debe saber coacutemo usar funciones para tener un coacutedigo maacutesorganizado y coacutemo usar los tipos integrados de Julia para organizar sus datos Elsiguiente paso es aprender a construir sus propios tipos para organizar tanto elcoacutedigo como los datos Este es un gran tema y por lo tanto tomaraacute un par decapiacutetulos abarcar todo

Tipos CompuestosSe han utilizado muchos tipos integrados en Julia y ahora se va a definir unnuevo tipo A modo de ejemplo se crea un tipo llamado Punto que representa unpunto en un espacio bidimensional

En notacioacuten matemaacutetica los puntos suelen escribirse entre pareacutentesis con unacoma que separa las coordenadas Por ejemplo representa el origen y representa el punto localizado unidades a la derecha y unidades hacia arribadel origen

Hay varias formas en que se podriacutean representar puntos del plano cartesiano enJulia

bull Almacenando las coordenadas por separado en dos variables x e y

bull Almacenando las coordenadas como elementos de un arreglo o tupla

bull Creando un nuevo tipo para representar puntos como objetos

Crear un nuevo tipo exige un poco maacutes de esfuerzo que las otras dos opcionespero tiene algunas ventajas como pronto se veraacute

Un tipo compuesto definido por el programador tambieacuten se denomina estructura(struct en ingleacutes) La definicioacuten de estructura de un punto se ve asiacute

struct Punto x yend

El encabezado indica que la nueva estructura se llama Punto El cuerpo definelos atributos o campos de la estructura La estructura de Punto tiene doscampos x e y

Una estructura es como una faacutebrica que crea objetos Para crear un punto sedebe llamar a Punto como si fuera una funcioacuten que tiene como argumentos losvalores de los campos Cuando Punto se usa como una funcioacuten se llamaconstructor

Tipos Compuestos 199

juliagt p = Punto(30 40)Punto(30 40)

El valor de retorno es una referencia a un objeto Punto el cual es asignado a p

La creacioacuten de un nuevo objeto se llama instanciacioacuten y el objeto creado es unainstancia del tipo

Cuando se imprime una instancia Julia dice a queacute tipo pertenece y cuaacuteles son losvalores de los atributos

Cada objeto es una instancia de alguacuten tipo por lo que objeto e instancia sonintercambiables No obstante en este capiacutetulo se utiliza instancia para indicarque se estaacute hablando de un tipo definido por el programador

Un diagrama de estado que muestra un objeto y sus atributos se denominadiagrama de objeto (ver Figura 20)

Figura 20 Diagrama de objeto

Las Estructuras son Inmutables

Puede obtener los valores de los campos utilizando la notacioacuten

juliagt x = px30juliagt py40

La expresioacuten px significa Vaya al objeto al que se apunta p y obtenga el valorde x En el ejemplo se asigna ese valor a una variable llamada x No hayconflicto entre la variable x y el atributo x

Puede usar esa notacioacuten de punto como parte de cualquier expresioacuten Porejemplo

juliagt distancia = sqrt(px^2 + py^2)50

Sin embargo las estructuras son inmutables por defecto y despueacutes de laconstruccioacuten los campos no pueden cambiar su valor

200 Capiacutetulo 15 Estructuras y Objetos

juliagt py = 10ERROR setfield immutable struct of type Punto cannot be changed

Esto puede parecer extrantildeo al principio pero tiene varias ventajas

bull Puede ser maacutes eficiente

bull No es posible violar las invariantes (requisitos que deberiacutean cumplirse entodos los objetos en todo momento) de los constructores de un tipocompuesto (ver Seccioacuten 174)

bull El coacutedigo que usa objetos inmutables puede ser maacutes faacutecil de entender

Estructuras MutablesDe ser necesario se pueden declarar tipos compuestos mutables con la palabrareservada mutable struct A continuacioacuten se muestra la definicioacuten de un puntomutable

mutable struct MPunto x yend

Puede asignar valores a una instancia de una estructura mutable utilizandonotacioacuten de punto ()

juliagt blanco = MPunto(00 00)MPunto(00 00)juliagt blancox = 3030juliagt blancoy = 4040

RectaacutengulosA veces decidir cuaacuteles deberiacutean ser los campos de un objeto es faacutecil pero enotros casos no Por ejemplo imagine que se quiere un tipo que represente unrectaacutengulo iquestQueacute campos usariacutea para especificar la ubicacioacuten y el tamantildeo de unrectaacutengulo Puede ignorar el aacutengulo Para simplificar las cosas suponga que elrectaacutengulo es vertical u horizontal

Hay al menos dos posibilidades

bull Puede especificar una esquina del rectaacutengulo (o el centro) el ancho y laaltura

Estructuras Mutables 201

bull Puede especificar dos esquinas opuestas

Es difiacutecil decir que una opcioacuten es mejor que la otra por lo que implementaremosla primera a modo de ejemplo

Representa un rectaacutengulo

atributos ancho alto esquinastruct Rectangulo ancho alto esquinaend

El texto escrito entre comillas triples es llamado cadena de documentacioacuten (odocstring) y permite documentar La documentacioacuten es el acto de comentarconvenientemente cada una de las partes que tiene el programa

En este ejemplo la cadena de documentacioacuten (o docstring) enumera losatributos Los atributos ancho y alto son nuacutemeros y esquina es un objeto Puntoque especifica la esquina inferior izquierda

Para representar un rectaacutengulo debe crear una instancia del tipo Rectangulo

juliagt origen = MPunto(00 00)MPunto(00 00)juliagt caja = Rectangulo(1000 2000 origen)Rectangulo(1000 2000 MPunto(00 00))

Figura 21 muestra el estado de este objeto Un objeto es embebido si es atributode otro objeto Debido a que el atributo esquina se refiere a un objeto mutablese dibuja fuera del objeto Rectangulo

Figura 21 Diagrama de objeto

Instancias como ArgumentosPodemos pasar una instancia como argumento de la manera habitual Porejemplo

202 Capiacutetulo 15 Estructuras y Objetos

function imprimirpunto(p) println(($(px) $(py)))end

imprimirpunto toma un Punto como argumento y lo muestra en notacioacutenmatemaacutetica Puede llamar a imprimirpunto con un argumento p

juliagt imprimirpunto(blanco)(30 40)

Ejercicio 15-1

Escriba una funcioacuten llamada distanciaentrepuntos que tome dos puntos comoargumentos y devuelva la distancia entre ellos

Si un objeto de estructura mutable se pasa a una funcioacuten como argumento lafuncioacuten puede modificar los campos del objeto Por ejemplo moverpunto tomaun objeto mutable Punto y dos nuacutemeros dx y dy los cuales suma a los atributos xe y de Punto respectivamente

function moverpunto(p dx dy) px += dx py += dy nothingend

Aquiacute hay un ejemplo que muestra como funciona

juliagt origen = MPunto(00 00)MPunto(00 00)juliagt moverpunto(origen 10 20)

juliagt origenMPunto(10 20)

Dentro de la funcioacuten p es un alias de origen por lo que cuando la funcioacutenmodifica p origen tambieacuten cambia

Al pasar un objeto inmutable Punto a moverpunto se produce un error

juliagt moverpunto(p 10 20)ERROR setfield immutable struct of type Punto cannot be changed

Sin embargo se puede modificar el valor de un atributo mutable de un objeto

Instancias como Argumentos 203

inmutable Por ejemplo moverrectangulo tiene como argumentos un objetoRectangulo y dos nuacutemeros dx y dy Esta funcioacuten usa moverpunto para mover laesquina del rectaacutengulo

function moverrectangulo(rect dx dy) moverpunto(rectesquina dx dy)end

Ahora p en moverpunto es un alias para rectesquina por lo que cuando p semodifica rectesquina tambieacuten cambia

juliagt cajaRectangulo(1000 2000 MPunto(00 00))juliagt moverrectangulo(caja 10 20)

juliagt cajaRectangulo(1000 2000 MPunto(10 20))

AVISO

No puede reasignar un atributo mutable de un objeto inmutable

juliagt cajaesquina = MPunto(10 20)ERROR setfield immutable struct of type Rectangulo cannotbe changed

Instancias como Valores de RetornoLas funciones pueden devolver instancias Por ejemplo encontrarcentro toma unRectangulo como argumento y devuelve un Punto que contiene las coordenadasdel centro del rectaacutengulo

function encontrarcentro(rect) Punto(rectesquinax + rectancho 2 rectesquinay + rectalto 2)end

La expresioacuten rectcornerx significa ldquoVaya al objeto al que rect apunta yseleccione el atributo llamado esquina Luego vaya a ese objeto y seleccione elatributo llamado x

A continucioacuten se observa un ejemplo que toma caja como argumento y asigna elPunto resultante a centro

juliagt centro = encontrarcentro(caja)Punto(510 1020)

204 Capiacutetulo 15 Estructuras y Objetos

CopiadoEl uso de alias puede hacer que un programa sea difiacutecil de leer ya que loscambios hechos en un lugar pueden tener efectos inesperados en otro lugar Esdifiacutecil estar al tanto de todas las variables a las que puede apuntar un objetodado

Copiar un objeto es muchas veces una alternativa a la creacioacuten de un alias Juliaprovee una funcioacuten llamada copy que puede duplicar cualquier objeto

juliagt p1 = MPunto(30 40)MPunto(30 40)juliagt p2 = deepcopy(p1)MPunto(30 40)juliagt p1 equiv p2falsejuliagt p1 == p2false

El operador equiv indica que p1 y p2 no son el mismo objeto lo cual es esperable Loque no es del todo esperable es que == no devuelva true aunque estos puntoscontengan los mismos datos Resulta que para los objetos mutables elcomportamiento predeterminado del operador == es el mismo que el operador=== es decir comprueba la identidad del objeto no la equivalencia del objetoEsto se debe a que Julia no sabe queacute deberiacutea considerarse equivalente para lostipos compuestos mutables Al menos no todaviacutea

Ejercicio 15-2

Cree una instancia de Punto haga una copia y verifique la equivalencia y laigualdad de ambas El resultado puede sorprenderlo pero explica por queacute elalias no es un problema para un objeto inmutable

DepuracioacutenAl comenzar a trabajar con objetos es probable que encuentre algunasexcepciones nuevas Si intenta acceder a un campo que no existe obtendraacute

juliagt p = Punto(30 40)Punto(30 40)juliagt pz = 10ERROR type Punto has no field z

Si no estaacute seguro del tipo de un objeto puede saberlo de la siguiente manera

Copiado 205

juliagt typeof(p)Punto

Tambieacuten puede usar isa para verificar si un objeto es una instancia de un tipoespeciacutefico

juliagt p isa Puntotrue

Si no estaacute seguro de si un objeto tiene un atributo particular puede usar lafuncioacuten fieldnames

juliagt fieldnames(Punto)(x y)

o la funcioacuten isdefined

juliagt isdefined(p x)truejuliagt isdefined(p z)false

El primer argumento puede ser cualquier objeto y el segundo argumento es elsiacutembolo seguido del nombre del atributo

Glosarioestructura

Un tipo compuesto

constructorUna funcioacuten con el mismo nombre que un tipo que crea instancias de estetipo

instanciaUn objeto que pertenece a un tipo

instanciarCrear un nuevo objeto

atributo o campoUn valor con nombre asociado un objeto

206 Capiacutetulo 15 Estructuras y Objetos

objeto embebidoUn objeto que se almacena como atributo de otro objeto

deep copy o copia profundaCopiar el contenido de un objeto y cualquier objeto embebido en eacutel y a suvez cualquier objeto embebido en ellos y asiacute sucesivamente Implementadopor la funcioacuten deepcopy

diagrama de objetoUn diagrama que muestra objetos sus atributos y valores de atributos

Ejercicios

Ejercicio 15-3

1 Escriba una definicioacuten de un tipo llamado Circulo que tenga atributos centroy radio y doacutende centro sea un objeto Punto y radio un nuacutemero

2 Cree una instancia de un objeto Circulo que represente a un ciacuterculo concentro en y radio 75

3 Escriba una funcioacuten llamada puntoencirculo que tome un objeto Circulo y unobjeto Punto y devuelva true si el punto se encuentra dentro o en el liacutemitedel ciacuterculo

4 Escriba una funcioacuten llamada rectencirculo que tome un objeto Circulo y unobjeto Rectangulo y devuelva true si el rectaacutengulo se encuentracompletamente dentro o en el liacutemite del ciacuterculo

5 Escriba una funcioacuten llamada sobreposicionrectcirc que tome un objetoCirculo y un objeto Rectangulo y devuelva true si alguna de las esquinas delrectaacutengulo cae dentro del ciacuterculo Una versioacuten maacutes desafiante es escribiruna funcioacuten que devuelva true si alguna parte del rectaacutengulo (nonecesariamente una esquina) cae dentro del ciacuterculo

Ejercicio 15-4

1 Escriba una funcioacuten llamada dibujarrect que tome como argumentos unobjeto turtle y un objeto Rectaacutengulo y use turtle para dibujar el rectaacutenguloConsulte el Capiacutetulo 4 para ver ejemplos que usen objetos Turtle

2 Escriba una funcioacuten llamada dibujarcirculo que tome como argumentos unobjeto Turtle y un objeto Circulo y dibuje el ciacuterculo

Ejercicios 207

Capiacutetulo 16 Estructuras y FuncionesAhora que se ha tratado coacutemo crear tipos compuestos el siguiente paso esescribir funciones que tomen objetos definidos por el programador comoparaacutemetros y que devuelvan otros como resultados En este capiacutetulo tambieacuten sepresenta el estilo de programacioacuten funcional y dos nuevas formas dedesarrollar programas

TiempoComo otro ejemplo de tipo compuesto se define una estructura llamada Horaque registra la hora del diacutea La definicioacuten de esta estructura se muestra acontinuacioacuten

Representa la hora del diacutea

atributos hora minuto segundostruct Hora hora minuto segundoend

Observacioacuten Time es una palabra reservada de Julia

juliagt tiempo = Hora(11 59 30)Hora(11 59 30)

El diagrama de objeto para el objeto Hora luce asiacute Figura 22

Figura 22 Diagrama de objeto

Ejercicio 16-1

Escriba una funcioacuten llamada imprimirhora que tome un objeto Hora y lo imprimacon el formato horaminutosegundo Printf de la macro printf del moacuteduloStdLib permite imprimir un nuacutemero entero con el formato 02d es decirutilizando al menos dos diacutegitos incluido un cero inicial si es necesario

208 Capiacutetulo 16 Estructuras y Funciones

Ejercicio 16-2

Escriba una funcioacuten booleana llamada estadespues que tome dos objetos Horat1 y t2 y devuelva true si la hora t1 estaacute despueacutes que t2 y false de lo contrarioDesafiacuteo no use sentencias if

Funciones PurasEn las siguientes secciones se escriben dos versiones de una funcioacuten que calculala suma de horas La primera versioacuten muestra un tipo de funcioacuten llamado funcioacutenpura y la segunda un tipo llamado modificador Ademaacutes estas versionespermitiraacuten mostrar un nuevo plan de desarrollo de programas llamado desarrollode prototipos una forma de abordar un problema complejo comenzando con unprototipo simple y lidiando gradualmente con las complicaciones

Este es un primer prototipo de la funcioacuten sumahora

function sumahora(t1 t2) Hora(t1hora + t2hora t1minuto + t2minuto t1segundo +t2segundo)end

La funcioacuten crea un nuevo objeto Hora inicializa sus atributos y devuelve unareferencia al nuevo objeto A esto se le llama funcioacuten pura porque no modificaninguno de los objetos que se le pasan como argumento y no tiene efectos (comomostrar un valor o tomar una entrada del usuario) maacutes que devolver un valor

Para probar esta funcioacuten se crean dos objetos Hora inicio que contiene la horade inicio de una peliacutecula como Roma y duracion que contiene la duracioacuten de lapeliacutecula que es dos horas y 15 minutos

sumahora calcula cuaacutendo se terminaraacute la peliacutecula

imprimirhora (generic function with 1 method)

juliagt inicio = Hora(9 50 0)

juliagt duracion = Hora(2 15 0)

juliagt finaliza = sumahora(inicio duracion)

juliagt imprimirhora(finaliza)116500

El resultado 116500 no es lo que se buscaba El problema es que esta funcioacuten

Funciones Puras 209

no considera los casos en los que el nuacutemero de segundos o minutos suma maacutesque sesenta Cuando esto ocurre debemos acarrear (como en una suma) lossegundos sobrantes a la columna de los minutos o los minutos extras a lacolumna de las horas He aquiacute una versioacuten corregida de la funcioacuten

function sumahora(t1 t2) segundo = t1segundo + t2segundo minuto = t1minuto + t2minuto hora = t1hora + t2hora if segundo gt= 60 segundo -= 60 minuto += 1 end if minuto gt= 60 minuto -= 60 hora += 1 end Hora(hora minuto segundo)end

Aunque esta funcioacuten es correcta es muy larga Maacutes adelante se exploraraacute unaalternativa maacutes corta

ModificadoresHay veces en las que es uacutetil que una funcioacuten modifique uno o maacutes de los objetosque recibe como paraacutemetros En ese caso los cambios son visibles en el nivel endonde se ubica la sentencia de llamada Estas funciones se llaman modificadores

La funcioacuten incrementar que agrega un nuacutemero dado de segundos a un objetoHora puede escribirse naturalmente como un modificador Aquiacute se muestra unprototipo de la funcioacuten

function incrementar(tiempo segundos) tiemposegundo += segundos if tiemposegundo gt= 60 tiemposegundo -= 60 tiempominute += 1 end if tiempominuto gt= 60 tiempominuto -= 60 tiempohora += 1 endend

La primera liacutenea realiza la suma de los segundos y las restantes se ocupan de los

210 Capiacutetulo 16 Estructuras y Funciones

casos especiales vistos anteriormente

iquestEs correcta esta funcioacuten iquestQueacute ocurre si el paraacutemetro segundos es muchomayor que sesenta

En tal caso no es suficiente con acarrear una vez debemos seguir hacieacutendolohasta que tiemposegundo sea menor que sesenta Una solucioacuten es sustituir lassentencias if por sentencias while Esta funcioacuten seriacutea correcta pero no es lasolucioacuten maacutes eficiente

Ejercicio 16-3

Escriba una versioacuten correcta de incrementar sin bucles

Todo lo que se pueda hacer con modificadores tambieacuten puede lograrse confunciones puras De hecho algunos lenguajes de programacioacuten solo permitenfunciones puras Hay ciertas evidencias de que los programas que usanfunciones puras son maacutes raacutepidos de desarrollar y menos propensos a errores quelos programas que usan modificadores Sin embargo a veces los modificadoresson uacutetiles y en algunos casos los programas funcionales (es decir con funcionespuras) tienden a ser menos eficientes

En general recomendamos que escriba funciones puras siempre que searazonable y recurra a los modificadores soacutelo si hay una ventaja convincente Esteenfoque podriacutea llamarse estilo de programacioacuten funcional

Ejercicio 16-4

Escriba una versioacuten pura de incrementar que cree y devuelva un nuevo objetoHora en vez de modificar el paraacutemetro

Desarrollo de prototipos frente a la planificacioacutenEl desarrollo de programas que veremos ahora se llama ldquodesarrollo deprototiposrdquo En cada una de las funciones anteriores escribimos un prototipoque realizaba el caacutelculo baacutesico y luego lo probamos sobre unos cuantos casoscorrigiendo los errores a medida que iban apareciendo

Este enfoque puede ser efectivo especialmente si auacuten no tiene un conocimientoprofundo del problema No obstante las correcciones incrementales puedengenerar coacutedigo innecesariamente complicado (que considere muchos casosespeciales) y poco confiable (es difiacutecil saber si ha encontrado todos los errores)

Una alternativa es el desarrollo planificado en el que la comprensioacuten delproblema en profundidad puede facilitar en gran medida la programacioacuten En elcaso de sumahora se puede ver un objeto Hora como iexclun nuacutemero de tres diacutegitosen base 60 (vea httpsenwikipediaorgwikiSexagesimal ) El atributo segundoes la ldquocolumna de unidadesrdquo el atributo minuto es la ldquocolumna de los sesentasrdquo y

Desarrollo de prototipos frente a la planificacioacuten 211

el atributo hora es la ldquocolumna de los tres mil seiscientosrdquo

Cuando se escribiacutea sumahora e incrementar efectivamente se estaba sumandoen base 60 por eso se tuvo que acarrear de una columna a la siguiente

Esta observacioacuten sugiere otro enfoque para el problema se pueden convertir losobjetos Hora en enteros y aprovechar el hecho de que la computadora saberealizar aritmeacutetica con enteros

La siguiente funcioacuten convierte un objeto Hora en un entero

function horaaentero(tiempo) minutos = tiempohora 60 + tiempominuto segundos = minutos 60 + tiemposegundoend

Ahora para convertir un entero en un objeto Hora (recuerde que divrem divideel primer argumento por el segundo y devuelve el cociente y el resto como unatupla)

function enteroahora(segundos) (minutos segundo) = divrem(segundos 60) hora minuto = divrem(minutos 60) Hora(hora minuto segundo)end

Puede que tenga que pensar un poco y realizar algunas pruebas paraconvencerse de que estas funciones son correctas Una forma de probarlas esverificar que horaaentero((enteroahora(x)) == x para muchos valores de x Estees un ejemplo de prueba de consistencia

Una vez que esteacute convencido puede usar estas funciones para reescribirsumahora

function sumahora(t1 t2) segundos = horaaentero(t1) + horaaentero(t2) enteroahora(segundos)end

Esta versioacuten es maacutes corta que la original y maacutes faacutecil de verificar

Ejercicio 16-5

Reescriba incrementar usando horaaentero y enteroahora

Convertir de base 60 a base 10 y viceversa es maacutes difiacutecil que solo trabajar con

212 Capiacutetulo 16 Estructuras y Funciones

los tiempos El cambio de base es maacutes abstracto pero la intuicioacuten humana paratratar con las horas es mejor

Si al usuario se le ocurre tratar los tiempos como nuacutemeros de base 60 e invierteun poco de tiempo en escribir las funciones de conversioacuten (horaaentero yenteroahora) obtiene un programa maacutes corto faacutecil de leer y depurar y confiable

El cambio de base tambieacuten hace que sea maacutes faacutecil antildeadir funcionalidadesposteriormente Por ejemplo imagine restar dos Horas para hallar el intervaloentre ellas El enfoque simple seriacutea implementar una resta con preacutestamo perousar funciones de conversioacuten seriacutea maacutes faacutecil y con mayor probabilidad correcto

Iroacutenicamente a veces hacer un poblema maacutes complejo (o maacutes general) lo hacemaacutes faacutecil porque hay menos casos especiales y por lo tanto el margen de errores menor

DepuracioacutenUn objeto Hora estaacute bien definido si los valores de minuto y segundo estaacuten entre0 y 60 (incluido 0 pero no 60) y si hora es positivo hora y minuto deben servalores enteros pero se podriacutea permitir que segundo sea fraccional

Los requisitos como estos se denominan invariantes porque siempre deben serverdaderos Dicho de otra manera si no son ciertos algo estaacute mal

Escribir coacutedigo para verificar invariantes puede ayudar a detectar errores yencontrar sus causas Por ejemplo podriacutea tener una funcioacuten como eshoravalidaque tome un objeto Hora y devuelva false si viola una invariante

function eshoravalida(tiempo) if tiempohora lt 0 || tiempominuto lt 0 || tiemposegundo lt 0 return false end if tiempominuto gt= 60 || tiemposegundo gt= 60 return false end trueend

Al comienzo de cada funcioacuten puede verificar los argumentos para asegurarse deque sean vaacutelidos

Depuracioacuten 213

function sumahora(t1 t2) if eshoravalida(t1) || eshoravalida(t2) error(objeto Hora en sumahora es invaacutelido) end segundos = horaaentero(t1) + horaaentero(t2) enteroahora(segundos)end

O podriacutea usar una macro assert que verifica un invariante dado y genera unaexcepcioacuten si falla

function sumahora(t1 t2) assert(eshoravalida(t1) ampamp eshoravalida(t2) objeto Hora en sumahoraes invaacutelido) segundos = horaaentero(t1) + horaaentero(t2) enteroahora(segundos)end

Las macros assert son uacutetiles porque permiten distinguir el coacutedigo que tratacondiciones normales del coacutedigo que verifica los errores

Glosariodesarrollo de prototipos

Una forma de desarrollar programas que involucra generar un prototipo delprograma hacer pruebas y corregir errores a medida que son encontrados

desarrollo planificadoUna forma de desarrollar programas que implica una profunda comprensioacutendel problema y maacutes planificacioacuten que desarrollo incremental o desarrollo deprototipos

funcioacuten puraUna funcioacuten que no modifica los objetos que recibe como paraacutemetros Lamayoriacutea de las funciones puras son productivas

modificadorUna funcioacuten que modifica uno o maacutes de los objetos que recibe comoparaacutemetros La mayoriacutea de los modificadores son nulos es decir entreganresultado nothing

estilo funcional de programacioacutenUn estilo de programacioacuten en el que la mayoriacutea de las funciones son puras

214 Capiacutetulo 16 Estructuras y Funciones

invarianteUna condicioacuten que nunca deberiacutea cambiar durante la ejecucioacuten de unprograma

Ejercicios

Ejercicio 16-6

Escriba una funcioacuten llamada multhora que tome un objeto Hora y un nuacutemero ydevuelva un nuevo objeto Hora que contenga el producto entre Hora original y elnuacutemero

Luego use multhora para escribir una funcioacuten que tome un objeto Hora querepresente el tiempo de duracioacuten de una carrera y un nuacutemero que represente ladistancia y devuelva un objeto Hora que represente el ritmo promedio (minutospor kiloacutemetro)

Ejercicio 16-7

Julia proporciona objetos de tiempo similares a los objetos Hora de este capiacutetulopero que tienen un amplio conjunto de funciones y operadores Lea ladocumentacioacuten en httpsdocsjulialangorgenv1stdlibDates

1 Escriba un programa que tome la fecha actual e imprima el diacutea de lasemana

2 Escriba un programa que tome como entrada una fecha de cumpleantildeos eimprima la edad del usuario y la cantidad de diacuteas horas minutos ysegundos hasta su proacuteximo cumpleantildeos

3 Para dos personas nacidas en diacuteas diferentes hay un diacutea en que una tiene eldoble de edad que la otra Ese es su Diacutea Doble Escriba un programa quetome dos cumpleantildeos y calcule su Diacutea doble

4 Desafiacuteo Escriba una versioacuten maacutes general que calcule el diacutea en que unapersona es veces mayor que la otra

Ejercicios 215

Capiacutetulo 17 Dispatch MuacuteltipleJulia permite escribir coacutedigo que puede funcionar con diferentes tipos Esto sellama programacioacuten geneacuterica

En este capiacutetulo se discutiraacute sobre las declaraciones de tipo en Julia Ademaacutes sepresentan los meacutetodos que son formas de implementar diferentescomportamientos en una funcioacuten dependiendo del tipo de sus argumentos Estoes conocido como dispatch muacuteltiple

Declaraciones de Tipo

El operador asocia anotaciones de tipo con expresiones y variables

juliagt (1 + 2) Float64ERROR TypeError in typeassert expected Float64 got a value of typeInt64juliagt (1 + 2) Int643

Esto ayuda a verificar que el programa funciona de la manera esperada

El operador tambieacuten se puede agregar al lado izquierdo de una asignacioacuten ocomo parte de una declaracioacuten

juliagt function devolverfloat() xFloat64 = 100 x enddevolverfloat (generic function with 1 method)juliagt x = devolverfloat()1000juliagt typeof(x)Float64

La variable x siempre es de tipo Float64 y su valor se convierte en un puntoflotante si es necesario

Tambieacuten se puede antildeadir una anotacioacuten de tipo al encabezado de una definicioacutende funcioacuten

216 Capiacutetulo 17 Dispatch Muacuteltiple

function sinc(x)Float64 if x == 0 return 1 end sin(x)(x)end

El valor de retorno de sinc siempre se convierte al tipo Float64

En Julia cuando se omiten los tipos los valores pueden ser de cualquier tipo(Any)

MeacutetodosEn Capiacutetulo 16 definimos una estructura llamada Hora y en Seccioacuten 161escribimos una funcioacuten llamada imprimirhora

using Printf

struct Hora hora Int64 minuto Int64 segundo Int64end

function imprimirhora(tiempo) printf(02d02d02d tiempohora tiempominuto tiemposegundo)end

Para mejorar el rendimiento se pueden (y deben) agregar las declaraciones detipo a los atributos en una definicioacuten de estructura

Para llamar a esta funcioacuten debe pasarle un objeto Hora como argumento

juliagt inicio = Hora(9 45 0)Hora(9 45 0)juliagt imprimirhora(inicio)094500

Para agregar un meacutetodo a la funcioacuten imprimirhora con el fin de que esta soloacepte como argumento un objeto Hora todo lo que hay que hacer es agregar seguido de Hora al argumento tiempo en la definicioacuten de funcioacuten

Meacutetodos 217

function imprimirhora(tiempoHora) printf(02d02d02d tiempohora tiempominuto tiemposegundo)end

Un meacutetodo es una definicioacuten de funcioacuten con una especificacioacuten imprimirhoratiene un argumento de tipo Hora

Llamar a la funcioacuten imprimirhora con un objeto Hora produce el mismo resultadoque antes

juliagt imprimirhora(inicio)094500

Se redefine el primer meacutetodo sin la anotacioacuten de tipo lo cual permite unargumento de cualquier tipo

function imprimirhora(tiempo) println(No seacute coacutemo imprimir el tiempo del argumento)end

Si se llama a la funcioacuten imprimirhora con un objeto diferente de Hora seobtendraacute

juliagt imprimirhora(150)No seacute coacutemo imprimir el tiempo del argumento

Ejercicio 17-1

Reescriba horaaentero y enteroahora (de Seccioacuten 164) especificando el tipo delos argumentos

enteroahora (generic function with 1 method)

Ejemplos AdicionalesAquiacute hay una versioacuten de la funcioacuten incrementar (Ejercicio 16-5 de Seccioacuten 163)reescrita especificando el tipo de los argumentos

function incrementar(tiempoHora segundosInt64) segundos += horaaentero(tiempo) enteroahora(segundos)end

218 Capiacutetulo 17 Dispatch Muacuteltiple

Tenga en cuenta que ahora incrementar es una funcioacuten pura no un modificador

Asiacute es como se llama a la funcioacuten incrementar

juliagt inicio = Hora(9 45 0)Hora(9 45 0)juliagt incrementar(inicio 1337)Hora(10 7 17)

Si se colocan los argumentos en el orden incorrecto se obtiene un error

juliagt incrementar(1337 inicio)ERROR MethodError no method matching incrementar(Int64 Hora)

La especificacioacuten del meacutetodo es incrementar(tiempoHora segundosInt64) noincrementar(segundosInt64 tiempoHora)

Al reescribir estadespues (Ejercicio 16-2 de Seccioacuten 163) para que solo acepteobjetos Hora se tiene

function estadespues(t1Hora t2Hora) (t1hora t1minuto t1segundo) gt (t2hora t2minuto t2segundo)end

Hace falta destacar que los argumentos opcionales permiten definir muacuteltiplesmeacutetodos Por ejemplo esta definicioacuten

function f(a=1 b=2) a + 2bend

se traduce en los siguientes tres meacutetodos

f(a b) = a + 2bf(a) = f(a 2)f() = f(1 2)

Estas expresiones son definiciones vaacutelidas de meacutetodos de Julia Esta es unanotacioacuten abreviada para definir funcionesmeacutetodos

ConstructoresUn constructor es una funcioacuten especial que se llama para crear un objeto Losmeacutetodos por defecto del constructor Hora tienen las siguientes especificaciones

Constructores 219

Hora(hora minuto segundo)Hora(horaInt64 minutoInt64 segundoInt64)

Tambieacuten se pueden agregar meacutetodos propios de constructores externos

function Hora(tiempoHora) Hora(tiempohora tiempominuto tiemposegundo)end

Este meacutetodo se llama constructor de copia porque el nuevo objeto Hora es unacopia de su argumento

Para imponer invariantes se necesitan meacutetodos de constructor interno

struct Hora hora Int64 minuto Int64 segundo Int64 function Hora(horaInt64=0 minutoInt64=0 segundoInt64=0) assert(0 le minuto lt 60 Minuto no estaacute entre 0 y 60) assert(0 le segundo lt 60 Segundo no estaacute entre 0 y 60) new(hora minuto segundo) endend

La estructura Hora tiene ahora 4 meacutetodos de constructor interno

Hora()Hora(horaInt64)Hora(horaInt64 minutoInt64)Hora(horaInt64 minutoInt64 segundoInt64)

Un meacutetodo de constructor interno siempre se define dentro del bloque de unadeclaracioacuten de tipo y tiene acceso a una funcioacuten especial llamada new que creaobjetos del tipo recieacuten declarado

AVISOSi se define alguacuten constructor interno el constructor por defectoya no estaacute disponible Se tienen que escribir expliacutecitamente todoslos constructores internos necesarios

Tambieacuten existe un meacutetodo sin argumentos de la funcioacuten local new

220 Capiacutetulo 17 Dispatch Muacuteltiple

mutable struct Hora hora Int64 minuto Int64 segundo Int64 function Hora(horaInt64=0 minutoInt64=0 segundoInt64=0) assert(0 le minuto lt 60 Minuto estaacute entre 0 y 60) assert(0 le segundo lt 60 Segundo estaacute entre 0 y 60) tiempo = new() tiempohora = hora tiempominuto = minuto tiemposegundo = segundo tiempo endend

Esto permite construir estructuras de datos recursivas es decir una estructuradonde uno de los atributos es la estructura misma En este caso la estructuradebe ser mutable ya que sus atributos se modifican despueacutes de la creacioacuten deinstancias

showshow es una funcioacuten especial que devuelve la representacioacuten de cadena de unobjeto A continuacioacuten se muestra el meacutetodo show para objetos Hora

using Printf

function Baseshow(ioIO tiempoHora) printf(io 02d02d02d tiempohora tiempominutotiemposegundo)end

Esta funcioacuten guarda como cadena de texto una hora dada en el archivo al que iohace referencia

El prefijo Base es necesario si se quiere agregar un nuevo meacutetodo a la funcioacutenBaseshow

Cuando se imprime un objeto Julia llama a la funcioacuten show (esto ocurre siemprey como agregamos un nuevo meacutetodo a la funcioacuten Baseshow entonces se muestraHora con el formato que queremos)

juliagt tiempo = Hora(9 45 0)094500

Al escribir un nuevo tipo compuesto casi siempre es preferible empezar

show 221

escribiendo un constructor externo puesto que facilita la creacioacuten de instanciasde objetos y show que es uacutetil para la depuracioacuten

Ejercicio 17-2

Escriba un meacutetodo de constructor externo para la clase Punto que tome x e ycomo paraacutemetros opcionales y los asigne a los atributos correspondientes

incrementar (generic function with 1 method)

Sobrecarga de OperadoresEs posible cambiar la definicioacuten de los operadores cuando se aplican a tiposdefinidos por el usuario Esto se hace definiendo meacutetodos del operador Porejemplo si se define un meacutetodo llamado + con dos argumentos Hora se puedeusar el operador + en los objetos Hora

Asiacute es como se veriacutea la definicioacuten

import Base+

function +(t1Hora t2Hora) segundos = horaaentero(t1) + horaaentero(t2) enteroahora(segundos)end

La sentencia import agrega el operador + al aacutembito local (local scope) para quese puedan agregar meacutetodos

A continuacioacuten se muestra coacutemo usar este operador para objetos Hora

juliagt inicio = Hora(9 45)094500juliagt duracion = Hora(1 35 0)013500juliagt inicio + duracion112000

Al aplicar el operador + a objetos Hora Julia invoca el meacutetodo recieacuten agregadoCuando REPL muestra el resultado Julia invoca a show iexclHay muchas cosasocurriendo pero que no se observan

Ampliar el comportamiento de los operadores de modo que funcionen con tiposdefinidos por el usuarioprogramador se denomina sobrecarga del operador

222 Capiacutetulo 17 Dispatch Muacuteltiple

Dispatch MuacuteltipleEn la seccioacuten anterior se sumaron dos objetos Hora Imagine que ahora se quieresumar un nuacutemero entero a un objeto Hora

function +(tiempoHora segundosInt64) incrementar(tiempo segundos)end

He aquiacute un ejemplo que usa el operador + con un objeto Hora y un entero

juliagt inicio = Hora(9 45)094500juliagt inicio + 1337100717

La suma es un operador conmutativo por lo que se debe agregar otro meacutetodo

function +(segundosInt64 tiempoHora) tiempo + segundosend

Y se obtiene el mismo resultado

juliagt 1337 + inicio100717

La eleccioacuten del meacutetodo a ejecutar cuando se aplica una funcioacuten se llamadispatch Julia permite que el proceso de dispatch elija a cuaacutel de los meacutetodos deuna funcioacuten llamar en funcioacuten del nuacutemero y tipo de los argumentos dados El usode todos los argumentos de una funcioacuten para elegir el meacutetodo que se debeinvocar se conoce como dispatch muacuteltiple

Ejercicio 17-3

Escriba los siguientes meacutetodos + para objetos Punto

bull Si ambos operandos son objetos Punto el meacutetodo deberiacutea devolver un nuevoobjeto Punto cuya coordenada x sea la suma de las coordenadas x de losoperandos De manera anaacuteloga haga lo mismo para la coordenada y

bull Si el primer o el segundo operando es una tupla el meacutetodo debe agregar elprimer elemento de la tupla a la coordenada x y el segundo elemento a lacoordenada y y devolver un nuevo objeto Punto con el resultado

Dispatch Muacuteltiple 223

Programacioacuten GeneacutericaEl dispatch muacuteltiple es uacutetil cuando es necesario pero (afortunadamente) nosiempre lo es A menudo puede evitarse escribiendo funciones que funcionencorrectamente para argumentos de diferentes tipos

Muchas de las funciones que se han visto para cadenas tambieacuten funcionan paraotros tipos de secuencia Por ejemplo en Seccioacuten 112 se usa histograma paracontar la cantidad de veces que cada letra aparece en una palabra

function histograma(s) d = Dict() for c in s if c notin keys(d) d[c] = 1 else d[c] += 1 end end dend

Esta funcioacuten tambieacuten funciona para listas tuplas e incluso diccionarios siemprey cuando los elementos de s sean hashables ya que asiacute pueden usarse comoclaves de d

juliagt t = (spam huevo spam spam tocino spam)(spam huevo spam spam tocino spam)juliagt histograma(t)DictAnyAny with 3 entries spam =gt 4 huevo =gt 1 tocino =gt 1

Las funciones que pueden tomar paraacutemetros de diferentes tipos se llamanpolimoacuterficas El polimorfismo puede facilitar la reutilizacioacuten del coacutedigo

Por ejemplo la funcioacuten integrada sum que suma los elementos de una secuenciafunciona siempre que los elementos de la secuencia permitan la suma

Como se antildeadioacute el meacutetodo + para los objetos Hora entonces se puede usar sumpara Hora

224 Capiacutetulo 17 Dispatch Muacuteltiple

juliagt t1 = Hora(1 7 2)010702juliagt t2 = Hora(1 5 8)010508juliagt t3 = Hora(1 5 0)010500juliagt sum((t1 t2 t3))031710

Si todas las operaciones realizadas dentro de la funcioacuten se pueden aplicar al tipola funcioacuten se puede aplicar al tipo

El mejor tipo de polimorfismo es el que no se busca cuando usted descubre queuna funcioacuten que habiacutea escrito se puede aplicar a un tipo para el que nunca lahabiacutea planeado

Interfaz e implementacioacutenUno de los objetivos del dispatch muacuteltiple es hacer que el software sea maacutes faacutecilde mantener lo que significa poder mantener el programa funcionando cuandootras partes del sistema cambian y modificar el programa para cumplir con losnuevos requisitos

Una teacutecnica de disentildeo que ayuda a lograr ese objetivo es mantener las interfacesseparadas de las implementaciones Esto significa que los meacutetodos que tienen unargumento con anotacioacuten de tipo no deberiacutean depender de coacutemo se representanlos atributos de ese tipo

Por ejemplo en este capiacutetulo se desarrolla una estructura que representa unahora del diacutea Los meacutetodos que tienen un argumento con anotacioacuten de este tipoincluyen horaaentero estadespues y +

Se pueden implementar esos meacutetodos de varias maneras Los detalles de laimplementacioacuten dependen de coacutemo se represente Hora En este capiacutetulo losatributos de un objeto Hora son hora minuto y segundo

Otra opcioacuten seriacutea reemplazar estos atributos con un solo entero que representeel nuacutemero de segundos desde la medianoche Esta implementacioacuten hariacutea quealgunas funciones como estadespues sean maacutes faacuteciles de escribir pero hace queotras sean maacutes difiacuteciles

Despueacutes de implementar un tipo puede descubrir una mejor implementacioacuten Siotras partes del programa estaacuten usando su tipo cambiar la interfaz puede llevarmucho tiempo y ser propenso a errores No obstante si hizo un buen disentildeoacute deinterfaz puede cambiar la implementacioacuten sin cambiar la interfaz lo quesignifica que otras partes del programa no tienen que cambiar

Interfaz e implementacioacuten 225

DepuracioacutenLlamar a una funcioacuten con los argumentos correctos puede ser difiacutecil cuando seespecifica maacutes de un meacutetodo para la funcioacuten Julia permite examinar lasespecificaciones de los meacutetodos de una funcioacuten

Para saber queacute meacutetodos estaacuten disponibles para una funcioacuten determinada puedeusar la funcioacuten methods

juliagt methods(imprimirhora) 2 methods for generic function imprimirhora[1] printtime(timeMyTime) in Main at REPL[3]2[2] printtime(time) in Main at REPL[4]2

En este ejemplo la funcioacuten imprimirhora tiene 2 meacutetodos uno con un argumentoHora y otro con un argumento Any

Glosarioanotacioacuten de tipo

El operador seguido de un tipo que indica que una expresioacuten o unavariable es de ese tipo

meacutetodoUna definicioacuten de un posible comportamiento de una funcioacuten

dispatchLa eleccioacuten de queacute meacutetodo ejecutar cuando se ejecuta una funcioacuten

especificacioacutenEl nuacutemero y tipo de argumentos de un meacutetodo que permite al dispatchseleccionar el meacutetodo maacutes especiacutefico de una funcioacuten durante la llamada afuncioacuten

constructor externoConstructor definido fuera de la definicioacuten de tipo para definir meacutetodosuacutetiles para crear un objeto

constructor internoConstructor definido dentro de la definicioacuten de tipo para imponerinvariantes o para construir objetos recursivos

constructor por defectoConstructor interno que estaacute disponible cuando el usuario no defineconstructores internos

226 Capiacutetulo 17 Dispatch Muacuteltiple

constructor de copiaMeacutetodo de constructor externo de un tipo que tiene como uacutenico argumentoun objeto del tipo Crea un nuevo objeto que es una copia del argumento

sobrecarga de operadoresAmpliar el comportamiento de los operadores como ++ de modo quetrabajen con tipos definidos por el usuario

dispatch muacuteltipleDispatch basado en todos los argumentos de una funcioacuten

programacioacuten geneacutericaEscribir coacutedigo que pueda funcionar con maacutes de un tipo

Ejercicios

Ejercicio 17-4

Cambie los atributos de Hora para que sea un solo nuacutemero entero querepresente los segundos desde la medianoche Luego modifique los meacutetodosdefinidos en este capiacutetulo para que funcionen con la nueva implementacioacuten

Ejercicio 17-5

Escriba una definicioacuten para un tipo llamado Canguro con un atributo llamadocontenidodemarsupio de tipo Arreglo y los siguientes meacutetodos

bull Un constructor que inicialice contenidodemarsupio a un arreglo vaciacuteo

bull Un meacutetodo llamado ponerenmarsupio que tome un objeto Canguro y unobjeto de cualquier tipo y lo agregue a contenidodemarsupio

bull Un meacutetodo show que devuelva una representacioacuten de cadena del objetoCanguro y el contenido del marsupio

Pruebe su coacutedigo creando dos objetos Canguro asignaacutendolos a variablesllamadas cangu y ro y luego agregando ro al contenido del marsupio de cangu

Ejercicios 227

Capiacutetulo 18 SubtiposEn el capiacutetulo anterior se presentoacute el dispatch muacuteltiple y los meacutetodospolimoacuterficos Al no especificar el tipo de los argumentos de un meacutetodo este sepuede invocar con argumentos de cualquier tipo Ahora se veraacute coacutemo especificarun subconjunto de tipos permitidos en las especificaciones de un meacutetodo

En este capiacutetulo se explica el concepto de subtipo usando tipos que representannaipes mazos de naipes y manos de poacuteker

Si usted nunca ha jugado poacuteker puede leer sobre eacutel en httpseswikipediaorgwikiPC3B3quer aunque no es necesario ya que se explicaraacute todo lonecesario para los ejercicios

NaipesHay cincuenta y dos naipes en una baraja inglesa cada uno de los cualespertenece a uno de los cuatro palos y tiene un valor Los palos son Picas (spades)Corazones (hearts) Diamantes (diams) y Treacuteboles (clubs) Los valores son As (A) 2 3 4 5 67 8 9 10 Jota (J) Reina (Q) y Rey (K) Dependiendo del tipo de juego el valordel As puede ser mayor que al Rey o inferior al 2

Si queremos definir un nuevo objeto para representar un naipe son obvios losatributos que deberiacutea tener valor y palo Lo que no es tan obvio es el tipo que sedebe dar a estos atributos Una opcioacuten es usar cadenas de caracteres quecontengan palabras como Picas para los palos y Reina para los valores Unproblema de esta implementacioacuten es que no seriacutea faacutecil comparar naipes para vercuaacutel tiene mayor valor o palo

Una alternativa es usar nuacutemeros enteros para codificar los valores y palos Eneste contexto codificar significa definir una asociacioacuten entre nuacutemeros y paloso entre nuacutemeros y valores Este tipo de codificacioacuten no estaacute relacionada concifrar o traducir a un coacutedigo secreto (eso seriacutea cifrado)

Por ejemplo esta tabla muestra una correspondencia entre palos y coacutedigos(nuacutemeros) enteros

bull spades 4

bull hearts 3

bull diams 2

bull clubs 1

Este coacutedigo facilita la comparacioacuten de naipes los palos maacutes altos se asignan a losnuacutemeros maacutes altos por lo tanto podemos comparar los palos al comparar suscoacutedigos

228 Capiacutetulo 18 Subtipos

Estamos usando el siacutembolo para dejar en claro que estas asignaciones no sonparte de Julia Forman parte del disentildeo del programa pero no aparecenexpliacutecitamente en el coacutedigo

La definicioacuten de estructura de Naipe se ve asiacute

struct Naipe palo Int64 valor Int64 function Naipe(paloInt64 valorInt64) assert(1 le palo le 4 el palo no estaacute entre 1 y 4) assert(1 le valor le 13 el valor no estaacute entre 1 y 13) new(palo valor) endend

Para crear un Naipe se debe llamar a Naipe con el palo y el valor del naipedeseado

juliagt reina_de_diamantes = Naipe(2 12)Naipe(2 12)

Variables GlobalesPara poder imprimir los objetos Naipe de una manera que sea faacutecil de leer senecesita establecer una correspondencia entre los coacutedigos enteros y suscorrespondientes palos y valores Una manera natural de hacer esto es conarreglos de cadenas

const nombres_palo = [clubs diams hearts spades]const nombres_valor = [A 2 3 4 5 6 7 8 9 10J Q K]

Las variables nombres_palo y nombres_valor son variables globales Ladeclaracioacuten const significa que la variable solo se puede asignar una vez Estoresuelve el problema de rendimiento de las variables globales

Ahora se puede implementar un meacutetodo show apropiado

function Baseshow(ioIO naipeNaipe) print(io nombres_valor[naipevalor] nombres_palo[naipepalo])end

La expresioacuten nombres_valor[naipevalor] significa use el atributo valor delobjeto naipe como iacutendice en el arreglo nombres_valor y seleccione la cadena

Variables Globales 229

correspondiente

Con los meacutetodos que se tienen hasta ahora se pueden crear e imprimir naipes

juliagt Naipe(3 11)Jhearts

Comparacioacuten de naipesPara los tipos integrados existen operadores relacionales (lt gt == etc) quecomparan valores y determinan cuaacutendo uno es mayor menor o igual a otro Paralos tipos definidos por el usuario se puede sustituir el comportamiento de estosoperadores si se proporciona un meacutetodo llamado lt

El orden correcto de los naipes no es obvio Por ejemplo iquestcuaacutel es mejor el 3 deTreacuteboles o el 2 de Diamantes Uno tiene un valor mayor pero el otro tiene unpalo mayor Para hacer que los naipes sean comparables se debe decidir queacute esmaacutes importante valor o palo

La respuesta puede depender del tipo de juego pero para simplificar las cosasse establece la eleccioacuten arbitraria de que el palo es maacutes importante por lo quetodas los treacuteboles superan a todos los diamantes y asiacute sucesivamente

Con esa decisioacuten tomada se puede escribir lt

import Baselt

function lt(c1Naipe c2Naipe) (c1palo c1valor) lt (c2palo c2valor)end

Ejercicio 18-1

Escriba un meacutetodo lt para objetos Hora Puede usar comparacioacuten de tuplas ocomparacioacuten de enteros

Prueba unitariaUna prueba unitaria permite verificar el correcto funcionamiento de su coacutedigocomparando los resultados obtenidos con los esperados Esto puede ser uacutetil paraverificar que su coacutedigo funciona correctamente despueacutes de haberlo modificado ytambieacuten es una forma de predefinir el comportamiento correcto de su coacutedigodurante el desarrollo

Se pueden realizar pruebas unitarias simples con las macros test

230 Capiacutetulo 18 Subtipos

juliagt using Test

juliagt test Naipe(1 4) lt Naipe(2 4)Test Passedjuliagt test Naipe(1 3) lt Naipe(1 4)Test Passed

test devuelve Test Passed (Prueba aprobada) si la expresioacuten que sigue estrue Test Failed (Prueba fallida) si es false y Error Result (Resultado deerror) si no se pudo evaluar

MazosAhora que ya tenemos Naipes el proacuteximo paso es definir Mazos Como un mazoestaacute compuesto de naipes naturalmente cada Mazo contendraacute un arreglo denaipes como atributo

A continuacioacuten se muestra una definicioacuten para Mazo El constructor crea elatributo naipes y genera la baraja estaacutendar de cincuenta y dos naipes

struct Mazo naipes ArrayNaipe 1end

function Mazo() mazo = Mazo(Naipe[]) for palo in 14 for valor in 113 push(mazonaipes Naipe(palo valor)) end end mazoend

La forma maacutes faacutecil de poblar el mazo es mediante un bucle anidado El bucleexterior enumera los palos desde 1 hasta 4 El bucle interior enumera los valoresdesde 1 hasta 13 Cada iteracioacuten crea un nuevo Naipe con el palo y valor actualy lo agrega a mazonaipes

Este es un meacutetodo show para Mazo

Mazos 231

function Baseshow(ioIO mazoMazo) for naipe in mazonaipes print(io naipe ) end println()end

Asiacute es como se ve el resultado

juliagt Mazo()Aclubs 2clubs 3clubs 4clubs 5clubs 6clubs 7clubs 8clubs 9clubs 10clubs Jclubs Qclubs Kclubs Adiams 2diams 3diams 4diams 5diams 6diams 7diams 8diams 9diams 10diams JdiamsQdiams Kdiams Ahearts 2hearts 3hearts 4hearts 5hearts 6hearts 7hearts 8hearts 9hearts 10hearts Jhearts Qhearts Khearts Aspades 2spades 3spades 4spades 5spades 6spades 7spades 8spades 9spades10spades Jspades Qspades Kspades

Antildeadir Eliminar Barajar y OrdenarPara repartir los naipes se debe tener una funcioacuten que elimine un naipe delmazo y lo devuelva La funcioacuten pop proporciona una forma conveniente derealizar esto

function Basepop(mazoMazo) pop(mazonaipes)end

Como pop elimina el uacuteltimo naipe en el arreglo se estaacute repartiendo desde elextremo inferior del mazo

Para antildeadir un naipe se puede usar la funcioacuten push

function Basepush(mazoMazo naipeNaipe) push(mazonaipes naipe) mazoend

Un meacutetodo como este que usa otro meacutetodo sin hacer mucho maacutes se llamaenchapado La metaacutefora proviene de la carpinteriacutea donde un enchapado es unacapa fina de madera de alta calidad que se pega a la superficie de una pieza demadera de baja calidad para mejorar su apariencia

En este caso push es un meacutetodo fino que expresa una operacioacuten de arreglosadecuada para los mazos Mejora la apariencia o interfaz de la implementacioacuten

Tambieacuten podemos escribir un meacutetodo llamado shuffle (barajar en ingleacutes) usandola funcioacuten Randomshuffle

232 Capiacutetulo 18 Subtipos

using Random

function Randomshuffle(mazoMazo) shuffle(mazonaipes) mazoend

Ejercicio 18-2

Escriba una funcioacuten llamada sort (ordenar en ingleacutes) que use la funcioacuten sortpara ordenar las cartas en un Mazo sort usa el meacutetodo isless que definimospara determinar el orden

Tipos Abstractos y SubtiposSe busca que un tipo represente una mano es decir los naipes que tiene unjugador Una mano es similar a un mazo ambos estaacuten compuestos de unconjunto de naipes y ambos requieren de operaciones tales como agregar yeliminar una carta

Una mano es diferente de un mazo en ciertos aspectos ya que existen ciertasoperaciones sobre una mano que no tendriacutean sentido sobre un mazo Porejemplo en el poker se debe comparar una mano con otra para ver quieacuten ganaEn bridge se necesita calcular el puntaje de la mano para asiacute poder hacer lasubasta

Por lo tanto hace falta una forma de agrupar los tipos concretos que estaacutenrelacionados En Julia esto se hace definiendo un abstract type (tipo abstracto eningleacutes) que sea padre de Mazo y Mano A esto se le llama crear subtipos

Se llama al tipo abstracto ConjuntoDeCartas

abstract type ConjuntoDeCartas end

Se puede crear un nuevo tipo abstracto con la palabra reservada abstract typeDe manera opcional se puede especificar un tipo padre de una estructuracolocando despueacutes del nombre de esta el siacutembolo lt seguido del nombre de untipo abstracto existente

Cuando no se proporciona un supertipo el supertipo por defecto es Any es decirun tipo abstracto predefinido del que todos los objetos son instancias y del quetodos los tipos son subtipos

Ahora se puede expresar que Mazo es un hijo de ConjuntoDeCartas

Tipos Abstractos y Subtipos 233

struct Mazo lt ConjuntoDeCartas naipes ArrayNaipe 1end

function Mazo() mazo = Mazo(Naipe[]) for palo in 14 for valor in 113 push(mazonaipes Naipe(palo valor)) end end mazoend

El operador isa comprueba si un objeto es de un tipo dado

juliagt mazo = Mazo()

juliagt mazo isa ConjuntoDeCartastrue

Una mano tambieacuten es un ConjuntoDeCartas

struct Mano lt ConjuntoDeCartas naipes ArrayNaipe 1 etiqueta Stringend

function Mano(etiquetaString=) Mano(Naipe[] etiqueta)end

En lugar de llenar la mano con 52 naipes nuevos el constructor de Manoinicializa naipes a un arreglo vaciacuteo Se puede etiquetar a la Mano pasando unargumento opcional al constructor

juliagt mano = Mano(nueva mano)Mano(Naipe[] nueva mano)

Tipos Abstractos y FuncionesAhora podemos expresar las operaciones que tienen en comuacuten Mazo y Mano alser funciones que tienen como argumento a ConjuntoDeCartas

234 Capiacutetulo 18 Subtipos

function Baseshow(ioIO cdcConjuntoDeCartas) for naipe in cdcnaipes print(io naipe ) endend

function Basepop(cdcConjuntoDeCartas) pop(cdcnaipes)end

function Basepush(cdcConjuntoDeCartas naipeNaipe) push(cdcnaipes naipe) nothingend

Se puede usar pop y push para repartir una carta

juliagt mazo = Mazo()Aclubs 2clubs 3clubs 4clubs 5clubs 6clubs 7clubs 8clubs 9clubs 10clubs Jclubs Qclubs Kclubs Adiams 2diams 3diams 4diams 5diams 6diams 7diams 8diams 9diams 10diams JdiamsQdiams Kdiams Ahearts 2hearts 3hearts 4hearts 5hearts 6hearts 7hearts 8hearts 9hearts 10hearts Jhearts Qhearts Khearts Aspades 2spades 3spades 4spades 5spades 6spades 7spades 8spades 9spades10spades Jspades Qspades Kspadesjuliagt shuffle(mazo)10clubs 9hearts 7spades 2spades Ahearts 4clubs Jhearts 2diams 6clubs Qclubs 8diams 8hearts 3hearts 7clubs 3diams 2clubs Jclubs 8clubs 9diams 6spades 3spades 5spades Adiams Aclubs10hearts 4spades Qhearts Jdiams Kspades 10diams Khearts Kclubs 5clubs 5hearts 5diams 10spades 7diams 3clubs 9spades Aspades 2hearts 7hearts 9clubs Qdiams 6hearts 8spades Jspades 4diamsQspades 6diams Kdiams 4heartsjuliagt naipe = pop(mazo)4heartsjuliagt push(mano naipe)

A continuacioacuten se encapsula este coacutedigo en una funcioacuten llamada mover

function mover(cdc1ConjuntoDeCartas cdc2ConjuntoDeCartas nInt) assert 1 le n le length(cs1naipes) for i in 1n naipe = pop(cdc1) push(cdc2 naipe) end nothingend

mover toma tres argumentos dos objetos ConjuntoDeCartas y el nuacutemero decartas a repartir Modifica ambos objetos ConjuntoDeCartas y devuelve nothing

En algunos juegos las cartas se mueven de una mano a otra o de una mano almazo Puede usar mover para cualquiera de estas operaciones cdc1 y cdc2pueden ser un Mazo o una Mano

Tipos Abstractos y Funciones 235

Diagramas de tiposHasta ahora se han visto diagramas de pila que muestran el estado de unprograma y diagramas de objetos que muestran los atributos de un objeto y susvalores Estos diagramas son como una foto sacada durante la ejecucioacuten de unprograma por lo que cambian a medida que se ejecuta el programa

Tambieacuten son muy detallados en algunos casos demasiado detallados Undiagrama de tipos es una representacioacuten maacutes abstracta de la estructura de unprograma En vez de mostrar objetos individuales muestra los tipos y lasrelaciones entre ellos

Hay varias formas de relacioacuten entre tipos

bull Los objetos de un tipo concreto pueden contener referencias a objetos deotro tipo Por ejemplo cada Rectaacutengulo contiene una referencia a un Puntoy cada Mazo contiene referencias a un conjunto de Naipes Este tipo derelacioacuten se llama TIENE-UN como por ejemplo un Rectaacutengulo tiene unPunto

bull Un tipo concreto puede tener un tipo abstracto como supertipo Estarelacioacuten se llama ES-UN como por ejemplo una Mano es unConjuntoDeCartas

bull Un tipo puede depender de otro si los objetos de un tipo toman objetos delsegundo tipo como paraacutemetros o usan objetos del segundo tipo como partede un caacutelculo Este tipo de relacioacuten se llama dependencia

Figura 23 Diagrama de tipo

Cada una de las flechas superiores representa una relacioacuten ES-UN En este casoindica que Mano tiene como supertipo a ConjuntoDeCartas

Cada una de las flechas inferiores representa una relacioacuten TIENE-UN en estecaso un Mazo tiene referencias a objetos Naipe

El asterisco () cerca de la flecha es una multiplicidad e indica cuaacutentos Naipestiene un Mazo Una multiplicidad puede ser un nuacutemero simple como 52 unrango como 57 o un asterisco lo cual indica que un Mazo puede tener cualquiernuacutemero de Naipes

236 Capiacutetulo 18 Subtipos

No hay dependencias en este diagrama Normalmente se mostrariacutean con unaflecha achurada Si hay muchas dependencias a veces se omiten

Un diagrama maacutes detallado podriacutea mostrar que un Mazo en realidad contiene unarreglo de Naipes pero los tipos integrados como arreglos y diccionariosgeneralmente no se incluyen en los diagramas de tipos

DepuracioacutenUtilizar subtipos puede dificultar la depuracioacuten ya que al llamar a una funcioacutencon un objeto como argumento puede ser complicado determinar queacute meacutetodo seinvocaraacute

Al escribir una funcioacuten que funciona con objetos Mano se busca que funcionecon todo tipo de Manos como ManoDePoker ManoDeBridge etc Si el usuarioinvoca un meacutetodo como sort podriacutea obtener el meacutetodo definido para un tipoabstracto Mano pero si existiera un meacutetodo sort que tuviera como argumentocualquiera de estos subtipos de Mano obtendriacutea esa versioacuten Estecomportamiento suele ser algo bueno pero puede ser confuso

function Basesort(manoMano) sort(manonaipes)end

Si usted no estaacute seguro del flujo de ejecucioacuten de un programa la solucioacuten maacutessimple es agregar sentencias de impresioacuten al inicio de sus meacutetodos maacutesrelevantes Si shuffle imprimiera un mensaje como Ejecutando shuffle en Mazodurante la ejecucioacuten del programa seriacutea posible rastrear el flujo de ejecucioacuten

Una mejor alternativa es la macro which

juliagt which sort(mano)sort(manoMano) in Main at REPL[5]1

Entonces el meacutetodo sort de mano es el que tiene como argumento un objeto detipo Mano

Una sugerencia para el disentildeo del programa cuando anula un meacutetodo lainterfaz del nuevo meacutetodo deberiacutea ser la misma que la anterior Deberiacutea tomarlos mismos paraacutemetros devolver el mismo tipo y obedecer las mismascondiciones previas y posteriores Si sigue esta regla cualquier funcioacuten disentildeadapara funcionar con una instancia de un supertipo como un ConjuntoDeCartastambieacuten funcionaraacute con instancias de sus subtipos Mazo y Mano

Si viola esta regla llamada principio de sustitucioacuten de Liskov su coacutedigocolapsaraacute como un castillo de naipes (jeje)

Depuracioacuten 237

La funcioacuten supertype permite encontrar el supertipo directo de un tipo

juliagt supertype(Mazo)ConjuntoDeCartas

Encapsulado de DatosLos capiacutetulos anteriores muestran un plan de desarrollo que podriacuteamos llamardisentildeo orientado a tipos Se identifican los objetos necesarios como PuntoRectaacutengulo y Hora y se definen estructuras para representarlos En cada casohay una correspondencia obvia entre el objeto y alguna entidad en el mundo real(o al menos en el mundo matemaacutetico)

A veces no es tan obvio saber queacute objetos se necesitan y coacutemo estos debeninteractuar En ese caso se necesita un plan de desarrollo diferente Lo mismoque ocurre con interfaces de funciones por encapsulado y generalizacioacuten ocurrecon interfaces de tipo por encapsulado de datos

El anaacutelisis de Markov de Seccioacuten 138 es un buen ejemplo Si descarga el coacutedigodesde httpsgithubcomBenLauwensThinkJuliajlblobmastersrcsolutionschap13jl veraacute que se usan dos variables globales sufijos y prefijo las cuales seleen y escriben desde varias funciones

sufijos = Dict()prefijos = []

Debido a que estas variables son globales solo se puede ejecutar un anaacutelisis a lavez Si se leen dos textos sus prefijos y sufijos se agregariacutean a las mismasestructuras de datos (lo que generariacutea un texto interesante)

Para ejecutar muacuteltiples anaacutelisis y mantenerlos separados se puede encapsular elestado de cada anaacutelisis en un objeto Asiacute es como se veriacutea

struct Markov orden Int64 sufijos DictTupleStringVarargString ArrayString 1 prefijo ArrayString 1end

function Markov(ordenInt64=2) new(orden DictTupleStringVarargString ArrayString 1()ArrayString 1())end

A continuacioacuten se transforman las funciones en meacutetodos Por ejemplo para

238 Capiacutetulo 18 Subtipos

procesarpalabra

function procesarpalabra(markovMarkov palabraString) if length(markovprefijo) lt markovorden push(markovprefijo palabra) return end get(markovsufijos (markovprefijo) ArrayString 1()) push(markovsufijos[(markovprefijo)] palabra) popfirst(markovprefijo) push(markovprefijo palabra)end

Transformar un programa asiacute (cambiando el disentildeo sin cambiar elcomportamiento) es otro ejemplo de refactorizacioacuten (vea Seccioacuten 47)

Este ejemplo sugiere el siguiente plan de desarrollo para disentildear tipos

bull Comience escribiendo funciones que lean y escriban variables globales(cuando sea necesario)

bull Una vez que el programa esteacute funcionando busque asociaciones entre lasvariables globales y las funciones que las usan

bull Encapsule variables relacionadas como atributos de una estructura

bull Transforme las funciones asociadas en meacutetodos que tengan comoargumentos objetos del nuevo tipo

Exercise 18-3

Descargue el coacutedigo de Markov de httpsgithubcomBenLauwensThinkJuliajlblobmastersrcsolutionschap13jl y siga los pasos descritos anteriormente paraencapsular las variables globales como atributos de una nueva estructurallamada Markov

Glosariocodificar

Representar un conjunto de valores utilizando otro conjunto de valoresgenerando una asociacioacuten entre ellos

prueba unitariaManera estandarizada de probar que el coacutedigo estaacute correcto

enchapadoUn meacutetodo o funcioacuten que mejora la interfaz de otra funcioacuten sin hacermuchos caacutelculos

Glosario 239

crear subtiposLa capacidad de definir una jerarquiacutea de tipos relacionados

tipo abstractoUn tipo que puede ser padre de otro tipo

tipo concretoUn tipo que se puede construir

subtipoUn tipo que tiene como padre un tipo abstracto

supertipoUn tipo abstracto que es el padre de otro tipo

relacioacuten ES-UNUna relacioacuten entre un subtipo y su supertipo

relacioacuten TIENE-UNUna relacioacuten entre dos tipos donde las instancias de un tipo contienenreferencias a instancias del otro

dependenciaUna relacioacuten entre dos tipos donde las instancias de un tipo usan instanciasdel otro tipo pero no las almacenan como atributos

diagrama de tiposUn diagrama que muestra los tipos en un programa y las relaciones entreellos

multiplicidadUna notacioacuten en un diagrama de tipo que muestra para una relacioacutenTIENE-UN cuaacutentas referencias hay a instancias de otra clase

encapsulado de datosUn plan de desarrollo de programas que implica hacer un prototipo que usevariables globales y una versioacuten final que convierta las variables globales enatributos de instancia

Ejercicios

Ejercicio 18-4

Para el siguiente programa dibuje un diagrama de tipos que muestre estos tiposy las relaciones entre ellos

240 Capiacutetulo 18 Subtipos

abstract type PadrePingPong end

struct Ping lt PadrePingPong pong PadrePingPongend

struct Pong lt PadrePingPong pings ArrayPing 1 function Pong(pings=ArrayPing 1()) new(pings) endend

function agregarping(pongPong pingPing) push(pongpings ping) nothingend

pong = Pong()ping = Ping(pong)agregarping(pong ping)

Ejercicio 18-5

Escriba un meacutetodo llamado repartir que tome tres paraacutemetros un Mazo elnuacutemero de manos y el nuacutemero de naipes por mano Deberiacutea crear el nuacutemeroapropiado de objetos Mano repartir el nuacutemero apropiado de naipes por mano ydevolver un arreglo de Manos

Ejercicio 18-6

Las siguientes son las posibles manos en el poacuteker en orden de valor creciente yprobabilidad decreciente

parejaDos cartas del mismo nuacutemero

doble parejaDos pares de cartas del mismo nuacutemero

triacuteoTres cartas del mismo nuacutemero

escaleraCinco cartas consecutivas (los ases pueden ser considerados altos o bajospor lo tanto As-2-3-4-5 es escalera 10-Jota-Reina-Rey-As tambieacuten pero

Ejercicios 241

Reina-Rey-As-2-3 no)

colorCinco cartas del mismo palo

fullTres cartas iguales en su valor maacutes otras dos iguales en su valor

poacutekerCuatro cartas iguales en su valor

escalera de colorCinco cartas consecutivas del mismo palo

El objetivo de este ejercicio es estimar la probabilidad de tener cada una de estasmanos

1 Agregue meacutetodos llamados tienepareja tienedoblepareja etc quedevuelvan true o false seguacuten si la mano cumple o no con los criteriosrelevantes Su coacutedigo deberiacutea funcionar correctamente para manos quecontengan cualquier nuacutemero de naipes (aunque 5 y 7 son los tamantildeos maacutescomunes)

2 Escriba un meacutetodo llamado clasificar que descubra la clasificacioacuten de mayorvalor para una mano y defina el atributo etiqueta con esta clasificacioacuten Porejemplo una mano de 7 cartas que contiene un color y una pareja debeetiquetarse como color

3 Cuando esteacute convencido de que sus meacutetodos de clasificacioacuten estaacutenfuncionando correctamente estime las probabilidades de las distintasmanos Escriba una funcioacuten que baraje un mazo de naipes la divida endiferentes manos clasifique las manos y cuente la cantidad de veces queaparecen varias clasificaciones

4 Imprima una tabla de las clasificaciones y sus probabilidades Ejecute suprograma con un nuacutemero cada vez mayor de manos hasta que los valores desalida converjan con un grado razonable de precisioacuten Compare susresultados con los valores en httpsenwikipediaorgwikiHand_rankings

242 Capiacutetulo 18 Subtipos

Capiacutetulo 19 Extra SintaxisUno de los objetivos de este libro es ensentildearle lo justo y necesario de Julia Seexplica una sola forma de hacer las cosas y en ocasiones se deja como ejercicioal lector una segunda manera

Ahora se veraacuten algunos temas que se han dejado de lado pero que son uacutetilesJulia proporciona una serie de caracteriacutesticas que no son realmente necesarias(se puede escribir un buen coacutedigo sin ellas) pero a veces permiten escribir uncoacutedigo maacutes conciso legible yo eficiente

En este capiacutetulo y el siguiente se discute aquello que se ha omitido en loscapiacutetulos anteriores

bull maacutes sintaxis

bull funciones tipos y macros disponibles directamente de Base

bull funciones tipos y macros de la Biblioteca Estaacutendar (Standard Library)

Tuplas con nombreEs posible colocarle nombre a los componentes de una tupla creando una tuplacon nombre

juliagt x = (a=1 b=1+1)(a = 1 b = 2)juliagt xa1

En las tuplas con nombre se puede acceder a los atributos con su nombreutilizando la sintaxis de punto (xa)

FuncionesLas funciones en Julia tambieacuten se pueden definir mediante una sintaxiscompacta de la siguiente forma

juliagt f(xy) = x + yf (generic function with 1 method)

Funciones Anonimas

Podemos definir una funcioacuten sin especificar su nombre

Tuplas con nombre 243

juliagt x -gt x^2 + 2x - 11 (generic function with 1 method)juliagt function (x) x^2 + 2x - 1 end3 (generic function with 1 method)

Estos son ejemplos de funciones anoacutenimas Las funciones anoacutenimasgeneralmente se usan como argumento de otra funcioacuten

juliagt using Plots

juliagt plot(x -gt x^2 + 2x - 1 0 10 xlabel=x ylabel=y)

Figura 24 muestra el resultado del comando plot (graficar en ingleacutes)

Figura 24 Plot

Argumentos con nombre

Tambieacuten se puede poner nombre a los argumentos de una funcioacuten

juliagt function migrafico(x y style=continua width=1 color=negro) endmigrafico (generic function with 1 method)juliagt migrafico(010 010 style=dotted color=blue)

Los argumentos con nombre en una funcioacuten se especifican despueacutes de un punto ycoma en la especificacioacuten pero al llamar a la funcioacuten se pueden utilizar solocomas

244 Capiacutetulo 19 Extra Sintaxis

Clausuras

Una clausura es una teacutecnica que permite que una funcioacuten capture una variabledefinida fuera del aacutembito de la funcioacuten

juliagt foo(x) = ()-gtxfoo (generic function with 1 method)

juliagt bar = foo(1)1 (generic function with 1 method)

juliagt bar()1

En este ejemplo la funcioacuten foo devuelve una funcioacuten anoacutenima que tiene acceso alargumento x de la funcioacuten foo bar apunta a la funcioacuten anoacutenima y devuelve elvalor del argumento de foo

BloquesUn bloque es una forma de agrupar varias sentencias Un bloque comienza con lapalabra reservada begin y termina con end

En Capiacutetulo 4 se presentoacute la macro svg

ὂ = Turtle()svg begin forward(ὂ 100) turn(ὂ -90) forward(ὂ 100)end

En este ejemplo la macro svg tiene un uacutenico argumento un bloque queagrupa 3 llamadas a funciones

Bloques let

Un bloque let es uacutetil para crear nuevas ligaduras (o bindings) es decir variableslocales que pueden apuntar a valores

Bloques 245

juliagt x y z = -1 -1 -1

juliagt let x = 1 z show x y z endx = 1y = -1ERROR UndefVarError z not definedjuliagt show x y zx = -1y = -1z = -1

En el ejemplo la primera macro show muestra la variable local x la variableglobal y y la variable local indefinida z Las variables globales se mantienenintactas

Bloques do

En Seccioacuten 142 se cierra el archivo despueacutes de terminar de escribir en eacutel Estose puede hacer automaacuteticamente usando un Bloque do

juliagt datos = El Cid convoca a sus vasallosneacutestos se destierran coneacutelnEl Cid convoca a sus vasallosneacutestos se destierran con eacutelnjuliagt open(salidatxt w) do fout write(fout datos) end61

En este ejemplo fout es el archivo stream utilizado para la salida

Esto es equivalente a

juliagt f = fout -gt begin write(fout datos) end3 (generic function with 1 method)juliagt open(f salidatxt w)61

La funcioacuten anoacutenima se utiliza como primer argumento de la funcioacuten open

246 Capiacutetulo 19 Extra Sintaxis

function open(fFunction args) io = open(args) try f(io) finally close(io) endend

Un bloque do puede capturar variables de su aacutembito envolvente (enclosedscope) Por ejemplo la variable datos en el ejemplo anterior de open do escapturada desde el aacutembito externo

Estructuras de control

Operador ternario

El operador ternario puede utilizarse en vez de una sentencia if-elseif Estasentencia se usa cuando se necesita elegir entre diferentes expresiones con valoruacutenico

juliagt a = 150150juliagt a 2 == 0 println(par) println(impar)par

La expresioacuten que va antes de es una expresioacuten de condicioacuten Si la condicioacuten estrue se evaluacutea la expresioacuten que va antes de De lo contrario se evaluacutea laexpresioacuten que va despueacutes de

Evaluacioacuten de cortocircuito

Los operadores ampamp y || realizan una evaluacioacuten de cortocircuito es decir seevaluacutea el siguiente argumento solo cuando es necesario para determinar el valorfinal

Por ejemplo una funcioacuten factorial recursiva podriacutea definirse asiacute

function fact(nInteger) n gt= 0 || error(n debe ser no negativo) n == 0 ampamp return 1 n fact(n-1)end

Estructuras de control 247

Tarea (o Corrutina)

Una tarea es una estructura de control que puede ceder el control de formacooperativa sin hacer return En Julia una tarea puede implementarse como unafuncioacuten con un objeto Channel como primer argumento Se usa un channel parapasar valores de la funcioacuten a la sentencia que la llama

El teacutermino cooperativo alude a que los programas deben cooperar para quetodo el esquema de programacioacuten funcione

La secuencia de Fibonnaci se puede generar mediante una tarea

function fib(cChannel) a = 0 b = 1 put(c a) while true put(c b) (a b) = (b a+b) endend

put almacena valores en un objeto channel y take lee valores desde eacutel

juliagt fib_gen = Channel(fib)

juliagt take(fib_gen)0juliagt take(fib_gen)1juliagt take(fib_gen)1juliagt take(fib_gen)2juliagt take(fib_gen)3

El constructor Channel crea la tarea La funcioacuten fib se suspende despueacutes de cadallamada a put y se reanuda al llamar a take Por razones de rendimiento sealmacenan varios valores de la secuencia en el objeto channel durante un ciclode reanudacioacutensuspensioacuten

Un objeto channel tambieacuten se puede usar como iterador

248 Capiacutetulo 19 Extra Sintaxis

juliagt for val in Channel(fib) print(val ) val gt 20 ampamp break end0 1 1 2 3 5 8 13 21

Tipos

Tipos Primitivos

Un tipo concreto compuesto por bits se llama tipo primitivo A diferencia de lamayoriacutea de los lenguajes en Julia se puede declarar nuestros propios tiposprimitivos Los tipos primitivos estaacutendar se definen de la misma manera

primitive type Float64 lt AbstractFloat 64 endprimitive type Bool lt Integer 8 endprimitive type Char lt AbstractChar 32 endprimitive type Int64 lt Signed 64 end

El nuacutemero en las sentencias especifica cuaacutentos bits son necesarios

El siguiente ejemplo crea un tipo primitivo Byte y un constructor

juliagt primitive type Byte 8 end

juliagt Byte(valUInt8) = reinterpret(Byte val)Bytejuliagt b = Byte(0x01)Byte(0x01)

La funcioacuten reinterpret se usa para almacenar los bits de un entero sin signo con8 bits (UInt8) en el byte

Tipos Parameacutetricos

El sistema de tipos de Julia es parameacutetrico lo que significa que los tipos puedentener paraacutemetros

Los paraacutemetros de un tipo se colocan despueacutes del nombre del tipo entre llaves

struct PuntoTltReal xT yTend

Tipos 249

Con esto se define un nuevo tipo parameacutetrico PuntoTltReal que contiene doscoordenadas de tipo T que puede ser cualquier tipo que tenga Real comosupertipo

juliagt Punto(00 00)PuntoFloat64(00 00)

Ademaacutes de los tipos compuestos los tipos abstractos y los tipos primitivostambieacuten pueden tener paraacutemetros

OBSERVACIOacuteN

Para mejorar el rendimiento es totalmenterecomendable tener tipos concretos como atributos deuna estructura por lo que esta es una buena manera dehacer que Punto sea raacutepido y flexible

Union de Tipo

Una union de tipo es un tipo parameacutetrico abstracto que puede actuar comocualquiera de los tipos de sus argumentos

juliagt EnteroOCadena = UnionInt64 StringUnionInt64 Stringjuliagt 150 EnteroOCadena150juliagt Julia EnteroOCadenaJulia

Una unioacuten de tipos es en la mayoriacutea de los lenguajes informaacuteticos unaconstruccioacuten interna para trabajar con tipos Sin embargo Julia pone adisposicioacuten esta caracteriacutestica para sus usuarios ya que permite generar uncoacutedigo eficiente (cuando la unioacuten es entre pocos tipos) Esta caracteriacutestica otorgauna gran flexibilidad para controlar el dispatch

Meacutetodos

Meacutetodos Parameacutetricos

Las definiciones de meacutetodos tambieacuten pueden tener paraacutemetros de tipo quelimiten su especificacioacuten

250 Capiacutetulo 19 Extra Sintaxis

juliagt espuntoentero(pPuntoT) where T = (T === Int64)espuntoentero (generic function with 1 method)juliagt p = Punto(1 2)PuntoInt64(1 2)juliagt espuntoentero(p)true

Objetos Similares a Funciones

Cualquier objeto arbitrario de Julia puede hacerse invocable Tales objetosinvocables a veces se denominan funtores

struct PolinomioR coefVectorRend

function (pPolinomio)(x) val = pcoef[end] for coef in pcoef[end-1-11] val = val x + coef end valend

Para evaluar el polinomio simplemente debemos llamarlo

juliagt p = Polinomio([110100])PolinomioInt64([1 10 100])juliagt p(3)931

ConstructoresLos tipos parameacutetricos se pueden construir expliacutecita o impliacutecitamente

juliagt Punto(12) T implicitoPuntoInt64(1 2)juliagt PuntoInt64(1 2) T explicitoPuntoInt64(1 2)juliagt Punto(125) T implicitoERROR MethodError no method matching Punto(Int64 Float64)

Se generan constructores internos y externos por defecto para cada T

Constructores 251

struct PuntoTltReal xT yT PuntoT(xy) where TltReal = new(xy)end

Punto(xT yT) where TltReal = PuntoT(xy)

y tanto x como y deben ser del mismo tipo

Cuando x e y son de tipos diferentes se puede definir el siguiente constructorexterno

Punto(xReal yReal) = Punto(promote(xy))

La funcioacuten promote se detalla en Seccioacuten 1982

Conversioacuten y PromocioacutenJulia tiene un sistema para convertir argumentos de diferentes tipos a un tipocomuacuten Esto es llamado promocioacuten y aunque no es automaacutetico se puede realizarfaacutecilmente

Conversioacuten

Un valor se puede convertir de un tipo a otro

juliagt x = 1212juliagt typeof(x)Int64juliagt convert(UInt8 x)0x0cjuliagt typeof(ans)UInt8

Se pueden agregar nuestros propios meacutetodos convert

juliagt Baseconvert(TypePuntoT xArrayT 1) where TltReal =Punto(x)

juliagt convert(PuntoInt64 [1 2])PuntoInt64(1 2)

252 Capiacutetulo 19 Extra Sintaxis

Promocioacuten

Promocioacuten es la conversioacuten de valores de diferentes tipos a un solo tipo comuacuten

juliagt promote(1 25 3)(10 25 30)

Generalmente los meacutetodos para la funcioacuten promote no se definen directamentesino que se usa la funcioacuten auxiliar promot_rule para especificar las reglas de lapromocioacuten

promote_rule(TypeFloat64 TypeInt32) = Float64

MetaprogramacioacutenUn coacutedigo de Julia se puede representar como una estructura de datos del mismolenguaje Esto permite que un programa escriba y manipule su propio coacutedigo

Expresiones

Cada programa de Julia comienza como una cadena

juliagt prog = 1 + 21 + 2

El siguiente paso es analizar cada cadena en un objeto llamado expresioacutenrepresentado por el tipo de Julia Expr

juliagt ex = Metaparse(prog)(1 + 2)juliagt typeof(ex)Exprjuliagt dump(ex)Expr head Symbol call args ArrayAny((3)) 1 Symbol + 2 Int64 1 3 Int64 2

La funcioacuten dump muestra objetos expr con anotaciones

Las expresiones se pueden construir directamente con el prefijo entrepareacutentesis o usando un bloque quote

Metaprogramacioacuten 253

juliagt ex = quote 1 + 2 end

eval

Julia puede evaluar un objeto de expresioacuten usando la funcioacuten eval

juliagt eval(ex)3

Cada moacutedulo tiene su propia funcioacuten eval que evaluacutea las expresiones de suaacutembito

AVISO Generalmente si un coacutedigo tiene muchas llamadas a eval significaque algo estaacute mal eval se considera malo

Macros

Las macros pueden incluir coacutedigo generado en un programa Una macro asociauna tupla de objetos Expr directamente con una expresioacuten compilada

Aquiacute hay una macro simple

macro contenedorvariable(contenedor elemento) return esc(($(Symbol(contenedorelemento)) = $contenedor[$elemento]))end

Las macros se llaman anteponiendo (arroba) a su nombre La llamada a lamacro contenedorvariable letras 1 se reemplaza por

(letras1 = letras[1])

macroexpand contenedorvariable letras 1 returns this expression which isextremely useful for debugging

Este ejemplo ilustra coacutemo una macro puede acceder al nombre de susargumentos algo que una funcioacuten no puede hacer Se debe escapar de laexpresioacuten de retorno con esc porque debe resolverse en el entorno de la macrollamada

254 Capiacutetulo 19 Extra Sintaxis

NOTA

iquestPor queacute usar Macros

Las macros generan e incluyen fragmentos de coacutedigopersonalizado durante el tiempo de anaacutelisis es decir antes deejecutar el programa completo

Funciones Generadas

La macro generated crea coacutedigo especializado para meacutetodos dependiendo deltipo de los argumentos

generated function cuadrado(x) println(x) (x x)end

El cuerpo devuelve una expresioacuten citada como una macro

Para la sentencia que llama la funcioacuten generada se comporta como una funcioacutennormal

juliagt x = cuadrado(2) nota la salida es de la instruccioacuten println ()que estaacute en el cuerpoInt64juliagt x ahora imprimimos x4juliagt y = cuadrado(spam)Stringjuliagt yspamspam

Datos FaltantesLos datos faltantes se pueden representar a traveacutes del objeto missing que es lainstancia uacutenica del tipo Missing

Los arreglos pueden contener datos que faltan missing values en ingleacutes

juliagt a = [1 missing]2-element ArrayUnionMissing Int641 1 missing

El tipo de dicho arreglo es UnionMissing T doacutende T es el tipo de los valoresque realmente tenemos en el arreglo

Datos Faltantes 255

Las funciones de reduccioacuten devuelven missing cuando se invocan con arreglosque contienen valores que faltan

juliagt sum(a)missing

En este caso se puede usar la funcioacuten skipmissing para omitir los valores quefaltan

juliagt sum(skipmissing([1 missing]))1

Llamar a Coacutedigo de C y FortranSe escribe mucho coacutedigo en C o Fortran Reutilizar un coacutedigo que ya ha sidoprobado generalmente es mejor que escribir su propia versioacuten en otro lenguajeJulia puede llamar directamente a las bibliotecas C o Fortran existentesutilizando la sintaxis ccall

En Seccioacuten 146 se presentoacute una interfaz de Julia de la biblioteca GDBM defunciones de base de datos La biblioteca estaacute escrita en C Para cerrar la base dedatos se debe hacer una llamada a la funcioacuten close(db)

Baseclose(dbmDBM) = gdbm_close(dbmhandle)

function gdbm_close(handlePtrCvoid) ccall((gdbm_close libgdbm) Cvoid (PtrCvoid) handle)end

Un objeto dbm tiene un atributo handle de tipo PtrCvoid Este atributocontiene un puntero de C que apunta a la base de datos Para cerrar la base dedatos debe llamarse a la funcioacuten de C gdbm_close teniendo como uacutenicoargumento el puntero C apuntando a la base de datos sin valor de retorno Juliahace esto directamente con la funcioacuten ccall que tiene como argumentos

bull una tupla que consiste en un siacutembolo que contiene el nombre de la funcioacutenque queremos llamar gdbm_close y la libreriacutea compartida especificadacomo una cadena +libgdm

bull el tipo de retorno Cvoid

bull una tupla de tipos de argumentos (PtrCvoid)

bull los valores del argumento handle

Una visioacuten completa de la libreriacutea GDBM se puede encontrar como ejemplo enlas fuentes de ThinkJulia

256 Capiacutetulo 19 Extra Sintaxis

Glossaryclausura

Funcioacuten que captura variables del aacutembito en doacutende estaacute definida

bloque letBloque de asignacioacuten de nuevas ligaduras variables

funcioacuten anoacutenimaFuncioacuten definida sin nombre

tupla con nombreTupla con componentes con nombre

argumentos con nombreArgumentos identificados por su nombre en vez de solo por la posicioacuten queocupan

bloque doConstruccioacuten usada para definir y llamar a una funcioacuten anoacutenima parecida aun bloque de coacutedigo normal

operador ternarioOperador de estructura de control que toma tres operandos una condicioacutenuna expresioacuten que se ejecutaraacute si la condicioacuten devuelve true y una expresioacutenque se ejecutaraacute si la condicioacuten devuelve false

evaluacioacuten de cortocircuitoEvaluacioacuten de un operador booleano para el que se ejecuta o evaluacutea elsegundo argumento solo si el primero no es suficiente para determinar elvalor de la expresioacuten

tareas (corrutina)Caracteriacutestica de las estructuras de control que permite suspender yreanudar caacutelculos de manera flexible

tipo primitivoTipo concreto cuyos datos estaacuten compuestos de bits

unioacuten de tiposTipo que incluye todas las instancias de cualquiera de sus tipos deparaacutemetros como objetos

Glossary 257

tipo parameacutetricoTipo que tiene paraacutemetros

funtorObjeto con un meacutetodo asociado para que sea invocable

conversioacutenPermite convertir un valor de un tipo a otro

promocioacutenConversioacuten de valores de diferentes tipos a un solo tipo comuacuten

expresioacutenTipo de Julia que contiene una construccioacuten de lenguaje

macroForma de incluir el coacutedigo generado en el cuerpo final de un programa

funciones generadasFunciones capaces de generar coacutedigo especializado seguacuten el tipo de losargumentos

datos faltantesInstancias que representan datos sin valor

258 Capiacutetulo 19 Extra Sintaxis

Capiacutetulo 20 Extra Base y Libreriacutea EstaacutendarJulia tiene todo lo necesario El moacutedulo Base contiene las funciones tipos ymacros maacutes uacutetiles los cuales estaacuten disponibles directamente en Julia

Julia tambieacuten posee una gran cantidad de moacutedulos especializados en suBiblioteca Estaacutendar (moacutedulos para fechas computacioacuten distribuida aacutelgebralineal perfiles nuacutemeros aleatorios entre otros) Las funciones los tipos y lasmacros definidos en la Biblioteca Estaacutendar deben importarse antes de poderusarse

bull import _Module_ importa el modulo y _Modulefn_(x) llama a la funcioacuten _fn_

bull using _Module_ importa todas las funciones tipos y macros exportadas de_Module_

Ademaacutes es posible agregar maacutes funciones a una gran cantidad de paquetes(httpsjuliaobservercom)

Este capiacutetulo no es un reemplazo de la documentacioacuten oficial de Julia Soacutelo sedan algunos ejemplos para ilustrar lo que es posible hacer sin ser exhaustivoLas funciones ya vistas no estaacuten incluidas Se puede encontrar una explicacioacutenmaacutes completa en httpsdocsjulialangorg

Midiendo el RendimientoHemos visto que algunos algoritmos funcionan mejor que otros fibonnaci enSeccioacuten 116 es mucho maacutes raacutepido que fib en Seccioacuten 67 La macro timepermite cuantificar la diferencia

juliagt fib(1)1juliagt fibonacci(1)1juliagt time fib(40) 0567546 seconds (5 allocations 176 bytes)102334155juliagt time fibonacci(40) 0000012 seconds (8 allocations 1547 KiB)102334155

time imprime el tiempo que tardoacute en ejecutarse la funcioacuten el nuacutemero deasignaciones (allocations) y la memoria asignada antes de devolver el resultadoLa funcioacuten fibonacci que guarda resultados previos es mucho maacutes raacutepida peronecesita maacutes memoria

Midiendo el Rendimiento 259

El teorema No free lunch dice que no existe un uacutenico modelo que funcionemejor en todos los casos

OBSERVACIOacuteN

Para comparar dos algoritmos estos debenimplementarse como funciones Una funcioacuten en Julia secompila la primera vez que se ejecuta por lo tanto sedebe excluir la primera vez que se llama a estasfunciones al medir el rendimiento De lo contrariotambieacuten se mediriacutea el tiempo de compilacioacuten

El paquete BenchmarkTools (httpsgithubcomJuliaCIBenchmarkToolsjl) proporciona la macro btime querealiza una evaluacioacuten comparativa de la maneracorrecta iexclAsiacute que uacutesela

Colecciones y Estructuras de DatosEn Seccioacuten 136 se usan diccionarios para encontrar las palabras que apareciacuteanen un documento y que no apareciacutean en un arreglo de palabras La funcioacuten quese escribioacute tomaba d1 que conteniacutea las palabras del documento como claves yd2 que conteniacutea el arreglo de palabras Y devolviacutea un diccionario que conteniacutealas claves de d1 que no estaban en d2

function resta(d1 d2) res = Dict() for clave in keys(d1) if clave notin keys(d2) res[clave] = nothing end end resend

En todos estos diccionarios los valores son nothing porque nunca son usadosCon esto se estaacute desperdiciando espacio de almacenamiento

Julia ofrece otro tipo integrado llamado conjunto que se comporta como unacoleccioacuten de claves de diccionario sin valores Agregar elementos a un conjuntoes raacutepido y tambieacuten lo es verificar si un elemento forma parte de eacutel Ademaacutes losconjuntos proporcionan funciones y operadores para calcular operaciones deconjuntos

Por ejemplo la resta de conjuntos estaacute disponible como una funcioacuten llamadasetdiff Entonces reescribiendo resta

260 Capiacutetulo 20 Extra Base y Libreriacutea Estaacutendar

function resta(d1 d2) setdiff(d1 d2)end

El resultado es un conjunto en vez de un diccionario

Algunos de los ejercicios en este libro se pueden hacer de manera eficiente yconcisa con conjuntos Por ejemplo a continuacioacuten se muestra una solucioacuten pararepetido de Seccioacuten 10157 que usa un diccionario

function repetido(t) d = Dict() for x in t if x isin d return true end d[x] = nothing end falseend

Cuando un elemento aparece por primera vez se agrega al diccionario Si elmismo elemento aparece nuevamente la funcioacuten devuelve true

Usando conjuntos podemos escribir la misma funcioacuten

function repetido(t) length(Set(t)) lt length(t)end

Un elemento solo puede aparecer en un conjunto una vez por lo que si unelemento en t aparece maacutes de una vez el conjunto seraacute maacutes pequentildeo que t Si nohay elementos repetidos el conjunto tendraacute el mismo tamantildeo que t

Tambieacuten podemos usar conjuntos para hacer algunos de los ejercicios deCapiacutetulo 9 Por ejemplo aquiacute hay una versioacuten de usasolo con un bucle

function usasolo(palabra disponibles) for letra in palabra if letra notin disponibles return false end end trueend

Colecciones y Estructuras de Datos 261

usasolo comprueba si todas las letras en palabra estaacuten en disponibles Podemosreescribir esta funcioacuten

function usasolo(palabra disponibles) Set(palabra) sube Set(disponibles)end

El operador sube (subseteq TAB) verifica si un conjunto es un subconjunto deotro incluida la posibilidad de que sean iguales lo cual es cierto si todas lasletras en palabra aparecen en disponibles

Exercise 20-1

Reescriba la funcioacuten evita de Capiacutetulo 9 usando conjuntos

MatemaacuteticasTambieacuten se pueden usar nuacutemeros complejos en Julia La constante global im estaacuteasociada al nuacutemero complejo que representa la raiacutez cuadrada principal de

Ahora se puede verificar la identidad de Euler

juliagt ℯ^(imπ)+100 + 12246467991473532e-16im

El siacutembolo ℯ (euler TAB) es la base de los logaritmos naturales

Se puede analizar la naturaleza compleja de las funciones trigonomeacutetricas

Se puede probar esta foacutermula para diferentes valores de

juliagt x = 0012π000162juliagt cos(x) == 05(ℯ^(imx)+ℯ^(-imx))true

Aquiacute se muestra otro ejemplo del operador punto Julia tambieacuten permite usarvalores numeacutericos con identificadores (siacutembolos leacutexicos que nombran entidadescomo π) como en 2π

262 Capiacutetulo 20 Extra Base y Libreriacutea Estaacutendar

CadenasEn Capiacutetulo 8 y Capiacutetulo 9 se realizan algunas buacutesquedas en cadenas AdemaacutesJulia puede usar expresiones regulares (o regexes) compatibles con Perl lo quefacilita la tarea de encontrar patrones complejos en cadenas

La funcioacuten usasolo se puede implementar como una expresioacuten regular

function usasolo(palabra disponibles) r = Regex([^$(disponibles)]) occursin(r palabra)end

La expresioacuten regular busca un caraacutecter que no estaacute en la cadena disponible yoccursin devuelve true si el patroacuten se encuentra en palabra

juliagt usasolo(banana abn)truejuliagt usasolo(bananas abn)false

Las expresiones regulares tambieacuten se pueden construir como literales de cadenano estaacutendar con el prefijo r

juliagt match(r[^abn] banana)

juliagt m = match(r[^abn] bananas)RegexMatch(s)

En este caso la interpolacioacuten de cadenas no estaacute permitida La funcioacuten matchdevuelve nothing si no se encuentra el patroacuten de lo contrario devuelve un objetoregexmatch

Podemos extraer la siguiente informacioacuten de un objeto regexmatch

bull La subcadena que coincide mmatch

bull Las subcadenas que coinciden en forma de arreglo de cadenas mcaptures

bull La primera posicioacuten en la que se encuentra el patroacuten moffset

bull Las posiciones de las subcadenas que coinciden en forma de arreglomoffsets

Cadenas 263

juliagt mmatchsjuliagt moffset7

Las expresiones regulares son extremadamente poderosas y el manual de PERLhttpperldocperlorgperlrehtml explica coacutemo realizar hasta las buacutesquedas maacutesextrantildeas

ArreglosEn el Capiacutetulo 10 se usa un objeto de arreglo unidimensional con un iacutendice paraacceder a sus elementos Sin embargo en Julia las matrices sonmultidimensionales

Se puede crear una matriz de ceros de 2 por 3

juliagt z = zeros(Float64 2 3)2times3 ArrayFloat642 00 00 00 00 00 00juliagt typeof(z)ArrayFloat642

El tipo de esta matriz es un arreglo que contiene nuacutemeros de punto flotante Estamatriz es de 2 dimensiones

La funcioacuten size devuelve una tupla con el nuacutemero de elementos en cadadimensioacuten

juliagt size(z)(2 3)

La funcioacuten ones construye una matriz con elementos de valor unitario

juliagt s = ones(String 1 3)1times3 ArrayString2

El elemento de valor unitario de una cadena es una cadena vaciacutea

264 Capiacutetulo 20 Extra Base y Libreriacutea Estaacutendar

AVISO

s no es un arreglo unidimensional

juliagt s == [ ]false

s es un vector fila y [ ] es un vector columna

Se puede crear una matriz usando espacios para separar elementos en una fila ypunto y coma para separar filas

juliagt a = [1 2 3 4 5 6]2times3 ArrayInt642 1 2 3 4 5 6

Se pueden usar corchetes para modificar elementos de una matriz

juliagt z[12] = 11juliagt z[23] = 11juliagt z2times3 ArrayFloat642 00 10 00 00 00 10

Se pueden usar porciones en cada dimensioacuten para seleccionar un subgrupo deelementos

juliagt u = z[2end]2times2 ArrayFloat642 10 00 00 10

El operador aplica una operacioacuten en todas las dimensiones

juliagt ℯ^(imu)2times2 ArrayComplexFloat642 0540302+0841471im 10+00im 10+00im 0540302+0841471im

Arreglos 265

InterfacesJulia especifica algunas interfaces informales para definir comportamientos esdecir meacutetodos con un objetivo especiacutefico Cuando se extienden estos meacutetodospara un tipo los objetos de ese tipo se pueden usar para construir estoscomportamientos

Si parece un pato nada como un pato y grazna como un pato entoncesprobablemente sea un pato

En Seccioacuten 67 implementamos la funcioacuten fib que devuelve el elemento -eacutesimode la secuencia de Fibonnaci

Recorrer los valores de una coleccioacuten lo cual recibe el nombre de iteracioacuten esuna interfaz de este tipo Se puede crear un iterador que devuelva la secuenciade Fibonacci

struct FibonacciTltReal endFibonacci(dDataType) = dltReal Fibonaccid() error(No Real type)

Baseiterate(FibonacciT) where TltReal = (zero(T) (one(T) one(T)))Baseiterate(FibonacciT stateTupleT T) where TltReal =(state[1] (state[2] state[1] + state[2]))

Se implementa un tipo parameacutetrico Fibonacci sin atributos un constructorexterno y dos meacutetodos iterate Se llama al primer meacutetodo iterate para inicializarel iterador y este devuelve una tupla que consta de un primer valor 0 y unestado El estado en este caso es una tupla que contiene el segundo y el tercervalor 1 y 1

Se llama al segundo meacutetodo iterate para obtener el siguiente valor de lasecuencia de Fibonacci y devuelve una tupla que tiene como primer elemento elsiguiente valor y como segundo elemento el estado que es una tupla con los dosvalores siguientes

Ahora se puede usar Fibonacci en un bucle for

juliagt for e in Fibonacci(Int64) e gt 100 ampamp break print(e ) end0 1 1 2 3 5 8 13 21 34 55 89

Parece sacado debajo de la manga pero la explicacioacuten es simple Un bucle for enJulia

266 Capiacutetulo 20 Extra Base y Libreriacutea Estaacutendar

for i in iter bodyend

se traduce en

next = iterate(iter)while next == nothing (i state) = next body next = iterate(iter state)end

Este es un ejemplo de coacutemo una interfaz bien definida permite que unaimplementacioacuten use todas las funciones disponibles en esta interfaz

Moacutedulo Interactive UtilitiesYa se ha visto el moacutedulo InteractiveUtils en Seccioacuten 1810 La macro which essolo una de las tantas opciones

La biblioteca LLVM transforma el coacutedigo de Julia en coacutedigo de maacutequina envarios pasos Podemos visualizar la salida de cada etapa

Aquiacute se muestra un ejemplo simple

function sumacuadrada(aFloat64 bFloat64) a^2 + b^2end

El primer paso es mirar el coacutedigo de bajo nivel (lowered code)

juliagt using InteractiveUtils

juliagt code_lowered sumacuadrada(30 40)CodeInfo(1 1 = Coreapply_type(BaseVal 2) 2 = (1)() 3 = Baseliteral_pow(^ a 2) 4 = Coreapply_type(BaseVal 2) 5 = (4)() 6 = Baseliteral_pow(^ b 5) 7 = 3 + 6 return 7)

Moacutedulo Interactive Utilities 267

La macro code_lowered devuelve un arreglo de una representacioacuten intermediadel coacutedigo que utiliza el compilador para generar coacutedigo optimizado

El siguiente paso antildeade informacioacuten del tipo

juliagt code_typed sumacuadrada(30 40)CodeInfo(1 1 = Basemul_float(a a)Float64 2 = Basemul_float(b b)Float64 3 = Baseadd_float(1 2)Float64 return 3) =gt Float64

El tipo de resultados intermedios y el valor de retorno se infiere correctamente

Esta representacioacuten del coacutedigo se transforma en coacutedigo LLVM

juliagt code_llvm sumacuadrada(30 40) none1 within `sumacuadradadefine double julia_sumacuadrada_6080(double double) top none2 within `sumacuadrada intfuncsjl296 within `literal_pow floatjl405 within ` 2 = fmul double 0 0 3 = fmul double 1 1 floatjl401 within `+ 4 = fadd double 2 3 ret double 4

Y finalmente se genera el coacutedigo de maacutequina

268 Capiacutetulo 20 Extra Base y Libreriacutea Estaacutendar

juliagt code_native sumacuadrada(30 40) text none2 within `sumacuadrada intfuncsjl296 within `literal_pow floatjl405 within ` vmulsd xmm0 xmm0 xmm0 vmulsd xmm1 xmm1 xmm1 floatjl401 within `+ vaddsd xmm1 xmm0 xmm0 retq nopl (rax)

DepuracioacutenLas macros Logging son una alternativa al andamiaje con sentencias deimpresioacuten

juliagt warn iexclOh vosotros los que entraacuteis abandonad la depuracioacuten conprintf Warning iexclOh vosotros los que entraacuteis abandonad la depuracioacuten conprintf Main REPL[1]1

Las sentencias de depuracioacuten (debug) no tienen que eliminarse del coacutedigo Porejemplo en contraste con el warn anterior

juliagt debug La suma de algunos valores $(sum(rand(100)))

debug por defecto no produce salida En este caso sum(rand(100)) nunca seevaluaraacute a menos que debug logging esteacute habilitado

El nivel de logging puede seleccionarse mediante la variable de entornoJULIA_DEBUG

$ JULIA_DEBUG=all julia -e debug La suma de algunos valores$(sum(rand(100))) Debug La suma de algunos valores 47116520814555024 Main none1

Aquiacute hemos utilizado all para obtener toda la informacioacuten de depuracioacuten perotambieacuten se puede optar por generar salida solo para un archivo o moacuteduloespeciacutefico

Depuracioacuten 269

Glosarioregex

Expresioacuten regular una secuencia de caracteres que definen un patroacuten debuacutesqueda

matrizArreglo bidimensional

representacioacuten intermediaEstructura de datos utilizada internamente por un compilador pararepresentar el coacutedigo fuente

coacutedigo de maacutequinaInstrucciones que pueden ser ejecutadas directamente por la unidad centralde procesamiento de una computadora

debug loggingAlmacenar mensajes de depuracioacuten en un registro (log)

270 Capiacutetulo 20 Extra Base y Libreriacutea Estaacutendar

Capiacutetulo 21 DepuracioacutenAl depurar es necesario distinguir entre los diferentes tipos de errores pararastrearlos maacutes raacutepidamente

bull Los errores de sintaxis se descubren cuando el inteacuterprete traduce el coacutedigofuente a coacutedigo de bytes Estos errores indican que hay una falla en laestructura del programa Por ejemplo omitir la palabra reservada end alfinal de un bloque de funciones genera el mensaje ERROR LoadErrorsyntax incomplete function requires end

bull Los errores en tiempo de ejecucioacuten se presentan si algo falla mientras seejecuta el programa La mayoriacutea de los mensajes de error en tiempo deejecucioacuten indican doacutende ocurrioacute el error y queacute funciones se estabanejecutando Ejemplo Una recursioacuten infinita eventualmente causa el error entiempo de ejecucioacuten ERROR StackOverflowError

bull Los errores semaacutenticos ocurren cuando un programa se ejecuta sin generarmensajes de error pero no hace lo que deberiacutea Por ejemplo una expresioacutenpuede no evaluarse en el orden esperado generando un resultadoincorrecto

El primer paso en la depuracioacuten es averiguar el tipo de error al que se enfrentaAunque las siguientes secciones estaacuten organizadas por tipo de error algunasteacutecnicas son aplicables en maacutes de una situacioacuten

Errores de SintaxisLos errores de sintaxis suelen ser faacuteciles de corregir una vez se descubre cuaacutelesson Desafortunadamente muchas veces los mensajes de error no son uacutetiles Losmensajes maacutes comunes son

ERROR LoadError syntax incomplete premature end of input

y

ERROR LoadError syntax unexpected =

los cuales no son muy informativos

Por otro lado el mensaje indica en queacute parte del programa se produjo elproblema En realidad indica doacutende Julia notoacute que habiacutea un problema que no esnecesariamente doacutende estaacute el error A veces el error es anterior a la ubicacioacutendel mensaje de error generalmente en la liacutenea anterior

Si estaacute programando incrementalmente el usuario deberiacutea tener casi localizadoel error ya que estaraacute en la uacuteltima liacutenea que agregoacute

Si estaacute copiando coacutedigo de un libro comience comparando su coacutedigo con el

Errores de Sintaxis 271

coacutedigo del libro y verifique cada letra Al mismo tiempo recuerde que el libropuede contener errores por lo que si ve algo que parece un error de sintaxis esposible que lo sea

Aquiacute hay algunas formas de evitar los errores de sintaxis maacutes comunes

1 Aseguacuterese de no estar usando una palabra reservada de Julia en un nombrede variable

2 Compruebe que tiene la palabra reservada end al final de cada sentenciacompuesta incluyendo los bloques for while if y function

3 Aseguacuterese de que las cadenas tengan su par de comillas de apertura ycierre Aseguacuterese de que todas las comillas sean comillas rectas y no otrotipo de comillas

4 Si tiene cadenas que ocupan varias liacuteneas con triples comillas aseguacuterese deque ha terminado la cadena correctamente Una cadena sin terminar puedeprovocar un error invalid token al final de su programa o puede hacer quela siguiente parte del programa sea tratada como una cadena hasta llegar ala siguiente cadena iexclEl segundo caso podriacutea no presentar mensaje de error

5 Un pareacutentesis sin cerrar mdash( or [mdash hace que Julia continuacutee con la liacuteneasiguiente como parte de la sentencia actual Generalmente se produce unerror casi inmediatamente en la siguiente liacutenea

6 Verifique el claacutesico error que se produce al ocupar = en lugar de == dentrode un condicional

7 Si tiene caracteres que no son ASCII en el coacutedigo (incluidas cadenas ycomentarios) esto podriacutea causar un problema aunque Julia generalmentemaneja caracteres no ASCII Tenga cuidado si pega texto de una paacutegina webu otra fuente

Si nada funciona pase a la siguiente seccioacuten hellip

Sigo haciendo cambios y no hay diferencia

Si el REPL dice que hay un error y usted no lo ve podriacutea deberse a que usted y elREPL no estaacuten viendo el mismo coacutedigo Verifique su entorno de programacioacutenpara asegurarse de que el programa que estaacute editando es el que Julia estaacutetratando de ejecutar

Si no estaacute seguro intente poner un error de sintaxis obvio y deliberado alcomienzo del programa Ahora ejecuacutetelo de nuevo Si REPL no encuentra elnuevo error no estaacute ejecutando el nuevo coacutedigo

Estas son algunas de las posibles razones

bull Editoacute el archivo y olvidoacute guardar los cambios antes de ejecutarlonuevamente Algunos entornos de programacioacuten hacen esto por usted pero

272 Capiacutetulo 21 Depuracioacuten

otros no

bull Cambioacute el nombre del archivo pero auacuten estaacute ejecutando el archivo con elnombre anterior

bull Algo en su entorno de desarrollo estaacute configurado incorrectamente

bull Si estaacute escribiendo un moacutedulo y estaacute usando using aseguacuterese de no darle asu moacutedulo el mismo nombre que uno de los moacutedulos estaacutendar de Julia

bull Si estaacute usando using para importar un moacutedulo recuerde que debe reiniciarREPL cuando modifique el coacutedigo en el moacutedulo Si vuelve a importar elmoacutedulo no ocurre nada

Si se queda atascado y no puede darse cuenta de lo que estaacute sucediendo unenfoque es comenzar de nuevo con un nuevo programa como iexclHola Mundo yasegurarse de que puede ejecutar este programa ya conocido Luego puedeagregar gradualmente las piezas del programa original al nuevo

Errores en Tiempo de EjecucioacutenUna vez que su programa es sintaacutecticamente correcto Julia puede leerlo y almenos comenzar a ejecutarlo iquestQueacute podriacutea salir mal

Mi programa no hace absolutamente nada

Este problema es comuacuten cuando su archivo consta de funciones y clases pero enrealidad no llama a ninguna funcioacuten para iniciar la ejecucioacuten Esto puede serintencional si soacutelo se busca importar este moacutedulo para suministrar clases yfunciones

Si no es intencional aseguacuterese de que haya una llamada a la funcioacuten en elprograma y aseguacuterese de que el flujo de ejecucioacuten pase por esta llamada (veaSeccioacuten 21223)

Mi programa se congela

Si un programa se detiene y parece no estar haciendo nada estaacute congeladoGeneralmente eso significa que estaacute atrapado en un bucle infinito o en unarecursioacuten infinita

bull Si hay un bucle en particular que le resulta sospechoso de poder provocar elproblema agregue una sentencia de impresioacuten justo antes del bucle quediga entrando al bucle y otra inmediatamente posterior que diga saliendodel bucle

Ejecute el programa Si recibe el primer mensaje y no el segundo tiene unbucle infinito Vea Seccioacuten 21221

bull La mayoriacutea de las veces una recursioacuten infinita haraacute que el programa se

Errores en Tiempo de Ejecucioacuten 273

ejecute por un rato y luego produzca un error ERROR LoadErrorStackOverflowError Si eso sucede vea Seccioacuten 21222

Si no obtiene este error pero sospecha que hay un problema con un meacutetodoo funcioacuten recursiva igual puede utilizar las teacutecnicas de Seccioacuten 21222

bull Si ninguno de esos pasos funciona comience a probar otros bucles y otrasfunciones y meacutetodos recursivos

bull Si esto no funciona quizaacutes es porque usted no entiende el flujo de ejecucioacutende su programa Vea Seccioacuten 21223

Bucle Infinito

Si cree tener un bucle infinito y cree saber cuaacutel es antildeada una sentencia deimpresioacuten que imprima los valores de las variables de la condicioacuten al final delbucle junto con el valor de la condicioacuten

Por ejemplo

while x gt 0 ampamp y lt 0 hacer algo con x hacer algo con y debug variables x y debug condicion x gt 0 ampamp y lt 0end

Ahora cuando ejecute el programa en modo de depuracioacuten veraacute el valor de lasvariables y la condicioacuten en cada iteracioacuten En la uacuteltima iteracioacuten la condicioacutendebe ser false Si el ciclo continuacutea podraacute ver los valores de x e y y podraacuteaveriguar por queacute no se actualizan correctamente

Recursioacuten Infinita

La mayoriacutea de las veces una recursioacuten infinita hace que el programa se ejecutedurante un tiempo y luego produzca un error

ERROR LoadError StackOverflowError

Si sospecha que una funcioacuten o un meacutetodo estaacute causando una recursioacuten infinitacomience por asegurarse de que hay un caso base En otras palabras deberiacuteahaber una condicioacuten que haga que la funcioacuten devuelva un valor sin hacer otrallamada recursiva Si no necesita revisar el algoritmo y encontrar ese caso base

Si hay un caso base pero el programa no parece llegar hasta eacutel antildeada unasentencia de impresioacuten al inicio de la funcioacuten que imprima los paraacutemetrosAhora cuando ejecute el programa veraacute el valor de los paraacutemetros cada vez quese llame la funcioacuten Si los paraacutemetros no se acercan al caso base eso le daraacute

274 Capiacutetulo 21 Depuracioacuten

alguna idea de por queacute no lo hace

Flujo de Ejecucioacuten

Si no estaacute seguro del flujo de ejecucioacuten en su programa antildeada sentencias deimpresioacuten al principio de cada funcioacuten con mensajes como ldquoentrando a la funcioacutenfunrdquo donde fun sea el nombre de la funcioacuten

Ahora cuando ejecute el programa se imprimiraacute una mensaje en cada funcioacuten amedida que estas sean llamadas

Cuando ejecuto el programa recibo una excepcioacuten

Si algo sale mal durante la ejecucioacuten Julia imprime un mensaje que incluye elnombre de la excepcioacuten la liacutenea del programa donde sucedioacute el problema y untrazado inverso

El trazado inverso identifica la funcioacuten que se estaacute ejecutando y la funcioacuten que lallamoacute y luego la funcioacuten que llamoacute a esa y asiacute sucesivamente En otras palabrastraza la ruta de las llamadas a las funciones que le llevaron a donde seencuentra Tambieacuten incluye los nuacutemeros de las liacuteneas de su archivo doacutendesuceden todas esas llamadas

El primer paso es examinar el lugar del programa donde ocurrioacute el error y ver sipuede adivinar lo que sucedioacute Estos son algunos de los errores en tiempo deejecucioacuten maacutes comunes

ArgumentErrorUno de los argumentos para llamar a una funcioacuten no tiene la formaesperada

BoundsErrorSe estaacute tratando de acceder a un elemento de un arreglo fuera de los liacutemitesde indexacioacuten

DomainErrorEl argumento de una funcioacuten o constructor no pertenece al dominio vaacutelido

DivideErrorSe intentoacute dividir un entero por 0

EOFErrorNo habiacutea maacutes datos disponibles para leer desde un archivo o stream

InexactErrorNo se puede convertir a un tipo

Errores en Tiempo de Ejecucioacuten 275

KeyErrorSe estaacute tratando de acceder o eliminar un elemento inexistente de un objetoAbstractDict (Dict) o Set

MethodErrorNo existe un meacutetodo con la especificacioacuten de tipo requerida en la funcioacutengeneacuterica dada Alternativamente no existe un meacutetodo uacutenico maacutes especiacutefico

OutOfMemoryErrorUna operacioacuten asignoacute demasiada memoria para que el sistema o elrecolector de basura opere correctamente

OverflowErrorEl resultado de una expresioacuten es demasiado grande para el tipo especificadoy se produce un desbordamiento

StackOverflowErrorUna llamada a funcioacuten trata de usar maacutes espacio que el que estaacute disponibleen la pila de llamadas Esto generalmente ocurre cuando una llamada serepite infinitamente

StringIndexErrorSe produjo un error al intentar acceder a un iacutendice invaacutelido de una cadena

SystemErrorFalloacute una llamada al sistema y se muestra un mensaje de error

TypeErrorError de asercioacuten de tipo o error producido al llamar a una funcioacutenintegrada con un tipo de argumento incorrecto

UndefVarErrorUn siacutembolo en el entorno (o aacutembito) actual no estaacute definido

Puse tantas sentencias de impresioacuten que me ahogo eninformacioacuten

Uno de los problemas de usar sentencias print en la depuracioacuten es que puedeterminar ahogado por tanta informacioacuten Hay dos formas de resolver estosimplificar la salida o simplificar el programa

Para simplificar la salida puede eliminar o comentar (convertir en comentariosno evaluados coacutemo oacuterdenes del programa) las sentencias print que no sean uacutetileso combinarlas Tambieacuten puede dar a la salida un formato que la haga maacutescomprensible

276 Capiacutetulo 21 Depuracioacuten

Para simplificar el programa puede hacer varias cosas Primero puede reducir laescala del problema en el que estaacute trabajando el programa Por ejemplo si estaacutebuscando algo en una lista buacutesquelo en una lista pequentildea Si el programa aceptaentradas del usuario ingrese la entrada maacutes simple que provoque el problema

Segundo puede limpiar el programa Elimine el coacutedigo muerto y reorganice elprograma para hacerlo tan legible como sea posible Por ejemplo si sospechaque el problema estaacute en una parte del programa con un anidamiento (nesting)muy profundo pruebe a reescribir esa parte con una estructura maacutes simple Sisospecha de una funcioacuten muy larga trate de dividirla en funciones maacutes pequentildeasy prueacutebelas separadamente

Generalmente el proceso de encontrar el caso de prueba miacutenimo lleva el usuarioa encontrar el error Si encuentra que un programa funciona en una situacioacutenpero no en otra eso le daraacute una pista sobre lo que estaacute sucediendo

De forma parecida reescribir una porcioacuten de coacutedigo puede ayudarle a encontrarerrores sutiles Si realiza un cambio que cree que no deberiacutea afectar elprograma pero lo hace entonces eso puede darle una pista

Errores SemaacutenticosEn cierto modo los errores semaacutenticos son los maacutes difiacuteciles de corregir ya que elinteacuterprete no entrega informacioacuten sobre lo que estaacute mal Soacutelo usted sabe lo quese supone que debe hacer el programa

El primer paso es hacer una conexioacuten entre el coacutedigo y el comportamiento queestaacute viendo Necesita una hipoacutetesis sobre lo que realmente estaacute haciendo elprograma Una de las dificultades que nos encontramos es la alta velocidad delos computadores

A menudo seriacutea deseable ralentizar el programa a una velocidad humana Eltiempo que lleva colocar unas sentencias print en los lugares adecuados sueleser menor que el que lleva configurar un depurador poner y quitar puntos deinterrupcioacuten y ldquohacer avanzarrdquo al programa hasta donde se produce el error

Mi programa no funciona

Deberiacutea hacerse estas preguntas

bull iquestHay algo que se supone que deberiacutea hacer el programa pero que nosucede Busque la seccioacuten del coacutedigo que realiza esa funcioacuten y aseguacuterese deque se ejecuta cuando deberiacutea

bull iquestOcurre algo que no deberiacutea Busque el coacutedigo en su programa que realizaesa funcioacuten y vea si se ejecuta cuando no debe

bull iquestHay alguna seccioacuten del coacutedigo que cause un efecto que no esperabaAseguacuterese de que entiende el coacutedigo en cuestioacuten especialmente si incluye

Errores Semaacutenticos 277

funciones o meacutetodos de otros moacutedulos de Julia Lea la documentacioacuten de lasfunciones a las que llama Prueacutebelas escribiendo casos de prueba simples ycomprobando sus resultados

Para programar necesitaraacute tener un modelo mental de coacutemo funcionan losprogramas Si escribe un programa que no hace lo que esperaba de eacutel muchasveces el problema no estaraacute en el programa sino en su modelo mental

La mejor manera de corregir su modelo mental es dividiendo el programa en suscomponentes (normalmente en funciones y meacutetodos) y probando cadacomponente de forma independiente Una vez que encuentre la discrepanciaentre su modelo y la realidad podraacute solucionar el problema

Por supuesto deberiacutea ir haciendo y probando componentes a medida quedesarrolla el programa Si encuentra un problema soacutelo habriacutea que revisar unapequentildea cantidad de coacutedigo nuevo

Tengo una expresioacuten grande y peliaguda y no hace lo queespero

Estaacute bien escribir expresiones complejas mientras sean legibles pero pueden serdifiacuteciles de depurar Suele ser una buena idea dividir una expresioacuten compleja enuna serie de asignaciones de variables temporales

Por ejamplo

agregarcarta(juegomanos[i] sacarcarta(juegomanos[encontrarvecino(juegoi)]))

Puede reescribirse como

vecino = encontrarvecino(juego i)cartaseleccionada = sacarcarta(juegomanos[vecino])agregarcarta(juegomanos[i] cartaseleccionada)

La versioacuten expliacutecita es maacutes faacutecil de leer porque los nombres de variables nosentregan documentacioacuten adicional y es maacutes faacutecil de depurar porque se puedencomprobar los tipos de las variables intermedias y mostrar sus valores

Otro problema que puede suceder con las expresiones grandes es que el ordende evaluacioacuten puede no ser el que usted esperaba Por ejemplo si estaacutetraduciendo la expresioacuten a Julia podriacutea escribir

y = x 2 π

Esto no es correcto ya que la multiplicacioacuten y la divisioacuten tienen la misma

278 Capiacutetulo 21 Depuracioacuten

precedencia y se evaluacutean de izquierda a derecha De este modo la anteriorexpresioacuten calcula

Una buena forma de depurar expresiones es antildeadir pareacutentesis para que seaexpliacutecito el orden de evaluacioacuten

y = x (2 π)

Siempre que no esteacute seguro del orden de evaluacioacuten utilice pareacutentesis Elprograma no soacutelo seraacute correcto (en el sentido de que hace lo que usted quiere)sino que ademaacutes seraacute maacutes legible para otras personas que no hayan memorizadolas reglas de precedencia y que lean el coacutedigo

Tengo una funcioacuten que no devuelve lo que esperaba

Si tiene una sentencia return con una expresioacuten compleja no tendraacute laoportunidad de imprimir el valor de retorno antes de retornar De nuevo puedeusar una variable temporal Por ejemplo en lugar de

return sacarpares(juegomanos[i])

podriacutea escribir

contar = sacarpares(juegomanos[i])return contar

Ahora ya tiene la oportunidad de mostrar el valor de count antes de retornar

Estoy atascado de verdad y necesito ayuda

Primero intente alejarse del computador durante unos minutos Trabajar con uncomputador puede provocar estos efectos

bull Frustracioacuten yo furia

bull Creencias supersticiosas (ldquoel computador me odiardquo) y pensamiento maacutegico(ldquoel programa soacutelo funciona cuando me pongo la gorra hacia atraacutesrdquo)

bull Programar dando palos de ciego (el empentildeo de programar escribiendo todoslos programas posibles y eligiendo el que hace lo correcto)

Si se encuentra afectado por alguno de estos siacutentomas levaacutentese y deacute un paseoCuando esteacute calmado piense en el programa iquestQueacute es lo que hace iquestCuaacutelespueden ser las causas de tal comportamiento iquestCuaacutendo fue la uacuteltima vez que suprograma funcionaba y queacute fue lo siguiente que hizo

A veces lleva tiempo encontrar un error Muchas veces encontramos errores

Errores Semaacutenticos 279

cuando estamos lejos del computador y divagamos Algunos de los mejoreslugares para encontrar errores son los trenes las duchas y la cama justo antesde quedarse dormido

No de verdad necesito ayuda

Sucede Incluso los mejores programadores se atascan de vez en cuando A vecestrabaja durante tanto tiempo en un programa que no puede ver el error Lo quenecesita es un par de ojos nuevos

Antes de llamar a alguien aseguacuterese de estar preparado Su programa deberiacuteaser tan simple como sea posible y usted deberiacutea estar trabajando con la entradamiacutenima que provoca el error Deberiacutea tener sentencias print en los lugaresadecuados (y lo que dicen deberiacutea ser comprensible) y deberiacutea tambieacuten entenderel problema lo bastante bien como para describirlo de manera concisa

Cuando llame a alguien para que le ayude aseguacuterese de darle la informacioacuten quenecesitan

bull Si hay un mensaje de error iquestcuaacutel es y queacute parte del programa sentildeala

bull iquestQueacute fue lo uacuteltimo que hizo antes de que apareciera el error iquestCuaacuteles sonlas uacuteltimas liacuteneas de coacutedigo que escribioacute o cuaacutel es el nuevo caso de pruebaque falla

bull iquestQueacute ha intentado hasta ahora y queacute ha averiguado

Cuando encuentre el error toacutemese un momento para pensar acerca de lo quepodriacutea haber hecho para encontrarlo maacutes raacutepido La siguiente vez que vea algoparecido seraacute capaz de encontrar el error antes

Recuerde el objetivo no es solo hacer que el programa funcione El objetivo esaprender coacutemo hacer funcionar el programa

280 Capiacutetulo 21 Depuracioacuten

Apeacutendice A Entrada de UnicodeLa siguiente tabla muestra algunos de los muchos caraacutecteres Unicode quepueden ingresarse mediante abreviaciones similares a aquellas utilizadas enLatex en el REPL de Julia (y en muchos otros entornos de edicioacuten)

Caraacutecter Tab completionsequence

representacioacuten ASCII

sup2 ^2₁ _1₂ _2ἴ appleἴ bananaὂ camelἵ pearὂ turtlecap capequiv equiv ===

ℯ eulerisin in in

ge ge gt=

le le lt=

ne ne =

notin notinπ pi pi

sube subseteqε varepsilon

Apeacutendice A Entrada de Unicode 281

Apeacutendice B JuliaBoxJuliaBox permite ejecutar Julia en su navegador Ingrese a la paacuteginahttpswwwjuliaboxcom inicie sesioacuten y comience a usar el entorno Jupyter

La pantalla inicial se muestra en Figura 25 El botoacuten new (nuevo) permite lacreacioacuten de un notebook de Julia un archivo de texto (text file) una carpeta(folder) o una sesioacuten de terminal (terminal session)

En una sesioacuten de terminal el comando julia inicia REPL como se muestra enFigura 26

La interfaz del notebook permite mezclar texto (en modo Markdown) y coacutedigocon su respectiva salida Figura 27 muestra un ejemplo

Puedes encontrar maacutes documentacioacuten en el sitio web de Jupyterhttpjupyterorgdocumentation

Figura 25 Pantalla inicial

282 Apeacutendice B JuliaBox

Figura 26 Sesioacuten de terminal

Apeacutendice B JuliaBox 283

Figura 27 Notebook

284 Apeacutendice B JuliaBox

Apeacutendice C Cambios de ThinkJuliaEste libro es una traduccioacuten de ThinkJulia que estaacute disponible bajo la LicenciaCreative Commons Atribucioacuten-NoComercial 30 No portada Esta licenciarequiere que los trabajos derivados (como este libro) enumeren los cambiosrealizados en relacioacuten a la fuente

Las diferencias de este libro respecto a ThinkJulia incluyen lo siguiente

bull Traduccioacuten del ingleacutes al espantildeol

bull Se cambiaron muchas frases idiomaacuteticas que no seriacutean familiares para loshispanohablantes (Se cayoacute el centavo)

bull En vez de usar el texto de la novela Emma en el Capiacutetulo 13 se usa eltexto de Don Quijote

bull Debido a que OrsquoReilly no financioacute la traduccioacuten algunas de las referencias aOrsquoReilly en el prefacio fueron eliminadas

Apeacutendice C Cambios de ThinkJulia 285

Index 126 57=

veacutease ne 57

veacutease cadena vaciacutea 101

veacutease comillas triples 51hellip (comillas)

veacutease comillas 11

veacutease comentario 22$

veacutease interpolacioacuten de cadenas102

161veacutease operador moacutedulo 56

ampamp 247 57 21 21 (asterisco)

operador de multiplicacioacutenveacutease asterisco 9

+ 21+ (operador de suma)

veacutease suma 9+= 127 (coma)

no usar en enterosveacutease coma 11

- 21- (operador de resta)

veacutease subtraction 9 200 201 265

veacutease operador punto 128 21 (operador de divisioacuten)

veacutease division 10 206 253 244 25 265 64lt 57lt=

veacutease le 57=

veacutease sentencia de asignacioacuten 17== 105 205 57 75===

veacutease equiv 131=gt 142gt 57gt=

veacutease ge 57

veacutease help 51 247 254assert 214code_llvm 268code_lowered 267code_native 268code_typed 268contenedorvariable 254debug 269generated 255macroexpand 254printf 187show 73svg 43test 230time 259warn 269which 237 267[]

veacutease slice operator 125[]

veacutease operador corchete 97n 196r 196t 175 196] 42^ 21 21^ (circunflejo)

operador de exponenciacioacutenveacutease circunflejo 10

_ (guioacuten bajo)en enteros

veacutease guioacuten bajo (_) 11``

286 Index

veacutease comillas invertidas 193

veacutease llaves 142|| 247 57divide 161

veacutease operador divisioacuten entera 56hellip 161isin

veacutease in 104notin 115cap 177ne 57equiv 131 205le 57ge 57sube 262

Aabreviaturas tipo LaTeX 18abs 71 92abspath 188abstract type 233 233 240ack 83actualizacioacuten 94acumulador 127 137 174algoritmo 93 95alias 133 138 167 203 205ambas 105analizar 32andamiaje 154 73 83anidado 122anotacioacuten de tipo 226anular 177 184Any 123 142 217anaacutelisis de Markov 179anaacutelisis de sintaxis 12 15append 126arc 49archivo de texto 196arco 49 53areacirculo 74ArgumentError 27 275 64argumento 27 30 32 33 38argumento opcional 131 176argumentos con nombre 244 257argumentos opcionales 138

Arreglo 123arreglo 122 137 166arreglo vaciacuteo 122 124asignacioacuten 160 191 24asignacioacuten aumentada 137asignacioacuten de tupla 160 164asignacioacuten en tupla 168asignacioacuten muacuteltiple 86 94asterisco ()

operador de multiplicacioacuten 9atributo 199 206

Bbandera 151 155Base 243 259base de datos 191 197begin 245benchmarking 182 184Biblioteca Estaacutendar 243bloque 245bloque do 257bloque let 257Bool 57borrarprimero 133BoundsError 107 160 275break 89bucle 44 52 88bucle infinito 273 88 95bugs

veacutease errores 15Byte 249buacutesqueda 102 103 109 109 115 155buacutesqueda de biseccioacuten 178buacutesqueda inversa 155

Ccadena 166 97 97

concatenacioacutenveacutease concatenar 21

repeticioacutenveacutease repeticioacuten 22

cadena vaciacutea 101 108cadenas 10 14calculadora 26campo

veacutease atributo 199

Index 287

Canguro 227capturar 197capturar una excepcion 190Car Talk 120 157 169carpeta

veacutease directorio actual 188caraacutecter guioacuten bajo 18Caraacutecter Unicode 17caraacutecter Unicode 30 72caso base 63 66caso especial 119 120catch 190ccall 256cd 193Channel 248Char 112 97cifrado Ceacutesar 112Circulo 207circunflejo (^)

operador de exponenciacioacuten 10clasificar 242clausura 257clave 142 154close 113 187 192codificacioacuten UTF-8 108 99codificar 228 239coinciden 164cola 135collect 130 146 163coma ()

no usar en enteros 11coma final 158comentario 22 25comillas 30comillas (hellip)

entre 11comillas invertidas 193comillas triples 51comparacioacuten de cadenas 105componentes leacutexicos 11 15composicioacuten 29 33 39 74concatenacioacuten de cadenas 25concatenar 21 34concatenar_dos 34condicional alternativa 71condicional anidada 59 66

condicional encadenada 59 66condicioacuten 58 66conjetura de Collatz 89conjuntoanagramas 198ConjuntoDeCartas 233const 153 229constructor 199 206 219 251

copiaveacutease constructor de copia

220externo

veacutease constructor externo220

internoveacutease constructor interno

220constructor de copia 220 227constructor externo 220 226constructor interno 220 226constructor por defecto 226contador 104 109ContarLineas 195contarlineas 194conteo 109continue 90conversioacuten 252 258conversioacuten de tipo 27convert 252copia 125copiar 193 205copodenieve 69corchetes 142 265cos 33cuadrado 46cuatroveces 40cuenta regresiva 61cuentaregresiva 88cuerpo 30 38curva de Koch 69ciacuterculo 47 50coacutedigo ASCII 108 97coacutedigo de maacutequina 268coacutedigo muerto 277 71 82

Ddatos faltantes 255 258

288 Index

DBM 191de Cervantes

Miguel 174debug logging 269 270declaracioacuten 151 156decremento 88 94deepcopy 205 206 207definicioacuten circular 76definicioacuten de funcioacuten 29 38definicioacuten recursiva 76deleteat 130delimitador 131 138dependencia 236 240depuracioacuten 106 119 135 153 154

167 182 196 205 213 22623 269 37 52 65 72 81 93

emociones de la manejando las13

veacutease errores (bugs) probando15

depuracioacuten del pato de goma 183 184depuracioacuten experimental 37depuracioacuten por biseccioacuten 93desarrollo de prototipos 209 211 214desarrollo incremental 72 82desarrollo planificado 212 214deserialize 192desplazarpalabra 112 156determiniacutestico 172 183devolverfloat 216diaframa de estado 123diagrama

estadoveacutease diagrama de estado 17

graacutefico de llamadasveacutease graacutefico de llamadas

149objeto

veacutease diagrama de objeto200

pilaveacutease diagrama de pila 34

tiposveacutease diagrama de tipos 236

diagrama de estado 131 132 149166 166 17 24 86

diagrama de objeto 200 202 207diagrama de pila 134 34 39 62 68

78diagrama de tipos 236 240dibujarcirculo 207dibujarrect 207diccionario 142 154Dict 142Dijkstra

Edsger W 119dimensioacuten 264directorio 188 196disentildeo orientado a tipos 238dispatch 223 226dispatch muacuteltiple 223 227dispersar 168dispersioacuten 162distancia 72distanciaentrepuntos 203DivideError 275divisioacuten

operador de divisioacuten () 10divisioacuten entera 65divrem 161do 246docstring 202 51 53DomainError 275dosveces 40Doyle

Arthur Conan 37dump 196 253

Eeachindex 124eachline 114 194ejecucioacuten alternativa 58ejecutar 19 24elemento 122 137else 58elseif 59embebido 202emoji 97 99enbiseccion 141encabezado 30 38encapsulacioacuten 47encapsulado 53

Index 289

encapsulado de dato 238encapsulado de datos 240enchapado 232 239encontrarcentro 204end 101 124 190 195 199 245 30

44 58 98enteroahora 212 218entrelazan 141enumerate 164EOFError 275equivalente 132 138error 147 213

BaseEOFError 275KeyError 143StringIndexError 99SystemError 189

CoreArgumentError 27BoundsError 107DivideError 275DomainError 275InexactError 275MethodError 98OutOfMemoryError 276OverflowError 276StackOverflowError 63TypeError 216UndefVarError 34

semaacutenticoveacutease error semaacutentico 23

sintaxisveacutease error de sintaxis 18

tiempo de ejecucioacutenveacutease error de tiempo de

ejecucioacuten 23error de forma 168error de sintaxis 18 23 25 271 29error de tiempo de ejecucioacuten 23 25error en tiempo de ejecucioacuten 271 34error semaacutentico 23 25 271errores (bugs) 13

veacutease depuracioacuten 15errores de forma 167ES-UN 236esabecedaria 115 117

esanagrama 140esc 254escogerdelhistograma 173esdivisible 75eshoravalida 213espalindromo 110 118 84especificacioacuten 218 226 250espotencia 84esreverso 106 119estadespues 209 219estaordenada 140estilo de programacioacuten funcional 211estilo funcional de programacioacuten 214estimarpi 96estriangulo 68estructura 11 15estructura de dato 168estructuras de datos 167estructuras de datos recursivas 221eval 254 95evalbucle 96evaluacioacuten de cortocircuito 247 257evaluar 19 24evita 115 262evitar 114excepcioacuten

veacutease error de tiempo deejecucioacuten 23

exp 29export 195Expr 253expresioacuten 18 24 253 258expresioacuten booleana 57 66extension

jl 19extrema 161

Ffact 247 77 80 81factorial 78false 57faltantes 255fib 79Fibonacci 266fibonnaci 149 79file stream 113 119

290 Index

filter 174filtro 128 138finally 190findall 148findfirst 104findnext 104firstindex 99float 27flujo de ejecucioacuten 273 32 39 71 77

81 88for 44formateando 187formatting 154forward 42fractal 69funccioacuten

definida por el programadorconjuntoanagramas 198

funciondefinida por el programador

aacuterea 70funciones generadas 255 258funcioacuten 27 29 38

Baseabs 71abspath 188append 126buacutesqueda 109ccall 256coinciden 164collect 130conteo 109convert 252cos 33deepcopy 205 206deleteat 130divrem 161dump 196eachindex 124eachline 114enumerate 164error 147esc 254exp 29extrema 161factorial 78

filter 174findall 148firstindex 99float 27get 145get 156include 194insert 130isdefined 206isdir 188isequal 148isfile 189isletter 171ispath 188iterate 266join 131joinpath 189keys 143length 40log 28log10 28lpad 121match 263max 162maximum 161min 162minimum 161new 220nextind 99occursin 263ones 264open 113parse 27pop 129popfirst 129print 41promote 252promote_rule 253push 125pushfirst 130put 248pwd 188rand 140readdir 189readline 113 64reinterpret 249

Index 291

repr 196reverse 167reverse 167run 193setdiff 260show 36sin 28size 264sizeof 99skipmissing 256sort 126sort 126splice 129split 130sqrt 28string 28sum 127supertype 238take 192 248time 67trunc 27tupla 158uppercase 104values 144vcat 134walkdir 189write 186zeros 264zip 163

ContarLineascontarlineas 195

Coreeval 254 95

definida por el programadorack 83ambas 105areacirculo 74borrarprimero 133buacutesqueda 102clasificar 242cola 135concatenar_dos 34contarlineas 194copodenieve 69cuadrado 46cuatroveces 40

cuenta regresiva 61ciacuterculo 47desplazarpalabra 112devolverfloat 216dibujarcirculo 207dibujarrect 207distancia 72distanciaentrepuntos 203dosveces 40enbiseccion 141encontrarcentro 204enteroahora 212esabecedaria 115esanagrama 140escogerdelhistograma 173esdivisible 75eshoravalida 213espalindromo 84espotencia 84esreverso 106estadespues 209estaordenada 140estimarpi 96estriangulo 68evalbucle 96evita 114fact 77fib 79findfirst 104findnext 104histograma 145horaaentero 212imprimircuadricula 41imprimirdosveces 32imprimirhist 146imprimirhora 208imprimirmascomun 176imprimirpalabra 40imprimirpunto 202imprimirtodo 161incrementar 210interior 139interior 139invertirdic 148justificar_a_la_derecha 39koch 69

292 Index

leeranagramas 198mascomun 175masfrecuente 168mcd 85medio 84minmax 161miraiz 95mover 235moverpunto 203multhora 215noborrarprimero 135notiene_e 114palabraalazar 178palabrasdiferentes 175palabrastotales 174par inverso 141polyline 49poliacutegono 47ponerenmarsupio 227primera 84printn 62probarraiz 95procesararchivo 173procesarlinea 173procesarpalabra 239puntoencirculo 207recorrer 189rectencirculo 207recursioacuten 63repartir 241repetido 140repetirletras 30resta 177sed 197seq 89sinc 216sobreposicionrectcirc 207solomayusculas 128sumaacumulada 139sumaanidada 139sumacuadrada 267sumahora 209sumartodo 162tienedoblepareja 242tienepareja 242todoenmayusculas 127

ultima 84usasolo 115usatodo 115valorabsoluto 70verificarfermat 67

definido por el programadorimprimirletras 29

IntroAJuliaforward 42pendown 43penup 43turn 43

Metaparse 253 95

Plotsgraficar 185 244

programmer-definedarco 49

Randomshuffle 232

Serializacioacutendeserialize 192serialize 192

funcioacuten Ackermann 83funcioacuten anoacutenima 244 257funcioacuten booleana 75funcioacuten de Ackermann 156funcioacuten definida por el programador

29 33funcioacuten exponencial

veacutease exp 29funcioacuten factorial 77funcioacuten gamma 80funcioacuten hash 155funcioacuten logaritmo

veacutease log 28funcioacuten matemaacutetica 28funcioacuten nula 35 39funcioacuten productiva 35 39 70funcioacuten pura 209 214funcioacuten raiacutez

veacutease sqrt 28funcioacuten recursiva 61funcioacuten trigonomeacutetrica 28funcioacuten typeof 10function 29

Index 293

funtor 251 258

GGDBM 191generalizacioacuten 47 53get 145get 156 174global 151 99graficar 185graacutefico de llamada 155graacutefico de llamadas 149guardian 81guardiaacuten 83guioacuten bajo (_)

en enteros 11

Hhash 149hash table 144hashable 149 155help 51histograma 145 224Holmes

Sherlock 37Hora 208 217horaaentero 212 218

Iidentidad de Euler 262ideacutentico 132 138if 58im 262immutable 102 108 158 167 200implementacioacuten 144 155 225import 195 259imprimircuadricula 41imprimirdosveces 32imprimirhist 146imprimirhora 208 217imprimirletras 29imprimirmascomun 176imprimirpalabra 40imprimirpunto 202imprimirtodo 161in 100 124 143 156 44include 194

incrementar 218incrementar 210incremento 88 94indentacioacuten 46indicador 64

en REPL 14 9indice 98InexactError 275informaacuteticos habilidades de

veacutease programacioacuten 7inicializacioacuten 94initializacioacuten 87input 113insert 130 136instancia 200 206instanciacioacuten 200instanciar 206instrucciones

veacutease sentencias 7Int 112InteractiveUtils 237 267interfaz 225 266 48 53interior 139interior 139intermediate representation 270interpolacioacuten de cadenas 102 109

187 263IntroAJulia 42invariante 213 215invertirdic 148IOBuffer 192isa 206 234 80isdefined 206isdir 188isequal 148isfile 189isletter 171 174ispath 188item 122 142 154iteracioacuten 191 86 88 94iterador 163 168 266iterate 266

Jjoin 131joinpath 189

294 Index

Juliaejecutando 8

JuliaBox 19 8notebook graacutefico 42

justificar_a_la_derecha 39

KKeyError 143 276keys 143keyword

elseveacutease else 58

importveacutease import 259

koch 69

LLaTeX-like abbreviations 281leeranagramas 198lemario 113length 143 40 84 98lenguaje de programacioacuten 11 15lenguaje de programacioacuten completo 76lenguaje formal 11 15lenguaje natural 11 14ley de Zipf 184Linux 38lista anidada 137Llamada a funcioacuten 27 38llaves 142 249LLVM code 268log 28log10 28lookup 147lowercase 174lpad 121

Mmachine code 270macro 254 258 43

Baseassert 214debug 269generated 255macroexpand 254show 73

time 259warn 269

definida por el programadorcontenedorvariable 254

InteractiveUtilscode_llvm 268code_lowered 267code_native 268code_typed 268which 237

Luxorsvg 43

Printfprintf 187

Testtest 230

Mano 234map 128mapeo 138 142 154marco 34 39 62Markov 238mascomun 175masfrecuente 168match 263matemaacuteticas

operadores aritmeacuteticos 9matrix 264 270max 162maximum 161mayuacutescula 127Mazo 231mcd 85md5 194md5sum 194medio 84mensaje de error 23MethodError 101 159 162 219 276

98min 162minimum 161minmax 161miraiz 95Missing 255modelo mental 278modificador 210 214modo interactivo 19 24 36

Index 295

modo script 19 24 36module 195

ContarLineasveacutease ContarLineas 195

InteractiveUtilsveacutease InteractiveUtils 237

Randomveacutease Random 232

Testveacutease Test 230

modulo 42 52veacutease IntroAJulia 42

mover 235moverpunto 203MPunto 201multhora 215multiplicidad 236 240mutable 123 133 167mutable struct 201meacutetodo 217 226meacutetodo de Newton 91meacutetodos 226moacutedulo

Plotsveacutease Plots 184 244

Serializacioacutenveacutease Serializacioacuten 192

Nnada 39Naipe 229new 220nextind 99noborrarprimero 135norma Unicode 108 97notacioacuten de punto

veacutease 200nothing 177 36 36 70notiene_e 114 115nuacutemeros complejos 262

Oobjeto 131 138objeto de comando 193 197objeto de funcioacuten 38 40objeto embebido 207

objeto zip 163 168occursin 263ones 264open 113 186 246operacioacuten con cadenas 21operacioacuten de reduccioacuten 127 138operador

Base= 57 56+= 127 128lt 57lt= 57== 57gt 57gt= 57 247[] 125[] 97in 104isa 206 234divide 56isin 104notin 115cap 177ne 57equiv 131le 57ge 57sube 262

cadenas 21operador corchete 101 101 122 123

159 191 97operador de divisioacuten entera 56operador de exponenciacioacuten (^) 10operador de multiplicacioacuten () 9operador de resta (-) 9operador de suma (+) 9operador loacutegico 57 66operador moacutedulo 56 65operador porcioacuten 125 135 159operador punto 128 137operador relacional 159 57 66operador ternario 257

veacutease 247

296 Index

operadores 14 9aritmeacuteticos 9

operadores aritmeacuteticos 9operando 24orden alfabeacutetico 105orden de operaciones 21OutOfMemoryError 276output

sentencia de impresioacuten 14 9OverflowError 276

Ppalabra clave 18 24palabra reservada

abstract type 233begin 245break 89catch 190const 153 229continue 90do 246elseif 59export 195final 30finally 190for 44function 30global 151if 58import 195in 44module 195mutable struct 201quote 253return 62struct 199tipo primitivo 249try 190using 42while 88

palabraalazar 178palabrasdiferentes 175palabrastotales 174paliacutendromo 84PAPOMUDAS 21paquete 42 52

par clave-valor 142 154 165par inverso 141Paradoja del cumpleantildeos 140pares de metaacutetesis 169parse 253 64 95paraacutemetro 32 34 38pareacutentesis 158 164 21 27

vaciacuteos 30pendown 43penup 43persistente 186 196pi 17 28pista 150 155 156 170plan de desarrollo de programa 117

211 239 50 53 82plot 244Plots 184 244polimorfismo 225polimoacuterfica 224polygon 49polyline 49poliacutegono 47Poncela

Enrique Jardiel 114ponerenmarsupio 227pop 129 232 234popfirst 129 133porcioacuten 108 109 265postcondicioacuten 52 53 81precedencia del operador 25precondicioacuten 52 53 81prefijo 179primera 84Principal 35principio de sustitucioacuten de Liskov 237print 187 41println 187 41printn 62probarraiz 95procesararchivo 173procesarlinea 173procesarpalabra 239programacioacuten de caminata aleatoria

183programacioacuten geneacuterica 227programas 14 7

Index 297

promocioacuten 253 258promote 252 253promote_rule 253Proyecto Gutenberg 171prueba de consistencia 154prueba de cordura 154prueba unitaria 230 239pseudoaleatorio 172 184Ptr 256Punto 199 222puntoencirculo 207push 125 130 134 136 141 232

234pushfirst 130 136put 248pwd 188

Qquote 253

Rrama 59 66rand 140 172Random 232read 194readdir 189readline 113 64 90reasignacioacuten 151 204recopila 161recorrer 189recorrido 106 108 124 99Rectangulo 202rectencirculo 207recursividad 61recursioacuten 117 63 66 68 76 86 88recursioacuten infinita 274 63 67 80recursos en liacutenea

JuliaBox 8reduccioacuten a un problema previamente

resuelto 120reduccioacuten a un problema resuelto

previamente 117reducible 170reducir el tamantildeo 153refactorizacioacuten 239 50 53referencia 133 138 200

Regex 263regex 263 270RegexMatch 263reinterpret 249relacioacuten ES-UN 240relacioacuten TIENE-UN 240repartir 241repeticioacuten 22 34

veacutease iteracioacuten 8repetido 140 156 261repetirletras 30repetition 43REPL 281REPL (Read-Eval-Print Loop) 14 8replace 174repr 196representacioacuten intermedia 268resolucioacuten de problemas 14 7resta 177 260return 62reunir 168reverse 167 175reverse lookup 147reverse 167run 193ruta 188 197ruta absoluta 188 197ruta relativa 188 197

Ssangriacutea 30 60script 19 24secuencia 108 97 97secuencias de secuencias 166sed 197semaacutentica 25sentencia 19 24sentencia break 89 94sentencia compuesta 58 66sentencia condicional 58 66 76sentencia continue 90 95sentencia de asignacioacuten 123 17 86sentencia de asignacioacuten aumentada

127sentencia de depuracioacuten 269sentencia de impresioacuten 14

298 Index

funcioacuten println 9sentencia for 100 114 117 124 163

165 191 266 44 86 88sentencia global 152 155sentencia if 58sentencia print 81 94sentencia return 62 66 70sentencia try 190sentencia using 42 52sentencia while 117 88 94 99separador 175seq 89Serializacioacuten 192serialize 192Set 260setdiff 260shell 193 197show 221 227 229 234 36shuffle 232sin 28 32sinc 216singleton 148 155sintaxis 11 15sintaxis de punto 129 138 243size 264sizeof 99skipmissing 256slice 101sobrecarga de operadores 227sobrecarga del operador 222sobreposicionrectcirc 207solomayusculas 128sort 126 137 146 167 175sort 126 136 136 167 233splice 129split 130 160 174sqrt 28 73square 47StackOverflowError 274 276 63 80stacktrace 63String 97string 187 263 28StringIndexError 276 99strip 136struct 199 206subtipo 233 233 240 240

sufijo 179sum 127 162 224suma de verificacioacuten 194sumaacumulada 139sumaanidada 139sumacuadrada 267sumahora 209 213sumartodo 162supertipo 233 240supertype 238SVG picture 43Symbol 206SystemError 189 276

Ttabla hash 155take 192 248tarea 248 257teorema de Pitaacutegoras 72tesis de Turing 76Test 230TIENE-UN 236tienedoblepareja 242tienepareja 242Time 208time 67tipo 199 233

BaseAny 123 142Array 123Bool 57Channel 248Char 97Dict 142Expr 253IOBuffer 192Missing 255nothing 36Ptr 256Regex 263RegexMatch 263Set 260Symbol 206Tuple 158UInt8 249Union 250

Index 299

DatesTime 208

definida por el programadorByte 249Canguro 227Circulo 207ConjuntoDeCartas 233Fibonacci 266Hora 208Mano 234Markov 238Mazo 231MPunto 201Naipe 229Punto 199Rectangulo 202

IntroAJuliaDBM 191

LuxorTurtle 42

tipo compuesto 199tipo compuesto mutable 201tipo concreto 233 240tipo de punto flotante (Float64) 10 14tipo entero (Int64) 10 14tipo parameacutetrico 258tipo primitivo 249 257tipos 10 14

Float64veacutease tipo de punto flotante

10Int64

veacutease tipo entero 10String

veacutease cadenas 10tipos de datos

veacutease tipos 10todoenmayusculas 127 129Torvalds

Linus 38transitorio 186trazado inverso 35 39true 57trunc 27try 190tupla 158 158 166 167

tupla con nombre 243 257Tuple 158Turing

Alan 76turn 43Turtle 42TypeError 216 276typeof 122 158 205

UUInt8 249ultima 84UndefVarError 152 276 34 35 87Unicode character 281Union 250union de tipo 250unioacuten de tipos 257update 87uppercase 104usasolo 115 116 261 263usatodo 115 116using 259 42

Vvalor 131 142 154 17valor de retorno 27 39valor por defecto 184valor predeterminado 176valorabsoluto 70valores 10 14values 144variable 131 17 24

local 34variable de entorno 269variable global 151 155 229variable global constante 153 156variable local 34 38variable temporal 279 70 75 82vcat 134 136verificar 154verificar automaacuteticamente 154verificarfermat 67voto de confianza 78

Wwalkdir 189

300 Index

while 88write 186

Zzeros 264zip 163 165 167 167

Aacuteaacutembito 195aacuterea 70

Iacuteiacutendice 108 123

Uacuteuacuteltimo teorema de Fermat 67

Ππ

veacutease pi 17

ℯ 262

Index 301

  • Introduccioacuten a la Programacioacuten en Julia
  • Tabla de Contenido
  • Licencia
  • Dedicatoria
  • Prefacio
  • Capiacutetulo 1 El camino de la programacioacuten
  • Capiacutetulo 2 Variables expresiones y sentencias
  • Capiacutetulo 3 Funciones
  • Capiacutetulo 4 Estudio de Caso Disentildeo de Interfaz
  • Capiacutetulo 5 Condicionales y recursividad
  • Capiacutetulo 6 Funciones productivas
  • Capiacutetulo 7 Iteracioacuten
  • Capiacutetulo 8 Cadenas
  • Capiacutetulo 9 Estudio de Caso Juego de Palabras
  • Capiacutetulo 10 Arreglos
  • Capiacutetulo 11 Diccionarios
  • Capiacutetulo 12 Tuplas
  • Capiacutetulo 13 Estudio de Caso Seleccioacuten de Estructura de Datos
  • Capiacutetulo 14 Archivos
  • Capiacutetulo 15 Estructuras y Objetos
  • Capiacutetulo 16 Estructuras y Funciones
  • Capiacutetulo 17 Dispatch Muacuteltiple
  • Capiacutetulo 18 Subtipos
  • Capiacutetulo 19 Extra Sintaxis
  • Capiacutetulo 20 Extra Base y Libreriacutea Estaacutendar
  • Capiacutetulo 21 Depuracioacuten
  • Apeacutendice A Entrada de Unicode
  • Apeacutendice B JuliaBox
  • Apeacutendice C Cambios de ThinkJulia
  • Index
Page 3: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar

LicenciaCopyright copy 2018 Allen Downey Ben Lauwens Todos los derechos reservados

Este libro estaacute disponible bajo la Licencia Creative Commons Atribucioacuten-NoComercial 30 No portada Es una traduccioacuten de ThinkJulia el cual tiene lamisma licencia Una lista de las diferencias entre ThinkJulia y este libro estaacutedisponible en el Apeacutendice C

Un PDF de este libro estaacute disponible aquiacute

Ben Lauwens es profesor de matemaacuteticas en Royal Military Academy (RMABeacutelgica) Tiene un doctorado en ingenieriacutea y maestriacuteas de KU Leuven y RMAademaacutes de una licenciatura de RMA

Allen Downey es profesor de informaacutetica en Olin College of Engineering Hadado clases en Wellesley College Colby College y UC Berkeley Tiene undoctorado en informaacutetica de UC Berkeley y maestriacuteas y licenciaturas del MIT

Licencia 1

DedicatoriaPara Emeline Arnaud y Tibo

2 Dedicatoria

PrefacioEn enero de 2018 comenceacute a preparar un curso de programacioacuten pensado paraestudiantes que no tuvieran experiencia previa en programacioacuten Queriacutea usarJulia como lenguaje de programacioacuten y descubriacute que no existiacutea ninguacuten libro paraaprender a programar que usara Julia como primer lenguaje de programacioacutenHay tutoriales maravillosos que explican los conceptos clave de Julia peroninguno de ellos se dedicaba lo suficiente a ensentildear a pensar como programador

Conociacutea el libro Think Python de Allen Downey el cual contiene todos loselementos clave para aprender a programar correctamente Sin embargo estelibro se basa en el lenguaje de programacioacuten Python Mi primer borrador delcurso fue una mezcla de muchas referencias pero a medida que trabajaba eneste el contenido comenzoacute a parecerse cada vez maacutes a los capiacutetulos de ThinkPython Pronto la idea de desarrollar mi curso como base para trasladar eselibro a Julia se hizo realidad

Todo el material estaba disponible en un repositorio de GitHub en forma denotebooks de Jupyter Despueacutes de publicar un mensaje en el sitio Discourse deJulia sobre el progreso de mi curso los comentarios fueron abrumadoresAparentemente un libro sobre conceptos baacutesicos de programacioacuten con Juliacomo primer lenguaje de programacioacuten era algo que faltaba en el universo deJulia Contacteacute a Allen para ver si podiacutea iniciar oficialmente la versioacuten de ThinkPython para Julia y su respuesta fue inmediata ldquoiexcladelanterdquo me puso encontacto con su editor de OrsquoReilly Media y ahora un antildeo despueacutes estoy haciendolos retoques finales a este libro

Fue un camino difiacutecil En Agosto de 2018 se lanzoacute Julia v10 y como todos miscolegas programadores de Julia tuve que hacer una migracioacuten del coacutedigo Todoslos ejemplos en el libro se prueban durante la conversioacuten de los archivos fuente aarchivos ASCIIDoc compatibles con OrsquoReilly Tanto la cadena de herramientascomo el coacutedigo de los ejemplos teniacutean que ser compatibles con Julia v10Afortunadamente no hay cursos en Agostohellip

Espero que disfrutes al trabajar con este libro y que te ayude a aprender aprogramar y pensar como informaacutetico al menos un poco

Ben Lauwens

iquestPor queacute JuliaJulia fue lanzado originalmente en 2012 por Alan Edelman Stefan Karpinski JeffBezanson y Viral Shah Es un lenguaje de programacioacuten gratuito y de coacutedigoabierto

La eleccioacuten de un lenguaje de programacioacuten es siempre subjetiva Para miacute lassiguientes caracteriacutesticas de Julia son decisivas

iquestPor queacute Julia 3

bull Julia estaacute desarrollado como un lenguaje de programacioacuten de altorendimiento

bull Julia usa enviacuteo muacuteltiple (ldquomultiple dispatchrdquo en ingleacutes) que le permite alprogramador elegir entre diferentes patrones de programacioacuten de acuerdoa la aplicacioacuten

bull Julia es un lenguaje de tipo dinaacutemico que se puede usar faacutecilmente de formainteractiva

bull Julia tiene una sintaxis de alto nivel que es faacutecil de aprender

bull Julia es un lenguaje de programacioacuten con tipos opcionales cuyos tipos dedatos (definidos por el usuario) hacen que el coacutedigo sea claro y robusto

bull Julia tiene una biblioteca estaacutendar extendida ademaacutes estaacuten disponiblesnumerosos paquetes de terceros

Julia es un lenguaje de programacioacuten uacutenico ya que resuelve el problema de losdos idiomas No se necesita de ninguacuten otro lenguaje de programacioacuten paraescribir coacutedigo de alto rendimiento Esto no significa que ocurraautomaacuteticamente Es responsabilidad del programador optimizar el coacutedigo quegenere cuellos de botella aunque esto puede hacerse directamente en Julia

iquestA quieacuten estaacute dirigido este libroEste libro es para cualquier persona que quiera aprender a programar No serequieren conocimientos formales previos

Los nuevos conceptos se introducen gradualmente y los temas maacutes avanzados sedescriben en capiacutetulos posteriores

Introduccioacuten a Julia puede ser usado como un curso de un semestre de nivelsecundario o universitario

Convenciones utilizadas en este libroEn este libro se siguen las siguientes convenciones tipograacuteficas

CursivaIndica nuevos teacuterminos URL direcciones de correo electroacutenico nombres dearchivo y extensiones de archivo

Ancho constanteSe utiliza para mostrar coacutedigo de programas asiacute como dentro de lospaacuterrafos para referirse a elementos del programa como nombres devariables o funciones bases de datos tipos de datos variables de entornosentencias y palabras reservadas

4 Prefacio

Ancho constante en negrita

Muestra comandos u otro texto que el usuario debe escribir

Ancho constante en cursivaMuestra el texto que debe reemplazarse con valores proporcionados por elusuario o por valores determinados por el contexto

OBSERVACIOacuteN Esto indica consejo o sugerencia

NOTA Esto es una nota general

AVISO Esto indica una advertencia o precaucioacuten

Usando los coacutedigos de ejemploTodo el coacutedigo utilizado en este libro estaacute disponible en un repositorio de Git enGitHub httpsgithubcomJuliaIntroIntroAJuliajl Si no estaacute familiarizado conGit es un sistema de control de versiones que le permite realizar seguimiento alos archivos que componen un proyecto Una coleccioacuten de archivos controladospor Git se denomina ldquorepositoriordquo GitHub es un servicio de hosting queproporciona almacenamiento para repositorios de Git y una interfaz webconveniente

El siguiente paquete puede ser de utilidad y se puede agregar directamente aJulia Simplemente escriba add httpsgithubcomJuliaIntroIntroAJuliajlen el REPL en modo Pkg

La forma maacutes faacutecil de ejecutar un coacutedigo de Julia es yendo a httpsjuliaboxcome iniciar una sesioacuten de prueba gratuita Es posible utilizar tanto las interfacesREPL como de notebooks Si desea tener Julia instalada localmente en sucomputadora puede descargar JuliaPro de Julia Computing gratuitamenteConsiste en una versioacuten reciente de Julia el IDE de Juno basado en Atom y variospaquetes de Julia preinstalados Si es maacutes aventurero puede descargar Juliadesde httpsjulialangorg instale el editor que prefiera por ejemplo Atom oVisual Studio Code activando los complementos para su integracioacuten de Julia Enel caso de una instalacioacuten local tambieacuten puede agregar el paquete IJulia que lepermite ejecutar un notebook de Jupyter en su computadora

AgradecimientosRealmente quiero agradecer a Allen por escribir Think Python y permitirmetrasladar este libro a Julia iexclTu entusiasmo es contagioso

Tambieacuten me gustariacutea agradecer a los revisores teacutecnicos de este libro quehicieron muchas sugerencias uacutetiles Tim Besard Bart Janssens y David P

Usando los coacutedigos de ejemplo 5

Sanders

Gracias a Melissa Potter de OrsquoReilly Media por hacer de este un mejor libro Meobligaste a hacer las cosas bien y hacer que este libro sea lo maacutes originalposible

Gracias a Matt Hacker de OrsquoReilly Media que me ayudoacute con la cadena deherramientas Atlas y algunos problemas al destacar la sintaxis

Gracias a todos los estudiantes que trabajaron con una versioacuten temprana de estelibro y a todos los colaboradores (enumerados a continuacioacuten) que enviaroncorrecciones y sugerencias

Lista de ColaboradoresSi tiene una sugerencia o correccioacuten abra un issue en GitHub Si se realiza uncambio basado en sus comentarios seraacute agregado a la lista de contribuyentes (amenos que solicite ser omitido)

Aviacutesenos con queacute versioacuten del libro estaacute trabajando y en queacute formato Si incluyeal menos parte de la oracioacuten en la que aparece el error eso facilita la buacutesquedaLos nuacutemeros de paacutegina y seccioacuten tambieacuten son uacutetiles pero no es tan faacutecil trabajarcon ellos iexclGracias

bull Scott Jones sentildealoacute el cambio de nombre de Void a Nothing y con esto secomenzoacute la migracioacuten a Julia v10

bull Robin Deits encontroacute algunos errores tipograacuteficos en el Capiacutetulo 2

bull Mark Schmitz sugirioacute destacar la sintaxis

bull Zigu Zhao encontroacute algunos errores en el Capiacutetulo 8

bull Oleg Soloviev detectoacute un error en la url al agregar el paquete ThinkJulia

bull Aaron Ang encontroacute algunos problemas de representacioacuten y nomenclatura

bull Sergey Volkov encontroacute un enlace caiacutedo en el Capiacutetulo 7

bull Sean McAllister sugirioacute mencionar el excelente paquete BenchmarkTools

bull Carlos Bolech envioacute una larga lista de correcciones y sugerencias

bull Krishna Kumar corrigioacute el ejemplo de Markov en el Capiacutetulo 18

6 Prefacio

Capiacutetulo 1 El camino de la programacioacutenEl objetivo de este libro es ensentildearle a pensar como un informaacutetico Esta manerade pensar combina las mejores caracteriacutesticas de las matemaacuteticas la ingenieriacutea ylas ciencias naturales Los informaacuteticos al igual que los matemaacuteticos usanlenguajes formales para expresar ideas (especiacuteficamente caacutelculos) De manerasimilar a los ingenieros disentildean estructuras ensamblan componentes paraformar sistemas evaluando los costos y beneficios entre las alternativasAdemaacutes observan el comportamiento de sistemas complejos elaboran hipoacutetesisy prueban predicciones como los cientiacuteficos

La habilidad maacutes importante para un informaacutetico es la resolucioacuten de problemasEsto implica ser capaz de formular problemas encontrar soluciones creativasexpresando una solucioacuten de forma clara y precisa Como resultado el proceso deaprender a programar es una excelente oportunidad para practicar habilidadesde resolucioacuten de problemas Es por ello que este capiacutetulo se llama El camino dela programacioacuten

Por una parte aprenderaacute a programar que es una habilidad muy uacutetil por siacutemisma Pero ademaacutes la programacioacuten se constituiraacute como un medio para un finA medida que avancemos este fin seraacute maacutes claro

iquestQueacute es un programa

Un programa es una secuencia de instrucciones que especifica coacutemo hacer uncaacutelculo El caacutelculo puede ser de naturaleza matemaacutetica tal como resolver unsistema de ecuaciones o encontrar las raiacuteces de un polinomio pero tambieacutenpuede ser un caacutelculo simboacutelico como buscar y reemplazar texto en undocumento o bien algo graacutefico tal como procesar una imagen o reproducir unvideo

Los detalles difieren para cada lenguaje pero algunas instrucciones baacutesicasaparecen en casi todos los lenguajes

EntradaInputSe obtienen datos a traveacutes del teclado un archivo una red u otrodispositivo

SalidaOutputLos datos se muestran por pantalla se guardan en un archivo se enviacutean atraveacutes de la red etc

MatemaacuteticasSe realizan operaciones matemaacuteticas baacutesicas como la suma y lamultiplicacioacuten

iquestQueacute es un programa 7

Ejecucioacuten condicionalSe verifican ciertas condiciones y se ejecuta el coacutedigo apropiado

RepeticioacutenSe realiza alguna accioacuten repetidamente generalmente con alguna variacioacuten

Aunque no lo crea eso es todo lo que se debe hacer Cada programa que hausado sin importar su complejidad estaacute construido basaacutendose en instruccionesque se asemejan a estas De esta manera la programacioacuten puede entendersecomo el proceso de dividir una tarea compleja y larga en pequentildeas subtareas losuficientemente simples como para realizarse con una de estas instruccionesbaacutesicas

Ejecutando Julia

Uno de los desafiacuteos al comenzar a utilizar Julia es su instalacioacuten ademaacutes delsoftware relacionado Si estaacute familiarizado con su sistema operativo y se sientecoacutemodo con la interfaz de liacutenea de comandos no tendraacute problemas No obstantepara los principiantes puede ser difiacutecil aprender sobre administracioacuten de sistemay programacioacuten al mismo tiempo

Para evitar ese problema se recomienda que comience ejecutando Julia en unnavegador Maacutes tarde cuando se sienta coacutemodo con Julia se haraacuten sugerenciaspara instalar Julia en su ordenador

En el navegador puede ejecutar Julia en JuliaBox No se requiere instalacioacutensimplemente abra su navegador y entre a la paacutegina de JuliaBox inicie sesioacuten ycomience a programar (consulte Apeacutendice B)

Julia REPL (de ReadndashEvalndashPrint Loop que se traduce en Bucle de Leer-Evaluar-Imprimir) es un programa que lee y ejecuta coacutedigo de Julia Puede iniciar REPLabriendo un terminal en JuliaBox y escribiendo julia en la liacutenea de comandoCuando comienza deberiacutea ver una salida como esta

_ _ _ _(_)_ | Documentation httpsdocsjulialangorg (_) | (_) (_) | _ _ _| |_ __ _ | Type for help ] for Pkg help | | | | | | | _` | | | | |_| | | | (_| | | Version 152 (2020-09-23) _ |___|_|_|___| | Official httpsjulialangorg release|__ |

juliagt

Las primeras liacuteneas contienen informacioacuten sobre el REPL por lo que esto puede

8 Capiacutetulo 1 El camino de la programacioacuten

mostrarse diferente en su computadora Debe verificar que la versioacuten sea almenos 100

El uacuteltima liacutenea es un indicador sentildealando que el REPL estaacute listo para que seingrese una instruccioacuten Si escribe una liacutenea de coacutedigo y presiona Enter la REPLmuestra el resultado

juliagt 1 + 12

Los fragmentos de coacutedigo se pueden copiar y pegar textualmente incluido elindicador juliagt y cualquier salida

Ahora ya estaacute listo para comenzar De aquiacute en adelante ya sabraacute coacutemo iniciar laREPL de Julia y ejecutar su coacutedigo

El primer programaTradicionalmente el primer programa que se escribe en un nuevo lenguaje sellama ldquoiexclHola mundordquo porque todo lo que hace es mostrar las palabras ldquoiexclHolamundordquo En Julia se ve asiacute

juliagt println(iexclHola mundo)iexclHola mundo

Este es un ejemplo de una sentencia de impresioacuten aunque en realidad noimprime nada en papel Muestra un resultado en la pantalla

Las comillas en el programa marcan el principio y el final del texto que semostraraacute y no apareceraacuten en el resultado

Los pareacutentesis indican que println es una funcioacuten Se estudiaraacuten funciones enCapiacutetulo 3

Operadores aritmeacuteticos

Despueacutes de nuestro programa ldquoiexclHola mundordquo el siguiente paso es laaritmeacutetica Julia tiene operadores los cuales son siacutembolos que representancaacutelculos como la suma y la multiplicacioacuten

Los operadores + - y realizan las operaciones de suma resta y multiplicacioacutenrespectivamente como se muestra en los siguientes ejemplos

El primer programa 9

juliagt 40 + 242juliagt 43 - 142juliagt 6 742

El operador realiza la divisioacuten

juliagt 842420

Quizaacutes se pregunte por queacute el resultado es 420 en vez de 42 Esto seraacuteexplicado en la siguiente seccioacuten

Finalmente el operador ^ realiza la potencicioacuten es decir eleva un nuacutemero a unapotencia

juliagt 6^2 + 642

Valores y tipos

Un valor es uno de los elementos baacutesicos con los que trabaja un programa talcomo una letra o un nuacutemero Algunos de los valores que hemos visto hasta ahorason 2 420 y Hola Mundo

Estos valores pertenecen a diferentes tipos 2 es un entero (integer en ingleacutes)420 es un nuacutemero de punto flotante (floating-point number en ingleacutes) y HolaMundo es una cadena de caracteres (string en ingleacutes) llamada asiacute porque lasletras que contiene estaacuten unidas

Si no estaacute seguro del tipo de un valor el REPL puede ayudarle

juliagt typeof(2)Int64juliagt typeof(420)Float64juliagt typeof(iexclHola mundo)String

Los enteros pertenecen al tipo Int64 las cadenas pertenecen a String y losnuacutemeros de punto flotante pertenecen a Float64

10 Capiacutetulo 1 El camino de la programacioacuten

iquestQueacute pasa con los valores 2 y 420 Parecen nuacutemeros pero estaacuten entrecomillas como si fueran cadenas Estos valores tambieacuten son cadenas

juliagt typeof(2)Stringjuliagt typeof(420)String

Si se quiere escribir un nuacutemero de grandes dimensiones se podriacutea caer en lacostumbre de usar comas para separar sus cifras como por ejemplo 1000000Este no es un entero vaacutelido en Julia aunque siacute es vaacutelido

juliagt 1000000(1 0 0)

iexclEsto no es lo que se podriacutea esperar Julia entiende 1000000 como unasecuencia de enteros separados por comas Maacutes adelante aprenderemos maacutessobre este tipo de secuencias

Sin embargo puede obtener el resultado esperado usando 1_000_000

Lenguajes formales y naturales

Los lenguajes naturales son los lenguajes hablados como el espantildeol el ingleacutes oel franceacutes no fueron disentildeados por personas (aunque las personas intentanimponerles un orden) sino que evolucionaron naturalmente

Los lenguajes formales son lenguajes disentildeados por personas para propoacutesitosespeciacuteficos Por ejemplo la notacioacuten que usan los matemaacuteticos es un lenguajeformal particularmente uacutetil para denotar relaciones entre nuacutemeros y siacutembolosLos quiacutemicos usan un lenguaje formal para representar la estructura quiacutemica delas moleacuteculas Los lenguajes de programacioacuten tambieacuten son lenguajes formales yhan sido disentildeados para expresar caacutelculos

Los lenguajes formales tienden a dictar reglas estrictas de sintaxis quegobiernan la estructura de las sentencias Por ejemplo en matemaacuteticas lasentencia tiene la sintaxis correcta pero no En quiacutemica esuna foacutermula sintaacutecticamente correcta pero no lo es

Las reglas de sintaxis pueden ser de dos tipos correspondientes a componentesleacutexicos y a estructura Los componentes leacutexicos son los elementos baacutesicos dellenguaje como palabras nuacutemeros y elementos quiacutemicos Uno de los problemascon es que no es un componente leacutexico vaacutelido en matemaacuteticas (al menos

Lenguajes formales y naturales 11

hasta donde conocemos) Del mismo modo no es vaacutelido porque no existeninguacuten elemento con la abreviatura

El segundo tipo de reglas de sintaxis se refiere a la forma en que se combinan loscomponentes leacutexicos La ecuacioacuten no es vaacutelida porque aunque y soncomponentes leacutexicos vaacutelidos no se puede tener uno justo despueacutes el otro Delmismo modo en una foacutermula quiacutemica el subiacutendice se coloca despueacutes del nombredel elemento no antes

Esta es un oracioacuten en espa$ol bien estructurada con cmponentes leacutexicos novaacutelidos Esta oracioacuten leacutexicos todos componentes los tiene pero estructura una novaacutelida con

Cuando se lee una oracioacuten en espantildeol o en un lenguaje formal se tiene quedescubrir la estructura (aunque en un lenguaje natural se haceinconscientemente) Este proceso se llama parsing o anaacutelisis de sintaxis

Aunque los lenguajes formales y naturales tienen muchas caracteriacutesticas encomuacutenmdashcomponentes leacutexicos estructura y sintaxismdashexisten algunas diferencias

AmbiguumledadLos lenguajes naturales estaacuten llenos de ambiguumledades este problema esabordado mediante el uso del contexto y otra informacioacuten Los lenguajesformales estaacuten disentildeados para ser casi completamente precisos lo quesignifica que cualquier declaracioacuten tiene exactamente un significadoindependientemente del contexto

RedundanciaPara compensar la ambiguumledad y reducir los malentendidos los lenguajesnaturales emplean mucha redundancia Como resultado a menudo sonverbosos Los lenguajes formales son menos redundantes y maacutes concisos

MetaacuteforaLos lenguajes naturales estaacuten llenos de modismos y metaacuteforas Si se diceldquoCaiacute en la cuentardquo probablemente no haya una cuenta y nada que se caiga(este modismo significa que alguien entendioacute algo despueacutes de un periacuteodo deconfusioacuten) Por otro lado los lenguajes formales significan exactamente loque expresan

Debido a que todo el mundo crece hablando lenguajes naturales a veces esdifiacutecil adaptarse a los lenguajes formales La diferencia entre lenguaje formal ynatural es como la diferencia entre la poesiacutea y la prosa

PoesiacuteaLas palabras se usan por sus sonidos y significados El poema en conjuntocrea un efecto o una respuesta emocional La ambiguumledad no soacutelo es comuacutensino a menudo deliberada

12 Capiacutetulo 1 El camino de la programacioacuten

ProsaEl significado literal de las palabras es maacutes importante y la estructuraaporta significado La prosa es maacutes faacutecil de analizar que la poesiacutea pero amenudo sigue siendo ambigua

ProgramasEl significado de un programa computacional es inequiacutevoco y literal ypuede entenderse por completo mediante el anaacutelisis de los componentesleacutexicos y de estructura

Los lenguajes formales son maacutes densos que los naturales por lo que lleva maacutestiempo leerlos Ademaacutes la estructura es importante por lo que no siempre esmejor leer de arriba a abajo y de izquierda a derecha En cambio aprenderaacute aanalizar el programa mentalmente identificando los componentes leacutexicos einterpretando la estructura Finalmente los detalles son importantes Pequentildeoserrores de ortografiacutea y puntuacioacuten que pueden pasar desapercibidos en loslenguajes naturales pueden hacer una gran diferencia en un lenguaje formal

Depuracioacuten

Los programadores cometen errores Los errores de programacioacuten se denominanbugs y el proceso para rastrearlos se denomina debugging o depuracioacuten

La programacioacuten y especialmente la depuracioacuten pueden provocar emocionesnegativas Frente a un error difiacutecil de solucionar puede sentir enojo verguumlenzaoacute cansancio

Existe evidencia de que las personas responden naturalmente a lascomputadoras como si fueran personas Cuando trabajan bien se los consideracompantildeeros de equipo y cuando son obstinados o groseros se los trata de lamisma manera que a personas groseras y obstinadas [1]

Prepararse para estas reacciones puede ayudarlo a lidiar con ellas Un enfoquees pensar en la computadora como un empleado con ciertas fortalezas como lavelocidad y la precisioacuten y debilidades particulares como la falta de empatiacutea y laincapacidad para comprender el panorama general

Su trabajo es ser un buen gerente debe encontrar formas de aprovechar lasfortalezas y mitigar las debilidades Ademaacutes debe encontrar formas de usar susemociones para involucrarse con el problema sin dejar que sus reaccionesinterfieran con su capacidad para trabajar de manera efectiva

Aprender a depurar puede ser frustrante pero es una habilidad valiosa que esuacutetil para muchas actividades maacutes allaacute de la programacioacuten Al final de cadacapiacutetulo hay una seccioacuten como esta con algunas sugerencias para ladepuracioacuten iexclEspero que le sean de ayuda

Depuracioacuten 13

Glosarioresolucioacuten de problemas

El proceso de formular un problema encontrar una solucioacuten y expresarla

programaUna secuencia de instrucciones que especifica un caacutelculo

REPLUn programa que de manera reiterada lee una entrada la ejecuta y generaresultados

indicadorCaracteres mostrados por el REPL para indicar que estaacute listo para recibirinformacioacuten de entrada de parte del usuario

sentencia de impresioacuten (print)Una instruccioacuten que hace que el REPL de Julia muestre un valor en lapantalla

operadorUn siacutembolo que representa un caacutelculo simple como la suma lamultiplicacioacuten o la concatenacioacuten de cadenas

valorUna de las unidades baacutesicas de datos como un nuacutemero o cadena quemanipula un programa

tipoUna categoriacutea de valores Los tipos que se han visto hasta ahora sonenteros (Int64) nuacutemeros de punto flotante (Float64) y cadenas (String)

enteroUn tipo que representa nuacutemeros enteros

punto flotanteUn tipo que representa nuacutemeros con un punto decimal

cadenaUn tipo que representa secuencias de caracteres

lenguaje naturalCualquier lenguaje hablado que evoluciona naturalmente

14 Capiacutetulo 1 El camino de la programacioacuten

lenguaje formalCualquier lenguaje disentildeado para fines especiacuteficos como la representacioacutende ideas matemaacuteticas o programas de computadora Todos los lenguajes deprogramacioacuten son lenguajes formales

sintaxisLas reglas que gobiernan la estructura de un programa

componente leacutexicoUno de los elementos baacutesicos de la estructura de un programa anaacutelogo auna palabra en un lenguaje natural

estructuraLa manera en que los componentes leacutexicos se combinan

anaacutelisis de sintaxisExaminar un programa y analizar la estructura sintaacutectica

bugUn error en un programa

depuracioacutendebuggingEl proceso de buacutesqueda y correccioacuten de errores

Ejercicios

OBSERVACIOacuteNEs una buena idea leer este libro frente a unacomputadora para hacer los ejemplos y ejerciciosconforme avance

Ejercicio 1-1

Siempre que esteacute experimentando con algo nuevo debe intentar cometererrores Por ejemplo en el programa ldquoiexclHola mundordquo iquestQueacute sucede si omite unade las comillas iquestQueacute pasa si omite ambas iquestQueacute ocurre si escribe mal println

Este tipo de ejercicios le ayuda a recordar lo que leyoacute tambieacuten le ayuda aprogramar porque puede saber queacute significan los mensajes de error Es mejorcometer errores ahora y a propoacutesito en lugar de despueacutes y accidentalmente

1 En un comando print iquestQueacute sucede si omite uno de los pareacutentesis o ambos

2 Si estaacute intentando imprimir un string iquestQueacute sucede si omite una de lascomillas o ambas

3 Se puede usar un signo menos para escribir un nuacutemero negativo como -2

Ejercicios 15

iquestQueacute sucede si pone un signo + antes de un nuacutemero iquestQueacute pasa con 2++2

4 En notacioacuten matemaacutetica los ceros a la izquierda son correctos como en 02iquestQueacute pasa si intenta esto en Julia

5 iquestQueacute sucede si tiene dos valores sin operador entre ellos

Ejercicio 1-2

Inicie el REPL de Julia y uacuteselo como una calculadora

1 iquestCuaacutentos segundos hay en 42 minutos y 42 segundos

2 iquestCuaacutentas millas hay en 10 kiloacutemetros

OBSERVACIOacuteN Hay 161 kiloacutemetros en una milla

3 Si corre una carrera de 10 kiloacutemetros en 37 minutos y 48 segundos iquestCuaacuteles su ritmo promedio (tiempo por milla en minutos y segundos) iquestCuaacutel es suvelocidad promedio en millas por hora

[1] Reeves Byron and Clifford Ivar Nass 1996 ldquoThe Media Equation How People Treat ComputersTelevision and New Media Like Real People and Placesrdquo Chicago IL Center for the Study of Language andInformation New York Cambridge University Press

16 Capiacutetulo 1 El camino de la programacioacuten

Capiacutetulo 2 Variables expresiones y sentenciasUna de las caracteriacutesticas maacutes poderosas de un lenguaje de programacioacuten es lacapacidad de manipular variables Una variable es un nombre que hacereferencia a un valor

Sentencias de asignacioacuten

Una sentencia de asignacioacuten crea una nueva variable y le asigna un valor

juliagt mensaje = Y ahora algo completamente diferenteY ahora algo completamente diferentejuliagt n = 1717juliagt π_val = 31415926535897933141592653589793

Este ejemplo realiza tres asignaciones La primera asigna una cadena a unanueva variable llamada mensaje la segunda le asigna el entero 17 a la variable nla tercera asigna el valor (aproximado) de π (pi TAB) a la variable π_val

Una forma comuacuten de representar variables en papel es escribir el nombre de lavariable con una flecha apuntando a su valor Este tipo de figura se llamaldquodiagrama de estadordquo porque muestra en queacute estado se encuentra cada una delas variables La Figura 1 Figura 1 muestra el resultado del ejemplo anterior

Figura 1 Diagrama de estado

Nombres de variablesLos programadores generalmente eligen nombres representativos para susvariables es decir nombres que explican para queacute se usa o queacute contiene lavariable

Los nombres de las variables pueden ser tan largos como se desee Puedencontener casi todos los caracteres Unicode (consulte Seccioacuten 81) pero nopueden comenzar con un nuacutemero Es vaacutelido usar letras mayuacutesculas pero locomuacuten es usar solo minuacutesculas para nombres de variables

Los caracteres Unicode se pueden ingresar mediante autocompletado portabulacioacuten de las abreviaturas tipo LaTeX en el REPL de Julia

El caraacutecter guioacuten bajo _ puede formar parte del nombre de una variable

Sentencias de asignacioacuten 17

Generalmente se usa como separador en nombres con varias palabras como porejemplo en tu_nombre ovelocidad_aerodinamica_de_una_golondrina_sin_cargamento

Si se le da un nombre invaacutelido a una variable aparece un error de sintaxis

juliagt 76trombones = un gran desfileERROR syntax 76 is not a valid function argument name (ERRORsintaxis 76 no es un nombre de argumento de funcioacuten vaacutelido)juliagt mas = 1000000ERROR syntax extra token after end of expression (ERROR sintaxiscomponente leacutexico adicional despueacutes del final de la expresioacuten)juliagt struct = Quiacutemica avanzadaERROR syntax unexpected = (ERROR sintaxis = inesperado)

76trombones es un nombre de variable invaacutelido porque comienza con un nuacutemeroTambieacuten es invaacutelido mas porque contiene el caraacutecter invaacutelido Pero iquestCuaacutel esel error en struct

Resulta que struct es una de las palabras reservadas de Julia Julia usa laspalabras reservadas para reconocer la estructura del programa por ello nopueden usarse como nombres de variables

Julia tiene las siguientes palabras reservadas

abstract type baremodule begin break catchconst continue do else elseifend export finally for functionglobal if import importall inlet local macro module mutable structprimitive type quote return try usingstruct where while

No es necesario memorizar esta lista En la mayoriacutea de los entornos dedesarrollo las palabras reservadas se muestran en un color diferente por lotanto si intenta usar una como nombre de variable lo sabraacute

Expresiones y sentenciasUna expresioacuten es una combinacioacuten de valores variables y operadores Un valor ouna variable por siacute solos se consideran una expresioacuten por lo que las siguientesexpresiones son vaacutelidas

18 Capiacutetulo 2 Variables expresiones y sentencias

juliagt 4242juliagt n17juliagt n + 2542

Cuando escribe una expresioacuten en el indicador el REPL la evaluacutea lo que significaque encuentra el valor de la expresioacuten En este ejemplo n tiene el valor 17previamente asignado y n+25 retorna el valor 42

Una sentencia es una unidad de coacutedigo que tiene un efecto tal como crear unavariable o mostrar un valor

juliagt n = 1717juliagt println(n)17

La primera liacutenea es una sentencia de asignacioacuten ya que asigna un valor a n Lasegunda liacutenea es una sentencia de impresioacuten que muestra el valor de n

Cuando escribe una sentencia REPL la ejecuta es decir hace lo que dice lasentencia

Modo scriptHasta ahora se ha ejecutado Julia en modo interactivo lo que significa que se hainteractuado directamente con el REPL Este modo es una buena manera decomenzar pero si estaacute trabajando con varias liacuteneas de coacutedigo puede resultarincoacutemodo

Una alternativa es guardar el coacutedigo en un archivo de oacuterdenes o script y luegoutilizar Julia en modo script para ejecutarlo Por convencioacuten los scripts de Juliatienen nombres que terminan con la extensioacuten jl

Si sabe coacutemo crear y ejecutar un script en su computadora estaacute listo paracomenzar De lo contrario es recomendable usar JuliaBox nuevamente Abra unarchivo de texto escriba el script y guaacuterdelo con la extensioacuten jl El script sepuede ejecutar en una terminal con el comando julia nombre_del_scriptjl

Debido a que Julia proporciona ambos modos puede probar liacuteneas de coacutedigo enmodo interactivo antes de colocarlos en un script Auacuten asiacute tenga enconsideracioacuten que existen diferencias entre el modo interactivo y el modo scriptque pueden generar confusioacuten

Por ejemplo si estaacute utilizando Julia como una calculadora puede escribir

Modo script 19

juliagt millas = 262262juliagt millas 16142182

La primera liacutenea asigna un valor a millas y muestra el valor La segunda liacutenea esuna expresioacuten por lo que el REPL la evaluacutea y muestra el resultado Gracias alcoacutedigo anterior sabemos que una maratoacuten tiene unos 42 kiloacutemetros

Pero si escribe el mismo coacutedigo en un script y lo ejecuta no obtendraacute ninguacutenresultado En el modo script una expresioacuten por siacute sola no tiene ninguacuten efectovisible Julia evaluacutea la expresioacuten pero no muestra el valor a menos que se loindique

millas = 262println(millas 161)

Al principio este comportamiento puede ser confuso

Un script generalmente contiene una secuencia de sentencias Si hay maacutes de unasentencia los resultados aparecen de uno a la vez a medida que se ejecutan lassentencias

Por ejemplo el script

println(1)x = 2println(x)

produce la salida

12

Notar que la sentencia de asignacioacuten x = 2 no tiene salida

Ejercicio 2-1

Para comprobar que ha comprendido lo recientemente explicado escriba lassiguientes sentencias en el REPL de Julia y vea lo que hace cada una

5x = 5x + 1

20 Capiacutetulo 2 Variables expresiones y sentencias

Ahora coloque las mismas sentencias en un script y ejecuacutetelo iquestCuaacutel es elresultado Modifique el script transformando cada expresioacuten en una sentencia deimpresioacuten y luego ejecuacutetelo de nuevo

Orden de operacionesCuando una expresioacuten contiene maacutes de un operador el orden de evaluacioacutendepende de las reglas de precedencia Julia sigue la convencioacuten matemaacutetica parael orden de evaluacioacuten de los operadores matemaacuteticos El acroacutenimo PAPOMUDASes una forma uacutetil de recordar estas reglas

bull PAreacutentesis tienen la mayor precedencia y se pueden utilizar para forzar laevaluacioacuten de una expresioacuten en el orden que se desee Dado que lasexpresiones entre pareacutentesis se evaluacutean primero 2(3-1) es 4 y (1+1)^(5-2) es 8 Tambieacuten puede usar pareacutentesis para hacer una expresioacuten maacutes faacutecilde leer como en (minuto100)60 incluso si no cambia el resultado

bull POtenciacioacuten tiene la siguiente precedencia maacutes alta por lo que 1+2^3 es9 no 27 y 23^2 es 18 no 36

bull MUltiplicacioacuten y Divisioacuten tienen mayor precedencia que la Adicioacuten ySustraccioacuten Entonces 23-1 es 5 no 4 y 6+42 es 8 no 5

bull Los operadores con la misma precedencia se evaluacutean de izquierda a derecha(excepto potencias) Entonces en la expresioacuten grados2π la divisioacuten ocurreprimero y el resultado se multiplica por π Para dividir entre puede usarpareacutentesis escribir grados2π o grados2π

OBSERVACIOacuteNNo se esfuerce demasiado en recordar el orden de lasoperaciones Si el orden no es evidente mirando laexpresioacuten use pareacutentesis para que siacute lo sea

Operaciones con cadenasEn general no se pueden realizar operaciones matemaacuteticas con cadenas aunquelas cadenas puedan parecer nuacutemeros por lo que lo siguiente es invaacutelido

2 - 1huevos faacuteciltercero + talismaacuten

No obstante hay dos excepciones y ^

El operador realiza concatenacioacuten de cadenas lo que significa que une lascadenas de extremo a extremo Por ejemplo

Orden de operaciones 21

juliagt primer_str = autoautojuliagt segundo_str = moacutevilmoacuteviljuliagt primer_str segundo_strautomoacutevil

El operador ^ tambieacuten funciona con cadenas generando repeticiones Porejemplo Spam^3 es SpamSpamSpam Si uno de los valores es una cadena elotro tiene que ser un nuacutemero entero

De manera anaacuteloga este uso de y ^ tambieacuten tiene sentido en la multiplicacioacuten ypotencia Asiacute como 4^3 es equivalente a 444 esperamos que el Spam^3 sea lomismo que el SpamSpamSpam y lo es

ComentariosA medida que los programas se hacen maacutes largos y complejos se vuelven maacutesdifiacuteciles de leer Los lenguajes formales son densos y a menudo es difiacutecil leer elcoacutedigo y entender queacute estaacute haciendo o por queacute

Por esta razoacuten es una buena idea agregar notas a sus programas para explicaren lenguaje natural lo que estaacute haciendo el programa Estas notas se llamancomentarios y comienzan con el siacutembolo

calcula el porcentaje de hora que ha transcurridoporcentaje = (minuto 100) 60

En este caso el comentario aparece soacutelo en una liacutenea Tambieacuten puede ponercomentarios al final de una liacutenea

porcentaje = (minuto 100) 60 porcentaje de una hora

Todo desde el hasta el final de la liacutenea se ignora y no tiene ninguacuten efecto en laejecucioacuten del programa

Los comentarios son maacutes uacutetiles cuando documentan caracteriacutesticas no obvias delcoacutedigo Es razonable suponer que el lector puede averiguar queacute hace el coacutedigopor lo tanto es maacutes uacutetil explicar por queacute

Este comentario es inuacutetil porque es redundante con el coacutedigo

v = 5 asigna 5 a v

Este comentario contiene informacioacuten uacutetil que no estaacute presente en el coacutedigo

22 Capiacutetulo 2 Variables expresiones y sentencias

v = 5 velocidad en metrossegundo

OBSERVACIOacuteNLos nombres de las variables tienen que ser descriptivospara asiacute reducir la necesidad de comentarios pero notan largos como para dificultar la lectura del coacutedigo

DepuracioacutenSe pueden producir tres tipos de errores en un programa errores de sintaxiserrores en tiempo de ejecucioacuten y errores semaacutenticos Es uacutetil distinguirlos pararastrearlos maacutes raacutepidamente

Error de sintaxisldquoSintaxisrdquo se refiere a la estructura de un programa y las reglas sobre esaestructura Por ejemplo los pareacutentesis deben presentarse de a pares por loque (1+2) es vaacutelido pero 8) es un error de sintaxis

Si hay un error de sintaxis en cualquier parte de su programa Julia muestraun mensaje de error y se cierra no pudiendo ejecutar el programa Durantesus primeras semanas como programador puede pasar mucho tiemporastreando errores de sintaxis A medida que gane experiencia cometeraacutemenos errores y los encontraraacute maacutes raacutepido

Error en tiempo de ejecucioacutenEl segundo tipo de error es el error en tiempo de ejecucioacuten llamado asiacuteporque aparece durante la ejecucioacuten del programa Estos errores tambieacutense denominan excepciones porque generalmente indican que ha sucedidoalgo excepcional (y malo)

Los errores en tiempo de ejecucioacuten son raros en los programas simples queveraacute en los primeros capiacutetulos por lo que puede pasar un tiempo antes deque encuentre uno

Error semaacutenticoEl tercer tipo de error es ldquosemaacutenticordquo es decir relacionado con elsignificado Si hay un error semaacutentico en su programa este se ejecutaraacute singenerar mensajes de error pero no haraacute lo que se desea sino que haraacute otracosa Especiacuteficamente haraacute lo que usted le dijo que hiciera (y no lo queusted desea que realice)

Identificar errores semaacutenticos puede ser complicado porque requiere que setrabaje a la inversa analizando la salida del programa para intentar descubrirqueacute estaacute haciendo

Depuracioacuten 23

Glosariovariable

Un nombre que hace referencia a un valor

asignacioacutenUna sentencia que asigna un valor a una variable

diagrama de estadoUna representacioacuten graacutefica de un conjunto de variables y los valores a losque hace referencia

palabra claveUna palabra reservada que se utiliza para definir la sintaxis y estructura deun programa no puede usar palabras reservadas como if function ywhile como nombres de variables

operandoUno de los valores sobre los que opera un operador

expresioacutenUna combinacioacuten de variables operadores y valores que representa un solovalor como resultado

evaluarSimplificar una expresioacuten realizando operaciones para obtener un solo valor

sentenciaUna seccioacuten de coacutedigo que representa un comando o accioacuten Hasta ahoralas sentencias que hemos visto son asignaciones e impresiones

ejecutarEjecutar una sentencia y hacer lo que eacutesta dice

modo interactivoUna forma de utilizar el REPL de Julia escribiendo coacutedigo en el indicador

modo scriptUna forma de usar Julia para leer coacutedigo desde un script y ejecutarlo

scriptUn programa almacenado en un archivo

24 Capiacutetulo 2 Variables expresiones y sentencias

precedencia del operadorReglas que rigen el orden en que se evaluacutean las expresiones que involucranmuacuteltiples operadores matemaacuteticos y operandos

concatenarUnir dos cadenas de extremo a extremo

comentarioInformacioacuten en un programa que estaacute destinada a otros programadores (ocualquier persona que lea el coacutedigo fuente) y que no tiene efecto en laejecucioacuten del programa

error de sintaxisUn error en un programa que hace que sea imposible de analizar (y por lotanto imposible de ejecutar)

error en tiempo de ejecucioacuten o excepcioacutenUn error que se detecta mientras se ejecuta el programa

semaacutenticaEl significado de un programa

error semaacutenticoEs un error en un programa que provoca que se haga algo diferente a loque el programador pretendiacutea

Ejercicios

Ejercicio 2-2

Repitiendo el consejo del capiacutetulo anterior cada vez que aprenda algo nuevodebe probarlo en el modo interactivo y cometer errores a propoacutesito para ver elresultado

1 Hemos visto que n=42 es vaacutelido iquestQueacute pasa con 42=n

2 iquestY con x=y=1

3 En algunos lenguajes cada sentencia termina con un punto y coma iquestQueacutesucede si pone un punto y coma al final de una sentencia en Julia

4 iquestQueacute pasa si pone un punto al final de una sentencia

5 En notacioacuten matemaacutetica puede multiplicar x e y de esta manera x y iquestQueacutepasa si intenta eso en Julia iquestY queacute sucede con 5x

Ejercicios 25

Ejercicio 2-3

Practique usando el REPL de Julia como una calculadora

1 El volumen de una esfera con radio es iquestCuaacutel es el volumen de unaesfera con radio 5

2 Supongamos que el precio de venta de un libro es de $2495 pero laslibreriacuteas obtienen un descuento del 40 El enviacuteo cuesta $3 por la primeracopia y 75 centavos por cada copia adicional iquestCuaacutel es el costo total al pormayor de 60 copias

3 Si una persona sale de casa a las 652 am y corre 1 milla a un ritmorelajado (815 minutos por milla) luego 3 millas maacutes raacutepido (712 minutospor milla) y 1 milla a ritmo relajado nuevamente iquestA queacute hora llega a casapara desayunar

26 Capiacutetulo 2 Variables expresiones y sentencias

Capiacutetulo 3 FuncionesEn el contexto de la programacioacuten una funcioacuten es una secuencia de sentenciasque ejecuta una operacioacuten deseada y tiene un nombre Cuando se define unafuncioacuten se especifica su nombre y secuencia de sentencias Una vez hecho estose puede llamar a la funcioacuten por su nombre

Llamada a funcioacuten

Ya se ha visto un ejemplo de una llamada a funcioacuten

juliagt println(iexclHola Mundo)iexclHola Mundo

El nombre de esta funcioacuten es println La expresioacuten entre pareacutentesis se llamaargumento de la funcioacuten

Es comuacuten decir que una funcioacuten toma un argumento y devuelve un resultadoEl resultado tambieacuten se llama valor de retorno

Julia tiene funciones integradas que convierten valores de un tipo a otro Lafuncioacuten parse toma una cadena y si es posible la convierte en cualquier tipo denuacutemero en caso contrario arroja error

juliagt parse(Int64 32)32juliagt parse(Float64 314159)314159juliagt parse(Int64 Hola)ERROR ArgumentError invalid base 10 digit H in Hola

(ERROR ArgumentError base invaacutelida de 10 diacutegitos H en Hola)

trunc puede convertir valores de punto flotante a enteros pero no redondea sinoque trunca

juliagt trunc(Int64 399999)3juliagt trunc(Int64 -23)-2

float convierte nuacutemeros enteros en nuacutemeros de punto flotante

Llamada a funcioacuten 27

juliagt float(32)320

Finalmente string convierte el argumento en una cadena

juliagt string(32)32juliagt string(314159)314159

Funciones matemaacuteticasEn Julia la mayoriacutea de las funciones matemaacuteticas conocidas estaacuten disponiblesdirectamente

proporcioacuten = potencia_de_sentildealpotencia_de_ruidodecibelios = 10log10(proporcioacuten)

Este primer ejemplo utiliza la funcioacuten log10 para calcular la proporcioacuten entresentildeal y ruido en decibelios (suponiendo que potencia_de_sentildeal ypotencia_de_ruido estaacuten definidos) Tambieacuten existe la funcioacuten log que calcula ellogaritmo natural

radianes = 07altura = sin(radianes)

Este segundo ejemplo encuentra la razoacuten seno (en ingleacutes sine) de la variableradianes El nombre de esta variable es una pista de que la funcioacuten sin y las otrasfunciones trigonomeacutetricas (cos tan etc) toman argumentos en radianes Paraconvertir grados a radianes se debe dividir por 180 y multiplicar por

juliagt grados=4545juliagt radianes=grados180π07853981633974483juliagt sin(radianes)07071067811865475

El valor de la variable π es una aproximacioacuten de punto flotante de con unaprecisioacuten de aproximadamente 16 diacutegitos

Si sabe de trigonometriacutea puede verificar el resultado anterior comparaacutendolo conla raiacutez cuadrada de dos dividido por dos

28 Capiacutetulo 3 Funciones

juliagt sqrt(2) 207071067811865476

ComposicioacutenHasta ahora hemos analizado los elementos de un programa (variablesexpresiones y sentencias) de forma aislada sin mencionar coacutemo se combinan

Una de las caracteriacutesticas maacutes uacutetiles de los lenguajes de programacioacuten es sucapacidad para combinar pequentildeos bloques de coacutedigo Por ejemplo elargumento de una funcioacuten puede ser cualquier tipo de expresioacuten incluidosoperadores aritmeacuteticos

x = sin(grados3602π)

E incluso llamadas a funciones

x = exp(log(x + 1))

Casi en cualquier lugar donde se pueda colocar un valor se puede colocar unaexpresioacuten arbitraria con una excepcioacuten el lado izquierdo de una sentencia deasignacioacuten debe ser un nombre de variable Cualquier otra expresioacuten en el ladoizquierdo genera un error de sintaxis (se veraacuten excepciones a esta regla maacutesadelante)

2

juliagt minutos = horas 60 bien120juliagt horas 60 = minutos malERROR syntax 60 is not a valid function argument name

(ERROR sintaxis 60 no es un nombre de argumento de funcioacuten vaacutelido)

Agregar nuevas funcionesHasta ahora solo hemos usado las funciones integradas en Julia pero tambieacuten esposible agregar nuevas funciones Una definicioacuten de funcioacuten especifica el nombrede una nueva funcioacuten y la secuencia de sentencias que se ejecutan cuando sellama a la funcioacuten A continuacioacuten se muestra un ejemplo

Composicioacuten 29

function imprimirletras() println(Juguemos en el bosque) println(mientras el lobo no estaacute)end

function es una palabra reservada que indica que esta es una definicioacuten defuncioacuten El nombre de la funcioacuten es imprimirletras Las reglas para losnombres de funciones son las mismas que para los nombres de variables puedencontener casi todos los caracteres Unicode (consulte Seccioacuten 81) pero el primercaraacutecter no puede ser un nuacutemero No puede usar una palabra reservada comonombre de una funcioacuten y debe evitar tener una variable y una funcioacuten con elmismo nombre

Los pareacutentesis vaciacuteos despueacutes del nombre indican que esta funcioacuten no tieneargumentos

La primera liacutenea de una definicioacuten de funcioacuten se llama encabezado el resto sellama cuerpo El cuerpo termina con la palabra reservada end y puede contenertodas las sentencias que desee Para facilitar la lectura el cuerpo de la funcioacutendeberiacutea tener sangriacutea

Las comillas deben ser comillas rectas () generalmente ubicadas junto a latecla Enter en el teclado Las comillas inglesas (ldquordquo)no son vaacutelidas en Julia

Si escribe una definicioacuten de funcioacuten en modo interactivo Julia REPL inserta unasangriacutea para informarle que la definicioacuten no estaacute completa

juliagt function imprimirletras() println(Juguemos en el bosque)

Para finalizar la funcioacuten debe escribir end

La sintaxis para llamar a la nueva funcioacuten es la misma que para las funcionesintegradas en Julia

juliagt imprimirletras()Juguemos en el bosquemientras el lobo no estaacute

Una vez definida una funcioacuten puede usarla dentro de otra funcioacuten Por ejemplopara repetir el estribillo anterior se podriacutea escribir una funcioacuten llamadarepetirletras

30 Capiacutetulo 3 Funciones

function repetirletras() imprimirletras() imprimirletras()end

Y luego llamar a repetirletras

juliagt repetirletras()Juguemos en el bosquemientras el lobo no estaacuteJuguemos en el bosquemientras el lobo no estaacute

Definiciones y usosAl unir los fragmentos de coacutedigo de la seccioacuten anterior todo el programa se veasiacute

function imprimirletras() println(Jueguemos en el bosque) println(mientras el lobo no estaacute)end

funcioacuten repetirletras() imprimirletras() imprimirletras()end

repetirletras()

Este programa contiene dos definiciones de funcioacuten imprimirletras yrepetirletras Las definiciones de funcioacuten se ejecutan al igual que otrassentencias pero su ejecucioacuten crea nuevas funciones Las sentencias dentro de lafuncioacuten no se ejecutan hasta que se llama a la funcioacuten y la definicioacuten de lafuncioacuten no genera salida

Como es de esperar debe crear una funcioacuten antes de poder ejecutarla En otraspalabras la definicioacuten de la funcioacuten tiene que ejecutarse antes de que se llame ala funcioacuten

Ejercicio 3-1

Mueva la uacuteltima liacutenea de este programa a la parte superior de modo que lallamada a funcioacuten aparezca antes de las definiciones Ejecute el programa y veaqueacute mensaje de error obtiene

Definiciones y usos 31

Ahora mueva la llamada a funcioacuten hacia abajo y coloque la definicioacuten deimprimirletras despueacutes de la definicioacuten de repetirletras iquestQueacute sucede cuandoejecuta este programa

Flujo de ejecucioacutenPara asegurarse de que una funcioacuten sea definida antes de su primer uso debeconocer el orden en que se ejecutan las instrucciones lo que se denomina flujode ejecucioacuten

La ejecucioacuten siempre comienza con la primera sentencia del programa Lassentencias se ejecutan una a la vez en orden descendente

Las definiciones de funcioacuten no alteran el flujo de ejecucioacuten del programa pero sedebe recordar que las sentencias dentro de la funcioacuten no se ejecutan hasta quese llama a la funcioacuten

Una llamada a funcioacuten es como un desviacuteo en el flujo de ejecucioacuten En lugar depasar a la siguiente sentencia el flujo salta al cuerpo de la funcioacuten ejecuta lassentencias que estaacuten alliacute y luego regresa para continuar el coacutedigo donde lo dejoacute

Esto suena bastante simple hasta que se tiene en cuenta que una funcioacuten puedellamar a otra Mientras se estaacute ejecutando una funcioacuten el programa podriacutea tenerque ejecutar las sentencias de otra funcioacuten Luego mientras ejecuta esa nuevafuncioacuten iexclel programa podriacutea tener que ejecutar otra funcioacuten maacutes

Afortunadamente Julia es capaz de hacer el seguimiento de sus movimientos asiacuteque cada vez que una funcioacuten termina el programa retoma la funcioacuten que lallamoacute justo donde la dejoacute Cuando llega al final del programa la ejecucioacutentermina

En resumen cuando lee un programa no siempre debe leer de arriba haciaabajo A veces tiene maacutes sentido seguir el flujo de ejecucioacuten

Paraacutemetros y argumentosAlgunas de las funciones que se han visto requieren argumentos Por ejemplo lafuncioacuten cos necesita un nuacutemero como argumento Algunas funciones toman maacutesde un argumento por ejemplo parse toma dos un nuacutemero y una cadena

Dentro de la funcioacuten los argumentos se asignan a variables llamadasparaacutemetros A continuacioacuten se muestra un ejemplo de definicioacuten de funcioacuten quetoma un argumento

32 Capiacutetulo 3 Funciones

function imprimirdosveces(juan) println(juan) println(juan)end

Esta funcioacuten asigna el argumento a un paraacutemetro llamado juan Cuando se llamaa la funcioacuten esta imprime el valor del paraacutemetro (cualquiera que sea) dos veces

Esta funcioacuten funciona con cualquier valor que se pueda imprimir

juliagt imprimirdosveces(Correo no deseado)Correo no deseadoCorreo no deseadojuliagt imprimirdosveces(42)4242juliagt imprimirdosveces(π)π = 31415926535897 π = 31415926535897

Las mismas reglas de composicioacuten que se aplican a las funciones integradastambieacuten se aplican a las funciones definidas por el programador por lo quepodemos usar cualquier tipo de expresioacuten como argumento paraimprimirdosveces

juliagt imprimirdosveces(Correo no deseado ^4)Correo no deseado Correo no deseado Correo no deseado Correo no deseadoCorreo no deseado Correo no deseado Correo no deseado Correo no deseadojuliagt imprimirdosveces(cos(π))-10-10

El argumento se evaluacutea antes de llamar a la funcioacuten por lo que en los ejemploslas expresiones Correo no deseado ^4 y cos(π) solo se evaluacutean una vez

Tambieacuten puede usar una variable como argumento

juliagt michael = La vida es bellaLa vida es bellajuliagt imprimirdosveces(michael)La vida es bellaLa vida es bella

El nombre de la variable que pasamos como argumento (michael) no tiene nadaque ver con el nombre del paraacutemetro (juan) Para la funcioacuten imprimirdosveces

Paraacutemetros y argumentos 33

todos los paraacutemetros se llaman juan sin importar el nombre de la variable quepasemos como argumento (en este caso michael)

Las variables y los paraacutemetros son localesCuando se crea una variable dentro de una funcioacuten esta es local es decir soloexiste dentro de la funcioacuten Por ejemplo

function concatenar_dos(parte1 parte2) concat = parte1 parte2 imprimirdosveces(concat)end

Esta funcioacuten toma dos argumentos los concatena e imprime el resultado dosveces Aquiacute hay un ejemplo

juliagt linea1 = Hola holaHola holajuliagt linea2 = adioacutes adioacutesadioacutes adioacutesjuliagt concatenar_dos(liacutenea1 liacutenea2)Hola hola adioacutes adioacutesHola hola adioacutes adioacutes

Cuando concatenar_dos termina la variable concat es destruida Si intentamosimprimirla obtendremos un error

juliagt println(concat)ERROR UndefVarError concat not defined

Los paraacutemetros tambieacuten son locales Por ejemplo fuera de la funcioacutenimprimirdosveces no existe juan

Diagramas de pilaPara seguir la pista de queacute variables se usan en queacute lugares es uacutetil dibujar undiagrama de pila Al igual que los diagramas de estado los diagramas de pilamuestran el valor de cada variable pero tambieacuten muestran la funcioacuten a la quepertenece cada una

Cada funcioacuten se representa por un marco Un marco es un recuadro con elnombre de una funcioacuten a un costado y los paraacutemetros y variables de la funcioacutendentro El diagrama de pila para el ejemplo anterior se muestra en Figura 2

34 Capiacutetulo 3 Funciones

Figura 2 Diagrama de pila

Los marcos se ordenan de tal manera que cada funcioacuten llama a la funcioacuteninmediatamente inferior En este ejemplo imprimirdosveces fue llamado porconcatenar_dos y concatenar_dos fue llamado por Main que es un nombreespecial para la funcioacuten de maacutes alto nivel Cuando se crea una variable afuera decualquier funcioacuten pertenece a Main

Cada paraacutemetro se refiere al mismo valor que su argumento correspondienteEntonces parte1 tiene el mismo valor que linea1 parte2 tiene el mismo valorque linea2 y juan tiene el mismo valor que concat

Si se produce un error durante una llamada a funcioacuten Julia imprime el nombrede la funcioacuten el nombre de la funcioacuten que la llamoacute el nombre de la funcioacuten que asu vez llamoacute a esta otra y asiacute sucesivamente hasta llegar a la funcioacuten de maacutes altonivel Main

Por ejemplo si intenta acceder a concat desde imprimirdosveces obtendraacute unUndefVarError

ERROR UndefVarError concat not definedStacktrace [1] imprimirdosveces at REPL[1]gt2 [inlined] [2] concatenar_dos(String String) at REPL[2]gt3

Esta lista de funciones se llama trazado inverso Indica en queacute archivo deprograma se produjo el error en queacute liacutenea y queacute funciones se estaban ejecutandoen ese momento Tambieacuten muestra la liacutenea de coacutedigo que causoacute el error

El orden de las funciones en el trazado inverso es el opuesto del orden de losrecuadros en el diagrama de pila La funcioacuten que se estaacute ejecutando actualmenteestaacute en la parte superior

Funciones productivas y funciones nulasAlgunas de las funciones que hemos utilizado como las funciones matemaacuteticasdevuelven resultados A este tipo de funciones se les llamaraacute funcionesproductivas a falta de un nombre mejor Otras funciones comoimprimirdosveces realizan una accioacuten pero no devuelven un valor Estas sellaman funciones nulas

Funciones productivas y funciones nulas 35

Cuando se llama a una funcioacuten productiva casi siempre se quiere hacer algo conel resultado por ejemplo asignarlo a una variable o usarlo como parte de unaexpresioacuten

x = cos(radianes)aurea = (sqrt(5)+1)2

Cuando se llama a una funcioacuten en modo interactivo Julia muestra el resultado

juliagt sqrt(5)223606797749979

Pero en un script si se llama a una funcioacuten productiva iexclel valor de retorno sepierde para siempre

sqrt(5)

Output

223606797749979

Este script calcula la raiacutez cuadrada de 5 pero como no almacena ni muestra elresultado no es muy uacutetil

Las funciones nulas pueden mostrar algo en la pantalla o tener alguacuten otro efectopero no tienen un valor de retorno Si asigna el resultado a una variableobtendraacute un valor especial llamado nothing (nada en ingleacutes)

juliagt resultado = imprimirdosveces(Bing)BingBingjuliagt show(resultado)nothing

Para imprimir el valor nothing debe usar la funcioacuten show que es como la funcioacutenprint pero permite el valor nothing

El valor nothing no es lo mismo que la cadena nothing Es un valor especial quetiene su propio tipo

juliagt typeof (nothing)Nothing

Las funciones que hemos escrito hasta ahora son nulas Comenzaremos a escribir

36 Capiacutetulo 3 Funciones

funciones productivas en unos pocos capiacutetulos

iquestPor queacute se necesitan funcionesPuede que no esteacute claro por queacute vale la pena dividir un programa en funcionesHay varias razones

bull Crear una nueva funcioacuten le brinda la oportunidad de darle nombre a ungrupo de sentencias lo que hace que su programa sea maacutes faacutecil de leer ydepurar

bull Las funciones pueden hacer que un programa sea maacutes corto al eliminarcoacutedigo repetitivo Ademaacutes si realiza un cambio solo tiene que hacerlo en unsolo lugar

bull Dividir un programa largo en funciones le permite depurar las partes de unaen una y luego unirlas

bull Las funciones bien disentildeadas pueden ser uacutetiles para muchos programasUna vez que escribe y depura una puede reutilizarla

bull En Julia las funciones pueden mejorar mucho el rendimiento

DepuracioacutenUna de las habilidades maacutes importantes que adquiriraacute es la depuracioacuten Aunquepuede ser frustrante la depuracioacuten es una de las partes maacutes intelectualmentegratificantes desafiantes e interesantes de la programacioacuten

La depuracioacuten puede ser vista como un trabajo de detective El programador seenfrenta a pistas y tiene que inferir los procesos y eventos que generaron losresultados que ve

La depuracioacuten tambieacuten es como una ciencia experimental Una vez que se tieneuna idea de lo que estaacute mal se modifica el programa y se intenta nuevamente Sila hipoacutetesis era correcta se puede predecir el resultado de la modificacioacuten y asiacuteestar un paso maacutes cerca de un programa totalmente funcional Si la hipoacutetesis eraincorrecta se tiene que encontrar una nueva Como Sherlock Holmes sentildealoacute

Cuando todo aquello que es imposible ha sido eliminado lo que quede pormuy improbable que parezca es la verdad

mdash A Conan Doyle El signo de los cuatro

Para algunas personas la programacioacuten y la depuracioacuten son lo mismo Es decirla programacioacuten es el proceso de depurar gradualmente un programa hasta quehaga lo que desea Lo ideal es comenzar con un programa que funcione y hacer

iquestPor queacute se necesitan funciones 37

pequentildeas modificaciones depuraacutendolas a medida que avanza

Por ejemplo Linux es un sistema operativo que contiene millones de liacuteneas decoacutedigo pero comenzoacute como un programa simple que Linus Torvalds usoacute paraexplorar el chip Intel 80386 Seguacuten Larry Greenfield Uno de los proyectosanteriores de Linus fue un programa que cambiariacutea entre imprimir AAAA yBBBB Esto luego evolucionoacute a Linux (The Linux Usersrsquo Guide Beta Version1)

Glosariofuncioacuten

secuencia de sentencias que ejecuta una operacioacuten deseada y tiene unnombre Las funciones pueden tomar o no argumentos y pueden producir ono un resultado

definicioacuten de funcioacutenUna sentencia que crea una nueva funcioacuten especificando su nombreparaacutemetros y las sentencias que contiene

objeto de funcioacutenUn valor creado por una definicioacuten de funcioacuten El nombre de la funcioacuten esuna variable que se refiere a un objeto de funcioacuten

encabezadoLa primera liacutenea de una definicioacuten de funcioacuten

cuerpoSecuencia de sentencias dentro de una definicioacuten de funcioacuten

paraacutemetroUn nombre usado dentro de una funcioacuten para referirse al valor pasado comoargumento

Llamada a funcioacutenUna sentencia que ejecuta una funcioacuten Compuesta por el nombre de lafuncioacuten seguido por la lista de argumentos que usa entre pareacutentesis

argumentoValor que se le pasa a una funcioacuten cuando se la llama Este valor se asignaal paraacutemetro correspondiente en la funcioacuten

variable localUna variable definida dentro de una funcioacuten Una variable local solo puedeusarse dentro de su funcioacuten

38 Capiacutetulo 3 Funciones

valor de retornoEl resultado de una funcioacuten Si se utiliza una llamada a funcioacuten como unaexpresioacuten el valor de retorno es el valor de la expresioacuten

funcioacuten productivaUna funcioacuten que devuelve un valor

funcioacuten vaciacuteaUna funcioacuten que siempre devuelve nothing

nothingUn valor especial devuelto por las funciones nulas

composicioacutenUsar una expresioacuten como parte de una expresioacuten maacutes grande o unasentencia como parte de una sentencia maacutes grande

flujo de ejecucioacutenEl orden en que las sentencias se ejecutan

diagrama de pilaUna representacioacuten graacutefica de una pila de funciones sus variables y losvalores a los que se refieren

marcoUn recuadro que en un diagrama de pila representa una llamada de funcioacutenContiene las variables locales y los paraacutemetros de la funcioacuten

trazado inversoUna lista de las funciones que se estaacuten ejecutando las cuales son impresascuando ocurre una excepcioacuten

Ejercicios

OBSERVACIOacuteN Estos ejercicios deben realizarse utilizando soacutelo lo quese ha tratado hasta ahora

Ejercicio 3-2

Escriba una funcioacuten llamada justificar_a_la_derecha que tome una cadena s comoparaacutemetro y que imprima la cadena con suficientes espacios en blanco para quela uacuteltima letra de la cadena se encuentre en la columna 70 de la pantalla

using IntroAJulia

Ejercicios 39

justificar_a_la_derecha(Celia)

OBSERVACIOacuteN

Use concatenacioacuten de cadenas y repeticioacuten AdemaacutesJulia tiene integrada una funcioacuten llamada length quedevuelve la longitud de una cadena por lo que el valorde length(Celia) es 5

Ejercicio 3-3

Un objeto de funcioacuten es un valor que se puede asignar a una variable o serpasado como argumento Por ejemplo dosveces es una funcioacuten que toma unobjeto de funcioacuten como argumento y lo llama dos veces

function dosveces(f) f() f()end

A continuacioacuten se muestra un ejemplo que usa dosveces para llamar a unafuncioacuten llamada imprimirgato dos veces

function imprimirpalabra() println(palabra)end

dosveces(imprimirpalabra)

1 Escriba este ejemplo en un script y prueacutebelo

2 Modifique dosveces para que tome dos argumentos un objeto de funcioacuten yun valor y que llame a la funcioacuten dos veces pasando el valor comoargumento

3 Copie la definicioacuten de imprimirdosveces mencionada antes en este capiacutetuloa su secuencia de comandos

4 Use la versioacuten modificada de dosveces para llamar a imprimirdosveces dosveces pasando palabra como argumento

5 Defina una nueva funcioacuten llamada cuatroveces que tome un objeto defuncioacuten y un valor y que llame a la funcioacuten cuatro veces pasando el valorcomo paraacutemetro Debe haber solo dos sentencias en el cuerpo de estafuncioacuten no cuatro

40 Capiacutetulo 3 Funciones

Ejercicio 3-4

1 Escriba la funcioacuten imprimircuadricula que dibuje una cuadriacutecula como lasiguiente

juliagt imprimircuadricula()+ - - - - + - - - - +| | || | || | || | |+ - - - - + - - - - +| | || | || | || | |+ - - - - + - - - - +

1 Escriba una funcioacuten que dibuje una cuadriacutecula similar con cuatro filas ycuatro columnas

Creacuteditos Este ejercicio se basa en un ejercicio en Oualline Practical CProgramming Third Edition OrsquoReilly Media 1997

OBSERVACIOacuteN

Para imprimir maacutes de un valor por liacutenea se puedeimprimir una secuencia de valores separados por comas

println (+ -)

La funcioacuten print no avanza a la siguiente liacutenea

print(+)println(-)

El resultado de estas sentencias es + - en la mismaliacutenea El resultado de una siguiente sentencia deimpresioacuten comenzariacutea en la siguiente liacutenea

Ejercicios 41

Capiacutetulo 4 Estudio de Caso Disentildeo de InterfazEste capiacutetulo presenta un segundo estudio de caso que muestra el proceso dedisentildear funciones que trabajen en conjunto

Se presentan graacuteficos turtle que es una forma de crear dibujos a traveacutes de laprogramacioacuten Los graacuteficos turtle no estaacuten incluidos en la Biblioteca Estaacutendarpor lo que se debe agregar el moacutedulo IntroAJulia a su configuracioacuten de Julia

Los ejemplos de este capiacutetulo se pueden ejecutar en un notebook graacutefico enJuliaBox el cual combina coacutedigo texto formateado matemaacuteticas y multimedia enun solo documento (vea Apeacutendice B)

TurtlesUn modulo es un archivo que contiene una coleccioacuten de funciones relacionadasJulia proporciona algunos moacutedulos en su Biblioteca Estaacutendar Ademaacutes es posibleagregar maacutes funciones a una gran cantidad de paquetes(httpsjuliaobservercom)

Los paquetes se pueden instalar en REPL ingresando al modo Pkg REPL con latecla ]

(v12) pkggt add httpsgithubcomJuliaIntroIntroAJuliajl

Esto puede demorar un poco

Antes de que podamos usar las funciones de un moacutedulo tenemos que importarlocon una sentencia using

juliagt using IntroAJulia

juliagt ὂ = Turtle()LuxorTurtle(00 00 true 00 (00 00 00))

El moacutedulo IntroAJulia proporciona una funcioacuten llamada Turtle (tortuga enespantildeol) que crea un objeto LuxorTurtle el cual es asignado a una variablellamada ὂ (turtle TAB)

Una vez que crea una tortuga puede llamar a una funcioacuten para moverla y asiacutehacer un dibujo con ella Por ejemplo para mover la tortuga hacia adelante(forward en ingleacutes)

42 Capiacutetulo 4 Estudio de Caso Disentildeo de Interfaz

svg begin forward(ὂ 100)end

Figura 3 Haciendo avanzar a la tortuga

La palabra reservada svg ejecuta una macro que dibuja una imagen SVG Lasmacros son una caracteriacutestica importante pero avanzada de Julia

Los argumentos de forward son la tortuga y una distancia en piacutexeles por lo queel tamantildeo real depende de su pantalla

Tambieacuten es posible hacer girar a la tortuga con la funcioacuten turn Los argumentosde esta funcioacuten son la tortuga y un aacutengulo en grados

Ademaacutes cada tortuga estaacute sosteniendo un laacutepiz que puede estar hacia arriba ohacia abajo si el laacutepiz estaacute hacia abajo la tortuga deja un rastro cuando semueve Figura 3 muestra el rastro dejado por la tortuga Las funciones penup ypendown significan laacutepiz hacia arriba y laacutepiz hacia abajo

Para dibujar un aacutengulo recto modifique la llamada a la macro

ὂ = Turtle()svg begin forward(ὂ 100) turn(ὂ -90) forward(ὂ 100)end

Ejercicio 4-1

Ahora modifique la macro para que dibuje un cuadrado iexclNo sigas hasta haberloterminado

Repeticioacuten Simple

Es probable que haya escrito algo como esto

Repeticioacuten Simple 43

ὂ = Turtle()svg begin forward(ὂ 100) turn(ὂ -90) forward(ὂ 100) turn(ὂ -90) forward(ὂ 100) turn(ὂ -90) forward(ὂ 100)end

Se puede hacer lo mismo de manera maacutes concisa con una sentencia for

juliagt for i in 14 println(iexclHola) endiexclHolaiexclHolaiexclHolaiexclHola

Este es el uso maacutes simple de la sentencia for aunque se veraacuten maacutes usos despueacutesEacutesto deberiacutea ser suficiente para reescribir su programa que dibuja un cuadradoNo continuacutee hasta que lo haga

Aquiacute hay una sentencia for que dibuja un cuadrado

ὂ = Turtle()svg begin for i in 14 forward(ὂ 100) turn(ὂ -90) endend

La sintaxis de una sentencia for es similar a la definicioacuten de una funcioacuten Tieneun encabezado y un cuerpo que termina con la palabra reservada end El cuerpopuede contener el nuacutemero de sentencias que desee

Una sentencia for tambieacuten es llamada bucle porque el flujo de ejecucioacuten recorreel cuerpo y luego vuelve a la parte superior En este caso ejecuta el cuerpocuatro veces

Esta versioacuten es en realidad un poco diferente del coacutedigo anterior que dibujaba uncuadrado porque hace otro giro despueacutes de dibujar el uacuteltimo lado del cuadradoEl giro adicional lleva maacutes tiempo pero simplifica el coacutedigo si se hace lo mismo

44 Capiacutetulo 4 Estudio de Caso Disentildeo de Interfaz

en cada iteracioacuten del ciclo Esta versioacuten tambieacuten tiene el efecto de dejar a latortuga nuevamente en la posicioacuten inicial mirando hacia la direccioacuten inicial

EjerciciosLos siguientes ejercicios usan tortugas Son divertidos pero tambieacuten tienen untrasfondo Mientras trabaja en ellos piense cuaacutel es ese trasfondo

OBSERVACIOacuteNLas siguientes secciones muestran las soluciones paraestos ejercicios asiacute que no mire hasta que hayaterminado (o al menos lo haya intentado)

Ejercicio 4-2

Escriba una funcioacuten llamada cuadrado que tome como paraacutemetro a un turtle tDeberiacutea usar este turtle para dibujar un cuadrado

Ejercicio 4-3

Escriba una llamada a funcioacuten que pase t como argumento a cuadrado y luegovuelva a ejecutar la macro

Ejercicio 4-4

Agregue otro paraacutemetro llamado lon a cuadrado Modifique el cuerpo para quela longitud de los lados sea lon y luego modifique la llamada a funcioacutenagregando este segundo argumento Ejecute la macro nuevamente Pruebe conun rango de valores para lon

Ejercicio 4-5

Haga una copia de cuadrado y cambie su nombre a poliacutegono Agregue otroparaacutemetro llamado n y modifique el cuerpo para que dibuje un poliacutegono regularde -lados

OBSERVACIOacuteN Los aacutengulos exteriores de un poliacutegono regular de -ladosson grados

Ejercicio 4-6

Escriba una funcioacuten llamada ciacuterculo que tome un turtle t y un radio r comoparaacutemetros y que dibuje un ciacuterculo aproximado llamando a poliacutegono con unalongitud y nuacutemero de lados apropiados Pruebe su funcioacuten con un rango devalores de r

Ejercicios 45

OBSERVACIOacuteN Calcule la circunferencia del ciacuterculo y aseguacuterese de quelen n == circunferencia

Ejercicio 4-7

Haga una versioacuten maacutes general de circulo llamada arco que tome un paraacutemetroadicional angulo y que determine queacute fraccioacuten de un ciacuterculo dibujar angulo estaacuteen grados entonces cuando angulo= 360 arco deberiacutea dibujar un ciacuterculocompleto

EncapsulacioacutenEl primer ejercicio le pide que coloque el coacutedigo que permite dibujar uncuadrado en una definicioacuten de funcioacuten y que luego llame a la funcioacuten pasando aturtle como paraacutemetro Aquiacute hay una solucioacuten

function cuadrado(t) for i in 14 forward(t 100) turn(t -90) endendὂ = Turtle()svg begin cuadrado(ὂ)end

Las sentencias maacutes internas forward y turn tienen doble sangriacutea para mostrarque estaacuten dentro del bucle for que a su vez estaacute dentro de la definicioacuten defuncioacuten

Dentro de la funcioacuten t se refiere a la misma tortuga ὂ entonces turn(t -90)tiene el mismo efecto que turn(ὂ -90) En ese caso iquestpor queacute no llamar alparaacutemetro ὂ La razoacuten es que t puede ser cualquier tortuga no solo ὂ por loque podriacuteamos crear una segunda tortuga y pasarla como argumento a cuadrado

ὂ = Turtle()svg begin cuadrado(ὂ)end

Colocar una porcioacuten de coacutedigo en una funcioacuten se denomina encapsulacioacuten Unode los beneficios de la encapsulacioacuten es que al ponerle un nombre al coacutedigo estosirve como una especie de documentacioacuten Otra ventaja es que si reutiliza elcoacutedigo iexcles maacutes conciso llamar a una funcioacuten dos veces que copiar y pegar el

46 Capiacutetulo 4 Estudio de Caso Disentildeo de Interfaz

cuerpo

GeneralizacioacutenEl siguiente paso es agregar un paraacutemetro lon a cuadrado Aquiacute hay unasolucioacuten

function cuadrado(t lon) for i in 14 forward(t lon) turn(t -90) endendὂ = Turtle()svg begin cuadrado(ὂ 100)end

Agregar un paraacutemetro a una funcioacuten se llama generalizacioacuten porque hace que lafuncioacuten sea maacutes general en la versioacuten anterior el cuadrado siempre teniacutea elmismo tamantildeo en esta versioacuten puede ser de cualquier tamantildeo

El siguiente paso tambieacuten es una generalizacioacuten En vez de dibujar cuadradospoligono dibuja poliacutegonos regulares con cualquier nuacutemero de lados Aquiacute hay unasolucioacuten

function poligono(t n lon) angulo = 360 n for i in 1n forward(t lon) turn(t -angulo) endendὂ = Turtle()svg begin poligono(ὂ 7 70)end

Este ejemplo dibuja un poliacutegono de 7 lados con una longitud de 70 por lado

Disentildeo de InterfazEl siguiente paso es escribir circulo que toma un radio r como paraacutemetro Aquiacutehay una solucioacuten simple que usa poligono para dibujar un poliacutegono de 50 lados

Generalizacioacuten 47

function circulo(t r) circunferencia = 2 π r n = 50 lon = circunferencia n poligono(t n lon)end

La primera liacutenea calcula la circunferencia de un ciacuterculo con radio usando lafoacutermula n es el nuacutemero de segmentos de liacutenea de nuestra aproximacioacuten a unciacuterculo y lon es la longitud de cada segmento Por lo tanto poliacutegono dibuja unpoliacutegono de 50 lados que se aproxima a un ciacuterculo de radio r

Una limitante de esta solucioacuten es que n es constante lo que significa que paraciacuterculos muy grandes los segmentos de liacutenea son demasiado largos y paraciacuterculos pequentildeos perdemos tiempo dibujando segmentos muy pequentildeos Unasolucioacuten seriacutea generalizar la funcioacuten tomando n como paraacutemetro Esto le dariacutea alusuario (quien llama a ciacuterculo) maacutes control pero la interfaz seriacutea menos pulcra

La interfaz de una funcioacuten es un resumen de coacutemo se usa iquestcuaacuteles son losparaacutemetros iquestQueacute hace la funcioacuten iquestY cuaacutel es el valor de retorno Una interfazes pulcra si le permite al usuario que la llama hacer lo que quiera sin tener quelidiar con detalles innecesarios

En este ejemplo r pertenece a la interfaz porque especifica el ciacuterculo a dibujar nes menos apropiado porque se refiere a los detalles de coacutemo se debe representarel ciacuterculo

En lugar de saturar la interfaz es mejor elegir un valor apropiado de ndependiendo de la circunferencia

function circulo(t r) circunferencia = 2 π r n = trunc(circunferencia 3) + 3 lon = circunferencia n poligono(t n lon)end

Ahora el nuacutemero de segmentos es un nuacutemero entero cercano a circunferencia3por lo que la longitud de cada segmento es aproximadamente 3 que es losuficientemente pequentildeo como para que los ciacuterculos se vean bien pero losuficientemente grandes como para ser eficientes y aceptables para cualquierciacuterculo

Agregar 3 a n garantiza que el poliacutegono tenga al menos 3 lados

48 Capiacutetulo 4 Estudio de Caso Disentildeo de Interfaz

RefactorizacioacutenCuando se escribioacute circulo se pudo reutilizar poligono ya que un poliacutegono demuchos lados es una buena aproximacioacuten de un ciacuterculo Pero arco no es tanversaacutetil no se puede usar poligono o circulo para dibujar un arco

Una alternativa es comenzar con una copia de poligono y transformarla en arcoEl resultado podriacutea verse asiacute

function arco(t r angulo) arco_lon = 2 π r angulo 360 n = trunc(arco_lon 3) + 1 paso_lon = arco_lon n paso_angulo = angulo n for i in 1n forward(t paso_lon) turn(t -paso_angulo) endend

La segunda mitad de esta funcioacuten se parece a poligono pero no se puedereutilizar poligono sin cambiar la interfaz Se podriacutea generalizar poligono paratomar un angulo como tercer argumento iexclpero entonces poligono ya no seriacutea unnombre apropiado En su lugar se puede llamar a esta funcioacuten maacutes generalpolilinea

function polilinea(t n lon angulo) for i in 1n forward(t lon) turn(t -angulo) endend

Ahora se puede reescribir poligono y arco usando polilinea

Refactorizacioacuten 49

function poligono(t n lon) angulo = 360 n polilinea(t n lon angulo)end

function arco(t r angulo) arco_lon = 2 π r angulo 360 n = trunc(arco_lon 3) + 1 paso_lon = arco_lon n paso_angulo = angulo n polilinea(t n paso_lon paso_angulo)end

Finalmente se puede reescribir circulo usando arco

function circulo(t r) arco(t r 360)end

Este proceso que reorganiza un programa para mejorar las interfaces y facilitarla reutilizacioacuten del coacutedigo se denomina refactorizacioacuten En este caso se observaque habiacutea un coacutedigo similar en arco y poligono por lo que lo factorizamos enpolilinea

Si se hubiese planeado con anticipacioacuten se podriacutea haber escrito polilineaprimero y haber evitado la refactorizacioacuten pero a menudo no se sabe losuficiente al comienzo de un proyecto para disentildear todas las interfaces Una vezque se comienza a programar se comprende mejor el problema A vecesrefactorizar es una sentildeal de que se ha aprendido algo

Un Plan de DesarrolloUn plan de desarrollo de programa es un proceso para escribir programas Elproceso que se utiliza en este estudio de caso es encapsulacioacuten ygeneralizacioacuten Los pasos de este proceso son

1 Comience escribiendo un pequentildeo programa sin definiciones de funciones

2 Una vez que el programa funcione identifique una porcioacuten de coacutedigo quetenga un objetivo especiacutefico encapsule esta porcioacuten en una funcioacuten yasiacutegnele un nombre

3 Generalice la funcioacuten agregando los paraacutemetros apropiados

4 Repita los pasos 1ndash3 hasta que tenga un conjunto de funciones De serposible copie y pegue coacutedigo para evitar volver a escribir (y volver adepurar)

50 Capiacutetulo 4 Estudio de Caso Disentildeo de Interfaz

5 Busque oportunidades para mejorar el programa refactorizando Porejemplo si tiene un coacutedigo similar en varios lugares considere factorizarloen una funcioacuten general apropiada

Este proceso tiene algunos inconvenientes se exploraraacuten alternativas maacutesadelante pero puede ser uacutetil si no sabe de antemano coacutemo dividir el programaen funciones Este enfoque permite disentildear conforme se avanza

DocstringUn docstring es una cadena que va antes de una funcioacuten y que explica la interfaz(doc es la abreviatura de documentacioacuten) Aquiacute hay un ejemplo

polilinea(t n lon angulo)

Dibuja n segmentos de liacutenea de la longitud dada y conaacutengulo entre ellos (en grados) dado t es una tortugafunction polilinea(t n lon angulo) for i in 1n forward(t lon) turn(t -angulo) endend

Se puede acceder a la documentacioacuten en REPL o en un notebook escribiendo seguido del nombre de una funcioacuten o macro y presionando ENTER

helpgt polilineasearch

polilinea(t n lon angulo)

Dibuja n segmentos de liacutenea de la longitud dada y con aacutengulo entre ellos(en grados) dado t es una tortuga

Los docstring generalmente son cadenas de comillas triples tambieacuten conocidascomo cadenas de liacuteneas muacuteltiples ya que las comillas triples permiten que lacadena abarque maacutes de una liacutenea

Un docstring contiene la informacioacuten esencial que alguien necesitariacutea para usaresta funcioacuten Explica de manera concisa lo que hace la funcioacuten (sin entrar endetalles sobre coacutemo lo hace) Explica queacute efecto tiene cada paraacutemetro en elcomportamiento de la funcioacuten y de queacute tipo debe ser cada paraacutemetro (si no esobvio)

Docstring 51

OBSERVACIOacuteN

Escribir este tipo de documentacioacuten es una parteimportante del disentildeo de la interfaz Una interfaz biendisentildeada debe ser simple de explicar si tienedificultades para explicar una de sus funciones tal vez lainterfaz podriacutea mejorarse

DepuracioacutenUna interfaz es como un contrato entre una funcioacuten y el usuario El usuarioacepta proporcionar ciertos paraacutemetros y la funcioacuten acepta hacer cierto trabajo

Por ejemplo polilinea requiere cuatro argumentos t tiene que ser una tortuga ntiene que ser un nuacutemero entero lon deberiacutea ser un nuacutemero positivo y angulotiene que ser un nuacutemero en grados

Estos requisitos se llaman precondiciones porque se supone que son verdaderosantes de que la funcioacuten comience a ejecutarse Por el contrario las condicionesal final de la funcioacuten son postcondiciones Las postcondiciones incluyen el efectodeseado de la funcioacuten (como dibujar segmentos de liacutenea) y cualquier efectosecundario (como mover la tortuga o hacer otros cambios)

Las condiciones previas son responsabilidad del usuario Si el usuario viola unaprecondicioacuten (iexcldebidamente documentada) y la funcioacuten no funcionacorrectamente el error estaacute en el usuario no en la funcioacuten

Si se cumplen las precondiciones pero no las postcondiciones el error estaacute en lafuncioacuten Si sus pre y postcondiciones son claras pueden ayudar con ladepuracioacuten

Glosariomodulo

Un archivo que contiene una coleccioacuten de funciones relacionadas y otrasdefiniciones

paqueteUna biblioteca externa con maacutes funcionalidades

sentencia usingUna sentencia que lee un archivo de moacutedulo y crea un objeto de moacutedulo

bucleUna parte de un programa que puede ejecutarse repetidamente

52 Capiacutetulo 4 Estudio de Caso Disentildeo de Interfaz

encapsulacioacutenEl proceso de transformar una secuencia de sentencias en una definicioacuten defuncioacuten

generalizacioacutenEl proceso de reemplazar algo innecesariamente especiacutefico (como unnuacutemero) con algo maacutes general (como una variable o paraacutemetro)

interfazUna descripcioacuten de coacutemo usar una funcioacuten incluido el nombre y lasdescripciones de los argumentos y el valor de retorno

refactorizacioacutenEl proceso de modificar un programa para mejorar las interfaces de lasfunciones y otras cualidades del coacutedigo

plan de desarrollo de programaUn proceso para escribir programas

docstringUna cadena que aparece en la parte superior de una definicioacuten de funcioacutenpara documentar la interfaz de la funcioacuten

precondicioacutenUn requisito que debe cumplir el usuario antes de que comience unafuncioacuten

postcondicioacutenUn requisito que debe cumplir la funcioacuten antes de que finalice

Ejercicios

Ejercicio 4-8

Copie y pegue el coacutedigo de este capiacutetulo en un notebook

1 Dibuje un diagrama de pila que muestre el estado del programa mientrasejecuta circulo(ὂ radio) Puede hacer la aritmeacutetica a mano o agregarsentencias de impresioacuten al coacutedigo

2 La versioacuten de arco en Seccioacuten 47 no es muy precisa ya que la aproximacioacutenlineal del ciacuterculo siempre queda por afuera del ciacuterculo verdadero Comoresultado la tortuga termina a unos pocos piacutexeles del destino correcto Lasiguiente solucioacuten muestra una forma de reducir el efecto de este error Leael coacutedigo y vea si tiene sentido Si dibuja un diagrama es posible queentienda mejor coacutemo funciona

Ejercicios 53

arco(t r angulo)

Dibuja un arco con el radio y el aacutengulo dados

t tortuga r radio angulo aacutengulo subtendido por el arco en gradosfunction arco(t r angulo) arco_lon = 2 π r abs(angulo) 360 n = trunc(arco_lon 4) + 3 paso_lon = arco_lon n paso_angulo = angulo n

haciendo un ligero giro a la izquierda antes de comenzar se reduce el error causado por la aproximacioacuten lineal del arco turn(t -paso_angulo2) polilinea(t n paso_lon paso_angulo) turn(t paso_angulo2)end

Ejercicio 4-9

Escriba un conjunto de funciones generales que permitan dibujar flores como enFigura 4

Figura 4 Flores con Turtle

Ejercicio 4-10

Escriba un conjunto de funciones generales que puedan dibujar formas como enFigura 5

Figura 5 Poliacutegonos con Turtle

54 Capiacutetulo 4 Estudio de Caso Disentildeo de Interfaz

Ejercicio 4-11

Las letras del alfabeto se pueden construir a partir de un nuacutemero pequentildeo deelementos baacutesicos como liacuteneas verticales y horizontales y algunas curvasDisentildee un alfabeto que se pueda dibujar con un nuacutemero miacutenimo de elementosbaacutesicos y luego escriba funciones que dibujen las letras

Deberiacutea escribir una funcioacuten para cada letra con nombres dibujar_a dibujar_betc y colocar sus funciones en un archivo llamado letrasjl

Ejercicio 4-12

Lea sobre espirales en httpseswikipediaorgwikiEspiral luego escriba unprograma que dibuje una espiral de Arquiacutemedes como en Figura 6

Figura 6 Espiral de Arquiacutemedes

Ejercicios 55

Capiacutetulo 5 Condicionales y recursividadEl tema principal de este capiacutetulo es la sentencia if la cual permite ejecutardiferentes acciones dependiendo del estado del programa Inicialmente sepresentan dos nuevos operadores divisioacuten entera y moacutedulo

Divisioacuten entera y MoacuteduloEl operador divisioacuten entera divide (div TAB) divide dos nuacutemeros y redondea haciaabajo el resultado Por ejemplo suponga que la duracioacuten de una peliacutecula es de105 minutos Es posible que desee saber la duracioacuten en horas La divisioacutenconvencional devuelve un nuacutemero de punto flotante

juliagt minutos = 105105juliagt minutos 60175

No obstante las horas no se suelen escribir con decimales La divisioacuten enteradevuelve el nuacutemero entero de horas redondeado hacia abajo

juliagt horas = minutos divide 601

Para obtener el resto de la divisioacuten se puede restar una hora (en minutos) a laduracioacuten total de la peliacutecula

juliagt resto = minutos - horas 6045

Otra alternativa es usar el operador moacutedulo que divide dos nuacutemeros ydevuelve el resto

juliagt resto = minutos 6045

OBSERVACIOacuteN

El operador moacutedulo es maacutes uacutetil de lo que parecePermite verificar por ejemplo si un nuacutemero es divisiblepor otro si xy es cero entonces x es divisible por y

Ademaacutes puede extraer el (o los) diacutegito(s) maacutes a laderecha de un nuacutemero Por ejemplo x10 devuelve eldiacutegito maacutes a la derecha de un entero x (en base 10) Delmismo modo x100 devuelve los dos uacuteltimos diacutegitos

56 Capiacutetulo 5 Condicionales y recursividad

Expresiones booleanasUna expresioacuten booleana es una expresioacuten que es verdadera o falsa Lossiguientes ejemplos usan el operador == que compara dos operandos ydevuelve el valor true (verdadero en espantildeol) si son iguales y el valor false(falso) de lo contrario

juliagt 5 == 5truejuliagt 5 == 6false

true y false son valores especiales que pertenecen al tipo Bool no son cadenas

juliagt typeof(true)Booljuliagt typeof(false)Bool

El operador == es un operador relacional El resto de operadores relacionalesson

x = y x no es igual a y x ne y (ne TAB) x gt y x es mayor que y x lt y x es menor que y x gt= y x es mayor o igual que y x ge y (ge TAB) x lt= y x es menor o igual que y x le y (le TAB)

AVISO

Aunque estas operaciones probablemente le sean familiares lossiacutembolos de Julia son diferentes de los siacutembolos matemaacuteticos Unerror comuacuten es usar un solo signo igual (=) en vez de un doblesigno igual (== Recuerde que = es un operador de asignacioacuten y== es un operador relacional No existe =lt o =gt

Operadores LoacutegicosHay tres operadores loacutegicos ampamp (y) || (o) y (no) La semaacutentica (significado) deestos operadores es similar a su significado en espantildeol Por ejemplo xgt0 ampampxlt10 es verdadero solo si x es mayor que 0 y menor que 10

n2==0 || n3 == 0 es verdadero si una o ambas condiciones son verdaderases decir si el nuacutemero es divisible por 2 o por 3

Expresiones booleanas 57

Tanto ampamp como || se asocian en primer lugar con el objeto a su derecha pero ampamptiene preferencia por sobre ||

Finalmente el operador niega una expresioacuten booleana entonces (xgty) esverdadero si xgty es falso es decir si x es menor o igual que y

Ejecucioacuten CondicionalPara escribir programas uacutetiles generalmente se necesita verificar condiciones ycambiar el comportamiento del programa acorde a ellas Las sentenciascondicionales permiten llevar esto a cabo La forma maacutes simple es la sentencia if(si en ingleacutes)

if x gt 0 println(x es positivo)end

La expresioacuten booleana despueacutes de if se llama condicioacuten Si es verdadera seejecuta la instruccioacuten con sangriacutea Si no nada ocurre

Las sentencias if tienen la misma estructura que las definiciones de funcioacuten unencabezado seguido del cuerpo terminado con la palabra reservada end (enespantildeol fin) Las sentencias como esta se denominan sentencias compuestas

No hay liacutemite en el nuacutemero de sentencias que pueden aparecer en el cuerpo Aveces es uacutetil tener un cuerpo sin sentencias (por lo general como un marcadorde posicioacuten para el coacutedigo que auacuten no se ha escrito)

if x lt 0 TODO se necesita realizar alguna accioacuten con los valores negativosend

Ejecucioacuten alternativaUna segunda forma de la sentencia if es la ejecucioacuten alternativa en la que haydos posibilidades y la condicioacuten determina cuaacutel se ejecuta La sintaxis se ve asiacute

if x 2 == 0 println(x es par)else println(x es impar)end

Si el resto de x dividido por 2 es 0 entonces x es par y el programa muestra unmensaje acorde Si la condicioacuten es falsa se ejecuta el segundo conjunto de

58 Capiacutetulo 5 Condicionales y recursividad

sentencias Como la condicioacuten debe ser verdadera o falsa se ejecutaraacuteexactamente una de las alternativas Las alternativas se llaman ramas porqueson ramas en el flujo de ejecucioacuten

Condicionales encadenadasA veces hay maacutes de dos posibilidades y se necesitan maacutes de dos ramas Unamanera de expresar este coacutemputo es a traveacutes de una condicional encadenada

if x lt y println(x es menor que y)elseif x gt y println(x es mayor que y)else println(x e y son iguales)end

De nuevo soacutelo se ejecutaraacute una rama No hay liacutemite al nuacutemero de sentenciaselseif Si hay una sentencia else debe estar al final (aunque no es necesario queesteacute)

if alternativa == a dibujar_a()elseif alternativa == b dibujar_b()elseif alternativa == c dibujar_c()end

Cada condicioacuten se comprueba en orden Si la primera es falsa se comprueba lasiguiente y asiacute se sigue con las demaacutes Si una de ellas es verdadera se ejecuta larama correspondiente y la sentencia se termina Si es verdadera maacutes de unacondicioacuten soacutelo se ejecuta la primera rama verdadera

Condicionales anidadasUna condicional puede estar anidada (nested en ingleacutes) dentro de otraPodriacuteamos haber escrito el ejemplo de la seccioacuten anterior de la siguiente manera

Condicionales encadenadas 59

if x == y println(x e y son iguales)else if x lt y println(x es menor a y) else println(x es mayor a y) endend

La condicional externa contiene dos ramas La primera rama contiene unasentencia simple La segunda rama contiene otra sentencia if que tiene dosramas propias Estas dos ramas son ambas sentencias simples aunque podriacuteanser sentencias condicionales

Aunque la sangriacutea no obligatoria de las sentencias hace evidente su estructuralas condicionales anidadas muy pronto se vuelven difiacuteciles de leer Se recomiendaevitarlas cuando pueda

Los operadores loacutegicos a menudo proporcionan una forma de simplificar lassentencias condicionales anidadas Por ejemplo es posible reescribir el siguientecoacutedigo usando un solo condicional

if 0 lt x if x lt 10 println(x es un nuacutemero positivo de un solo diacutegito) endend

La sentencia print soacutelo se ejecuta si conseguimos superar ambas condicionalesde modo que se puede obtener el mismo efecto con el operador ampamp

if 0 lt x ampamp x lt 10 println(x es un nuacutemero positivo de un solo diacutegito)end

Para este tipo de condicioacuten Julia proporciona una sintaxis maacutes concisa

if 0 lt x lt 10 println(x es un nuacutemero positivo de un solo diacutegito)end

60 Capiacutetulo 5 Condicionales y recursividad

RecursividadEstaacute permitido que una funcioacuten llame a otra y tambieacuten que una funcioacuten se llamea siacute misma Puede no parecer uacutetil pero siacute lo es como puede verse en la siguientefuncioacuten

function cuentaregresiva(n) if n le 0 println(Despegue) else print(n ) cuentaregresiva(n-1) endend

Si n es 0 o negativo muestra la palabra Despegue En otro caso muestra elvalor n y luego llama a la funcioacuten cuentaregresiva pasaacutendole n-1 comoargumento

iquestQueacute sucede si llamamos a una funcioacuten como esta

juliagt cuentaregresiva(3)3 2 1 Despegue

La ejecucioacuten de cuentaregresiva empieza con n = 3 y como n es mayor que 0muestra el valor 3 y luego se llama a siacute mismahellip

 La ejecucioacuten de cuentaregresiva empieza con n = 2 y como n es mayor que 0   muestra el valor 2 y luego se llama a siacute mismahellip

  La ejecucioacuten de cuentaregresiva empieza con n = 1 y como n es mayor que0    muestra el valor 1 y luego se llama a siacute mismahellip

   La ejecucioacuten de cuentaregresiva empieza con n = 0 y como n no es mayorque 0     muestra la palabra Despegue y luego termina

  La cuentaregresiva cuyo argumento es n = 1 termina

 La cuentaregresiva cuyo argumento es n = 2 termina

La cuentaregresiva cuyo argumento es n = 3 termina

Y volvemos a Main

Una funcioacuten que se llama a siacute misma es una funcioacuten recursiva y el proceso deejecucioacuten se llama recursividad

Recursividad 61

Como otro ejemplo se puede escribir una funcioacuten que imprima una cadena veces

function printn(s n) if n le 0 return end println(s) printn(s n-1)end

Si n lt= 0 se usa la sentencia return para salir de la funcioacuten El flujo de laejecucioacuten vuelve inmediatamente a la sentencia de llamada a funcioacuten y no seejecutan las liacuteneas restantes de la funcioacuten

El resto de la funcioacuten es similar a cuenta regresiva muestra s y luego se llama asiacute misma para mostrar s veces maacutes de modo que el nuacutemero de lineasmostradas es es decir

Para ejemplos simples como este es maacutes faacutecil usar un ciclo for Se mostraraacutenejemplos que son difiacuteciles de escribir con un ciclo for y faacuteciles de escribir conrecursividad

Diagramas de pila para funciones recursivasEn Seccioacuten 39 se usoacute un diagrama de pila para representar el estado de unprograma durante una llamada de funcioacuten El mismo tipo de diagrama puede serde utilidad para interpretar una funcioacuten recursiva

Cada vez que se llama a una funcioacuten Julia crea un marco que contiene lasvariables locales de la funcioacuten y los paraacutemetros En una funcioacuten recursiva puedehaber maacutes de un marco en el diagrama de pila al mismo tiempo

Figura 7 Diagrama de pila

Figura 7 muestra un diagrama de pila para cuentaregresiva utilizando n=3

Como siempre la parte superior de la pila es el marco para Main Estaacute vaciacuteopues no se crearon variables en Main ni tampoco se pasaron argumentos

62 Capiacutetulo 5 Condicionales y recursividad

Los cuatro marcos de cuentaregresiva tienen diferentes valores del paraacutemetro nLa parte inferior del diagrama de pila donde n = 0 es llamado caso base Nohace una llamada recursiva asiacute que no hay maacutes marcos

Ejercicio 5-1

Como ejercicio dibuje un diagrama de pila para printn llamada con s = Hola yn = 2 Luego escriba una funcioacuten llamada hacer_n que tome como argumentosuna funcioacuten y un nuacutemero n y que luego llame a la funcioacuten dada veces

Recursioacuten infinitaSi una recursioacuten nunca alcanza un caso base continuacutea haciendo llamadasrecursivas para siempre y el programa nunca termina Esto se conoce comorecursioacuten infinita y generalmente no es una buena idea Aquiacute hay un coacutedigo conuna recursioacuten infinita

function recursion() recursion()end

En la mayoriacutea de los entornos de programacioacuten un programa con recursioacuteninfinita realmente no se ejecuta para siempre Julia entrega un mensaje de errorcuando se alcanza la profundidad de recursioacuten maacutexima

juliagt recursion()ERROR StackOverflowErrorStacktrace [1] recursion() at REPL[1]2 (repeats 80000 times)

Este stacktrace es un poco maacutes grande que el que vimos en el capiacutetulo anteriorCuando se produce el error iexclhay 80000 marcos de recursion en el diagrama depila

Si por accidente encuentra una recursioacuten infinita en su coacutedigo revise su funcioacutenpara confirmar que hay un caso base que no realiza una llamada recursiva Sihay un caso base verifique si realmente puede ocurrir

Entrada por tecladoLos programas que se han escrito hasta ahora no aceptan entradas del usuarioSimplemente hacen lo mismo cada vez

Julia tiene una funcioacuten incorporada llamada readline que detiene el programa yespera a que el usuario escriba algo Cuando el usuario presiona RETURN oENTER el programa se reanuda y readline devuelve lo que el usuario escribioacute

Recursioacuten infinita 63

como una cadena

juliagt text = readline()iquestQueacute estaacute esperandoiquestQueacute estaacute esperando

Antes de recibir una entrada por teclado del usuario es una buena idea imprimirun mensaje que le diga al usuario queacute escribir

juliagt print(iquestCuaacutel es su nombre ) readline()iquestCuaacutel es su nombre iexclArturo Rey de los BretonesiexclArturo Rey de los Bretones

Un punto y coma permite colocar varias sentencias en la misma liacutenea En elREPL solo la uacuteltima sentencia devuelve su valor

Si espera que el usuario escriba un nuacutemero entero puede intentar convertir elvalor de retorno a Int64

juliagt println(iquestCuaacutentos dejaron su casa su tierra o su posesioacuten)numero = readline()iquestCuaacutentos dejaron su casa su tierra o su posesioacuten115115juliagt parse(Int64 numero)115

Pero si el usuario no escribe una cadena de diacutegitos obtendraacute un error

juliagt println(iquestCuaacutentos dejaron su casa su tierra o su posesioacuten)numero = readline()iquestCuaacutentos dejaron su casa su tierra o su posesioacutenMaacutes de ciento quince sonMaacutes de ciento quince sonjuliagt parse(Int64 speed)ERROR ArgumentError invalid base 10 digit M in Maacutes de ciento quinceson[]

Veremos queacute hacer con este tipo de error maacutes adelante

DepuracioacutenCuando se produce un error de sintaxis o de tiempo de ejecucioacuten el mensaje deerror contiene mucha informacioacuten lo cual puede ser abrumador Las partes maacutes

64 Capiacutetulo 5 Condicionales y recursividad

uacutetiles suelen ser

bull Queacute tipo de error fue

bull Doacutende ocurrioacute tal error

Los errores de sintaxis suelen ser faacuteciles de encontrar y hay algunos trucos Engeneral los mensajes de error indican doacutende se descubrioacute el problema pero elerror real podriacutea estar antes en el coacutedigo a veces en una liacutenea anterior

Lo mismo aplica para los errores de tiempo de ejecucioacuten Suponga que estaacutetratando de calcular una relacioacuten sentildealruido en decibelios La foacutermula es

En Julia se podriacutea escribir algo como esto

intensidad_sentildeal = 9intensidad_ruido = 10relacion = intensidad_sentildeal divide intensidad_ruidodecibeles = 10 log10(relacion)print(decibeles)

Obteniendo

-Inf

Este no es el resultado que esperaacutebamos

Para encontrar el error puede ser uacutetil imprimir el valor de la variable relacionque resulta ser 0 El problema estaacute en la liacutenea 3 que usa la divisioacuten entera enlugar de la divisioacuten de punto flotante

AVISOEl usuario debe tomarse el tiempo de leer los mensajes de errorcuidadosamente pero no se debe asumir que todo lo que dicen escorrecto

GlosarioDivisioacuten entera

Un operador denotado por divide que divide dos nuacutemeros y redondea haciaabajo (hacia el infinito negativo) a un entero

operador moacuteduloUn operador denotado con el signo de porcentaje () que se utiliza conenteros y devuelve el resto cuando un nuacutemero se divide por otro

Glosario 65

expresioacuten booleanaUna expresioacuten cuyo valor es verdadero o falso

operador relacionalUno de los operadores que compara sus operandos == ne (=) gt lt ge(gt=) and le (lt=)

operador loacutegicoUno de los operadores que combina expresiones booleanas ampamp (and) ||(or) and (not)

sentencia condicionalUna sentencia que controla el flujo de ejecucioacuten dependiendo de algunacondicioacuten

condicioacutenLa expresioacuten booleana en una sentencia condicional que determina queacuterama se ejecuta

sentencia compuestaUna sentencia que consta de un encabezado y un cuerpo El cuerpo terminacon la palabra reservada end

ramaUna de las secuencias alternativas de sentencias en una sentenciacondicional

condicional encadenadaUna sentencia condicional con una serie de ramas alternativas

condicional anidadaUna sentencia condicional que aparece en una de las ramas de otrasentencia condicional

sentencia returnUna sentencia que hace que una funcioacuten finalice de inmediato y que vuelvaa la sentencia de llamada a funcioacuten

recursividad o recursioacutenEl proceso de llamar a la funcioacuten que se estaacute ejecutando actualmente

caso baseUna rama condicional en una funcioacuten recursiva que no realiza una llamadarecursiva

66 Capiacutetulo 5 Condicionales y recursividad

recursioacuten infinitaUna recursioacuten que no tiene un caso base o que nunca llega a eacutelEventualmente una recursioacuten infinita provoca un error de tiempo deejecucioacuten

Ejercicios

Ejercicio 5-2

La funcioacuten time devuelve el tiempo medio de Greenwich actual en segundosdesde la eacutepoca que es un tiempo arbitrario utilizado como punto de referenciaEn sistemas UNIX la eacutepoca es el 1 de enero de 1970

juliagt time()1603600382165353e9

Escriba un script que lea la hora actual y la convierta a una hora del diacutea enhoras minutos y segundos maacutes el nuacutemero de diacuteas transcurridos desde la eacutepoca

Ejercicio 5-3

El uacuteltimo teorema de Fermat dice que no hay enteros positivos and tal que

para cualquier valor de mayor que 2

1 Escriba una funcioacuten llamada verificarfermat que tome cuatroparaacutemetrosmdasha b c y nmdash y que verifique si el teorema de Fermat es vaacutelidoSi n es mayor que 2 y a^n + b^n == c^n el programa deberiacutea imprimiriexclSanto cielo Fermat estaba equivocado De lo contrario el programadeberiacutea imprimir No eso no funciona

2 Escriba una funcioacuten que solicite al usuario ingresar valores para a b c y nque los convierta en enteros y que use verificarfermat para verificar siviolan el teorema de Fermat

Ejercicio 5-4

Si tiene tres barras estas podriacutean o no formar un triaacutengulo Por ejemplo si unade las barras tiene 12 centiacutemetros de largo y las otras dos tienen un centiacutemetrode largo no es posible que las barras pequentildeas puedan juntarse al medio Paracualquier triacuteo de longitudes hay una prueba simple para ver si es posible formarun triaacutengulo

Ejercicios 67

OBSERVACIOacuteN

Si cualquiera de las tres longitudes es mayor que lasuma de las otras dos entonces no se puede formar untriaacutengulo De lo contrario se puede (Si la suma de doslongitudes es igual a la tercera forman lo que se llamaun triaacutengulo degenerado)

1 Escriba una funcioacuten llamada estriangulo que tome tres enteros comoargumentos y que imprima ldquoSiacuterdquo o ldquoNordquo dependiendo de si se puede o noformar un triaacutengulo a partir de barras de las longitudes dadas

2 Escriba una funcioacuten que solicite al usuario ingresar tres longitudes debarras las convierta en enteros y use estriangulo para verificar si las barrascon las longitudes dadas pueden formar un triaacutengulo

Ejercicio 5-5

iquestCuaacutel es el resultado del siguiente programa Dibuje un diagrama de pila quemuestre el estado del programa cuando imprima el resultado

function recursion(n s) if n == 0 println(s) else recursion(n-1 n+s) endend

recursion(3 0)

1 iquestQueacute pasariacutea si se llamara a esta funcioacuten asiacute recursion(-1 0)

2 Escriba un documento que explique todo lo que alguien necesitariacutea saberpara usar esta funcioacuten (y nada maacutes)

Los siguientes ejercicios utilizan el moacutedulo IntroAJulia descrito en Capiacutetulo 4

Ejercicio 5-6

Lea la siguiente funcioacuten y vea si puede averiguar queacute hace (vea los ejemplos enCapiacutetulo 4) Luego ejecuacutetelo y vea si lo hizo bien

68 Capiacutetulo 5 Condicionales y recursividad

function dibujar(t distancia n) if n == 0 return end angulo = 50 adelante(t distancian) girar(t -angulo) dibujar(t distancia n-1) girar(t 2angulo) dibujar(t distancia n-1) girar(t -angulo) adelante(t -distancian)end

Ejercicio 5-7

Figura 8 Una curva de Koch

La curva de Koch es un fractal que luce como Figura 8 Para dibujar una curva deKoch con longitud todo lo que tiene que hacer es

1 Dibuje una curva de Koch con longitud

2 Gire a la izquierda 60 grados

3 Dibuje una curva de Koch con longitud

4 Gire a la derecha 120 grados

5 Dibuje una curva de Koch con longitud

6 Gire a la izquierda 60 grados

7 Dibuje una curva de Koch con longitud

La excepcioacuten es cuando es menor que 3 en ese caso puede dibujar una liacutenearecta con una longitud

1 Escribe una funcioacuten llamada koch que tome una tortuga y una longitudcomo paraacutemetros y que use la tortuga para dibujar una curva de Koch con lalongitud dada

2 Escriba una funcioacuten llamada copodenieve que dibuje tres curvas de Kochpara hacer el contorno de un copo de nieve

3 La curva de Koch se puede generalizar de varias maneras ConsultehttpsenwikipediaorgwikiKoch_snowflake para ver ejemplos eimplementar su favorito

Ejercicios 69

Capiacutetulo 6 Funciones productivasMuchas de las funciones de Julia que se han utilizado como las funcionesmatemaacuteticas producen valores de retorno Todas las funciones que se hanescrito hasta ahora son nulas es decir tienen un efecto (como imprimir un valor)pero devuelven el valor nothing En este capiacutetulo se ensentildea a escribir funcionesproductivas

Valores de retornoLlamar a una funcioacuten genera un valor de retorno que generalmente se asigna auna variable o se usa como parte de una expresioacuten

e = exp(10)altura = radio sin(radio)

Las funciones que se han escrito hasta ahora son nulas Coloquialmentehablando no tienen valor de retorno de manera formal su valor de retorno esnothing En este capiacutetulo (finalmente) se van a escribir funciones productivas Elprimer ejemplo es area que devuelve el aacuterea de un ciacuterculo dado un radio

function area(radio) a = π radio^2 return aend

Se ha visto la sentencia return antes pero en una funcioacuten productiva la sentenciareturn incluye una expresioacuten Esta sentencia significa Retorne inmediatamentede esta funcioacuten y use la siguiente expresioacuten como valor de retorno La expresioacutendada puede ser arbitrariamente complicada Asiacute pues se podriacutea haber escritoesta funcioacuten maacutes concisamente

function area(radio) π radio^2end

El valor devuelto por una funcioacuten es el valor de la uacuteltima expresioacuten evaluadaque por defecto es la uacuteltima expresioacuten en el cuerpo de la definicioacuten de lafuncioacuten

Por otro lado las variables temporales como a y las sentencias return expliacutecitaspueden facilitar la depuracioacuten

A veces es uacutetil tener muacuteltiples sentencias return una en cada rama de unasentencia condicional

70 Capiacutetulo 6 Funciones productivas

function valorabsoluto(x) if x lt 0 return -x else return x endend

Dado que estas sentencias return estaacuten en una condicional alternativa solo seejecuta una

En cuanto se ejecuta una sentencia return la funcioacuten termina sin ejecutarninguna de las sentencias siguientes El coacutedigo que aparece despueacutes de lasentencia return o en cualquier otro lugar al que el flujo de ejecucioacuten nuncallegaraacute se llama coacutedigo muerto

En una funcioacuten productiva es una buena idea asegurarse que cualquier posiblerecorrido del programa llegue a una sentencia return Por ejemplo

function valorabsoluto(x) if x lt 0 return -x end if x gt 0 return x endend

Esta versioacuten no es correcta porque si x es igual a 0 ninguna de las condicioneses verdadera y la funcioacuten termina sin alcanzar una sentencia return Si el flujo deejecucioacuten llega al final de la funcioacuten el valor de retorno es nothing queclaramente no es el valor absoluto de 0

juliagt show(valorabsoluto(0))nothing

OBSERVACIOacuteN Julia tiene una funcioacuten incorporada llamada abs quecalcula los valores absolutos

Ejercicio 6-1

Escriba la funcioacuten comparar que tome dos valores x y y y que devuelva 1 si x gty 0 si x == y y -1 si x lt y

Valores de retorno 71

Desarrollo incrementalConforme vaya escribiendo funciones maacutes extensas puede empezar a dedicarmaacutes tiempo a la depuracioacuten

Para lidiar con programas de complejidad creciente se sugiere una teacutecnicallamada desarrollo incremental El objetivo del desarrollo incremental es evitarlargas sesiones de depuracioacuten antildeadiendo y probando solamente pequentildeasporciones de coacutedigo cada vez

Por ejemplo suponga que desea encontrar la distancia entre dos puntos dadospor las coordenadas y Por el teorema de Pitaacutegoras la distancia es

El primer paso es considerar queacute aspecto tendriacutea la funcioacuten distancia en Julia Enotras palabras iquestcuaacuteles son las entradas (paraacutemetros) y cuaacutel es la salida (valor deretorno)

En este caso las entradas son los dos puntos que se pueden representar usandocuatro nuacutemeros El valor devuelto es la distancia que es un nuacutemero de puntoflotante

He aquiacute una primera versioacuten de la funcioacuten

function distancia(x₁ y₁ x₂ y₂) 00end

Obviamente esta versioacuten de la funcioacuten no calcula distancias sino que siempredevuelve cero Aun asiacute es correcta sintaacutecticamente hablando y se ejecutaraacute loque implica que se puede probar antes de hacerla maacutes compleja Los nuacutemeros desubiacutendice estaacuten disponibles en la codificacioacuten de caracteres Unicode (_1 TAB_2 TAB etc)

Para probar la nueva funcioacuten se llama con una muestra de valores

distance(1 2 4 6)

Se eligen estos valores de tal forma que la distancia horizontal sea igual a 3 y ladistancia vertical sea igual a 4 y de esa manera el resultado es 5 (la hipotenusadel triaacutengulo 3-4-5) Cuando se comprueba una funcioacuten es uacutetil conocer larespuesta correcta

Hasta el momento se ha podido confirmar que la funcioacuten es sintaacutecticamentecorrecta por lo que se puede empezar a agregar liacuteneas de coacutedigo El paso loacutegico

72 Capiacutetulo 6 Funciones productivas

siguiente es encontrar las diferencias y En la siguiente versioacuten de lafuncioacuten se almacenaraacuten estos valores en variables temporales y se mostraraacuten conel macro show

function distancia(x₁ y₁ x₂ y₂) dx = x₂ - x₁ dy = y₂ - y₁ show dx dy 00end

Si la funcioacuten trabaja bien las salidas deben ser dx = 3 y dy = 4 Si es asiacute se sabeque la funcioacuten estaacute obteniendo los paraacutemetros correctos y realizando el primercaacutelculo correctamente Si no entonces soacutelo hay unas pocas liacuteneas que revisar

A continuacioacuten se calcula la suma de los cuadrados de dx y dy

function distancia(x₁ y₁ x₂ y₂) dx = x₂ - x₁ dy = y₂ - y₁ dsup2 = dx^2 + dy^2 show dsup2 00end

De nuevo se quiere ejecutar el programa en esta etapa y comprobar la salida(que deberiacutea ser 25) Los nuacutemeros en superiacutendice tambieacuten estaacuten disponibles (^2TAB) Finalmente se puede usar sqrt para calcular y devolver el resultado

function distancia(x₁ y₁ x₂ y₂) dx = x₂ - x₁ dy = y₂ - y₁ dsup2 = dx^2 + dy^2 sqrt(dsup2)end

Si esto funciona correctamente ya se habriacutea terminado Si no se podriacutea mostrarel valor de la variable resultado antes de la sentencia de retorno

La versioacuten final de la funcioacuten no muestra nada cuando se ejecuta soacutelo retorna unvalor Las sentencias print son uacutetiles para la depuracioacuten pero una vez que elprograma esteacute funcionando correctamente se deben eliminar El coacutedigoeliminado se llama andamiaje porque es uacutetil para construir el programa pero noes parte del producto final

Al principio deberiacutea antildeadir solamente una o dos liacuteneas de coacutedigo cada vez

Desarrollo incremental 73

Conforme vaya ganando experiencia puede que se encuentre escribiendo ydepurando fragmentos mayores de coacutedigo Sin embargo el proceso de desarrolloincremental puede ahorrarle mucho tiempo de depuracioacuten

Los aspectos clave del proceso son

1 Iniciar con un programa que funcione y hacerle pequentildeos cambiosincrementales En cualquier momento si hay un error sabraacute exactamentedoacutende estaacute

2 Usar variables temporales para guardar valores intermedios para que puedamostrarlos y verificarlos

3 Una vez que el programa esteacute funcionando tal vez prefiera eliminar partedel andamiaje o consolidar muacuteltiples sentencias en expresiones compuestaspero soacutelo si eso no hace que el programa sea difiacutecil de leer

Ejercicio 6-2

Use la teacutecnica de desarrollo incremental para escribir una funcioacuten llamadahipotenusa que retorne el largo de la hipotenusa de un triaacutengulo rectaacutengulo dadoel largo de las otras dos aristas Registre cada etapa del proceso de desarrollo

ComposicioacutenAhora como usted esperariacutea se puede llamar a una funcioacuten desde otra Comoejemplo se escribe una funcioacuten que tome dos puntos el centro del ciacuterculo y unpunto del periacutemetro y calcule el aacuterea del ciacuterculo

Suponga que el punto central estaacute almacenado en las variables xc y yc y que elpunto del periacutemetro lo estaacute en xp y yp El primer paso es hallar el radio delciacuterculo que es la distancia entre los dos puntos La funcioacuten distancia que realizaesta tarea seriacutea

radio = distancia(xc yc xp yp)

El siguiente paso es encontrar el aacuterea del ciacuterculo usando este radio De nuevo seusa una de las funciones definidas previamente

resultado = area(radio)

Envolviendo todo en una funcioacuten se obtiene

74 Capiacutetulo 6 Funciones productivas

function areacirculo(xc yc xp yp) radio = distancia(xc yc xp yp) resultado = area(radio) return resultadoend

Las variables temporales radio y resultado son uacutetiles para el desarrollo y ladepuracioacuten pero una vez que el programa estaacute funcionando se puede hacer maacutesconciso componiendo las llamadas a funcioacuten

function areacirculo(xc yc xp yp) area(distancia(xc yc xp yp))end

Funciones BooleanasLas funciones pueden devolver valores booleanos lo que a menudo esconveniente para ocultar complicadas comprobaciones dentro de funciones Porejemplo

function esdivisible(x y) if x y == 0 return true else return false endend

Es comuacuten dar a las funciones booleanas nombres que suenan como preguntasque tienen como respuesta un si oacute un no esdivisible devuelve true o false paraindicar si x es o no divisible por y

Por ejemplo

juliagt esdivisible(6 4)falsejuliagt esdivisible(6 3)true

El resultado del operador == es booleano por lo tanto se puede escribir lafuncioacuten de una manera maacutes concisa devolviendo el resultado directamente

Funciones Booleanas 75

function esdivisible(x y) x y == 0end

Las funciones booleanas se usan a menudo en las sentencias condicionales

if esdivisible(x y) println(x es divisible por y)end

Puede parecer tentador escribir algo como

if esdivisible(x y) == true println(x es divisible por y)end

pero la comparacioacuten extra con true es innecesaria

Ejercicio 6-3

Escriba la funcioacuten entremedio(xyz) que devuelva true si x le y le z o false enotro caso

Maacutes recursividadSolo se ha cubierto una pequentildea parte de Julia pero le puede interesar saber queesta parte ya es un lenguaje de programacioacuten completo lo que significa quecualquier coacutemputo puede expresarse en este lenguaje Cualquier programa quese haya escrito podriacutea reescribirse usando solo lo que ha aprendido hasta ahora(en realidad necesitariacutea algunos comandos para controlar dispositivos como elmouse discos etc pero eso es todo)

Probar esta afirmacioacuten es un ejercicio no trivial realizado por primera vez porAlan Turing uno de los primeros cientiacuteficos de la computacioacuten (algunosargumentariacutean que era matemaacutetico pero muchos de los primeros cientiacuteficosinformaacuteticos comenzaron como matemaacuteticos) En consecuencia esto se conocecomo la Tesis de Turing Para una discusioacuten maacutes completa (y precisa) de la Tesisde Turing se recomienda el libro de Michael Sipser Introduccioacuten a la Teoriacutea de laComputacioacuten

Para darle una idea de lo que puede hacer con las herramientas que haaprendido hasta ahora se evaluacutean algunas funciones matemaacuteticas definidasrecursivamente Una definicioacuten recursiva es similar a una definicioacuten circular enel sentido de que la definicioacuten contiene una referencia a lo que estaacute siendodefinido Una definicioacuten verdaderamente circular no es muy uacutetil

76 Capiacutetulo 6 Funciones productivas

vorpalUn adjetivo usado para describir algo que es vorpal

Si esta definicioacuten apareciese en el diccionario la persona que la leyera podriacuteamolestarse Por otro lado si se busca la definicioacuten de la funcioacuten factorialdenotada con el siacutembolo se encuentra encontrar algo como esto

Esta definicioacuten dice que el factorial de 0 es 1 y el factorial de cualquier otrovalor es multiplicado por el factorial de

Entonces es 3 veces que es 2 veces que es 1 vez Es decir es igual a3 por 2 por 1 por 1 que es 6

Si se puede escribir una definicioacuten recursiva se puede escribir un programa deJulia para evaluarlo El primer paso es decidir cuaacuteles deberiacutean ser losparaacutemetros En este caso debe quedar claro que factorial toma valores enteros

function fact(n) end

Si el argumento es 0 la funcioacuten debe devolver 1

function fact(n) if n == 0 return 1 endend

De lo contrario y esto es lo interesante se tiene que hacer una llamada recursivapara encontrar el factorial de n-1 y luego multiplicarlo por n

function fact(n) if n == 0 return 1 else recursion = fact(n-1) resultado = n recursion return resultado endend

El flujo de ejecucioacuten de este programa es similar al flujo de cuentaregresiva enSeccioacuten 58 Si llamamos a fact con el valor 3

Maacutes recursividad 77

Como 3 no es 0 se toma la segunda rama y se calcula el factorial de n-1 hellip

 Como 2 no es 0 se toma la segunda rama y se calcula el factorial de n-1 hellip

  Como 1 no es 0 se toma la segunda rama y se calcula el factorial de + n-1 +hellip

   Como 0 es igual a 0 se toma la primera rama y devuelve 1 sin realizar      maacutes llamadas recursivas

  El valor de retorno 1 se multiplica por n que es 1 y se devuelve elresultado

 El valor de retorno 1 se multiplica por n que es 2 y se devuelve el resultado

El valor de retorno 2 se multiplica por n que es 3 y el resultado 6 se convierteen el valor de retorno de la llamada a funcioacuten que inicioacute todo el proceso

Figura 9 Diagrama de pila

Figura 9 muestra coacutemo se ve el diagrama de pila para esta secuencia dellamadas a funciones

Los valores de retorno se pasan de nuevo a la pila En cada marco el valor deretorno es el valor de resultado que es el producto de n y recursion

En el uacuteltimo marco las variables locales recursion y resultado no existen porquela rama que las crea no se ejecuta

OBSERVACIOacuteN Julia tiene la funcioacuten factorial para calcular el factorialde un nuacutemero entero

Voto de confianzaSeguir el flujo de ejecucioacuten es una forma de leer programas pero puede llegar aser abrumador Una alternativa es lo que se conoce como el voto deconfianza(en ingleacutes leap of faith) Cuando llega a una llamada de funcioacuten enlugar de seguir el flujo de ejecucioacuten asume que la funcioacuten funcionacorrectamente y devuelve el resultado correcto

De hecho ya se estaacute dando este voto de confianza cuando se usan funciones

78 Capiacutetulo 6 Funciones productivas

integradas de Julia Cuando se llaman a cos o exp no se examinan los cuerpos deesas funciones Simplemente se asume que funcionan porque las personas quelas escribieron eran buenos programadores

Lo mismo ocurre cuando el usuario llama a una de sus propias funciones Porejemplo en Seccioacuten 64 se escribe una funcioacuten llamada esdivisible quedetermina si un nuacutemero es divisible por otro Una vez que se confirme que estafuncioacuten es correcta mdashal examinar y probar el coacutedigomdash se puede usar la funcioacutensin mirar nuevamente el cuerpo

Lo mismo aplica a los programas recursivos Cuando llegue a la llamadarecursiva en lugar de seguir el flujo de ejecucioacuten debe suponer que la llamadarecursiva funciona (devuelve el resultado correcto) y luego preguntarseSuponiendo que pueda encontrar el factorial de iquestse puede calcular elfactorial de Estaacute claro que es posible multiplicando por

Por supuesto es un poco extrantildeo suponer que la funcioacuten funciona correctamentecuando no ha terminado de escribirla iexclpero por eso se llama voto de confianza

Un Ejemplo MaacutesDespueacutes de los factoriales el ejemplo maacutes comuacuten de una funcioacuten matemaacuteticadefinida de manera recursiva es fibonacci que tiene la siguiente definicioacuten (verhttpsenwikipediaorgwikiFibonacci_number)

Traducido a Julia se ve asiacute

function fib(n) if n == 0 return 0 elseif n == 1 return 1 else return fib(n-1) + fib(n-2) endend

Si intenta seguir el flujo de ejecucioacuten en esta funcioacuten incluso para valoresbastante pequentildeos de n su cabeza podriacutea estallar Dando un voto de confianzaes decir asumiendo que las dos llamadas recursivas funcionan correctamenteentonces estaacute claro que se obtiene el resultado correcto al sumarlas

Un Ejemplo Maacutes 79

Tipos de Comprobacioacuten

iquestQueacute pasa si se llama a fact con 15 como argumento

juliagt fact(15)ERROR StackOverflowErrorStacktrace [1] fact(Float64) at REPL[3]2

Parece una recursioacuten infinita iquestComo es esto posible La funcioacuten tiene un casobase (cuando n == 0) Pero si n no es un nuacutemero entero es posible perderse elcaso base y hacer recursioacuten para siempre

En la primera llamada recursiva el valor de n es 05 En la siguiente es -05 Apartir de ahiacute se vuelve maacutes pequentildeo (maacutes negativo) pero nunca seraacute 0

Existen dos opciones Se puede intentar generalizar la funcioacuten factorial paratrabajar con nuacutemeros de punto flotante o se puede hacer que fact verifique eltipo del argumento La primera opcioacuten se llama funcioacuten gamma y estaacute un pocomaacutes allaacute del alcance de este libro En este libro se proseguiraacute con la segunda

Se puede usar el operador integrado isa para verificar el tipo de argumentoTambieacuten podemos asegurarnos de que el argumento sea positivo

function fact(n) if (n isa Int64) error(El factorial uacutenicamente estaacute definido para nuacutemerosenteros) elseif n lt 0 error(El factorial no estaacute definido para enteros negativos) elseif n == 0 return 1 else return n fact(n-1) endend

El primer caso base se hace cargo de nuacutemeros no enteros y el segundo deenteros negativos En ambos casos el programa imprime un mensaje de error ydevuelve nothing para indicar que algo salioacute mal

juliagt fact(fred)ERROR El factorial uacutenicamente estaacute definido para nuacutemeros enterosjuliagt fact(-2)ERROR El factorial no estaacute definido para enteros negativos

80 Capiacutetulo 6 Funciones productivas

Si se superan ambas verificaciones se sabe que n es positivo o cero por lo quees posible probar que la recursioacuten termina

Este programa muestra un patroacuten a veces llamado guardian Los dos primeroscondicionales actuacutean como guardianes protegiendo el coacutedigo que sigue de losvalores que pueden causar un error Los guardianes hacen posible demostrar queel coacutedigo es correcto

En Seccioacuten 145 se exploraraacute una alternativa maacutes flexible para imprimir unmensaje de error generar una excepcioacuten

DepuracioacutenDividir un coacutedigo extenso en pequentildeas funciones crea naturalmente puntos decontrol para la depuracioacuten Si un programa no estaacute funcionando existen tresposibilidades a considerar

bull Hay algo incorrecto en los argumentos de la funcioacuten se viola una condicioacutenprevia

bull Hay algo incorrecto en la funcioacuten se viola una condicioacuten posterior

bull Hay algo incorrecto en el valor de retorno o la forma en que se estaacuteutilizando

Para descartar la primera posibilidad puede agregar una sentencia de impresioacutenal comienzo de la funcioacuten para mostrar los valores de los paraacutemetros (y tal vezsus tipos) o bien escribir liacuteneas de coacutedigo que verifiquen las condiciones previasde manera expliacutecita

Si los paraacutemetros estaacuten bien agregue una sentencia de impresioacuten antes de cadasentencia return y muestre el valor de retorno Si es posible verifique elresultado a mano Considere tambieacuten llamar a la funcioacuten con valores quefaciliten la verificacioacuten del resultado (como en Seccioacuten 62)

Si la funcioacuten parece estar funcionando revise la llamada a la funcioacuten paraasegurarse de que el valor de retorno se estaacute utilizando correctamente (iexcloincluso si se estaacute utilizando)

Agregar sentencias de impresioacuten al principio y al final de una funcioacuten puedeayudar a que el flujo de ejecucioacuten sea maacutes transparente Por ejemplo aquiacute hayuna versioacuten de fact con sentencias de impresioacuten

Depuracioacuten 81

function fact(n) espacio = ^ (4 n) println(espacio factorial n) if n == 0 println(espacio devolviendo 1) return 1 else recursion = fact(n-1) resultado = n recursion println(espacio devolviendo resultado) return resultado endend

espacio es una cadena de caracteres de espacios que permite generar sangriacutea enla salida

juliagt fact(4) factorial 4 factorial 3 factorial 2 factorial 1factorial 0devolviendo 1 devolviendo 1 devolviendo 2 devolviendo 6 devolviendo 2424

Si estaacute confundido con el flujo de ejecucioacuten este tipo de salida puede ser uacutetilDesarrollar un buen andamiaje toma tiempo pero un poco de andamiaje puedeahorrar al usuario mucha depuracioacuten

Glosariovariable temporal

Variable usada para almacenar un valor intermedio en un caacutelculo complejo

coacutedigo muertoParte de un programa que nunca puede ser ejecutado a menudo porqueaparece despueacutes de una sentencia return

desarrollo incrementalPlan de desarrollo de un programa que intenta evitar la depuracioacutenagregando y probando solamente una pequentildea porcioacuten de coacutedigo a la vez

82 Capiacutetulo 6 Funciones productivas

andamiajeCoacutedigo que se usa durante el desarrollo de un programa pero que no esparte de la versioacuten final del mismo

guardiaacutenUn patroacuten de programacioacuten que usa una sentencia condicional paraverificar y manejar circunstancias que pueden causar un error

Ejercicios

Ejercicio 6-4

Dibuje un diagrama de pila para el siguiente programa iquestQueacute imprime elprograma

function b(z) prod = a(z z) println(z prod) prodend

function a(x y) x = x + 1 x yend

function c(x y z) total = x + y + z cuadrado = b(total)^2 cuadradoend

x = 1y = x + 1println(c(x y+3 x+y))

Ejercicio 6-5

La funcioacuten de Ackermann se define

Vea httpsenwikipediaorgwikiAckermann_function Escriba una funcioacutenllamada ack que evaluacutee la funcioacuten de Ackermann Use su funcioacuten para evaluarack(3 4) que deberiacutea ser 125 iquestQueacute sucede para valores mayores de m y n

Ejercicios 83

Ejercicio 6-6

Un paliacutendromo es una palabra que se escribe igual en un sentido que en otrocomo ana y radar De manera recursiva una palabra es un paliacutendromo si laprimera y la uacuteltima letra son iguales y lo que estaacute entre ellas es un paliacutendromo

Las siguientes funciones toman un argumento de tipo cadena y devuelven laprimera letra la uacuteltima y las intermedias

function primera(palabra) primera = firstindex(palabra) palabra[primera]end

function ultima(palabra) ultima = lastindex(palabra) palabra[ultima]end

function medio(palabra) primera = firstindex(palabra) ultima = lastindex(palabra) palabra[nextind(palabra primera) prevind(palabra ultima)]end

Se veraacute coacutemo funcionan en Capiacutetulo 8

1 Pruebe estas funciones iquestQueacute sucede si llama a la funcioacuten medio con unacadena de dos letras iquestY con una cadena de una letra iquestQueacute pasa con lacadena vaciacutea que no contiene letras

2 Escriba una funcioacuten llamada espalindromo que tome un argumento de tipocadena y devuelva true si es un paliacutendromo y false de lo contrario Recuerdeque puede usar la funcioacuten integrada length para verificar la longitud de unacadena

Ejercicio 6-7

Un nuacutemero es una potencia de si es divisible por y es una potencia de Escriba una funcioacuten llamada espotencia que tome los paraacutemetros a y b ydevuelva true si a es una potencia de b

OBSERVACIOacuteN Tendraacute que pensar en el caso base

Ejercicio 6-8

El maacuteximo comuacuten divisor (MCD) de y es el nuacutemero maacutes grande que los divide

84 Capiacutetulo 6 Funciones productivas

a ambos con resto 0

Una forma de encontrar el MCD de dos nuacutemeros se basa en la observacioacuten deque si es el resto cuando se divide por entonces mcd(a b) = mcd(b r)Como caso base podemos usar mcd(a 0) = a

Escriba una funcioacuten llamada mcd que tome los paraacutemetros a y b y devuelva sumaacuteximo divisor comuacuten

Creacuteditos Este ejercicio se basa en un ejemplo del libro Estructura einterpretacioacuten de programas informaacuteticos de Abelson y Sussman

Ejercicios 85

Capiacutetulo 7 IteracioacutenEste capiacutetulo se centra en la iteracioacuten que es la capacidad de ejecutarrepetidamente un bloque de sentencias Se han visto dos tipos de iteracioacutenusando recursioacuten en Seccioacuten 58 y usando ciclos for en Seccioacuten 42 En estecapiacutetulo veremos otro tipo maacutes usando sentencias while Primeramente seintroduciraacuten algunos teacuterminos sobre asignacioacuten de variables

Asignacioacuten muacuteltiplePuede que ya haya descubierto que estaacute permitido realizar maacutes de unaasignacioacuten a la misma variable Una nueva asignacioacuten hace que la variableexistente se refiera a un nuevo valor (y deje de referirse al viejo valor)

juliagt x = 55juliagt x = 77

La primera vez que se muestra x su valor es 5 y la segunda vez su valor es 7

Figura 10 Diagrama de estado

Figura 10 muestra el aspecto de una asignacioacuten muacuteltiple en un diagrama deestado

Es necesario aclarar algo que puede causar confusioacuten Puesto que Julia usa elsigno igual (=) para la asignacioacuten es tentador interpretar una sentencia a = bcomo una sentencia de igualdad Pero esta interpretacioacuten es incorrecta

Para empezar la igualdad es simeacutetrica y la asignacioacuten no lo es Por ejemplo enmatemaacuteticas si entonces Pero en Julia la sentencia a = 7 es vaacutelida y 7= a no lo es

Ademaacutes en matemaacuteticas una sentencia de igualdad es verdadera o falsasiempre Si ahora entonces siempre seraacute igual a En Julia una sentenciade asignacioacuten puede hacer que dos variables sean iguales pero no tienen porqueacute quedarse asiacute

86 Capiacutetulo 7 Iteracioacuten

juliagt a = 55juliagt b = a a y b son iguales5juliagt a = 3 a y b ya no son iguales3juliagt b5

La tercera liacutenea cambia el valor de a pero no cambia el valor de b por lo tanto yadejan de ser iguales

AVISO

Reasignar variables puede ser uacutetil pero se debe tener precaucioacutenSi los valores cambian frecuentemente la reasignacioacuten puedehacer que el coacutedigo sea difiacutecil de leer y depurar

Estaacute permitido definir una funcioacuten con el mismo nombre de unavariable definida anteriormente

Actualizacioacuten de variablesUna de las formas maacutes comunes de asignacioacuten muacuteltiple es la actualizacioacutendoacutende el nuevo valor de la variable depende del anterior

juliagt x = x + 18

Esto significa ldquotome el valor actual de x suacutemele uno y despueacutes actualice x con elnuevo valorrdquo

Si intenta actualizar una variable que no existe obtendraacute un error puesto queJulia evaluacutea la expresioacuten del lado derecho antes de asignar un valor a x

juliagt y = y + 1ERROR UndefVarError y not defined

Antes de actualizar una variable tiene que inicializarla usualmente con unaasignacioacuten simple

juliagt y = 00juliagt y = y + 11

Actualizar una variable sumaacutendole 1 se denomina un incremento y restaacutendole 1

Actualizacioacuten de variables 87

se llama un decremento

La Sentencia whileLas computadoras se usan a menudo para automatizar tareas repetitivasRealizar repetidamente tareas ideacutenticas o similares sin cometer errores es algoque las computadoras hacen bien y que los seres humanos hacen limitadamenteLa ejecucioacuten repetida de un conjunto de sentencias se llama iteracioacuten

Ya se han visto dos funciones cuentaregresiva y printn que iteran usandorecursividad Por ser la iteracioacuten tan comuacuten Julia proporciona variascaracteriacutesticas que la hacen maacutes faacutecil Una es la sentencia for que se vio enSeccioacuten 42 a la cual se volveraacute maacutes adelante

Otra caracteriacutestica es la sentencia while Aquiacute hay una versioacuten decuentaregresiva que muestra el uso de la sentencia while

function cuentaregresiva(n) while n gt 0 print(n ) n = n - 1 end println(iexclDespegue)end

Casi podriacutea leer la sentencia while como si fuera Espantildeol La funcioacuten anteriorsignifica ldquoMientras n sea mayor que 0 continuacutee mostrando el valor de n y luegoreduciendo el valor de n en 1 Cuando llegue a 0 muestre la palabra iexclDespegueldquo

Maacutes formalmente el flujo de ejecucioacuten de una sentencia while es el siguiente

1 Se determina si la condicioacuten es verdadera o falsa

2 Si es falsa se sale de la sentencia while y continuacutea la ejecucioacuten con lasiguiente sentencia

3 Si es verdadera ejecuta cada una de las sentencias en el cuerpo y regresa alpaso 1

Este tipo de flujo se llama bucle porque el tercer paso vuelve a la parte superior

El cuerpo del bucle deberiacutea cambiar el valor de una o maacutes variables de maneraque en alguacuten momento la condicioacuten sea falsa y el bucle termine En casocontrario el bucle se repetiraacute indefinidamente lo cual se llama bucle infinitoUna interminable fuente de diversioacuten para los informaacuteticos es la observacioacuten deque las instrucciones del champuacute ldquoEnjabone enjuague repitardquo son un bucleinfinito

88 Capiacutetulo 7 Iteracioacuten

En el caso de cuentaregresiva podemos probar que el bucle termina si n es ceroo negativo el ciclo termina En otro caso el valor de n se hace maacutes pequentildeocada vez que pasa por el bucle asiacute en cierto momento se llega a 0

En otros casos no es tan faacutecil decirlo Por ejemplo

function seq(n) while n = 1 println(n) if n 2 == 0 n is par n = n 2 else n is impar n = n3 + 1 end endend

La condicioacuten de este bucle es n = 1 de manera que el bucle continuaraacute hastaque n sea 1 que haraacute que la condicioacuten sea falsa

Cada vez que pasa por el bucle el programa muestra como salida el valor de n yluego comprueba si es par o impar Si es par el valor de n se divide por dos Si esimpar el valor de n se sustituye por n3 + 1 Por ejemplo si el argumento pasadoa la funcioacuten seq es 3 los valores resultantes n son 3 10 5 16 8 4 2 1

Puesto que n a veces aumenta y a veces disminuye no hay una prueba obvia deque n alcance alguna vez el valor 1 o de que el programa vaya a terminar Paraalgunos valores particulares de n se puede probar que siacute termina Por ejemplosi el valor de inicio es una potencia de dos entonces el valor de n seraacute par cadavez que se pasa por el bucle hasta que llegue a 1 El ejemplo anterior producedicha secuencia si se inicia con 16

Lo diacuteficil es preguntarse si se puede probar que este programa termina paratodos los valores positivos de n Hasta ahora nadie ha sido capaz de probar quelo hace o iexclque no lo hace (Vea httpseswikipediaorgwikiConjetura_de_Collatz)

Ejercicio 7-1

Reescribe la funcioacuten printn de Seccioacuten 58 utilizando iteracioacuten en vez derecursioacuten

breakA veces no se sabe que un ciclo debe terminar hasta que se llega al cuerpo Enese caso se puede usar la sentencia break para salir del bucle

break 89

Por ejemplo suponga que se desea recibir entradas del usuario hasta que esteescriba listo Podriacuteamos escribir

while true print(gt ) linea = readline() if line == listo break end println(linea)endprintln(iexclListo)

La condicioacuten del bucle es true que siempre es verdadero por lo que el bucle seejecuta hasta que llega a la sentencia break

En cada iteracioacuten se le pide al usuario (con el siacutembolo gt ) una entrada Si elusuario escribe listo la sentencia break sale del bucle De lo contrario elprograma repite lo que escriba el usuario y vuelve a la parte superior del bucleA continuacioacuten se muestra coacutemo funciona este programa

gt no listono listogt listoiexclListo

Esta forma de escribir bucles while es comuacuten porque permite verificar lacondicioacuten en cualquier parte del bucle (no solo en la parte superior) y puedeexpresar la condicioacuten de teacutermino de manera afirmativa (detenerse cuando estosuceda) en vez de negativamente (continuar hasta que esto suceda)

continueLa sentencia break permite terminar el bucle Cuando aparece una sentenciacontinue dentro de un bucle se regresa al comienzo del bucle ignorando todoslas sentencias que quedan en la iteracioacuten actual del bucle e inicia la siguienteiteracioacuten Por ejemplo

for i in 110 if i 3 == 0 continue end print(i )end

Output

90 Capiacutetulo 7 Iteracioacuten

1 2 4 5 7 8 10

Si i es divisible por 3 la sentencia continue detiene la iteracioacuten actual ycomienza la siguiente iteracioacuten Solo se imprimen los nuacutemeros en el rango de 1 a10 no divisibles por 3

Raiacuteces CuadradasLos bucles son comuacutenmente utilizados en programas que calculan resultadosnumeacutericos y que comienzan con una respuesta aproximada que es iterativamentemejorada

Por ejemplo una forma de calcular raiacuteces cuadradas es el meacutetodo de NewtonSuponga que desea conocer la raiacutez cuadrada de Si comienza con casi cualquierestimacioacuten puede calcular una mejor aproximacioacuten con la siguiente foacutermula

Por ejemplo si es 4 y es 3

juliagt a = 44juliagt x = 33juliagt y = (x + ax) 221666666666666665

El resultado estaacute maacutes cerca de la respuesta correcta ( ) Si se repite elproceso con la nueva estimacioacuten se acerca auacuten maacutes

juliagt x = y21666666666666665juliagt y = (x + ax) 220064102564102564

Despueacutes de algunas actualizaciones la estimacioacuten es casi exacta

Raiacuteces Cuadradas 91

juliagt x = y20064102564102564juliagt y = (x + ax) 220000102400262145juliagt x = y20000102400262145juliagt y = (x + ax) 220000000000262146

En general no se sabe de antemano cuaacutentos pasos se necesitan para llegar a larespuesta correcta pero se sabe que se ha llegado a ella cuando la estimacioacutendeja de cambiar

juliagt x = y20000000000262146juliagt y = (x + ax) 220juliagt x = y20juliagt y = (x + ax) 220

Cuando y == x ya se pueden detener los coacutemputos A continuacioacuten se muestraun ciclo que comienza con una estimacioacuten inicial x la cual mejora hasta que dejade cambiar

while true println(x) y = (x + ax) 2 if y == x break end x = yend

Para la mayoriacutea de los valores de a esto funciona bien aunque en general no serecomienda probar igualdad entre nuacutemeros de punto flotante Los nuacutemeros depunto flotante son aproximadamente correctos la mayoriacutea de los nuacutemerosracionales como e irracionales como no pueden ser representadosexactamente con un Float64

En lugar de verificar si x e y son exactamente iguales es maacutes seguro usar lafuncioacuten integrada abs para calcular el valor absoluto o la magnitud de ladiferencia entre ellos

92 Capiacutetulo 7 Iteracioacuten

if abs(y-x) lt ε breakend

Donde ε (varepsilon TAB) toma un valor como 00000001 que determina coacutemode cerca es suficientemente cerca

AlgoritmosEl meacutetodo de Newton es un ejemplo de un algoritmo un proceso mecaacutenico quepermite resolver una categoriacutea de problemas (en este caso el caacutelculo de raiacutecescuadradas)

Para comprender queacute es un algoritmo podriacutea ayudar empezar con algo que no esun algoritmo Cuando aprendioacute a multiplicar nuacutemeros de un solo diacutegitoprobablemente memorizoacute la tabla de multiplicar En efecto memorizoacute 100soluciones especiacuteficas Ese tipo de conocimiento no es un algoritmo

Pero si fuera perezoso podriacutea haber aprendido algunos trucos Por ejemplopara encontrar el producto de y 9 puede escribir como el primer diacutegito y

como el segundo diacutegito Este truco es una solucioacuten general para multiplicarcualquier nuacutemero de un solo diacutegito por 9 iexclEsto siacute es un algoritmo

Del mismo modo las teacutecnicas que aprendioacute para la suma con ldquollevamos tantordquo laresta con ldquopedimos prestado tantordquo y la divisioacuten ldquolarga o con galera o de casitardquoson todas ellas algoritmos Una de las caracteriacutesticas de los algoritmos es que norequieren inteligencia para realizarlos Son procesos mecaacutenicos donde cada pasose sigue de acuerdo con un conjunto simple de reglas

Ejecutar algoritmos es aburrido pero disentildearlos es interesante intelectualmentedesafiante y constituyen una parte central de la informaacutetica

Algunas de las cosas que las personas hacen naturalmente sin dificultad oconscientemente son las maacutes difiacuteciles de expresar en algoritmos Comprender ellenguaje natural es un buen ejemplo Todo el mundo lo hace pero hasta ahoranadie ha podido explicar coacutemo se hace al menos no en forma de algoritmo

DepuracioacutenA medida que comience a escribir programas maacutes extensos es posible que pasemaacutes tiempo depurando Maacutes coacutedigo significa maacutes posibilidades de cometer unerror y maacutes lugares doacutende se pueden esconder los errores

Una forma de reducir el tiempo de depuracioacuten es depurar por biseccioacuten Porejemplo si hay 100 liacuteneas en su programa y las revisa una a la vez seriacutean 100revisiones

Algoritmos 93

Es mejor tratar de dividir el problema en dos Busque en la mitad del programa oun valor intermedio que pueda verificar Agregue una sentencia de impresioacuten (oalgo que permita verificar) y ejecute el programa

Si esta verificacioacuten es incorrecta debe haber un problema en la primera mitaddel programa Si es correcta el problema estaacute en la segunda mitad

Cada vez que realiza una verificacioacuten como esta reduce a la mitad el nuacutemero deliacuteneas que debe revisar Despueacutes de seis pasos (que es mucho menos que 100) sereduciriacutea a una o dos liacuteneas de coacutedigo al menos en teoriacutea

En la praacutectica no siempre se conoce doacutende estaacute la mitad del programa y nosiempre es posible verificarlo No tiene sentido contar liacuteneas y encontrar el puntomedio exacto En su lugar piense en los lugares del programa donde puedehaber errores y en los lugares donde es faacutecil verificar Luego elija un lugar endonde usted crea que las posibilidades de encontrar un error antes o despueacutes deesta verificacioacuten son maacutes o menos las mismas

Glosarioasignacioacuten muacuteltiple

Asignar un nuevo valor a una variable que ya existe

actualizacioacutenAsignacioacuten donde el nuevo valor de la variable depende del antiguo

inicializacioacutenAsignacioacuten que le da un valor inicial a una variable que seraacute actualizada

incrementoActualizacioacuten que incrementa el valor de la variable (usualmente en 1)

decrementoActualizacioacuten que disminuye el valor de la variable (usualmente en 1)

iteracioacutenEjecucioacuten repetida de un conjunto de sentencias usando una funcioacutenrecursiva o un bucle

sentencia whileSentencia que permite iteraciones controladas por una condicioacuten

sentencia breakSentencia que permite salir de un bucle

94 Capiacutetulo 7 Iteracioacuten

sentencia continueSentencia localizada dentro de un bucle que obliga a iniciar una nuevaiteracioacuten desde el inicio del bucle

bucle infinitoUn bucle cuya condicioacuten de teacutermino no es satisfecha

algoritmoProceso general para resolver una categoriacutea de problemas

Ejercicios

Ejercicio 7-2

Copie el bucle de Seccioacuten 76 e inseacutertelo en una funcioacuten llamada miraiz que tomea como paraacutemetro elija un valor razonable de x y devuelva una estimacioacuten de laraiacutez cuadrada de a

Para probarla escriba una funcioacuten llamada probarraiz que imprima una tablacomo esta

a mysqrt sqrt diff- ------ ---- ----10 10 10 0020 1414213562373095 14142135623730951 2220446049250313e-1630 17320508075688772 17320508075688772 0040 20 20 0050 223606797749979 223606797749979 0060 2449489742783178 2449489742783178 0070 26457513110645907 26457513110645907 0080 282842712474619 28284271247461903 4440892098500626e-1690 30 30 00

La primera columna es un nuacutemero a la segunda columna es la raiacutez cuadrada dea calculada con miraiz la tercera columna es la raiacutez cuadrada calculada con lafuncioacuten integrada sqrt y la cuarta columna es el valor absoluto de la diferenciaentre las dos estimaciones

Exercise 7-3

La funcioacuten integrada Metaparse toma una cadena y la transforma en unaexpresioacuten Esta expresioacuten se puede evaluar en Julia con la funcioacuten Coreeval Porejemplo

Ejercicios 95

juliagt expr = Metaparse(1+23)(1 + 2 3)juliagt eval(expr)7juliagt expr = Metaparse(sqrt(π))(sqrt(π))juliagt eval(expr)17724538509055159

Escriba una funcioacuten llamada evalbucle que iterativamente solicite una entrada alusuario tome la entrada resultante la evaluacutee usando eval y pase posteriormentea imprimir el resultado Debe continuar hasta que el usuario ingrese listo y luegodevolver el valor de la uacuteltima expresioacuten que evaluoacute

Exercise 7-4

El matemaacutetico Srinivasa Ramanujan encontroacute una serie infinita que puede usarsepara generar una aproximacioacuten numeacuterica de

Escriba una funcioacuten llamada estimarpi que utilice esta foacutermula para calcular ydevolver una estimacioacuten de π Debe usar un ciclo while para calcular losteacuterminos de la suma hasta que el uacuteltimo teacutermino sea menor que 1e-15 (que es lanotacioacuten de Julia para ) Puede verificar el resultado comparaacutendolo con π

96 Capiacutetulo 7 Iteracioacuten

Capiacutetulo 8 CadenasLas cadenas son diferentes de los nuacutemeros enteros flotantes y booleanos Unacadena es una secuencia es decir una coleccioacuten ordenada de valores En estecapiacutetulo se veraacute coacutemo acceder a los caracteres que forman una cadena y seconoceraacuten algunas funciones integradas en Julia relacionadas con cadenas

CaracteresLos hispanohablantes estaacuten familiarizados con algunos caracteres tales como lasletras del alfabeto (A B C hellip) los nuacutemeros y los signos de puntuacioacuten comunesEstos caracteres estaacuten estandarizados en el coacutedigo ASCII (Coacutedigo EstaacutendarEstadounidense para el Intercambio de Informacioacuten)

Por supuesto hay muchos otros caracteres utilizados en idiomas distintos delespantildeol que no estaacuten en el coacutedigo ASCII tales como aquellos usados en losidiomas griego aacuterabe chino hebreo hindi japoneacutes y coreano

Definir queacute es un caraacutecter es altamente complejo La norma Unicode permiteabordar este problema y se considera como el estaacutendar definitivo para ello Estanorma funciona asignando un nuacutemero uacutenico para cada caraacutecter a nivel global

Un valor Char representa un uacutenico caraacutecter y estaacute entre comillas simples

juliagt xx ASCIIUnicode U+0078 (category Ll Letter lowercase)juliagt ἴἴ Unicode U+1F34C (category So Symbol other)juliagt typeof(x)Char

Incluso los emojis son parte del estaacutendar Unicode (banana TAB)

Una Cadena es una SecuenciaUna cadena es una secuencia de caracteres Se puede acceder a un caraacutecter conel operador corchete

juliagt fruta = bananabananajuliagt letra = fruta[1]b ASCIIUnicode U+0062 (category Ll Letter lowercase)

La segunda sentencia selecciona el caraacutecter nuacutemero 1 de fruta y la asigna a lavariable letra

Caracteres 97

La expresioacuten entre corchetes se llama indice El iacutendice indica el caraacutecter de lasecuencia a obtener (de ahiacute el nombre)

La indexacioacuten en Julia es base 1 es decir el primer elemento de cualquier objetoindexado con enteros estaacute en el iacutendice 1 y el uacuteltimo en el iacutendice end

juliagt fruta[end]a ASCIIUnicode U+0061 (category Ll Letter lowercase)

Como iacutendice se pueden usar expresiones que contengan variables y operadores

juliagt i = 11juliagt fruta[i+1]a ASCIIUnicode U+0061 (category Ll Letter lowercase)juliagt fruta[end-1]n ASCIIUnicode U+006E (category Ll Letter lowercase)

No obstante el valor del iacutendice tiene que ser un nuacutemero entero De lo contrariose obtiene

juliagt letra = fruta[15]ERROR MethodError no method matching getindex(String Float64)

lengthlength es una funcioacuten integrada que devuelve el nuacutemero de caracteres de unacadena

juliagt frutas = ἴ ἴ ἵἴ ἴ ἵjuliagt len = length(frutas)5

Para obtener la uacuteltima letra de una cadena puede sentirse tentado a probar algocomo esto

juliagt last = frutas[len] ASCIIUnicode U+0020 (category Zs Separator space)

Pero con esto no se obtiene el resultado esperado

Las cadenas se codifican usando codificacioacuten UTF-8 UTF-8 es una codificacioacutende longitud variable lo que significa que no todos los caracteres estaacuten

98 Capiacutetulo 8 Cadenas

codificados con el mismo nuacutemero de bytes

La funcioacuten sizeof devuelve el nuacutemero de bytes de una cadena

juliagt sizeof(ἴ)4

Dado que un emoji estaacute codificado en 4 bytes y la indexacioacuten de cadenas estaacutebasada en bytes el quinto elemento de frutas es un ESPACIO

Esto significa que no todos los iacutendices de byte de una cadena UTF-8 sonnecesariamente iacutendices vaacutelidos para un caraacutecter Si en una cadena se indexa conun iacutendice de bytes no vaacutelido se genera un error

juliagt frutas[2]ERROR StringIndexError(ἴ ἴ ἵ 2)

En el caso de frutas el caraacutecter ἴ es un caraacutecter de cuatro bytes por lo que losiacutendices 2 3 y 4 no son vaacutelidos y el iacutendice del siguiente caraacutecter es 5 el siguienteiacutendice vaacutelido se puede calcular con nextind(frutas 1) el subsiguiente connextind(frutas5) y asiacute sucesivamente

RecorridoMuchos caacutelculos implican procesar una cadena caraacutecter por caraacutecter A menudoempiezan por el principio seleccionan cada caraacutecter por turno hacen algo con eacutely continuacutean hasta el final Este patroacuten de proceso se llama recorrido Una formade escribir un recorrido es con una sentencia while

indice = firstindex(frutas)while indice lt= sizeof(frutas) letra = frutas[indice] println(letra) global indice = nextind(frutas indice)end

Este bucle recorre la cadena y muestra cada letra en una liacutenea distinta Lacondicioacuten del bucle es index lt= sizeof(fruta) de modo que cuando el iacutendice esmayor al nuacutemero de bytes en la cadena la condicioacuten es falsa y no se ejecuta elcuerpo del bucle

La funcioacuten firstindex devuelve el primer iacutendice de bytes vaacutelido La palabrareservada global antes de indice indica que queremos reasignar la variableindice definida en Main (ver Seccioacuten 117)

Recorrido 99

Ejercicio 8-1

Escriba una funcioacuten que tome una cadena como argumento y que muestre lasletras desde la uacuteltima a la primera una por liacutenea

Otra forma de escribir un recorrido es con un bucle for

for letra in frutas println(letra)end

Cada vez que se recorre el bucle se asigna a la variable letra el siguientecaraacutecter de la cadena El bucle continuacutea hasta que no quedan maacutes caracteres

El ejemplo siguiente muestra coacutemo usar la concatenacioacuten (multiplicacioacuten decadenas) y un bucle for para generar una serie abecedaria (es decir una seriecon elementos en orden alfabeacutetico) Por ejemplo en el libro de Robert McCloskeyMake Way for Ducklings los nombres de los patitos son Jack Kack Lack MackNack Ouack Pack y Quack Este bucle muestra esos nombres en orden

prefijos = JKLMNOPQsufijo = ack

for letra in prefijos println(letra sufijo)end

Output

JackKackLackMackNackOackPackQack

Por supuesto esto no es del todo correcto porque ldquoOuackrdquo y ldquoQuackrdquo no estaacutencorrectamente escritos

Ejercicio 8-2

Modifique este programa para solucionar este error

100 Capiacutetulo 8 Cadenas

Porciones de CadenasA la subcadena de una cadena se le llama porcioacuten La seleccioacuten de una porcioacuten essimilar a la seleccioacuten de un caraacutecter

juliagt str = Julio Cesar

juliagt str[15]Julio

El operador [nm] devuelve la parte de la cadena desde el n-eacutesimo byte hasta elm-eacutesimo Por lo tanto se siguen las mismas reglas que para la indexacioacuten simple

La palabra reservada end se puede usar para indicar al uacuteltimo byte de la cadena

juliagt str[7end]Cesar

Si el primer iacutendice es mayor que el segundo el resultado es una cadena vaciacutearepresentada por dos comillas

juliagt str[87]

Una cadena vaciacutea no contiene caracteres y tiene una longitud de 0 pero apartede eso es igual a cualquier otra cadena

Ejercicio 8-3

Continuando este ejemplo iquestqueacute cree que significa str[] Pruebe y veraacute

Las Cadenas son InmutablesEs tentador usar el operador [] en el lado izquierdo de una asignacioacuten con laintencioacuten de cambiar un caraacutecter en una cadena Por ejemplo

juliagt saludo = iexclHola mundoiexclHola mundojuliagt saludo[3] = JERROR MethodError no method matching setindex(String CharInt64)

Nota del traductor De acuerdo con la codificacioacuten de caracteres en utf-8 o latin-

Porciones de Cadenas 101

1 el caraacutecter de exclamacioacuten lsquoiexclrsquo en la variable saludo ocupa dos posiciones deahiacute que la letra lsquoHrsquo esteacute localizada en el iacutendice 3

La razoacuten del error es que las cadenas son inmutables lo que significa que no sepuede cambiar una cadena existente Lo maacuteximo que se puede hacer es crearuna nueva cadena que sea una variacioacuten de la original

juliagt saludo = iexclJ saludo[4end]iexclJola mundo

Este ejemplo concatena la apertura del signo de exclamacioacuten y una nuevaprimera letra a una porcioacuten de saludo Esta operacioacuten no tiene efecto sobre lacadena original

Interpolacioacuten de CadenasConstruir cadenas usando concatenacioacuten puede ser un poco engorroso Paradisminuir la necesidad de las llamadas a string o multiplicaciones repetidas Juliapermite la interpolacioacuten de cadenas usando $

juliagt saludo = iexclHolaiexclHolajuliagt paraquien = mundomundojuliagt $saludo $(paraquien)iexclHola mundo

Esto es maacutes entendible y conveniente que la concatenacioacuten de cadenas saludo paraquien

La expresioacuten inmediatamente siguiente a $ se toma como la expresioacuten cuyo valorse va a interpolar en la cadena Por lo tanto puede interpolar cualquierexpresioacuten en una cadena usando pareacutentesis

juliagt 1 + 2 = $(1 + 2)1 + 2 = 3

Buacutesqueda

iquestQueacute hace la siguiente funcioacuten

102 Capiacutetulo 8 Cadenas

function busqueda(palabra letra) indice = primerindice(palabra) while indice lt= sizeof(palabra) if palabra[indice] == letra return indice end indice = nextind(palabra indice) end -1end

En cierto sentido la funcioacuten buacutesqueda es lo contrario del operador [] En lugarde tomar un iacutendice y extraer el caraacutecter correspondiente toma un caraacutecter yencuentra el iacutendice donde aparece el caraacutecter Si el caraacutecter no se encuentra lafuncioacuten devuelve -1

Este es el primer ejemplo de una sentencia return dentro de un bucle Sipalabra[indice] == letra la funcioacuten devuelve inmediatamente el iacutendiceescapando del bucle prematuramente

Si el caraacutecter no aparece en la cadena entonces el programa sale del buclenormalmente y devuelve -1

Este patroacuten de computacioacuten se llama a veces un recorrido eureka porque tanpronto como encontramos lo que buscamos podemos gritar ldquoiexclEureka rdquo y dejarde buscar

Ejercicio 8-4

Modifique la funcioacuten busqueda para que tenga un tercer paraacutemetro el iacutendice depalabra donde deberiacutea comenzar a buscar

Iterando y contandoEl siguiente programa cuenta el nuacutemero de veces que aparece la letra a en unacadena

palabra = bananacontador = 0for letra in palabra if letra == a global contador = contador + 1 endendprintln(contador)

Iterando y contando 103

Este programa es otro ejemplo del patroacuten de computacioacuten llamado conteo Lavariable contador se inicializa en 0 y se incrementa cada vez que encuentra laletra a Cuando termina el bucle contador contiene el resultado (el nuacutemero totalde letras a)

Ejercicio 8-5

Coloque este coacutedigo en una funcioacuten llamada conteo y generaliacutecelo de tal maneraque tome como argumentos una cadena y una letra

Luego vuelva a escribir la funcioacuten para que en vez de revisar toda la cadenautilice la funcioacuten busqueda de tres paraacutemetros de la seccioacuten anterior

Libreriacutea con cadenasJulia tiene funciones integradas que realizan una variedad de operaciones uacutetilesen cadenas Por ejemplo la funcioacuten uppercase toma una cadena y devuelve unanueva cadena con todas las letras mayuacutesculas

juliagt uppercase(iexclHola mundo)iexclHOLA MUNDO

Existe una funcioacuten llamada findfirst que es notablemente similar a la funcioacutenbusqueda que escribimos

juliagt findfirst(a banana)22

La funcioacuten findfirst es maacutes general que la funcioacuten creada puede encontrarsubcadenas no solo caracteres

juliagt findfirst(na banana)34

Por defecto findfirst empieza la buacutesqueda al comienzo de la cadena pero lafuncioacuten findnext toma un tercer argumento el indice donde deberiacutea comenzar

juliagt findnext(na banana 4)56

El operador isinEl operador isin (in TAB) es un operador booleano que toma un caraacutecter y unacadena y devuelve true si el primero aparece en el segundo

104 Capiacutetulo 8 Cadenas

juliagt a isin banana a en bananatrue

Por ejemplo la siguiente funcioacuten imprime todas las letras de palabra1 quetambieacuten aparecen en palabra2

function ambas(palabra1 palabra2) for letra in palabra1 if letra isin palabra2 print(letra ) end endend

Una buena eleccioacuten de nombres de variables permite que Julia se pueda leercomo el espantildeol Este bucle puede leerse como para (cada) letra en (la primera)palabra si (la) letra es un elemento de (la segunda) palabra imprima (la) letra

Esto es lo que se obtiene si se compara manzanas y naranjas

juliagt ambas(manzanas naranjas)a n a n a s

Comparacioacuten de CadenasLos operadores de comparacioacuten trabajan sobre cadenas Para ver si dos cadenasson iguales

palabra = Pintildeaif palabra == banana println(iexclTenemos bananas)end

Otras operaciones de comparacioacuten son uacutetiles para ordenar alfabeacuteticamentepalabras

if palabra lt banana println(Su palabra $palabra va antes de banana)elseif word gt banana println(Su palabra $palabra va antes de banana)else println(iexclTenemos bananas)end

Comparacioacuten de Cadenas 105

Julia no maneja las letras mayuacutesculas y minuacutesculas del mismo modo que sonmanejadas en cualquier lengua hablada Todas las letras mayuacutesculas van antesde las letras minuacutesculas seguacuten el estaacutendar de codificacioacuten Por lo tanto

Su palabra Pintildea va antes de banana

OBSERVACIOacuteNUna forma comuacuten de abordar este problema es convertirlas cadenas a un formato estaacutendar como por ejemplo aminuacutesculas antes de realizar la comparacioacuten

DepuracioacutenCuando se usan iacutendices para recorrer los valores en una secuencia es difiacutecilacceder al principio y al final del recorrido Aquiacute hay una funcioacuten que comparados palabras y devuelve true si una de las palabras es el reverso de la otra perocontiene dos errores

function espalindroma(palabra1 palabra2) if length(palabra1) = length(palabra2) return false end i = firstindex(palabra1) j = lastindex(palabra2) while j gt= 0 j = prevind(palabra2 j) if palabra1[i] = palabra2[j] return false end i = nextind(palabra1 i) end trueend

La primera sentencia if verifica si las palabras tienen la misma longitud Si no sedevuelve false inmediatamente De lo contrario para el resto de la funcioacuten sepuede suponer que las palabras tienen la misma longitud Este es un ejemplo delpatroacuten guardiaacuten

i y j son iacutendices i recorre palabra1 de derecha a izquierda mientras que j recorrepalabra2 de izquierda a derecha Si dos letras no coinciden se devuelve falseinmediatamente Si el ciclo termina y todas las letras coinciden se devuelve true

La funcioacuten lastindex devuelve el uacuteltimo iacutendice de bytes vaacutelido de una cadena yprevind el iacutendice vaacutelido anterior a un caraacutecter

Si se prueba esta funcioacuten con las palabras amor y roma se espera el valor de

106 Capiacutetulo 8 Cadenas

retorno true pero se obtiene false

juliagt espalindroma(amor roma)false

Para depurar este tipo de error primeramente se imprimen los valores de losiacutendices

espalindroma (generic function with 1 method)

Ahora al ejecutar el programa se obtiene maacutes informacioacuten

juliagt espalindroma(amor roma)i = 1j = 3false

En la primera iteracioacuten del bucle el valor de j es 3 pero tendriacutea que ser 4 Estose puede solucionar trasladando la liacutenea j = prevind (palabra2 j) al final del ciclowhile

Si se soluciona ese error y se ejecuta el programa nuevamente se obtiene

espalindroma (generic function with 1 method)

juliagt espalindroma(amor roma)i = 1j = 4i = 2j = 3i = 3j = 2i = 4j = 1i = 5j = 0ERROR BoundsError attempt to access String at index [5]

Esta vez se ha producido un BoundsError El valor de i es 5 que estaacute fuera delrango de la cadena amor

Depuracioacuten 107

Ejercicio 8-6

Ejecute el programa en papel cambiando los valores de i y j durante cadaiteracioacuten Encuentre y arregle el segundo error en esta funcioacuten

Glosariosecuencia

Una coleccioacuten ordenada de valores donde cada valor se identifica medianteun iacutendice entero

coacutedigo ASCIICoacutedigo de caracteres estaacutendar para el intercambio de informacioacuten

norma UnicodeUn estaacutendar en la industria informaacutetica para la codificacioacuten representacioacuteny manejo consistentes de texto en la mayoriacutea de los sistemas de escrituradel mundo

iacutendiceUn valor entero usado para seleccionar un miembro de un conjuntoordenado como puede ser un caraacutecter de una cadena En Julia los iacutendicescomienzan en 1

codificacioacuten UTF-8Una codificacioacuten de caracteres de longitud variable capaz de codificar todoslos 1112064 puntos de coacutedigo vaacutelidos en Unicode utilizando de uno a cuatrobytes de 8 bits

recorrerIterar sobre los elementos de un conjunto realizando una operacioacuten similaren cada uno de ellos

porcioacutenUna parte de una cadena especificada mediante un rango de iacutendices

cadena vaciacuteaUna cadena sin caracteres y longitud 0 representada por dos comillas

immutableLa propiedad de una secuencia que hace que a sus elementos no se lespueda asignar nuevos valores

interpolacioacuten de cadenasEl proceso de evaluar una cadena que contiene uno o maacutes marcadores de

108 Capiacutetulo 8 Cadenas

posicioacuten produciendo un resultado en el que los marcadores de posicioacuten sereemplazan con sus valores correspondientes

buacutesquedaUn patroacuten de recorrido que se detiene cuando encuentra lo que estaacutebuscando

contadorUna variable utilizada para contar algo generalmente inicializada en cero yluego incrementada

Ejercicios

Ejercicio 8-7

Lea la documentacioacuten de las funciones relacionadas con cadenas enhttpsdocsjulialangorgenv1manualstrings Es posible que desee probaralgunas de ellas para asegurarse de comprender coacutemo funcionan strip y replaceson particularmente uacutetiles

La documentacioacuten utiliza una sintaxis que puede ser confusa Por ejemplo ensearch(cadenaAbstractString caracterChars [comienzoInteger]) loscorchetes indican argumentos opcionales Por lo tanto cadena y caracter sonobligatorios pero comienzo es opcional

Ejercicio 8-8

Hay una funcioacuten integrada llamada count que es similar a la funcioacuten en Seccioacuten89 Lea la documentacioacuten de esta funcioacuten y uacutesela para contar el nuacutemero deletras a en banana

Ejercicio 8-9

Una porcioacuten de cadena puede tomar un tercer iacutendice El primero especifica elinicio el tercero el final y el segundo el tamantildeo del paso es decir el nuacutemero deespacios entre caracteres sucesivos Un tamantildeo de paso de 2 significa cada uncaracter 3 significa cada dos etc

juliagt fruta = bananabananajuliagt fruta[126]bnn

Un tamantildeo de paso de -1 recorre la palabra hacia la izquierda por lo que laporcioacuten [end-11] genera una cadena invertida

Ejercicios 109

Use esto para escribir una versioacuten de una liacutenea de coacutedigo de espalindroma deSeccioacuten 6113

Exercise 8-10

Las siguientes funciones estaacuten destinadas a verificar si una cadena contieneletras minuacutesculas pero algunas de ellas son incorrectas Para cada funcioacutendescriba queacute hace realmente la funcioacuten (suponiendo que el paraacutemetro es unacadena)

110 Capiacutetulo 8 Cadenas

function cualquierminuscula1(s) for c in s if islowercase(c) return true else return false end endend

function cualquierminuscula2(s) for c in s if islowercase(c) return true else return false end endend

function cualquierminuscula3(s) for c in s bandera = islowercase(c) end flagend

function cualquierminuscula4(s) bandera = false for c in s bandera = bandera || islowercase(c) end flagend

function cualquierminuscula5(s) for c in s if islowercase(c) return false end end trueend

Exercise 8-11

Un cifrado Ceacutesar es una forma simple de cifrado que implica desplazar cada letraun nuacutemero fijo de lugares Desplazar una letra significa reemplazarla por otra

Ejercicios 111

letra que se encuentra un nuacutemero fijo de posiciones maacutes adelante en el alfabetoEs posible desplazarse hasta el principio del abecedario si fuera necesario Deesta manera con un desplazamiento de 3 A es D y con un desplazamiento de1 Z es A

Para desplazar una palabra desplace cada letra en la misma cantidad Porejemplo con un desplazamiento de 6 ABCDEF es GHIJKL y con undesplazamiento de -6 BCDE es VWXY En la peliacutecula 2001 Una odisea delespacio la computadora de la nave se llama HAL que es IBM desplazada por -1

Escriba una funcioacuten llamada desplazarpalabra que tome una cadena y un nuacutemeroentero como paraacutemetros y devuelva una nueva cadena que contenga las letrasde la cadena original desplazadas por la cantidad dada

OBSERVACIOacuteN

Es posible que desee utilizar la funcioacuten integrada Intque convierte un caraacutecter en un coacutedigo numeacuterico yChar que convierte los coacutedigos numeacutericos encaracteres Las letras del alfabeto estaacuten codificadas enorden alfabeacutetico por ejemplo

juliagt Int(c) - Int(a)2

Porque c es la tercera letra del alfabeto Pero cuidadolos coacutedigos numeacutericos para las letras mayuacutesculas sondiferentes

juliagt Char(Int(A) + 32)a ASCIIUnicode U+0061 (category Ll Letterlowercase)

Algunos chistes ofensivos en Internet estaacuten codificados en ROT13 que es uncifrado Ceacutesar con desplazamiento 13 Si no se ofende faacutecilmente encuentre ydecodifice algunos de ellos

112 Capiacutetulo 8 Cadenas

Capiacutetulo 9 Estudio de Caso Juego de PalabrasEste capiacutetulo presenta un segundo estudio de caso que consiste en resolverpuzzles buscando palabras que tengan ciertas propiedades Por ejemplo sebuscaraacuten palabras cuyas letras aparezcan en orden alfabeacutetico Ademaacutes sepresentaraacute otra forma de desarrollar programas la reduccioacuten a un problemapreviamente resuelto

Leer listas de palabrasPara los ejercicios de este capiacutetulo se necesita una lista de palabras en espantildeolHay muchas listas de palabras disponibles en la Web pero la maacutes adecuada paranuestro propoacutesito es una de las listas de palabras recopiladas y contribuidas aldominio puacuteblico por Ismael Olea (see httpoleaorgproyectoslemarios) Estalista de 87900 palabras se encuentra en la paacutegina de Olea con el nombre dearchivo lemario-general-del-espanoltxt Tambieacuten es posible descargar una copiadesde httpsgithubcomJuliaIntroIntroAJuliajlblobmasterdatapalabrastxt

Este archivo es un archivo de texto simple por lo que puede ser abierto con uneditor de texto o leiacutedo con Julia La funcioacuten integrada open toma el nombre delarchivo como paraacutemetro y devuelve un objeto archivo que puede ser usado parala lectura del archivo

IOStream(ltfilehometravisbuildJuliaIntroIntroAJuliajlsrcdatapalabrastxtgt)

juliagt fin = open(palabrastxt)IOStream(ltfile palabrastxtgt)

fin es un objeto archivo que puede ser utilizado como entrada y cuando se dejade utilizar debe cerrarse con close(fin)

Julia tiene integradas varias funciones de lectura entre ellas readline que lee loscaracteres del archivo hasta que llega a un salto de liacutenea devolviendo elresultado como una cadena

juliagt readline(fin)a

La primera palabra en esta lista particular es a que indica direccioacuten intervalode tiempo finalidad entre otros

El objeto archivo lleva registro de doacutende quedoacute por uacuteltima vez por lo que sillama a readline nuevamente se obtendraacute la siguiente palabra

Leer listas de palabras 113

juliagt readline(fin)a-

La siguiente palabra es a- que es un prefijo que indica privacioacuten

Tambieacuten se puede usar un archivo como parte de un bucle for El siguienteprograma lee palabrastxt e imprime cada palabra una por liacutenea

for line in eachline(palabrastxt) println(line)end

Ejercicios

Ejercicio 9-1

Escriba un programa que lea palabrastxt e imprima solo las palabras con maacutes de20 caracteres (sin contar espacios en blanco)

Ejercicio 9-2

En 1927 Enrique Jardiel Poncela publicoacute cinco historias cortas omitiendo encada una de ellas una vocal Estas historias incluyen El Chofer Nuevonarracioacuten escrita sin la letra a y Un marido sin vocacioacuten sin la letra e Dadoque la letra e es la maacutes frecuente del espantildeol esto no es faacutecil de lograr

De hecho es difiacutecil pensar oraciones que no utilicen esta letra Intentarlo escomplicado pero con la praacutectica se vuelve maacutes faacutecil

Bueno volviendo al tema importante

Escriba una funcioacuten llamada notiene_e que devuelva true si una palabra dada notiene la letra e

Modifique su programa de la seccioacuten anterior para que imprima solo las palabrasque no tienen e y que ademaacutes calcule el porcentaje de palabras en la lista queno tengan e

Ejercicio 9-3

Escriba una funcioacuten llamada evitar que tome como argumentos una palabra yuna cadena de letras prohibidas y que devuelva true si la palabra no usaninguna de las letras prohibidas

Modifique su programa de la seccioacuten anterior para solicitar al usuario queingrese una cadena de letras prohibidas y que luego imprima el nuacutemero de

114 Capiacutetulo 9 Estudio de Caso Juego de Palabras

palabras que no contengan ninguna de ellas iquestEs posible encontrar unacombinacioacuten de 5 letras prohibidas que excluya la menor cantidad de palabras

Ejercicio 9-4

Escriba una funcioacuten llamada usasolo que tome una palabra y una cadena deletras y que devuelva true si la palabra contiene solo letras de la lista iquestPuedehacer una oracioacuten usando solo las letras oneacmil Aparte de iquestEl camino

Ejercicio 9-5

Escriba una funcioacuten llamada usatodo que tome una palabra y una cadena deletras y que devuelva true si la palabra usa todas las letras requeridas al menosuna vez iquestCuaacutentas palabras usan todas las vocales aeiou

Ejercicio 9-6

Escriba una funcioacuten llamada esabecedaria que devuelva true si las letras de unapalabra aparecen en orden alfabeacutetico iquestCuaacutentas palabras de este tipo hay

BuacutesquedaTodos los ejercicios en la seccioacuten anterior tienen algo en comuacuten se puedenresolver con el patroacuten de buacutesqueda El ejemplo maacutes simple es

function notiene_e(palabra) for letra in palabra if letra == e return false end end trueend

El bucle for recorre los caracteres de palabra Si encontramos la letra e puededevolver inmediatamente false de lo contrario hay que pasar a la siguiente letraSi se sale del bucle normalmente eso significa que no se encontroacute una e por loque la funcioacuten devuelve true

Esta funcioacuten podriacutea ser escrita de manera maacutes concisa usando el operador notin(notin TAB) pero se comienza con esta versioacuten porque muestra la loacutegica delpatroacuten de buacutesqueda

evita es una versioacuten maacutes general de notiene_e pero tiene la misma estructura

Buacutesqueda 115

function evita(palabra prohibidas) for letra in palabra if letter isin prohibidas return false end end trueend

Se devuelve false tan pronto como se encuentre una letra prohibida si llegamosal final del ciclo se devuelve true

usasolo es similar excepto que el sentido de la condicioacuten se invierte

function usasolo(palabra disponibles) for letra in palabra if letra notin disponibles return false end end trueend

En vez de un conjunto de letras prohibidas se tiene un conjunto de letrasdisponibles Si se encuentra una letra en palabra que no estaacute en disponible sedevuelve false

usatodo es similar excepto que se invierte el papel de la palabra y la cadena deletras

function usatodo(palabra requeridas) for letra in requeridas if letra notin palabra return false end end trueend

En lugar de recorrer las letras de la palabra el bucle recorre las letrasrequeridas Si alguna de las letras requeridas no aparece en la palabra sedevuelve false

Si se pensara como un informaacutetico se reconoceriacutea que usatodo es una instanciade un problema previamente resuelto y se podriacutea haber escrito

116 Capiacutetulo 9 Estudio de Caso Juego de Palabras

function usatodo(palabra requeridas) usasolo(requeridas palabra)end

Este es un ejemplo de una forma de desarrollar programas llamada reduccioacuten aun problema resuelto previamente lo que significa que se reconoce el problemaen el que se estaacute trabajando como una instancia de un problema ya resuelto y seaplica la solucioacuten existente

Bucle con iacutendicesLas funciones de la seccioacuten anterior fueron escritas con ciclos for porque solo senecesitaban los caracteres en las cadenas y no hubo necesidad de trabajar conlos iacutendices

Para esabecedaria tenemos que comparar letras adyacentes lo cual es un pococomplicado con un ciclo for

function esabecedaria(palabra) i = firstindex(palabra) previa = palabra[i] j = nextind(palabra i) for c in palabra[jend] if c lt previa return false end previa = c end trueend

Otra alternativa es usar recursividad

function esabecedaria(palabra) if length(palabra) lt= 1 return true end i = firstindex(palabra) j = nextind(palabra i) if palabra[i] gt palabra[j] return false end esabecedaria(palabra[jend])end

Una tercera opcioacuten es usar un ciclo while

Bucle con iacutendices 117

function esabecedaria(palabra) i = firstindex(palabra) j = nextind(palabra 1) while j lt= sizeof(palabra) if palabra[j] lt palabra[i] return false end i = j j = nextind(palabra i) end trueend

El ciclo comienza en i=1 y j=nextind(palabra 1) y termina cuandojgtsizeof(palabra) En cada iteracioacuten se compara el caraacutecter ieacutesimo (que sepuede considerar como el caraacutecter actual) con el caraacutecter jeacutesimo (que se puedeconsiderar como el siguiente)

Si el siguiente caraacutecter es menor (va antes en el alfabeto) que el actual entoncesla palabra no tiene sus letras en orden alfabeacutetico y se devuelve false

Si se llega al final del ciclo sin encontrar letras que imposibiliten el ordenalfabeacutetico entonces la palabra pasa la prueba Para convencerse de que el ciclotermina correctamente considere como ejemplo la palabra Abel

A continuacioacuten se muestra una versioacuten de espalindromo que usa dos iacutendices unocomienza al principio de la palabra y aumenta su valor y el otro comienza al finaly disminuye su valor

function espalindromo(palabra) i = firstindex(palabra) j = lastindex(palabra) while iltj if palabra[i] = palabra[j] return false end i = nextind(palabra i) j = prevind(palabra j) end trueend

O podriacuteamos reducir este problema a uno previamente resuelto y escribir

118 Capiacutetulo 9 Estudio de Caso Juego de Palabras

function espalindromo(palabra) isreverse(palabra palabra)end

Usando esreverso de Seccioacuten 813

DepuracioacutenComprobar el correcto funcionamiento de los programas es difiacutecil Las funcionesde este capiacutetulo son relativamente faacuteciles de probar porque se pueden verificarlos resultados a mano Aun asiacute es casi imposible elegir un conjunto de palabrasque permitan evaluar todos los posibles errores

Tomando notiene_e como ejemplo hay dos casos obvios que verificar laspalabras que tienen una e deberiacutean devolver false y las palabras que nodeberiacutean devolver true No deberiacutean haber problemas para encontrar un ejemplode cada uno

Dentro de cada caso hay algunos subcasos menos obvios Entre las palabras quetienen una e se deben probar las palabras con una e al principio al final y almedio Ademaacutes se deben probar palabras largas cortas y muy cortas como unacadena vaciacutea La cadena vaciacutea es un ejemplo de un caso especial no obviodonde pueden originarse errores

Ademaacutes de las instancias de prueba generadas tambieacuten puede probar suprograma con una lista de palabras como palabrastxt Al escanear el resultadoes posible que pueda detectar errores pero tenga cuidado puede detectar untipo de error (palabras que no deberiacutean incluirse pero lo estaacuten) y no otro(palabras que deberiacutean incluirse pero no lo estaacuten)

Por lo general las pruebas pueden ayudarlo a encontrar errores pero no es faacutecilgenerar un buen conjunto de instancias de prueba e incluso si lo hace no puedeestar seguro de que su programa sea correcto Seguacuten un informaacutetico muyfamoso

Las pruebas de programa se pueden usar para mostrar la presencia deerrores iexclpero nunca para mostrar su ausencia

mdash Edsger W Dijkstra

Glosarioobjeto archivo o file stream

Un valor que representa un archivo abierto

Depuracioacuten 119

reduccioacuten a un problema previamente resueltoUna manera de resolver un problema expresaacutendolo como una instancia deun problema previamente resuelto

caso especialUna instancia de prueba que es atiacutepica o no obvia (y por lo tanto menosprobable que se maneje correctamente)

Ejercicios

Ejercicio 9-7

Esta pregunta se basa en un Puzzle que se transmitioacute en el programa de radioCar Talk (httpswwwcartalkcompuzzlerbrowse)

Se tiene una secuencia de nuacutemeros y se desea saber cuaacutel es el siguiente Losnuacutemeros son 4 6 12 18 30 42 60 y luego X

Pista 1 Todos los nuacutemeros de la secuencia son pares Pista 2 El nuacutemero queva despueacutes del que estoy buscando es 102

iquestCuaacutel es el nuacutemero

Primero piense el patroacuten que busca y luego escriba un programa que le permitaencontrar el nuacutemero que sigue este patroacuten que se encuentra entre 60 y 102

Ejercicio 9-8

A continuacioacuten se muestra otro puzzle de Car Talk (httpswwwcartalkcompuzzlerbrowse)

120 Capiacutetulo 9 Estudio de Caso Juego de Palabras

Estaba conduciendo por la autopista el otro diacutea y vi mi odoacutemetro Como lamayoriacutea de los odoacutemetros muestra seis diacutegitos y solo en kiloacutemetros enterosEntonces si mi automoacutevil tuviera un kilometraje de 300000 por ejemploseriacutea 3-0-0-0-0-0

Ahora lo que vi ese diacutea fue muy interesante Noteacute que los uacuteltimos 4 diacutegitoseran palindroacutemicos es decir se leiacutean igual hacia adelante que hacia atraacutesPor ejemplo 5-4-4-5 es un paliacutendromo por lo que mi odoacutemetro podriacuteahaberse leiacutedo 3-1-5-4-4-5

Un kiloacutemetro despueacutes los uacuteltimos 5 nuacutemeros fueron palindroacutemicos Porejemplo podriacutea haberse leiacutedo 3-6-5-4-5-6 Un kiloacutemetro despueacutes de eso los 4nuacutemeros del medio eran palindroacutemicos iquestYhellip estaacutes listo para esto iexclUnkiloacutemetro despueacutes los 6 eran palindroacutemicos

La pregunta es iquestqueacute nuacutemero estaba en el odoacutemetro cuando mireacute porprimera vez

Escriba un programa de Julia que pruebe todos los nuacutemeros de seis diacutegitos eimprima cualquier nuacutemero que satisfaga estos requisitos

Ejercicio 9-9

Aquiacute hay otro puzzle de Car Talk que puede resolver con una buacutesqueda(httpswwwcartalkcompuzzlerbrowse)

Hace poco visiteacute a mi madre y nos dimos cuenta de que los dos diacutegitos quecomponen mi edad cuando se invertiacutean daban como resultado su edad Porejemplo si tiene 73 antildeos yo tengo 37 Nos preguntamos con queacute frecuenciaesto ha sucedido a lo largo de los antildeos pero nos desviamos de otros temas ynunca obtuvimos una respuesta

Cuando llegueacute a casa descubriacute que los diacutegitos de nuestras edades han sidoreversibles seis veces hasta ahora Tambieacuten descubriacute que si teniacuteamos suertevolveriacutea a suceder en unos antildeos y si tenemos mucha suerte sucederiacutea unavez maacutes despueacutes de eso En otras palabras habriacutea sucedido 8 vecesEntonces la pregunta es iquestcuaacutentos antildeos tengo ahora

Escriba un programa de Julia que busque soluciones para este puzzle

OBSERVACIOacuteN Puede encontrar la funcioacuten lpad uacutetil

Ejercicios 121

Capiacutetulo 10 ArreglosEste capiacutetulo presenta uno de los tipos maacutes uacutetiles de Julia los arreglos Tambieacutense trataraacuten objetos y lo que puede suceder cuando se tiene maacutes de un nombrepara el mismo objeto

Un arreglo es una secuenciaAl igual que una cadena de texto un arreglo es una secuencia de valores En unacadena los valores son caracteres en un arreglo pueden ser de cualquier tipoLos valores en un arreglo se denominan elementos o a veces items

Hay varias formas de crear un nuevo arreglo la maacutes sencilla es encerrar loselementos entre corchetes ([ ])

[10 20 30 40][abadejo falsiacutea estrambote]

El primer ejemplo es un arreglo de cuatro enteros El segundo es un arreglo detres cadenas de texto Los elementos de un arreglo no tienen por queacute ser delmismo tipo El siguiente arreglo contiene una cadena un nuacutemero de puntoflotante un entero y otro arreglo

[spam 20 5 [10 20]]

Se dice que un arreglo dentro de otro arreglo estaacute anidado

Un arreglo que no contiene elementos se llama arreglo vaciacuteo y se puede crearuno con corchetes vaciacuteos []

Como es de esperar se pueden asignar valores de arreglos a variables

juliagt quesos = [Cheddar Edam Gouda]

juliagt numeros = [42 123]

juliagt vacio = []

juliagt print(quesos numeros vacio)[Cheddar Edam Gouda] [42 123] Any[]

La funcioacuten typeof se puede usar para conocer el tipo del arreglo

122 Capiacutetulo 10 Arreglos

juliagt typeof(quesos)ArrayString1juliagt typeof(numeros)ArrayInt641juliagt typeof(vacio)ArrayAny1

El tipo del arreglo se especifica entre llaves y se compone de un tipo y unnuacutemero El nuacutemero indica las dimensiones El conjunto vaciacuteo contiene valores detipo Any es decir puede contener valores de todos los tipos

Los arreglos son mutablesLa sintaxis para acceder a los elementos de un arreglo es el mismo que paraacceder a los caracteres de una cadena el operador corchete La expresioacutendentro de los corchetes especifica el iacutendice Recuerde que los iacutendices comienzanen 1

juliagt quesos[1]Cheddar

A diferencia de las cadenas los arreglos son mutables lo que significa quepodemos cambiar sus elementos Se puede modificar uno de sus elementosusando el operador corchetes en el lado izquierdo de una asignacioacuten

juliagt numeros[2] = 55juliagt print(numeros)[42 5]

El segundo elemento de numeros que era 123 ahora es 5

Figura 11 muestra los diagramas de estado para quesos numeros y vacio

Figura 11 Diagrama de estado

Los arreglos son representados mediante cuadros con elementos del arreglo en

Los arreglos son mutables 123

su interior El arreglo quesos hace referencia a un arreglo con tres elementosindexados 1 2 y 3 El arreglo numeros contiene dos elementos El diagramamuestra que el valor del segundo elemento de numeros se ha reasignado de 123a 5 Finalmente vacio hace referencia a un arreglo sin elementos

Los iacutendices de un arreglo funcionan de la misma manera que los iacutendices de unacadena (pero sin los problemas generados por la codificacioacuten UTF-8)

bull Cualquier expresioacuten entera se puede usar como iacutendice

bull Si se intenta leer o escribir un elemento que no existe se obtiene unBoundsError

bull La palabra reservada end indica el uacuteltimo iacutendice del arreglo

El operador isin tambieacuten funciona en arreglos

juliagt Edam isin quesostruejuliagt Brie in quesosfalse

Recorriendo un ArregloLa forma maacutes comuacuten de recorrer los elementos de un arreglo es con un ciclo forLa sintaxis es la misma que para las cadenas

for queso in quesos println(queso)end

Esto funciona bien si solo se necesita leer los elementos del arreglo pero si sedesea escribir o actualizar los elementos es necesario utilizar iacutendices Una formacomuacuten de hacerlo es usando la funcioacuten integrada eachindex

for i in eachindex(numeros) numeros[i] = numeros[i] 2end

Este bucle recorre el arreglo y actualiza cada elemento En cada iteracioacuten delciclo i representa el iacutendice del elemento actual La sentencia de asignacioacuten usanumeros[i] para leer el valor original del elemento y asignar el nuevo valor

Por otra parte length devuelve el nuacutemero de elementos en el arreglo

Un ciclo for sobre un arreglo vaciacuteo nunca ejecuta el cuerpo del bucle

124 Capiacutetulo 10 Arreglos

for x in [] println(Esto nunca pasa)end

Aunque un arreglo puede contener otro arreglo este arreglo anidado cuentacomo un elemento uacutenico Por ejemplo la longitud de este arreglo es cuatro

[spam 1 [Brie Roquefort Camembert] [1 2 3]]

Porciones de arreglos

El operador porcioacuten tambieacuten funciona en arreglos

juliagt t = [a b c d e f]

juliagt print(t[13])[a b c]juliagt print(t[3end])[c d e f]

El operador porcioacuten [] hace una copia de todo el arreglo

juliagt print(t[])[a b c d e f]

Como los arreglos son mutables es uacutetil hacer una copia antes de realizaroperaciones que las modifiquen

Un operador porcioacuten en el lado izquierdo de una asignacioacuten puede actualizarvarios elementos

juliagt t[23] = [x y]

juliagt print(t)[a x y d e f]

Libreriacutea de ArreglosJulia tiene funciones integradas que operan en arreglos Por ejemplo pushagrega un nuevo elemento al final de un arreglo

Porciones de arreglos 125

juliagt t = [a b c]

juliagt push(t d)

juliagt print(t)[a b c d]

append agrega elementos de un arreglo al final de otro

juliagt t1 = [a b c]

juliagt t2 = [d e]

juliagt append(t1 t2)

juliagt print(t1)[a b c d e]

En este ejemplo t2 no es modificado

sort ordena los elementos de un arreglo de menor a mayor

juliagt t = [d c e b a]

juliagt sort(t)

juliagt print(t)[a b c d e]

sort devuelve una copia ordenada de los elementos de un arreglo

juliagt t1 = [d c e b a]

juliagt t2 = sort(t1)

juliagt print(t1)[d c e b a]juliagt print(t2)[a b c d e]

NOTA Como convencioacuten en Julia se agrega a los nombres de lasfunciones que modifican sus argumentos

126 Capiacutetulo 10 Arreglos

Mapear Filtrar y ReducirPara sumar todos los nuacutemeros en un arreglo se puede usar un ciclo como este

function sumartodo(t) total = 0 for x in t total += x end totalend

total se inicializa en 0 En cada iteracioacuten con += se antildeade un elemento delarreglo a la suma total El operador += es una forma simple de actualizar estavariable Esta sentencia de asignacioacuten aumentada

total += x

es equivalente a

total = total + x

A medida que se ejecuta el ciclo total acumula la suma de los elementos A vecesse denomina acumulador a una variable utilizada de esta manera

Sumar los elementos de un arreglo es una operacioacuten tan comuacuten que Julia tieneuna funcioacuten integrada para ello sum

juliagt t = [1 2 3 4]

juliagt sum(t)10

Una operacioacuten como esta que combina una secuencia de elementos en un solovalor a veces se denomina operacioacuten de reduccioacuten

Es comuacuten querer recorrer un arreglo mientras se construye otro Por ejemplo lasiguiente funcioacuten toma un arreglo de cadenas y devuelve un nuevo arreglo quecontiene las mismas cadenas pero en mayuacutesculas

Mapear Filtrar y Reducir 127

function todoenmayusculas(t) res = [] for s in t push(res uppercase(s)) end resend

res se inicializa con un arreglo vaciacuteo y en cada iteracioacuten se le agrega un nuevoelemento De esta manera res es otro tipo de acumulador

Una operacioacuten como todoenmayusculas a veces se denomina mapeo porqueasigna una funcioacuten (en este caso uppercase) a cada uno de los elementos deuna secuencia

Otra operacioacuten comuacuten es seleccionar solo algunos de los elementos de un arregloy devolver una sub-arreglo Por ejemplo la siguiente funcioacuten toma un arreglo decadenas y devuelve un arreglo que contiene solamente las cadenas enmayuacutesculas

function solomayusculas(t) res = [] for s in t if s == uppercase(s) push(res s) end end resend

Operaciones como solomayusculas se llaman filtro porque seleccionan soloalgunos elementos filtrando otros

Las operaciones de arreglos maacutes comunes son una combinacioacuten de mapeo filtroy reduccioacuten

Sintaxis de puntoPara cada operador binario como por ejemplo ^ existe un operador puntocorrespondiente ^ que automaacuteticamente define la operacioacuten ^ para cadaelemento de un arreglo Por ejemplo [1 2 3] ^ 3 no estaacute definido pero [12 3] ^ 3 se define como el resultado de realizar la operacioacuten ^ en cadaelemento [1^3 2^3 3^3]

128 Capiacutetulo 10 Arreglos

juliagt print([1 2 3] ^ 3)[1 8 27]

Cualquier funcioacuten f de Julia puede ser aplicada a cada elemento de cualquierarreglo con la sintaxis de punto Por ejemplo para poner en mayuacutesculas unarreglo de cadenas no es necesario un bucle expliacutecito

juliagt t = uppercase([abc def ghi])

juliagt print(t)[ABC DEF GHI]

Esta es una forma elegante de crear un mapeo Siguiendo esta loacutegica la funcioacutentodoenmayusculas puede implementarse con una liacutenea

function todoenmayusculas(t) uppercase(t)end

Borrando (Insertando) ElementosHay varias formas de eliminar elementos de un arreglo Si se conoce el iacutendice delelemento que se desea eliminar se puede usar splice

juliagt t = [a b c]

juliagt splice(t 2)b ASCIIUnicode U+0062 (category Ll Letter lowercase)juliagt print(t)[a c]

splice modifica el arreglo y devuelve el elemento que se eliminoacute

pop elimina y devuelve el uacuteltimo elemento

juliagt t = [a b c]

juliagt pop(t)c ASCIIUnicode U+0063 (category Ll Letter lowercase)juliagt print(t)[a b]

popfirst elimina y devuelve el primer elemento

Borrando (Insertando) Elementos 129

juliagt t = [a b c]

juliagt popfirst(t)a ASCIIUnicode U+0061 (category Ll Letter lowercase)juliagt print(t)[b c]

Las funciones pushfirst y push insertan un elemento al principio y al final delarreglo respectivamente

Si no se necesita el valor eliminado se puede usar la funcioacuten deleteat

juliagt t = [a b c]

juliagt print(deleteat(t 2))[a c]

La funcioacuten insert inserta un elemento en un iacutendice dado

juliagt t = [a b c]

juliagt print(insert(t 2 x))[a x b c]

Arreglos y CadenasUna cadena es una secuencia de caracteres y un arreglo es una secuencia devalores pero un arreglo de caracteres no es lo mismo que una cadena Paraconvertir una cadena a un arreglo de caracteres se puede usar la funcioacutencollect

juliagt t = collect(spam)

juliagt print(t)[s p a m]

La funcioacuten collect divide una cadena u otra secuencia en elementos individuales

Si desea dividir una cadena en palabras puede usar la funcioacuten split

juliagt t = split(En un lugar de la Mancha)

juliagt print(t)SubStringString[En un lugar de la Mancha]

130 Capiacutetulo 10 Arreglos

Un argumento opcional llamado delimitador especifica queacute caracteres usar comoliacutemites de palabra El siguiente ejemplo usa un guioacuten como delimitador

juliagt t = split(hola-hola-hola -)

juliagt print(t)SubStringString[hola hola hola]

join es el inverso de split Toma un arreglo de cadenas y concatena loselementos

juliagt t = [En un lugar de la Mancha]

juliagt s = join(t )En un lugar de la Mancha

En este caso el delimitador es un caraacutecter de espacio en blanco Para concatenarcadenas sin espacios no especifique un delimitador

Objeto y ValoresUn objeto es algo a lo que una variable puede referirse Hasta ahora podriacutea usarobjeto y valor indistintamente

Si ejecutamos estas sentencias de asignacioacuten

a = bananab = banana

Se sabe que a y b apuntan a una cadena pero no se sabe si estaacuten apuntando a lamisma cadena Hay dos estados posibles los cuales se muestran en la Figura 10-2

Figura 12 Diagramas de estado

En un caso a y b se refieren a dos objetos diferentes que tienen el mismo valorEn el segundo caso se refieren al mismo objeto

Para verificar si dos variables se refieren al mismo objeto se puede usar eloperador equiv (equiv TAB)) o ===

Objeto y Valores 131

juliagt a = bananabananajuliagt b = bananabananajuliagt a equiv btrue

En este ejemplo Julia solo creoacute un objeto de cadena y ambas variables a y bapuntan a ella Pero cuando se crean dos arreglos se obtienen dos objetos

juliagt a = [1 2 3]

juliagt b = [1 2 3]

juliagt a equiv bfalse

Entonces el diagrama de estado se ve asiacute Figura 13

Figura 13 Diagrama de estado

En este caso se podriacutea decir que los dos arreglos son equivalentes porquetienen los mismos elementos pero no ideacutenticos ya que no son el mismo objetoSi dos objetos son ideacutenticos tambieacuten son equivalentes pero si son equivalentesno son necesariamente ideacutenticos

Para ser precisos un objeto tiene un valor Si se evaluacutea [1 2 3] se obtendraacute unobjeto arreglo cuyo valor es una secuencia de enteros Si otro arreglo tiene losmismos elementos se dice que tiene el mismo valor pero no es el mismo objeto

Alias (poner sobrenombres)Si a apunta a un objeto y se asigna b = a entonces ambas variables se refierenal mismo objeto

juliagt a = [1 2 3]

juliagt b = a

juliagt b equiv atrue

El diagrama de estado seriacutea como este Figura 14

132 Capiacutetulo 10 Arreglos

Figura 14 Diagrama de estado

La asociacioacuten de una variable con un objeto se llama referencia En este ejemplohay dos referencias al mismo objeto

Un objeto con maacutes de una referencia tiene maacutes de un nombre por lo quedecimos que el objeto tiene un alias

Si el objeto con alias es mutable los cambios hechos a un alias afectan al otro

juliagt b[1] = 4242juliagt print(a)[42 2 3]

AVISOAunque este comportamiento puede ser uacutetil a veces puede inducira errores En general es maacutes seguro evitar los alias cuando setrabaje con objetos mutables

No hay problema con los alias al trabajar con objetos inmutables tales comocadenas de texto En este ejemplo

a = bananab = banana

Casi nunca es relevante que a y b se refieran a la misma cadena o no

Arreglos como argumentosCuando se pasa un arreglo como argumento de una funcioacuten en realidad se pasauna referencia a ella Si la funcioacuten modifica el arreglo el que hizo la llamadaveraacute el cambio Por ejemplo la funcioacuten borrarprimero elimina el primer elementode un arreglo

function borrarprimero(t) popfirst(t)end

Aquiacute se aprecia el uso de borrarprimero

Arreglos como argumentos 133

juliagt letras = [a b c]

juliagt borrarprimero(letras)

juliagt print(letras)[b c]

El paraacutemetro t y la variable letras son alias de un mismo objeto El diagrama deestado es asiacute Figura 15

Figura 15 Diagrama de estado

Como el arreglo estaacute compartido por dos marcos se dibuja entre ambos

Es importante distinguir entre operaciones que modifiquen arreglos yoperaciones que creen nuevas arreglos Por ejemplo push modifica un arreglopero vcat crea un nuevo arreglo

Aquiacute hay un ejemplo de push

juliagt t1 = [1 2]

juliagt t2 = push(t1 3)

juliagt print(t1)[1 2 3]

t2 es un alias de t1

Aquiacute hay un ejemplo de vcat

juliagt t3 = vcat(t1 [4])

juliagt print(t1)[1 2 3]juliagt print(t3)[1 2 3 4]

El resultado de vcat es un nuevo arreglo El arreglo original no ha sufridocambios

Esta diferencia es importante al momento de escribir funciones que modificanarreglos

134 Capiacutetulo 10 Arreglos

Por ejemplo esta funcioacuten no elimina el primer elemento de un arrreglo

function noborrarprimero(t) t = t[2end] MALOend

El operador porcioacuten crea un nuevo arreglo y la asignacioacuten hace que t se refiera aella pero eso no afecta al arreglo t fuera de la funcioacuten

juliagt t4 = noborrarprimero(t3)

juliagt print(t3)[1 2 3 4]juliagt print(t4)[2 3 4]

Al comienzo de noborrarprimero t y t3 se refieren al mismo arreglo Al final t serefiere a un nuevo arreglo pero t3 todaviacutea se refiere al arreglo original nomodificado

Una alternativa es escribir una funcioacuten que cree y devuelva un nuevo arregloPor ejemplo la funcioacuten cola devuelve todos menos el primer elemento de unarreglo

function cola(t) t[2end]end

Esta funcioacuten no modifica el arreglo original y se usa de la siguiente manera

juliagt letras = [a b c]

juliagt demas = cola(letras)

juliagt print(demas)[b c]

DepuracioacutenUn uso inadecuado de los arreglos (y otros objetos mutables) puede llevar alargas horas de depuracioacuten A continuacioacuten se muestran algunos errorescomunes y coacutemo evitarlos

bull La mayoriacutea de las funciones que operan en arreglos modifican el argumentoEsto es lo opuesto a lo que ocurre en las funciones que operan en cadenas

Depuracioacuten 135

de texto que devuelven una nueva cadena y dejan la original sinmodificaciones

Si estaacute acostumbrado a escribir coacutedigo con cadenas de texto como este

nueva_palabra = strip(palabra)

Puede parecer tentador escribir coacutedigo con arreglos como este

t2 = sort(t1)

Pero como sort devuelve el arreglo original t1 modificado t2 es un alias det1

OBSERVACIOacuteN

Antes de utilizar funciones y operadores dearreglos debe leer la documentacioacutendetenidamente y luego probarla en modointeractivo

bull Escoja una expresioacuten y queacutedese con ella

Parte del problema con los arreglos es que hay demasiadas formas de hacerlas cosas Por ejemplo para eliminar un elemento de un arreglo se puedeusar pop popfirst delete_at o incluso una asignacioacuten de porcioacuten Paraagregar un elemento se puede usar push pushfirst insert or vcatSuponiendo que t es un arreglo y x es un elemento estas formas soncorrectas

insert(t 4 x)push(t x)append(t [x])

Y estas incorrectas

insert(t 4 [x]) MALOpush(t [x]) MALOvcat(t [x]) MALO

bull Haga copias para evitar usar alias

Si se desea utilizar una funcioacuten como sort que modifica el argumento perotambieacuten se necesita mantener el arreglo original es posible hacer unacopia

136 Capiacutetulo 10 Arreglos

juliagt t = [3 1 2]

juliagt t2 = t[] t2 = copy(t)

juliagt sort(t2)

juliagt print(t)[3 1 2]juliagt print(t2)[1 2 3]

En este ejemplo tambieacuten podriacutea usar la funcioacuten incorporada sort quedevuelve un nuevo arreglo ordenado y no modifica el original

juliagt t2 = sort(t)

juliagt println(t)[3 1 2]juliagt println(t2)[1 2 3]

Glosarioarreglo

Una secuencia de valores

elementoUno de los valores de un arreglo (u otra secuencia) tambieacuten llamado iacutetem

lista anidadaUn arreglo que es elemento de otro arreglo

acumuladorUna variable utilizada en un ciclo para sumar o acumular un resultado

asignacioacuten aumentadaUna sentencia que actualiza el valor de una variable usando un operadorcomo +=

operador puntoOperador binario que se aplica a cada elemento de un arreglo

Glosario 137

sintaxis de puntoSintaxis utilizada para aplicar una funcioacuten a todos los elementos decualquier arreglo

operacioacuten de reduccioacutenUn patroacuten de procesamiento que recorre una secuencia y acumula loselementos en un solo resultado

mapeoUn patroacuten de procesamiento que recorre una secuencia y realiza unaoperacioacuten en cada elemento

filtroUn patroacuten de procesamiento que recorre una secuencia y selecciona loselementos que satisfacen alguacuten criterio

objetoUna cosa a la que se puede referir una variable Un objeto tiene tipo y valor

equivalenteTener el mismo valor

ideacutenticoSer el mismo objeto (lo que implica equivalencia)

referenciaLa asociacioacuten entre una variable y su valor

aliasMuacuteltiples variables que contienen referencias al mismo objeto

argumentos opcionalesArgumentos que no son necesarios

delimitadorUn caraacutecter o cadena utilizado para indicar donde debe cortarse unacadena

Ejercicios

estaordenada (generic function with 1 method)

138 Capiacutetulo 10 Arreglos

Ejercicio 10-1

Escriba una funcioacuten llamada sumaanidada que tome un arreglo de arreglos deenteros y sume los elementos de todos los arreglos anidados Por ejemplo

juliagt t = [[1 2] [3] [4 5 6]]

juliagt sumaanidada(t)21

Ejercicio 10-2

Escriba una funcioacuten llamada sumaacumulada que tome un arreglo de nuacutemeros ydevuelva la suma acumulativa es decir un nuevo arreglo donde el eacutesimoelemento es la suma de los primeros elementos del arreglo original Porejemplo

juliagt t = [1 2 3]

juliagt print(sumaacumulada(t))Any[1 3 6]

Ejercicio 10-3

Escriba una funcioacuten llamada interior que tome un arreglo y devuelva un nuevoarreglo que contenga todos los elementos excepto el primero y el uacuteltimo Porejemplo

juliagt t = [1 2 3 4]

juliagt print(interior(t))[2 3]

Ejercicio 10-4

Escriba una funcioacuten llamada interior que tome un arreglo lo modifiqueeliminando el primer y el uacuteltimo elemento y que no devuelva un valor Porejemplo

Ejercicios 139

juliagt t = [1 2 3 4]

juliagt interior(t)

juliagt print(t)[2 3]

Ejercicio 10-5

Escriba una funcioacuten llamada estaordenada que tome un arreglo como paraacutemetroy devuelva true si el arreglo se ordena en orden ascendente y false de locontrario Por ejemplo

juliagt estaordenada([1 2 2])truejuliagt estaordenada([b a])false

Ejercicio 10-6

Dos palabras son anagramas si se pueden ordenar las letras de una para escribirla otra Escriba una funcioacuten llamada esanagrama que tome dos cadenas ydevuelva true si son anagramas

Ejercicio 10-7

Escriba una funcioacuten llamada repetido que tome un arreglo y devuelva true si hayalguacuten elemento que aparece maacutes de una vez No debe modificar el arreglooriginal

Ejercicio 10-8

Este ejercicio se relaciona con la llamada paradoja del cumpleantildeos sobre la cualpuede leer en httpseswikipediaorgwikiParadoja_del_cumpleaC3B1os

Si hay 23 estudiantes en su clase iquestcuaacuteles son las posibilidades de que dos deustedes tengan el mismo cumpleantildeos Puede estimar esta probabilidadgenerando muestras aleatorias de 23 cumpleantildeos y buscando coincidencias

OBSERVACIOacuteN Puede generar cumpleantildeos aleatorios con rand(1365)

Ejercicio 10-9

Escriba una funcioacuten que lea el archivo palabrastxt y construya un arreglo con unelemento por palabra Escriba dos versiones de esta funcioacuten una con push y la

140 Capiacutetulo 10 Arreglos

otra con la expresioacuten t = [t x] iquestCuaacutel tarda maacutes en ejecutarse iquestPor queacute

Ejercicio 10-10

Para verificar si una palabra estaacute en el arreglo de palabras se puede usar eloperador isin Esto seriacutea lento pues este operador busca las palabras en orden

Debido a que las palabras estaacuten en orden alfabeacutetico se puede acelerar laverificacioacuten con una buacutesqueda de biseccioacuten (tambieacuten conocida como buacutesquedabinaria) que es similar a lo que se hace cuando se busca una palabra en eldiccionario Se comienza en el medio y se verifica si la palabra que se estaacutebuscando va antes que la palabra localizada en el medio Si es asiacute se busca en laprimera mitad de la matriz de la misma manera De lo contrario se busca en lasegunda mitad

En ambos casos se reduce el espacio de buacutesqueda restante a la mitad Si elarreglo de palabras tiene 113809 palabras se necesitaraacuten unos 17 pasos paraencontrar la palabra o concluir que no estaacute alliacute

Escriba una funcioacuten llamada enbiseccion que tome un arreglo ordenado y unvalor objetivo y devuelva true si la palabra estaacute en el arreglo y false si no lo estaacute

Ejercicio 10-11

Dos palabras son un par inverso si cada una es la inversa de la otra Escriba unprograma llamado parinverso que encuentre todos los pares inversos en elarreglo de palabras

Ejercicio 10-12

Dos palabras se entrelazan si al tomar letras alternando entre cada palabra seforma una nueva palabra Por ejemplo pi y as se entrelazan para formarpais

Creacutedito Este ejercicio estaacute inspirado en un ejemplo de httppuzzlersorg

1 Escriba un programa que encuentre todos los pares de palabras que seentrelazan

OBSERVACIOacuteN iexclNo enumere todos los pares

2 iquestPuede encontrar tres palabras que se entrelacen es decir cada terceraletra forma una palabra empezando de la primera segunda o tercera letrade la palabra

Ejercicios 141

Capiacutetulo 11 DiccionariosEste capiacutetulo presenta otro tipo integrado llamado diccionario

Un Diccionario es un MapeoUn diccionario es como una matriz pero maacutes general En una matriz los iacutendicestienen que ser enteros en un diccionario pueden ser (casi) de cualquier tipo

Un diccionario contiene una coleccioacuten de iacutendices llamados claves y unacoleccioacuten de valores Cada clave estaacute asociada a un solo valor La asociacioacutenentre una clave y un valor se denomina par clave-valor o a veces item

En lenguaje matemaacutetico un diccionario representa un mapeo de las claves a losvalores es decir cada clave apunta a un valor A modo de ejemplo se crea undiccionario que asocia palabras en espantildeol con palabras en ingleacutes En estediccionario las claves y los valores son cadenas

La funcioacuten Dict crea un nuevo diccionario sin elementos Como Dict es el nombrede una funcioacuten integrada de Julia debe evitar usarla como nombre de variable

juliagt ing_a_esp = Dict()DictAnyAny()

El tipo de este diccionario estaacute compuesto por el tipo de las claves y de losvalores entre llaves En este caso las claves y los valores son de tipo Any

El diccionario estaacute vaciacuteo Para agregar elementos a eacutel se pueden usar corchetes

juliagt ing_a_esp[one] = uno

Esta liacutenea de coacutedigo crea un elemento con la clave one que apunta al valoruno Si se imprime el diccionario nuevamente se ve un par clave-valor con unaflecha =gt entre la clave y el valor

juliagt ing_a_espDictAnyAny with 1 entry one =gt uno

Este formato de salida tambieacuten es un formato de entrada Por ejemplo se puedecrear un nuevo diccionario con tres iacutetems de la siguiente manera

142 Capiacutetulo 11 Diccionarios

juliagt ing_a_esp = Dict(one =gt uno two =gt dos three =gt tres)DictStringString with 3 entries two =gt dos one =gt uno three =gt tres

Todas las claves y valores iniciales son cadenas por lo que se crea unDictStringString

AVISO

El orden de los pares clave-valor podriacutea no ser el mismo Siescribe el mismo ejemplo en su computadora podriacutea obtener unresultado diferente En general el orden de los elementos en undiccionario es impredecible

Esto no significa un problema ya que los elementos de un diccionario nunca seindexan con iacutendices enteros En lugar de ello se utilizan las claves para buscarlos valores correspondientes

juliagt ing_a_esp[two]dos

La clave two da el valor dos asiacute que el orden de los iacutetems no importa

Si la clave no estaacute en el diccionario se da un mensaje de error

juliagt ing_a_esp[four]ERROR KeyError key four not found

La funcioacuten length tambieacuten funciona con diccionarios y devuelve el nuacutemero depares clave-valor

juliagt length(ing_a_esp)3

La funcioacuten keys devuelve una coleccioacuten con las claves del diccionario

juliagt ks = keys(ing_a_esp)

juliagt print(ks)[two one three]

Tambieacuten se puede usar el operador isin para ver si algo es una clave en undiccionario

Un Diccionario es un Mapeo 143

juliagt one isin kstruejuliagt uno isin ksfalse

Para ver si algo es un valor en un diccionario se puede usar la funcioacuten valuesque devuelve una coleccioacuten de valores y luego usar el operador isin

juliagt vs = values(ing_a_esp)

juliagt uno isin vstrue

El operador isin utiliza diferentes algoritmos para matrices y diccionarios Para lasmatrices busca los elementos de la matriz en orden como en Seccioacuten 88 Eltiempo de buacutesqueda es directamente proporcional al largo de la matriz

Para los diccionarios Julia usa un algoritmo llamado tabla hash que tiene unapropiedad importante el operador isin toma aproximadamente la misma cantidadde tiempo sin importar cuaacutentos elementos haya en el diccionario

Diccionario como una Coleccioacuten de FrecuenciasSuponga que tiene una cadena y desea contar cuaacutentas veces aparece cada letraHay varias formas de hacerlo

bull Podriacutea crear 27 variables una para cada letra del alfabeto Luego recorrerla cadena y para cada caraacutecter incrementar el contador correspondienteprobablemente utilizando condiciones encadenadas

bull Podriacutea crear una matriz con 27 elementos Luego podriacutea convertir cadacaraacutecter en un nuacutemero (usando la funcioacuten integrada Int) usar el nuacutemerocomo iacutendice en la matriz e incrementar el contador apropiado

bull Puede crear un diccionario con caracteres como claves y contadores comolos valores correspondientes La primera vez que vea un caraacutecter agregariacuteaun elemento al diccionario Despueacutes de eso incrementariacutea el valor de unelemento existente

Cada una de estas opciones realiza el mismo caacutelculo pero la implementacioacuten esdiferente

Una implementacioacuten es una forma de realizar un caacutelculo Algunasimplementaciones son mejores que otras por ejemplo una ventaja de laimplementacioacuten del diccionario es que no hace falta saber de antemano queacuteletras aparecen en la cadena y solo hay que agregar las letras que aparecen

144 Capiacutetulo 11 Diccionarios

Asiacute es como se veriacutea el coacutedigo

function histograma(s) d = Dict() for c in s if c notin keys(d) d[c] = 1 else d[c] += 1 end end dend

La funcioacuten se llama histograma que es un teacutermino en estadiacutestica para unacoleccioacuten de frecuencias (o conteos)

La primera liacutenea de la funcioacuten crea un diccionario vaciacuteo El ciclo for recorre lacadena s En cada iteracioacuten de este ciclo si el caraacutecter c no estaacute en eldiccionario se crea un nuevo elemento con la clave c y el valor inicial 1 (ya quehemos visto esta letra una vez) Si c ya estaacute en el diccionario se incrementa d[c]

Asiacute es como funciona

juliagt h = histograma(brontosaurus)DictAnyAny with 8 entries n =gt 1 s =gt 2 a =gt 1 r =gt 2 t =gt 1 o =gt 2 u =gt 2 b =gt 1

El histograma indica que las letras a y b aparecen una vez o aparece dosveces y asiacute sucesivamente

Los diccionarios tienen una funcioacuten llamada get que toma como argumentos undiccionario una clave y un valor predeterminado Si la clave aparece en eldiccionario get devuelve el valor correspondiente de lo contrario devuelve elvalor predeterminado Por ejemplo

Diccionario como una Coleccioacuten de Frecuencias 145

juliagt h = histograma(a)DictAnyAny with 1 entry a =gt 1juliagt get(h a 0)1juliagt get(h b 0)0

Ejercicio 11-1

Use get para escribir la funcioacuten histograma de manera maacutes concisa Deberiacuteapoder eliminar la declaracioacuten if

Iteracioacuten y DiccionariosEs posible recorrer las claves del diccionario con un ciclo for Por ejemploimprimirhist imprime cada clave y su valor correspondiente

function imprimirhist(h) for c in keys(h) println(c h[c]) endend

Asiacute es como se ve la salida

juliagt h = histograma(perros)

juliagt imprimirhist(h)s 1e 1p 1r 2o 1

Nuevamente las claves no estaacuten en un orden particular Para recorrer las clavesen orden puede usar sort y collect

146 Capiacutetulo 11 Diccionarios

juliagt for c in sort(collect(keys(h))) println(c h[c]) ende 1o 1p 1r 2s 1

Buacutesqueda inversaDado un diccionario d y una clave k es faacutecil encontrar el valor correspondiente v= d[k] Esta operacioacuten se llama buacutesqueda

Pero iquestqueacute pasa si se tiene v y se quiere encontrar k Existen dos problemasprimeramente puede haber maacutes de una clave que apunta al valor v Dependiendode lo que se quiera es posible que se pueda elegir una de estas claves o que setenga que hacer una matriz que las contenga a todas En segundo lugar no hayuna sintaxis simple para hacer una buacutesqueda inversa solo se debe buscar

A continuacioacuten se muestra una funcioacuten que toma un valor y que devuelve laprimera clave que apunta a ese valor

function busquedainversa(d v) for k in keys(d) if d[k] == v return k end end error(Error de Busqueda)end

Esta funcioacuten es otro ejemplo del patroacuten de buacutesqueda pero utiliza una funcioacutenque no hemos visto antes error La funcioacuten error se usa para producir unErrorException que interrumpe el flujo normal En este caso tiene el mensajeError de Busqueda que indica que no existe una clave

Si llega al final del ciclo eso significa que v no aparece en el diccionario como unvalor por lo que se produce una excepcioacuten

A continuacioacuten se muestra un ejemplo de una buacutesqueda inversa exitosa

juliagt h = histograma(perros)

juliagt key = busquedainversa(h 2)r ASCIIUnicode U+0072 (category Ll Letter lowercase)

Buacutesqueda inversa 147

y una no exitosa

juliagt key = busquedainversa(h 3)ERROR Error de Busqueda

El efecto cuando generamos una excepcioacuten es el mismo que cuando Julia generauna se imprime un trazado inverso y un mensaje de error

Julia proporciona una forma optimizada de hacer una buacutesqueda inversafindall(isequal(3)h)

AVISO

Una buacutesqueda inversa es mucho maacutes lenta que una buacutesquedadirecta Si tiene que hacer buacutesquedas inversas con frecuencia o siel diccionario es muy grande el rendimiento de su programa severaacute afectado

Diccionarios y MatricesLas matrices pueden aparecer como valores en un diccionario Por ejemplo si setiene un diccionario que asigna frecuencias a letras y se quiere invertir es decirtener un diccionario que asigne letras a frecuencias Dado que pueden habervarias letras con la misma frecuencia cada valor en el diccionario invertidodeberiacutea ser una matriz de letras

Aquiacute hay una funcioacuten que invierte un diccionario

function invertirdic(d) inverso = Dict() for clave in keys(d) val = d[clave] if val notin keys(inverso) inverso[val] = [clave] else push(inverso[val] clave) end end inversoend

Cada vez que se recorre el bucle se asigna a la variable clave una clave de d y aval el valor correspondiente Si val no estaacute en el diccionario inverso significa queno se ha visto este valor antes por lo que se crea un nuevo item y se inicializacon un singleton (una matriz que contiene un solo elemento) De lo contrario seha visto este valor antes por lo que se agrega la clave correspondiente a lamatriz

148 Capiacutetulo 11 Diccionarios

Aquiacute hay un ejemplo

juliagt hist = histograma(perros)

juliagt inverso = invertirdic(hist)DictAnyAny with 2 entries 2 =gt [r] 1 =gt [s e p o]

Figura 16 Diagrama de estado

Figura 16 es un diagrama de estado que muestra hist e inverso Un diccionariose representa como un cuadro con los pares clave-valor dentro En este libro silos valores son enteros nuacutemeros de punto flotante o cadenas de texto se dibujandentro del cuadro y las matrices (generalmente) se dibujan fuera del cuadrosolo para mantener el diagrama simple

NOTA

Anteriormente se mencionoacute que un diccionario se implementausando una tabla hash (tambieacuten llamada matriz asociativahashing mapa hash tabla de dispersioacuten o tabla fragmentada) locual significa que las claves deben ser hashable

Un hash es una funcioacuten que toma un valor (de cualquier tipo) ydevuelve un entero Los diccionarios usan estos enteros llamadosvalores hash para almacenar y buscar pares clave-valor

PistasSi estuvo jugando con la funcioacuten fibonacci de Seccioacuten 67 es posible que hayanotado que cuanto maacutes grande el argumento que le da maacutes tiempo tarda lafuncioacuten en ejecutarse Maacutes auacuten el tiempo de ejecucioacuten aumenta muyraacutepidamente

Para entender por queacute considere Figura 17 que muestra el graacutefico de llamadaspara la funcioacuten fibonacci con n = 4

Pistas 149

Figura 17 Graacutefico de llamadas

Un graacutefico de llamadas muestra un conjunto de cuadros de funciones con liacuteneasque conectan cada cuadro con los cuadros de las funciones a las que llama En laparte superior del graacutefico fibonacci con n = 4 llama a fibonacci con n = 3 y n =2 A su vez fibonacci con n = 3 llama a fibonacci con n = 2 y n = 1 Y asiacutesucesivamente

Cuente cuaacutentas veces se llama a fibonacci(0) y fibonacci(1) Esta es una solucioacutenineficiente al problema y empeora a medida que el argumento aumenta entamantildeo

Una solucioacuten es llevar un registro de los valores que ya se han calculadoalmacenaacutendolos en un diccionario Un valor que ya ha sido calculado yalmacenado para un uso posterior se le denomina pista Aquiacute hay unaimplementacioacuten de fibonacci con pistas

anteriores = Dict(0=gt0 1=gt1)

function fibonacci(n) if n isin keys(anteriores) return anteriores[n] end res = fibonacci(n-1) + fibonacci(n-2) anteriores[n] = res resend

El diccionario llamado anteriores mantiene un registro de los valores deFibonacci que ya conocemos El programa comienza con dos pares 0corresponde a 1 y 1 corresponde a 1

Siempre que se llama a fibonacci se comprueba si el diccionario contiene elresultado ya calculado Si estaacute ahiacute la funcioacuten puede devolver el valorinmediatamente Si no tiene que calcular el nuevo valor antildeadirlo al diccionario ydevolverlo

150 Capiacutetulo 11 Diccionarios

Si ejecuta esta versioacuten de fibonacci y la compara con la original se daraacute cuentaque es mucho maacutes raacutepida

Variables GlobalesEn el ejemplo anterior el diccionario anteriores se crea fuera de la funcioacuten porlo que pertenece al marco especial llamado Main Las variables en Main a vecesson llamadas globales porque se puede acceder a ellas desde cualquier funcioacutenA diferencia de las variables locales que desaparecen cuando finaliza su funcioacutenlas variables globales existen de una llamada de funcioacuten a la siguiente

Es comuacuten usar variables globales como flags o banderas es decir variablesbooleanas que indican si una condicioacuten es verdadera Por ejemplo algunosprogramas usan una bandera llamada verbosa para controlar el nivel de detalleen la salida

verbose = true

function ejemplo1() if verbosa println(Ejecutando ejemplo1) endend

Si intenta reasignar una variable global se sorprenderaacute El siguiente ejemplotrata de llevar registro sobre si se ha llamado o no a una funcioacuten

ha_sido_llamada = false

function ejemplo2() ha_sido_llamada = true MALOend

Pero si lo ejecuta veraacute que el valor de ha_sido_llamada no cambia El problemaes que ejemplo2 + crea una nueva variable local llamada +ha_sido_llamada Lavariable local desaparece cuando finaliza la funcioacuten y no tiene efecto en lavariable global

Para reasignar una variable global dentro de una funcioacuten debe declarar lavariable global antes de usarla (reasignacioacuten

Variables Globales 151

been_called = false

function ejemplo2() global ha_sido_llamada ha_sido_llamada = trueend

La sentencia global le dice al inteacuterprete algo como esto ldquoEn esta funcioacuten cuandodigo ha_sido_llamada me refiero a la variable global asiacute que no crees unavariable local

A continuacioacuten se muestra un ejemplo que intenta actualizar una variable global

conteo = 0

function ejemplo3() conteo = conteo + 1 MALOend

Si lo ejecuta obtiene

juliagt ejemplo3()ERROR UndefVarError conteo not defined

Julia asume que conteo es local y bajo esa suposicioacuten lo estaacute leyendo antes deescribirlo La solucioacuten nuevamente es declarar conteo como global

conteo = 0

function ejemplo3() global conteo conteo += 1end

Si una variable global se refiere a un valor mutable puede modificar el valor sindeclarar la variable global

anteriores = Dict(0=gt0 1=gt1)

function ejemplo4() anteriores[2] = 1end

Por lo tanto puede agregar eliminar y reemplazar elementos de una matriz

152 Capiacutetulo 11 Diccionarios

global o diccionario pero si desea reasignar la variable debe declararla global

anteriores = Dict(0=gt0 1=gt1)

function ejemplo5() global anteriores anteriores = Dict()end

Para mejorar el rendimiento puede declarar la variable global como constanteCon esto ya no se puede reasignar la variable pero si se refiere a un valormutable siacute se puede modificar el valor

const known = Dict(0=gt0 1=gt1)

function example4() known[2] = 1end

AVISOLas variables globales pueden ser uacutetiles pero si tiene muchas deellas y las modifica con frecuencia pueden dificultar ladepuracioacuten y empeorar el desempentildeo de los programas

DepuracioacutenA medida que trabaja con conjuntos de datos maacutes grandes la depuracioacutenmediante la impresioacuten y verificacioacuten de la salida de manera manual puedetornarse difiacutecil Aquiacute hay algunas sugerencias para depurar grandes conjuntos dedatos

bull Reduzca la entrada

Si es posible reduzca el tamantildeo del conjunto de datos Por ejemplo si elprograma lee un archivo de texto comience con solo las primeras 10 liacuteneaso con el ejemplo maacutes pequentildeo que pueda encontrar que produzca erroresNo debe editar los archivos sino modificar el programa para que solo lea lasprimeras liacuteneas

Si hay un error puede reducir al valor maacutes pequentildeo que manifieste elerror y luego aumentarlo gradualmente a medida que encuentre y corrijaerrores

bull Revisar resuacutemenes y tipos

En lugar de imprimir y verificar todo el conjunto de datos considereimprimir resuacutemenes de los datos Por ejemplo el nuacutemero de elementos en

Depuracioacuten 153

un diccionario o el total de una serie de nuacutemeros

Una causa comuacuten de los errores de tiempo de ejecucioacuten son los valores detipo incorrecto Para depurar este tipo de error generalmente es suficienteimprimir el tipo de un valor

bull Escribir autocomprobaciones

Puede escribir coacutedigo que verifique errores automaacuteticamente Por ejemplosi estaacute calculando el promedio de una matriz de nuacutemeros puede verificarque el resultado no sea mayor que el elemento maacutes grande de la matriz omenor que el maacutes pequentildeo Esto se llama prueba de cordura

Otro tipo de verificacioacuten compara los resultados de dos caacutelculos diferentespara ver si son consistentes Esta se llama prueba de consistencia

bull Formatear la salida

Formatear la salida de depuracioacuten puede hacer que sea maacutes faacutecil detectarun error Vimos un ejemplo en Seccioacuten 69

Nuevamente el tiempo que dedica a construir andamiaje puede reducir eltiempo que dedica a la depuracioacuten

Glosariomapeo

Una relacioacuten en la que cada elemento de un conjunto corresponde a unelemento de otro conjunto

diccionarioUna asignacioacuten de claves a sus valores correspondientes

par clave-valorLa representacioacuten de la asociacioacuten entre una clave y un valor

itemEn un diccionario otro nombre para un par clave-valor

claveUn objeto que aparece en un diccionario como la primera parte de un parclave-valor

valorUn objeto que aparece en un diccionario como la segunda parte de un parclave-valor Este teacutermino es maacutes especiacutefico que nuestro uso previo de lapalabra valor

154 Capiacutetulo 11 Diccionarios

implementacioacutenUna forma de realizar un caacutelculo

tabla hashEl algoritmo utilizado para implementar los diccionarios de Julia

funcioacuten hashUna funcioacuten utilizada por una tabla hash para calcular la ubicacioacuten de unaclave

hashableUn tipo que tiene una funcioacuten hash

buacutesquedaUna operacioacuten sobre un diccionario que toma una clave y encuentra el valorcorrespondiente

buacutesqueda inversaUna operacioacuten sobre un diccionario que toma un valor y encuentra una omaacutes claves que se asignan a eacutel

singletonUna matriz (u otra secuencia) con un solo elemento

graacutefico de llamadaUn diagrama que muestra cada cuadro creado durante la ejecucioacuten de unprograma con una flecha entre cada funcioacuten y sus respectivas funcionesllamadas

pistaValor precalculado y almacenado temporalmente para evitar caacutelculosredundantes

variable globalUna variable definida fuera de una funcioacuten Se puede acceder a las variablesglobales desde cualquier funcioacuten

sentencia globalUna sentencia que declara un nombre de variable global

banderaUna variable booleana utilizada para indicar si una condicioacuten es verdadera

Glosario 155

declaracioacutenUna sentencia como global que le dice al inteacuterprete algo sobre una variable

variable global constanteUna variable global que no se puede reasignar

Ejercicios

Ejercicio 11-2

Escriba una funcioacuten que lea las palabras en palabrastxt y las almacene comoclaves en un diccionario No importa cuaacuteles sean los valores Luego puede usar eloperador isin como una forma raacutepida de verificar si una cadena estaacute en eldiccionario

Si hizo Seccioacuten 101510 puede comparar la velocidad de esta implementacioacutencon el operador array isin y la buacutesqueda binaria

Ejercicio 11-3

Lea la documentacioacuten de la funcioacuten que opera sobre diccionarios get y uacuteselapara escribir una versioacuten maacutes concisa de invertirdic

Ejercicio 11-4

Use pistas en la funcioacuten de Ackermann de Seccioacuten 6112 y vea si esto permiteevaluar la funcioacuten con argumentos de mayor tamantildeo

Ejercicio 11-5

Si hizo Seccioacuten 10157 ya tiene una funcioacuten llamada repetido que toma unamatriz como paraacutemetro y devuelve true si hay alguacuten objeto que aparece maacutes deuna vez en la matriz

Use un diccionario para escribir una versioacuten maacutes raacutepida y simple de repetido

Ejercicio 11-6

Dos palabras son pares desplazados si puede desplazar una de ellas y obtenerla otra (vea desplazarpalabra en Seccioacuten 8155)

Escriba un programa que lea una matriz de palabras y encuentre todos los paresdesplazados

156 Capiacutetulo 11 Diccionarios

Ejercicio 11-7

Aquiacute hay otro Puzzle de Car Talk (httpswwwcartalkcompuzzlerbrowse)

This was sent in by a fellow named Dan OrsquoLeary He came upon a commonone-syllable five-letter word recently that has the following unique propertyWhen you remove the first letter the remaining letters form a homophone ofthe original word that is a word that sounds exactly the same Replace thefirst letter that is put it back and remove the second letter and the result isyet another homophone of the original word And the question is whatrsquos theword

Now Irsquom going to give you an example that doesnrsquot work Letrsquos look at thefive-letter word lsquowrackrsquo W-R-A-C-K you know like to lsquowrack with painrsquo If Iremove the first letter I am left with a four-letter word rsquoR-A-C-Krsquo As inlsquoHoly cow did you see the rack on that buck It must have been a nine-pointerrsquo Itrsquos a perfect homophone If you put the lsquowrsquo back and remove thelsquorrsquo instead yoursquore left with the word lsquowackrsquo which is a real word itrsquos justnot a homophone of the other two words

But there is however at least one word that Dan and we know of which willyield two homophones if you remove either of the first two letters to maketwo new four-letter words The question is whatrsquos the word

You can use the dictionary from Seccioacuten 11101 to check whether a string is inthe word array

OBSERVACIOacuteNTo check whether two words are homophones you canuse the CMU Pronouncing Dictionary You can downloadit from httpwwwspeechcscmueducgi-bincmudict

Write a program that lists all the words that solve the Puzzler

Ejercicios 157

Capiacutetulo 12 TuplasEste capiacutetulo presenta otro tipo integrado las tuplas Luego muestra coacutemo losarreglos los diccionarios y las tuplas funcionan en conjunto Tambieacuten se presentauna caracteriacutestica uacutetil para los arreglos de longitud variable como argumento losoperadores de recopilacioacuten y dispersioacuten

Las Tuplas son ImmutablesUna tupla es una secuencia de valores Estos valores pueden ser de cualquiertipo y estaacuten indexados por enteros por lo que las tuplas son muy parecidas a losarreglos La diferencia maacutes importante es que las tuplas son inmutables y quecada elemento puede tener su propio tipo

Una tupla es una lista de valores separados por comas

juliagt t = a b c d e(a b c d e)

Aunque no es necesario es comuacuten encerrar las tuplas entre pareacutentesis

juliagt t = (a b c d e)(a b c d e)

Para crear una tupla con un solo elemento se debe incluir una coma final

juliagt t1 = (a)(a)juliagt typeof(t1)TupleChar

AVISO

Un valor entre pareacutentesis sin coma no es una tupla

juliagt t2 = (a)a ASCIIUnicode U+0061 (category Ll Letter lowercase)juliagt typeof(t2)Char

Otra forma de crear una tupla es la funcioacuten de tupla integrada en Julia Sinargumento esta funcioacuten crea una tupla vaciacutea

juliagt tuple()()

158 Capiacutetulo 12 Tuplas

Si se tienen muacuteltiples argumentos el resultado es una tupla con los argumentosdados

juliagt t3 = tuple(1 a pi)(1 a π)

Ya que tuple es el nombre de una funcioacuten integrada debe evitar usarla comonombre de variable

La mayoriacutea de los operadores de arreglos tambieacuten sirven en las tuplas Eloperador corchete indexa un elemento

juliagt t = (a b c d e)

juliagt t[1]a ASCIIUnicode U+0061 (category Ll Letter lowercase)

Y el operador porcioacuten selecciona un rango de elementos

juliagt t[24](b c d)

Pero si se intenta modificar uno de los elementos de la tupla se obtendraacute unerror

juliagt t[1] = AERROR MethodError no method matching setindex(NTuple5Char CharInt64)

Como las tuplas son inmutables sus elementos no se pueden modificar

Los operadores relacionales funcionan con las tuplas y otras secuencias Juliacomienza comparando el primer elemento de cada secuencia Si son igualespasa a los siguientes elementos y asiacute sucesivamente hasta que encuentraelementos que difieren Los elementos posteriores no se consideran (incluso sison realmente grandes)

juliagt (0 1 2) lt (0 3 4)truejuliagt (0 1 2000000) lt (0 3 4)true

Las Tuplas son Immutables 159

Asignacioacuten de tuplaDe vez en cuando es uacutetil intercambiar los valores de dos variables Para hacerlocon sentencias de asignacioacuten convencionales se debe usar una variable temporalPor ejemplo para intercambiar a y b

temp = aa = bb = temp

Esta solucioacuten resulta aparatosa La asignacioacuten de tuplas soluciona este problemaelegantemente

a b = b a

El lado izquierdo es una tupla de variables y el lado derecho es una tupla deexpresiones Cada valor se asigna a su respectiva variable Todas las expresionesdel lado derecho se evaluacutean antes de las asignaciones

El nuacutemero de variables de la izquierda tiene que ser menor o igual que el nuacutemerode valores a la derecha

juliagt (a b) = (1 2 3)(1 2 3)juliagt a b c = 1 2ERROR BoundsError attempt to access (1 2) at index [3]

El lado derecho puede ser cualquier tipo de secuencia (cadena arreglo o tupla)Por ejemplo para dividir una direccioacuten de correo electroacutenico en nombre deusuario y dominio se puede escribir

juliagt addr = juliocesarromajuliocesarromajuliagt unombre dominio = split(addr )

El valor de retorno de split es un arreglo con dos elementos el primer elementose asigna a unombre y el segundo a dominio

juliagt unombrejuliocesarjuliagt dominioroma

160 Capiacutetulo 12 Tuplas

Tuplas como valor de retornoEstrictamente hablando una funcioacuten solo puede devolver un valor pero si elvalor es una tupla el efecto es el mismo que devolver muacuteltiples valores Porejemplo si desea dividir dos enteros y calcular el cociente y el resto esineficiente calcular x divide y y luego x y Es mejor calcular ambos al mismotiempo

La funcioacuten integrada divrem toma dos argumentos y devuelve una tupla de dosvalores el cociente y el resto El resultado puede ser almacenado como unatupla

juliagt t = divrem(7 3)(2 1)

Tambieacuten se puede utilizar asignacioacuten de tuplas para almacenar los elementos porseparado

juliagt q r = divrem(7 3)

juliagt show q rq = 2r = 1

Aquiacute hay un ejemplo de una funcioacuten que devuelve una tupla

function minmax(t) minimum(t) maximum(t)end

maximum y minimum son funciones integradas que encuentran los elementosmaacutes grandes y maacutes pequentildeos de una secuencia respectivamente La funcioacutenminmax calcula ambos y devuelve una tupla de dos valores Otra alternativa esutilizar la funcioacuten integrada extrema lo cual es maacutes eficiente

Tupla con Argumentos de Longitud VariableLas funciones pueden tomar un nuacutemero variable de argumentos Un nombre deparaacutemetro que termina con recopila argumentos en una tupla Por ejemploimprimirtodo toma cualquier nuacutemero de argumentos y los imprime

function imprimirtodo(args) println(args)end

Tuplas como valor de retorno 161

El paraacutemetro de recopilacioacuten puede tener cualquier nombre pero la convencioacutenes llamarlo args A continuacioacuten se muestra coacutemo funciona la funcioacuten

juliagt imprimirtodo(1 20 3)(1 20 3)

El opuesto de la recopilacioacuten es la dispersioacuten Si tiene una secuencia de valores ydesea pasarla a una funcioacuten como argumento muacuteltiple puede usar el operador Por ejemplo divrem toma exactamente dos argumentos y no funciona contuplas

juliagt t = (7 3)

juliagt divrem(t)ERROR MethodError no method matching divrem(TupleInt64Int64)

No obstante si dispersamos la tupla funciona

juliagt divrem(t)(2 1)

Muchas de las funciones integradas usan tuplas con argumentos de longitudvariable Por ejemplo max y min pueden tomar cualquier nuacutemero deargumentos

juliagt max(1 2 3)3

Pero sum no

juliagt sum(1 2 3)ERROR MethodError no method matching sum(Int64 Int64 Int64)

Ejercicio 12-1

Escriba una funcioacuten llamada sumartodo que tome cualquier nuacutemero deargumentos y devuelva su suma

En el mundo de Julia generalmente se le llama ldquoslurprdquo (sorber en espantildeol) areunir y splat (plaf en espantildeol como el ruido cuando cae algo) a dispersar

162 Capiacutetulo 12 Tuplas

Arreglos y tuplaszip es una funcioacuten integrada que toma dos o maacutes secuencias y devuelve unacoleccioacuten de tuplas donde cada tupla contiene un elemento de cada secuencia Elnombre de la funcioacuten se refiere a una cremallera que une e intercala dos filas dedientes

Este ejemplo une e intercala una cadena y un arreglo

juliagt s = abc

juliagt t = [1 2 3]

juliagt zip(s t)zip(abc [1 2 3])

El resultado es un objeto zip que permite iterar a traveacutes de los pares El uso maacutescomuacuten de zip es en un bucle for

juliagt for par in zip(s t) println(par) end(a 1)(b 2)(c 3)

Un objeto zip es un tipo de iterador que es cualquier objeto que itera a traveacutes deuna secuencia Los iteradores son en cierto modo similares a los arreglos peroa diferencia de estos uacuteltimos no se puede usar un iacutendice para seleccionar unelemento de un iterador

Si desea usar operadores y funciones de arreglos puede usar un objeto zip parahacer un arreglo

juliagt collect(zip(s t))3-element ArrayTupleCharInt641 (a 1) (b 2) (c 3)

El resultado es una serie de tuplas En este ejemplo cada tupla contiene uncaraacutecter de la cadena y el elemento correspondiente del arreglo

Si las secuencias no tienen la misma longitud el resultado tiene la longitud de lamaacutes corta

Arreglos y tuplas 163

juliagt collect(zip(Juan Gabriel))4-element ArrayTupleCharChar1 (J G) (u a) (a b) (n r)

Se puede usar asignacioacuten de tuplas en un bucle for para recorrer un arreglo detuplas

juliagt t = [(a 1) (b 2) (c 3)]

juliagt for (letra numero) in t println(numero letra) end1 a2 b3 c

En cada iteracioacuten del ciclo Julia selecciona la siguiente tupla en el arreglo yasigna estos elementos a letra y nuacutemero Los pareacutentesis de (letra nuacutemero) sonobligatorios

Combinando zip for y asignacioacuten de tuplas se obtiene una forma para recorrerdos (o maacutes) secuencias al mismo tiempo Por ejemplo la funcioacuten coinciden tomados secuencias t1 y t2 y devuelve true si hay un iacutendice i tal que t1[i] == t2[i]

function coinciden(t1 t2) for (x y) in zip(t1 t2) if x == y return true end end falseend

Si se necesita recorrer los elementos de una secuencia y sus iacutendices se puedeusar la funcioacuten integrada enumerate

juliagt for (indice elemento) in enumerate(abc) println(indice elemento) end1 a2 b3 c

164 Capiacutetulo 12 Tuplas

El resultado de enumerate es un objeto enumerate el cual hace una iteracioacutensobre una secuencia de pares doacutende cada par contiene un iacutendice (a partir de 1) yun elemento de la secuencia dada

Diccionarios y TuplasLos diccionarios se pueden usar como iteradores que iteran sobre los paresclave-valor Puede usarlos en un bucle for como este

juliagt d = Dict(a=gt1 b=gt2 c=gt3)

juliagt for (key value) in d println(key value) enda 1c 3b 2

Como es de esperar en un diccionario los elementos no estaacuten en un ordenparticular

Ahora si se quiere hacer lo contrario se puede usar una serie de tuplas parainicializar un nuevo diccionario

juliagt t = [(a 1) (c 3) (b 2)]

juliagt d = Dict(t)DictCharInt64 with 3 entries a =gt 1 c =gt 3 b =gt 2

Al combinar Dict con zip podemos crear un diccionario de una manera muysimple

juliagt d = Dict(zip(abc 13))DictCharInt64 with 3 entries a =gt 1 c =gt 3 b =gt 2

Es comuacuten usar tuplas como claves en los diccionarios Por ejemplo un directoriotelefoacutenico puede asignar nuacutemeros de teleacutefono a una tupla con apellido y nombreSuponiendo que se ha definido apellido nombre y numero podriacuteamos escribir

Diccionarios y Tuplas 165

directorio[apellido nombre] = numero

La expresioacuten entre pareacutentesis es una tupla Se podriacutea usar asignacioacuten de tuplaspara recorrer este diccionario

for ((apellido nombre) numero) in directorio println(nombre apellido numero)end

Este bucle recorre los pares clave-valor en directorio los cuales son tuplasAsigna los elementos de la clave de cada tupla a apellido y nombre y el valor anumero luego imprime el nombre y el nuacutemero de teleacutefono correspondiente

Hay dos formas de representar tuplas en un diagrama de estado La versioacuten maacutesdetallada muestra los iacutendices y elementos tal como aparecen en un arreglo Porejemplo la tupla (Cortaacutezar Julio) se veriacutea como en Figura 18

Figura 18 Diagrama de estado

Pero en un diagrama maacutes grande es posible que desee omitir algunos detallesPor ejemplo un diagrama del directorio telefoacutenico puede verse como en Figura19

Figura 19 Diagrama de estado

Aquiacute las tuplas se muestran usando la sintaxis de Julia para tener un esquemamaacutes simple El nuacutemero de teleacutefono del diagrama es el nuacutemero de reclamos de laBBC asiacute que no intentes llamar

Secuencias de SecuenciasHasta ahora el capiacutetulo se ha centrado en los arreglos de tuplas pero casi todoslos ejemplos que se han visto tambieacuten funcionan con arreglos de arreglos tuplasde tuplas y tuplas de arreglos Para evitar enumerar todas las posiblescombinaciones a veces es maacutes faacutecil hablar sobre secuencias de secuencias

En muchos contextos los diferentes tipos de secuencias (cadenas arreglos ytuplas) se pueden usar indistintamente Entonces iquestcoacutemo elegir uno u otro

166 Capiacutetulo 12 Tuplas

Para comenzar con lo mas obvio las cadenas son maacutes limitadas que las demaacutessecuencias porque los elementos deben ser caracteres Ademaacutes son inmutablesSi se necesita poder cambiar los caracteres en una cadena (en vez de crear unanueva) puede que lo mas adecuado sea elegir un arreglo de caracteres

Los arreglos se usan con mas frecuencia que las tuplas principalmente porqueson mutables No obstante hay algunos casos donde es posible que seapreferible usar tuplas

bull En algunos contextos como en una sentencia return resultasintaacutecticamente maacutes simple crear una tupla que un arreglo

bull Si se pasa una secuencia como argumento de una funcioacuten el uso de tuplasreduce los comportamientos potencialmente indeseados debido a lacreacioacuten de alias

bull Por rendimiento El compilador puede especializarse en este tipo

Dado que las tuplas son inmutables no tienen funciones como sort y reverseque modifiquen arreglos ya existentes Sin embargo Julia proporciona lasfunciones integradas sort que toma un arreglo y devuelve una secuencia nuevacon los mismos elementos ordenados y reverse que toma cualquier secuencia ydevuelve una secuencia nueva del mismo tipo con los mismos elementos en elorden contrario

DepuracioacutenLos arreglos diccionarios y tuplas son ejemplos de estructuras de datos En estecapiacutetulo se empiezan a ver estructuras de datos compuestas como arreglos otuplas y diccionarios que contienen tuplas como claves y arreglos como valoresLas estructuras de datos compuestas son uacutetiles aunque tambieacuten resultanpropensas a lo que se llaman errores de forma es decir errores causados cuandouna estructura de datos tiene el tipo tamantildeo o estructura incorrecta Porejemplo si estaacute esperando una lista con un entero y se le pasa simplemente unentero (no en una lista) no funcionaraacute

Julia permite antildeadir el tipo a elementos de una secuencia Esto se detalla enCapiacutetulo 17 Especificar el tipo elimina muchos errores de forma

Glosariotupla

Una secuencia inmutable de elementos donde cada elemento puede tener supropio tipo

asignacioacuten en tuplaUna asignacioacuten con una secuencia en el lado derecho y una tupla devariables en el izquierdo Primero se evaluacutea el lado derecho y luego sus

Depuracioacuten 167

elementos son asignados a las variables de la izquierda

reunirLa operacioacuten de armar una tupla con argumentos de longitud variable

dispersarLa operacioacuten de tratar una secuencia como una lista de argumentos

objeto zipEl resultado de llamar a la funcioacuten integrada zip un objeto que itera atraveacutes de una secuencia de tuplas

iteradorUn objeto que puede iterar a traveacutes de una secuencia pero que no tiene losoperadores y funciones de arreglos

estructura de datosUna coleccion de valores relacionados a menudo organizados en arreglosdiccionarios tuplas etc

error de formaUn error causado porque un valor tiene la forma incorrecta es decir el tipoo tamantildeo incorrecto

Ejercicios

Ejercicio 12-2

Escriba una funcioacuten llamada masfrecuente que tome una cadena e imprima lasletras en orden decreciente de frecuencia Encuentre muestras de texto de variosidiomas diferentes y vea coacutemo la frecuencia de las letras variacutea entre idiomasCompare sus resultados con las tablas en httpsenwikipediaorgwikiLetter_frequencies

Ejercicio 12-3

iexclMaacutes anagramas

1 Escriba un programa que lea una lista de palabras de un archivo (veaSeccioacuten 91) e imprima todos los conjuntos de palabras que son anagramas

Aquiacute hay un ejemplo de coacutemo se veriacutea la salida

168 Capiacutetulo 12 Tuplas

[brazo zobra broza zarbo][palabra parlaba][vida diva][gato toga gota]

OBSERVACIOacuteN

Es posible que desee crear un diccionario queasigne a una coleccioacuten de letras una serie depalabras que se puedan deletrear con esas letrasLa pregunta es iquestcoacutemo representar la coleccioacuten deletras de una manera que pueda usarse comoclave

2 Modifique el programa anterior para que imprima primero el arreglo maacuteslargo de anagramas seguido del segundo maacutes larga y asiacute sucesivamente

3 En Scrabble un bingo es cuando juegas las siete fichas de tu atril juntocon una letra del tablero para formar una palabra de ocho letras iquestQueacutecoleccioacuten de 8 letras forman parte del bingo maacutes probable

Ejercicio 12-4

Dos palabras metatizan si se puede transformar una en la otra intercambiandodos letras como es el caso de conversar y conservar Escriba un programaque encuentre todos los pares de metaacutetesis en el diccionario

OBSERVACIOacuteN No pruebe con todos los pares de palabras ni tampococon todos los intercambios posibles

Creacuteditos Este ejercicio estaacute inspirado en un ejemplo de httppuzzlersorg

Ejercicio 12-5

Aquiacute hay otro Puzzle de Car Talk (httpswwwcartalkcompuzzlerbrowse)

Ejercicios 169

iquestCuaacutel es la palabra en espantildeol maacutes larga que sigue siendo una palabra enespantildeol vaacutelida a medida que se eliminan sus letras una a una

Las letras se pueden eliminar de cualquier extremo o del medio pero no sepuede reordenar ninguna de ellas Cada vez que elimina una letra se quedacon otra palabra en espantildeol Eventualmente terminaraacute con una letra la cualtambieacuten seraacute una palabra en espantildeol que puede encontrar en el diccionarioSe desea saber cuaacutel es la palabra maacutes larga y cuaacutentas letras tiene

A modo de ejemplo piense en la palabra Palote iquestDe acuerdo Comienza conpalote elimina la letra p y queda alote luego se quita la t y queda aloe setoma la e y se tiene alo quitando la o se tiene al y finalmente eliminando lal queda a

Escriba un programa que encuentre todas las palabras que se pueden reducir deesta manera y luego encuentre la maacutes larga

OBSERVACIOacuteN

Este ejercicio es un poco maacutes desafiante que el resto asiacuteque aquiacute hay algunas sugerencias

1 Es posible que quiera escribir una funcioacuten que tomeuna palabra y calcule un arreglo de todas laspalabras que se pueden formar al eliminar unaletra Estos son los hijos de la palabra

2 De manera recursiva una palabra es reducible sialguno de sus hijos es reducible Como caso basepuede considerar la cadena vaciacutea reducible

3 La lista de palabras palabrastxt no tiene la cadenavaciacutea por lo que tendraacute que agregarla

4 Para mejorar el rendimiento de su programa esposible que desee guardar las palabras que se sabeque son reducibles

170 Capiacutetulo 12 Tuplas

Capiacutetulo 13 Estudio de Caso Seleccioacuten deEstructura de DatosHasta ahora hemos aprendido sobre las principales estructuras de datos de Juliay hemos visto algunos de los algoritmos que las utilizan

Este capiacutetulo presenta un estudio de caso con ejercicios que le permitenpracticar la eleccioacuten de estructuras de datos y su uso

Anaacutelisis de Frecuencia de PalabrasComo de costumbre se recomienda intentar resolver los ejercicios antes de leerlas soluciones

Ejercicio 13-1

Escriba un programa que lea un archivo divida cada liacutenea en palabras elimine elespacio en blanco y la puntuacioacuten de las palabras y luego las convierta enminuacutesculas

OBSERVACIOacuteN La funcioacuten isletter permite saber si un caraacutecterpertenece al alfabeto

Ejercicio 13-2

Vaya a la paacutegina de Proyecto Gutenberg (httpsgutenbergorg) y descargue sulibro favorito sin derechos de autor en formato de texto plano La mayoriacutea de loslibros estaacuten en ingleacutes pero existen algunos en espantildeol

Modifique su programa del ejercicio anterior para leer el libro que descargoacuteomita la informacioacuten del encabezado al comienzo del archivo y procese el restode las palabras tal como en el ejercicio previo

Luego modifique el programa para contar la cantidad total de palabras en ellibro y la cantidad de veces que se usa cada palabra

Imprima la cantidad de palabras diferentes que se usan en el libro Comparediferentes libros de diferentes autores escritos en diferentes eacutepocas iquestQueacute autorusa un vocabulario maacutes extenso

Ejercicio 13-3

Modifique el programa del ejercicio anterior para imprimir las 20 palabras maacutesutilizadas en el libro

Anaacutelisis de Frecuencia de Palabras 171

Ejercicio 13-4

Modifique el programa anterior para que lea una lista de palabras y luegoimprima todas las palabras del libro que no esteacuten en la lista de palabrasiquestCuaacutentos de ellos son errores tipograacuteficos iquestCuaacutentos de ellos son palabrascomunes que deberiacutean estar en la lista de palabras iquest Cuaacutentos de ellos sonteacuterminos realmente macabros

Nuacutemeros aleatoriosDadas las mismas entradas la mayor parte de los programas generan la mismasalida cada vez que los ejecutamos por lo que se dice que son deterministasNormalmente el determinismo es algo bueno ya que esperamos que un caacutelculonos entregue siempre el mismo resultado Para algunas aplicaciones sinembargo queremos que el computador sea impredecible Por ejemplo en losjuegos entre otros casos

Hacer que un programa sea realmente no determinista resulta difiacutecil pero hayformas de que hacer que al menos parezca no determinista Una de ellas es usaralgoritmos para generar nuacutemeros pseudoaleatorios Los nuacutemerospseudoaleatorios no son verdaderamente aleatorios porque se generan medianteun caacutelculo determinista pero al mirar estos nuacutemeros es casi imposibledistinguirlos de lo aleatorio

La funcioacuten rand devuelve un numero de punto flotante entre 00 y 10(incluyendo 00 pero no 10) Cada vez que usted llama a rand obtiene elsiguiente numero de una larga serie Para ver un ejemplo ejecute este bucle

for i in 110 x = rand() println(x)end

La funcioacuten rand puede tomar un iterador o arreglo como argumento y devuelveun elemento aleatorio de ellos

for i in 110 x = rand(16) print(x )end

Ejercicio 13-5

Escriba una funcioacuten llamada escogerdelhistograma que tome un histogramadefinido como en Seccioacuten 112 y devuelva un valor aleatorio del histogramaelegido con probabilidad proporcional a la frecuencia Por ejemplo para este

172 Capiacutetulo 13 Estudio de Caso Seleccioacuten de Estructura de Datos

histograma

juliagt t = [a a b]

juliagt histograma(t)DictAnyAny with 2 entries a =gt 2 b =gt 1

su funcioacuten debe devolver a con probabilidad y b con probabilidad

Histograma de PalabrasDebe hacer los ejercicios anteriores antes de continuar Tambieacuten necesitaraacutehttpsgithubcomJuliaIntroIntroAJuliajlblobmasterdataDonQuijotetxt

Aquiacute hay un programa que lee un archivo y construye un histograma de laspalabras en el archivo

function procesararchivo(nombrearchivo) hist = Dict() for linea in eachline(nombrearchivo) procesarlinea(linea hist) end histend

function procesarlinea(linea hist) linea = replace(linea - =gt ) for palabra in split(linea) palabra = string(filter(isletter [palabra])) palabra = lowercase(palabra) hist[palabra] = get(hist palabra 0) + 1 endend

Histograma de Palabras 173

DictAnyAny with 23607 entries enojoacute =gt 1 angosta =gt 1 hurto =gt 10 sirviesen =gt 2 solene =gt 1 coronan =gt 1 endereacutecese =gt 2 alteza =gt 15 rescatarlos =gt 1 enderezador =gt 1 libertad =gt 81 abundante =gt 5 bajeza =gt 4 embotoacute =gt 1 estime =gt 1 renovaban =gt 1 acreciente =gt 4 debieron =gt 8 garci =gt 1 ⋮ =gt ⋮

hist = procesararchivo(DonQuijotetxt)

Este programa lee DonQuijotetxt que contiene el texto de Don Quijote deMiguel de Cervantes

procesararchivo recorre las liacuteneas del archivo pasando una liacutenea a la vez aprocesarlinea El histograma hist se estaacute utilizando como acumulador

procesarlinea usa la funcioacuten replace para reemplazar los guiones por espaciosantes de usar split para dividir la liacutenea en un arreglo de cadenas Recorre elconjunto de palabras y usa filter isletter y lowercase para eliminar los signos depuntuacioacuten y convertir las palabras a minuacutesculas (Decir que las cadenas seconvierten es incorrecto recuerde que las cadenas son inmutables por lo queuna funcioacuten como lowercase devuelve cadenas nuevas)

Finalmente procesarlinea actualiza el histograma creando un nuevo elemento oincrementando uno existente

Para contar el nuacutemero total de palabras en el archivo podemos sumar lasfrecuencias en el histograma

function palabrastotales(hist) sum(values(hist))end

174 Capiacutetulo 13 Estudio de Caso Seleccioacuten de Estructura de Datos

El nuacutemero de palabras diferentes es el nuacutemero de elementos en el diccionario

function palabrasdiferentes(hist) length(hist)end

Para imprimir los resultados se puede usar el siguiente coacutedigo

juliagt println(Nuacutemero total de palabras palabrastotales(hist))Nuacutemero total de palabras 385925

juliagt println(Nuacutemero de palabras diferentes palabrasdiferentes(hist))Nuacutemero de palabras diferentes 23607

Observacioacuten No se considera el encabezado del archivo de texto soacutelo el libro

Palabras Maacutes ComunesPara encontrar las palabras maacutes comunes podemos hacer un arreglo de tuplasdonde cada tupla contiene una palabra y su frecuencia y ordenarlas Lasiguiente funcioacuten toma un histograma y devuelve un arreglo de tuplas defrecuencia de palabras

function mascomun(hist) t = [] for (clave valor) in hist push(t (valorclave)) end reverse(sort(t))end

En cada tupla la frecuencia aparece primero por lo que el arreglo resultante seordena por frecuencia A continuacioacuten se muestra un bucle que imprime las 10palabras maacutes comunes

t = mascomun(hist)println(Las palabras maacutes comunes son)for (frec palabra) in t[110] println(palabra t frec)end

En este ejemplo utilizamos un caraacutecter de tabulacioacuten (t) como separador envez de un espacio por lo que la segunda columna estaacute alineada A continuacioacutense muestran los resultados de Don Quijote

Palabras Maacutes Comunes 175

Las palabras maacutes comunes sonque 20626de 18217y 18188la 10363a 9881en 8241el 8210no 6345los 4748se 4690

OBSERVACIOacuteN

Este coacutedigo se puede simplificar usando comoargumento la palabra reservada rev de la funcioacuten sortPuede leer sobre esto en httpsdocsjulialangorgenv1basesortBasesort

Parametros OpcionalesSe han tratado funciones integradas de Julia que toman argumentos opcionalesTambieacuten es posible escribir funciones definidas por el programador conargumentos opcionales Por ejemplo aquiacute hay una funcioacuten que imprime laspalabras maacutes comunes en un histograma

function imprimirmascomun(hist num=10) t = mascomun(hist) println(Las palabras maacutes comunes son ) for (frec palabra) in t[1num] println(palabra t frec) endend

El primer paraacutemetro es obligatorio y el segundo es opcional El valorpredeterminado de num es 10

Si solo pasas un argumento

imprimirmascomun(hist)

num toma el valor predeterminado Si pasas dos argumentos

imprimirmascomun(hist 20)

num toma el valor del argumento En otras palabras el argumento opcional

176 Capiacutetulo 13 Estudio de Caso Seleccioacuten de Estructura de Datos

anula el valor predeterminado

Si una funcioacuten tiene paraacutemetros obligatorios y opcionales los paraacutemetrosobligatorios deben ir primero seguidos de los opcionales

Resta de DiccionarioEncontrar las palabras de un libro que no estaacuten en la lista de palabras depalabrastxt es un problema similar a una resta de conjuntos es decir se quiereencontrar todas las palabras de un conjunto (las palabras en el libro) que noestaacuten en el otro (las palabras en la lista)

resta toma los diccionarios d1 y d2 y devuelve un nuevo diccionario que contienetodas las claves de d1 que no estaacuten en d2 Como realmente no importan losvalores se fijan como nothing

function resta(d1 d2) res = Dict() for clave in keys(d1) if clave notin keys(d2) res[clave] = nothing end end resend

Para encontrar las palabras en el libro que no estaacuten en palabrastxt se ouedeusar procesararchivo para construir un histograma para palabrastxt y luego lafuncioacuten resta

palabras = procesararchivo(palabrastxt)dif = resta(hist palabras)

println(Palabras en el libro que no estaacuten en la lista de palabras)for palabra in keys(dif) print(palabra )end

Estos son algunos de los resultados de Don Quijote

Palabras en el libro que no estaacuten en la lista de palabrasenojoacute angosta coronan sirviesen solene endereacutecese rescatarlos embotoacuteestime renovaban

Algunas de estas palabras son conjugaciones de verbos Otros como solene yano son de uso comuacuten iexclPero algunas son palabras comunes que deberiacutean estar en

Resta de Diccionario 177

la lista

Ejercicio 13-6

Julia proporciona una estructura de datos llamada Set que permite muchasoperaciones comunes de conjuntos Puede leer sobre ellas en Seccioacuten 202 oconsultar la documentacioacuten en httpsdocsjulialangorgenv1basecollectionsSet-Like-Collections-1

Escriba un programa que use la resta de conjuntos para encontrar palabras en ellibro que no estaacuten en la lista de palabras

Palabras al AzarPara elegir una palabra aleatoria del histograma el algoritmo maacutes simple esconstruir un arreglo con muacuteltiples copias de cada palabra de acuerdo con lafrecuencia observada y luego elegir una palabra del arreglo

function palabraalazar(h) t = [] for (palabra frec) in h for i in 1frec push(t palabra) end end rand(t)end

Este algoritmo funciona pero no es muy eficiente ya que cada vez que elige unapalabra aleatoria reconstruye el arreglo que es tan grande como el librooriginal Una mejora es construir el arreglo una vez y luego hacer muacuteltiplesselecciones pero el arreglo sigue siendo grande

Una alternativa es

1 Use las claves para obtener un arreglo de palabras del libro

2 Cree un arreglo que contenga la suma acumulada de las frecuencias depalabras (vea Seccioacuten 10152) El uacuteltimo elemento en este arreglo es elnuacutemero total de palabras en el libro

3 Elija un nuacutemero aleatorio del 1 al Use buacutesqueda binaria (vea Seccioacuten101510) para encontrar el iacutendice donde se insertaraacute el nuacutemero aleatorio enla suma acumulada

4 Use el iacutendice para encontrar la palabra correspondiente en el arreglo depalabras

178 Capiacutetulo 13 Estudio de Caso Seleccioacuten de Estructura de Datos

Ejercicio 13-7

Escriba un programa que use este algoritmo para elegir una palabra aleatoriadel libro

Anaacutelisis de MarkovSi elige palabras del libro al azar puede tener una idea del vocabulario usadopero probablemente no se va a obtener una oracioacuten

rocinante plaacuteticas sazoacuten ojos Dulcinea Dios

Una serie de palabras aleatorias rara vez tiene sentido porque no hay relacioacutenentre palabras sucesivas Por ejemplo en una oracioacuten real se esperariacutea que unartiacuteculo como el fuese seguido por un sustantivo y probablemente no un verboo un adverbio

Una forma de medir este tipo de relaciones es con el anaacutelisis de Markov quedefine para una secuencia dada de palabras la probabilidad de las palabras quepodriacutean venir despueacutes Por ejemplo en la cancioacuten La vida es un carnaval (deCeliz Cruz)

Todo aquelQue piense que la vida siempre es cruelTiene que saber que no es asiacuteQue tan solo hay momentos malosY todo pasa

Todo aquelQue piense que esto nunca va cambiarTiene que saber que no es asiacuteQue al mal tiempo buena caraY todo cambia

Ay no hay que llorar (No hay que llorar)Que la vida es un carnavalQue es maacutes bello vivir cantando

En este texto la frase que piense siempre va seguida de la palabra que perola frase piense que puede ir seguida de la o esto

El resultado del anaacutelisis de Markov es un mapeo de cada prefijo (como quepiense y piense que) a todos los sufijos posibles (como la y esto)

Dada esta asignacioacuten se puede generar un texto aleatorio comenzando concualquier prefijo y eligiendo aleatoriamente entre los posibles sufijos A

Anaacutelisis de Markov 179

continuacioacuten puede combinar el final del prefijo y el nuevo sufijo para formar elsiguiente prefijo y repetir

Por ejemplo si comienza con el prefijo Que la la siguiente palabra seraacute vidaporque el prefijo solo aparece dos veces en el texto y siempre estaacute seguido deeste sufijo El siguiente prefijo es la vida por lo que el siguiente sufijo podriacuteaser siempre o es

En este ejemplo la longitud del prefijo siempre es dos pero puede hacer anaacutelisisde Markov con un prefijo de cualquier longitud

Ejercicio 13-8

Anaacutelisis de Markov

1 Escriba un programa que lea un texto desde un archivo y realice un anaacutelisisde Markov El resultado debe ser un diccionario que asocie prefijos y unacoleccioacuten de posibles sufijos La coleccioacuten puede ser un arreglo tupla odiccionario depende de usted hacer una eleccioacuten adecuada Puede probarsu programa con una longitud de prefijo de dos pero debe escribir elprograma de manera tal que sea faacutecil probar con otras longitudes

2 Agregue una funcioacuten al programa anterior para generar un texto aleatoriobasado en anaacutelisis de Markov Aquiacute hay un ejemplo de Don Quijote conlongitud de prefijo 2

Trifaldi habiacutea de Troya ni por la majestad real Y con mis quejasDesechaacutesteme iexcloh estremo su friacuteo del agravio a la espada tenieacutendolapor aca y maacutes que soacutelo se trueca y con el cual encendiacutea el ejemplo deaquellos cazadores

Para este ejemplo se dejoacute la puntuacioacuten anexa a las palabras El resultadoes casi sintaacutecticamente correcto Semaacutenticamente casi tiene sentido perono del todo

iquestQueacute sucede si aumenta la longitud del prefijo iquestEl texto aleatorio tiene maacutessentido

3 Una vez que su programa esteacute funcionando podriacutea probar combinandotexto de dos o maacutes libros El texto aleatorio que genere combinaraacute elvocabulario y las frases de las fuentes de maneras interesantes

Creacutedito Este estudio de caso se basa en un ejemplo de Kernighan y Pike ThePractice of Programming Addison-Wesley 1999

OBSERVACIOacuteN Debe hacer este ejercicio antes de continuar

180 Capiacutetulo 13 Estudio de Caso Seleccioacuten de Estructura de Datos

Estructuras de DatosUsar anaacutelisis de Markov para generar texto aleatorio es divertido pero ademaacuteseste ejercicio tiene un trasfondo la seleccioacuten de la estructura de datos En los losejercicios anteriores teniacutea que elegir

bull Coacutemo representar los prefijos

bull Coacutemo representar la coleccioacuten de los posibles sufijos

bull Coacutemo representar la asociacioacuten de cada prefijo con la coleccioacuten de posiblessufijos

El uacuteltimo es faacutecil un diccionario es la opcioacuten obvia para una asociacioacuten entreclaves y valores correspondientes

Para los prefijos las opciones maacutes obvias son cadena arreglo de cadenas o tuplade cadenas

Para los sufijos puede ser un arreglo o un histograma (diccionario)

iquestCoacutemo se elige El primer paso es pensar en las operaciones que deberaacuteimplementar para cada estructura de datos Para los prefijos se debe ser capazde eliminar palabras del principio y agregarlas al final Por ejemplo si el prefijoactual es que piense y la siguiente palabra es que debe poder formar elsiguiente prefijo piense que

Para los prefijos podriacutea elegir un arreglo ya que en eacutel es faacutecil agregar y eliminarelementos

Para la coleccioacuten de sufijos las operaciones que se deben realizar incluyenagregar un nuevo sufijo (o aumentar la frecuencia de uno existente) y elegir unsufijo aleatorio

Agregar un nuevo sufijo es igualmente faacutecil para la implementacioacuten del arreglo odel histograma Elegir un elemento aleatorio de un arreglo es faacutecil pero elegireficientemente de un histograma es maacutes difiacutecil (ver Seccioacuten 1371)

Hasta ahora se ha hablado principalmente sobre la facilidad de implementacioacutenpero hay otros factores a considerar al elegir las estructuras de datos Uno es eltiempo de ejecucioacuten A veces hay una razoacuten teoacuterica para esperar que unaestructura de datos sea maacutes raacutepida que otra Por ejemplo anteriormente semencionoacute que el operador in es maacutes raacutepido para los diccionarios que para losarreglos al menos cuando el nuacutemero de elementos es grande

Aunque generalmente no se sabe de antemano queacute implementacioacuten seraacute maacutesraacutepida una opcioacuten es implementar ambos y ver cuaacutel es mejor Este enfoque sellama benchmarking Una alternativa praacutectica es elegir la estructura de datosque sea maacutes faacutecil de implementar y luego ver si es lo suficientemente raacutepida parala aplicacioacuten prevista Si es asiacute no hay necesidad de continuar Si no hay

Estructuras de Datos 181

herramientas como el moacutedulo Profile que pueden identificar los lugares en unprograma que toman maacutes tiempo

El otro factor a considerar es el espacio de almacenamiento Por ejemplo usar unhistograma para la coleccioacuten de sufijos puede tomar menos espacio porque solotiene que almacenar cada palabra una vez sin importar cuaacutentas veces aparezcaen el texto En algunos casos ahorrar espacio tambieacuten puede hacer que suprograma se ejecute maacutes raacutepido En el peor de los casos su programa podriacutea noejecutarse si se queda sin memoria pero para muchas aplicaciones el espacio esuna consideracioacuten secundaria despueacutes del tiempo de ejecucioacuten

Una uacuteltima reflexioacuten en esta discusioacuten se ha dado a entender que se deberiacuteausar una estructura de datos para el anaacutelisis y la generacioacuten Pero dado queestas son fases separadas tambieacuten seriacutea posible usar una estructura para elanaacutelisis y luego convertirla en otra estructura para la generacioacuten Esto seriacuteaconveniente si el tiempo ahorrado durante la generacioacuten excede el tiempodedicado a la conversioacuten

OBSERVACIOacuteNEl paquete de Julia DataStructures (verhttpsgithubcomJuliaCollectionsDataStructuresjl)implementa una variedad de estructuras de datos

DepuracioacutenCuando estaacute depurando un programa y especialmente si estaacute tratando deresolver un error difiacutecil hay cinco cosas que puede probar

LeeExamine su coacutedigo leacutealo y verifique que dice lo que queriacutea decir

EjecutaExperimente haciendo cambios y ejecutando diferentes versiones Amenudo si muestra lo correcto en el lugar correcto del programa elproblema se vuelve obvio pero para ello a veces tiene que desarrollarandamiaje

ReflexionaiexclToacutemese un tiempo para pensar iquestQueacute tipo de error es de sintaxis tiempode ejecucioacuten o semaacutentica iquestQueacute informacioacuten puede obtener de los mensajesde error o de la salida del programa iquestQueacute tipo de error podriacutea causar elproblema que estaacutes viendo iquestQueacute cambioacute antes de que apareciera elproblema

HablaSi le explica el problema a otra persona a veces puede encontrar larespuesta incluso antes de terminar de hacer la pregunta Generalmente no

182 Capiacutetulo 13 Estudio de Caso Seleccioacuten de Estructura de Datos

es necesaria otra persona incluso se podriacutea hablar con un pato de gomaEste es el origen de la conocida estrategia llamada depuracioacuten del pato degoma Esto es real vea httpsenwikipediaorgwikiRubber_duck_debugging

Vuelve atraacutesEn ocasiones lo mejor que puede hacer es retroceder deshacer los cambiosrecientes hasta regresar a un programa que funcione y que comprenda Unavez logrado esto puede comenzar a reconstruir

Los programadores principiantes a veces se atascan en una de estas actividadesy olvidan las otras Cada actividad viene con su propia forma de fallar

Por ejemplo leer su coacutedigo podriacutea ayudar si el problema es un error tipograacuteficopero no si el problema es un malentendido conceptual Si no comprende lo quehace su programa puede leerlo 100 veces y nunca ver el error porque el errorestaacute en su cabeza

Ejecutar experimentos puede ayudar especialmente si ejecuta pruebas pequentildeasy simples pero si ejecuta experimentos sin pensar o leer su coacutedigo puede caeren un patroacuten llamado programacioacuten de caminata aleatoria que es el proceso dehacer cambios aleatorios hasta que el programa haga lo correcto No hace faltadecir que la programacioacuten de caminata aleatoria puede llevar mucho tiempo

La persona que programa tiene que tomarse su tiempo para pensar Ladepuracioacuten es como una ciencia experimental Debe tener al menos una hipoacutetesissobre la causa del problema Si hay dos o maacutes opciones trate de pensar en unaprueba que elimine una de ellas

Incluso las mejores teacutecnicas de depuracioacuten fallaraacuten si hay demasiados errores osi el coacutedigo que estaacute tratando de corregir es demasiado grande y complicado Aveces la mejor opcioacuten es volver atraacutes simplificando el programa hasta quellegue a algo que funcione y que comprenda

Los programadores principiantes a menudo son reacios a volver atraacutes porque nopueden soportar eliminar una liacutenea de coacutedigo (incluso si es incorrecto) Si le hacesentir mejor copie su programa en otro archivo antes de comenzar a eliminarloLuego puede copiar las piezas una por una

Encontrar un error difiacutecil requiere leer ejecutar reflexionar y a veces volveratraacutes Si se queda atascado en una de estas actividades pruebe las otras

Glosariodeterminiacutestico

Perteneciente a un programa que hace lo mismo cada vez que se ejecuta apartir de las mismas entradas

Glosario 183

pseudoaleatorioPerteneciente a una secuencia de nuacutemeros que parecen ser aleatorios peroque son generados por un programa determinista

valor por defecto (o valor por omisioacuten)El valor dado a un paraacutemetro opcional si no se proporciona un argumento

anularReemplazar un valor por defecto con un argumento

benchmarkingEl proceso de elegir entre estructuras de datos implementando alternativasy probaacutendolas con una muestra de las posibles entradas

depuracioacuten del pato de gomaDepuracioacuten en doacutende se explica el problema a un objeto inanimado talcomo un pato de goma Articular el problema puede ayudarle a resolverloincluso si el pato de goma no sabe de Julia

Ejercicios

Ejercicio 13-9

El rango de una palabra es su posicioacuten en un arreglo de palabras ordenadaspor frecuencia la palabra maacutes comuacuten tiene rango 1 la segunda maacutes comuacuten tienerango 2 etc

La ley de Zipf describe una relacioacuten entre los rangos y las frecuencias de laspalabras en idiomas naturales (httpsenwikipediaorgwikiZipfs_law)Especiacuteficamente predice que la frecuencia de la palabra con rango es

donde y son paraacutemetros que dependen del idioma y el texto Si aplicaslogaritmo a ambos lados de esta ecuacioacuten obtienes

Entonces si se grafica versus se deberiacutea obtener una liacutenea recta conpendiente e intercepto

Escriba un programa que lea un texto de un archivo cuente las frecuencias delas palabras e imprima una liacutenea para cada palabra en orden descendente defrecuencia con y

Instale una libreriacutea para graficar

184 Capiacutetulo 13 Estudio de Caso Seleccioacuten de Estructura de Datos

(v10) pkggt add Plots

Su uso es muy sencillo

using Plotsx = 110y = x^2plot(x y)

Use la libreriacutea Plots para graficar los resultados y verificar si forman una liacutenearecta

Ejercicios 185

Capiacutetulo 14 ArchivosEste capiacutetulo presenta el concepto de persistencia que alude a los programasque mantienen los datos en almacenamiento permanente y muestra coacutemo usardiferentes tipos de almacenamiento permanente tales como archivos y bases dedatos

PersistenciaLa mayoriacutea de los programas que hemos visto hasta ahora han sido transitorioses decir se ejecutan por un tiempo corto y generan una salida pero cuandofinalizan sus datos desaparecen Si ejecuta el programa nuevamente estecomienza de cero

Otros programas en cambio son persistentes se ejecutan durante un largoperiacuteodo de tiempo (o todo el tiempo) mantienen al menos parte de sus datos enalmacenamiento permanente (en un disco duro por ejemplo) y si se apagan yvuelven a comenzar retoman donde lo dejaron

Ejemplos de programas persistentes son los sistemas operativos que se ejecutansiempre que una computadora esteacute encendida y los servidores web que seejecutan todo el tiempo esperando a que lleguen solicitudes a la red

Una de las formas maacutes simples para que los programas mantengan sus datos esleyendo y escribiendo archivos de texto Ya se han visto programas que leenarchivos de texto y en este capiacutetulo se van a ver programas que los escriben

Otra alternativa es almacenar el estado del programa en una base de datos Eneste capiacutetulo tambieacuten se presentaraacute coacutemo usar una base de datos simple

Lectura y EscrituraUn archivo de texto es una secuencia de caracteres almacenados en un mediopermanente como un disco duro o una memoria flash Ya se vio coacutemo abrir y leerun archivo en Seccioacuten 91

Para escribir un archivo debe abrirlo usando el modo w (de write) comosegundo paraacutemetro

juliagt fout = open(salidatxt w)IOStream(ltfile salidatxtgt)

Si el archivo ya existe abrirlo en modo de escritura borra los datos antiguos ycomienza de nuevo iexclasiacute que tenga cuidado Si el archivo no existe se crea unonuevo open devuelve un objeto de archivo y la funcioacuten write escribe datos en elarchivo

186 Capiacutetulo 14 Archivos

juliagt linea1 = El Cid convoca a sus vasallosn

juliagt write(fout linea1)31

El valor de retorno es el nuacutemero de caracteres que se escribieron El objeto dearchivo fout lleva el registro de doacutende se quedoacute por uacuteltima vez por lo que sillama a write nuevamente esta agrega nuevos datos al final del archivo

juliagt linea2 = eacutestos se destierran con eacuteln

juliagt write(fout linea2)30

Cuando el usuario haya terminado de escribir debe cerrar el archivo

juliagt close(fout)

Si no cierra el archivo este se cierra cuando finaliza el programa

FormateoEl argumento de write tiene que ser una cadena por lo que si queremos ponerotros valores en un archivo tenemos que convertirlos a cadenas La forma maacutesfaacutecil de hacerlo es con la funcioacuten string o con interpolacioacuten de cadenas

juliagt fout = open(salidatxt w)IOStream(ltfile salidatxtgt)juliagt write(fout string(150))3

Otra alternativa es utilizar la familia de funciones de print(ln)

juliagt camellos = 4242juliagt println(fout He visto $camellos camellos)

OBSERVACIOacuteN

Una alternativa maacutes potente es la macro printf queimprime utilizando cadenas con especificacioacuten deformato al maacutes puro estilo C Puede leer maacutes sobre estoen httpsdocsjulialangorgenv1stdlibPrintf

Formateo 187

Nombre de Archivo y RutaLos archivos estaacuten organizados en directorios (tambieacuten llamados carpetas)Cada programa en ejecucioacuten tiene su propio directorio actual que es eldirectorio que usaraacute por defecto para para la mayoriacutea de las operaciones Porejemplo cuando abre un archivo para leer Julia lo busca en el directorio actual

La funcioacuten pwd (en ingleacutes print working directory) devuelve el nombre deldirectorio actual

juliagt cwd = pwd()homeben

cwd significa directorio del trabajo actual (en ingleacutes ldquocurrent workingdirectoryrdquo) El resultado en este ejemplo es homeben que es el directorio deinicio de un usuario llamado ben

Una cadena como homeben que identifica un archivo o directorio se llamaruta o path

Un nombre de archivo simple como memotxt tambieacuten se considera una rutaaunque es una ruta relativa porque comienza en el directorio actual Si eldirectorio actual es homeben el nombre de archivo memotxt se refiere ahomebenmemotxt

Una ruta que comienza con no depende del directorio actual Este tipo de rutase llama ruta absoluta Para encontrar la ruta absoluta de un archivo puede usarabspath

juliagt abspath(memotxt)homebenmemotxt

Julia tambieacuten tiene otras funciones para trabajar con nombres de archivo y rutasPor ejemplo ispath comprueba si existe un archivo o directorio

juliagt ispath(memotxt)true

Si existe isdir comprueba si es un directorio

juliagt isdir(memotxt)falsejuliagt isdir(homeben)true

188 Capiacutetulo 14 Archivos

Del mismo modo isfile comprueba que se trate de un archivo

readdir devuelve un arreglo de los archivos (y otros directorios) en el directoriodado

juliagt readdir(cwd)3-element ArrayString1 memotxt musica fotos

Para mostrar el comportamiento de estas funciones el siguiente ejemplorecorre un directorio imprime los nombres de todos los archivos y se llama a siacutemisma de manera recursiva en todos los directorios

function recorrer(nombredir) for nombre in readdir(nombredir) ruta = joinpath(nombredir nombre) if isfile(ruta) println(ruta) else recorrer(ruta) end endend

joinpath toma un directorio y un nombre de archivo y los une en una rutacompleta

OBSERVACIOacuteN

Julia tiene una funcioacuten integrada llamada walkdir (veahttpsdocsjulialangorgenv1basefileBaseFilesystemwalkdir) que es similar a esta pero maacutesversaacutetil Como ejercicio lea la documentacioacuten y uacuteselapara imprimir los nombres de los archivos en undirectorio dado y sus subdirectorios

Captura de ExcepcionesMuchas cosas pueden salir mal al intentar leer y escribir archivos Al intentarabrir un archivo que no existe se obtiene un SystemError

juliagt fin = open(archivo_malo)ERROR SystemError opening file archivo_malo No such file or directory

Si el usuario intenta abrir un archivo pero no tiene permiso para acceder a eacutel

Captura de Excepciones 189

obtiene el error de sistema Permission denied (Permiso denegado)

Para evitar estos errores se podriacutean usar funciones como ispath e isfile perotomariacutea mucho tiempo y liacuteneas de coacutedigo verificar todas las posibilidades

Es maacutes faacutecil intentar lidiar con los problemas a medida que ocurren que esexactamente lo que hace la sentencia try La sintaxis es similar a una sentenciaif

try fin = open(archivo_malotxt)catch exc println(Algo salioacute mal $exc)end

Julia comienza ejecutando el bloque try Si nada falla se saltaraacute el bloque catch yfinalizaraacute Si ocurre una excepcioacuten Julia saltaraacute fuera del bloque try y ejecutaraacuteel bloque catch

Gestionar una excepcioacuten con try recibe el nombre de capturar una excepcioacuten Eneste ejemplo el bloque catch muestra un mensaje de error que no es muy uacutetil Engeneral capturar una excepcioacuten da la oportunidad de corregir el problemavolverlo a intentar o al menos terminar el programa con elegancia

Cuando el coacutedigo realiza cambios de estado o usa recursos como archivosgeneralmente se deben hacer ciertas cosas al finalizar la programacioacuten delcoacutedigo como por ejemplo cerrar los archivos Las excepciones pueden complicaresta tarea ya que se podriacutea salir antes de lo esperado de un bloque de coacutedigo Lapalabra reservada finally permite ejecutar un coacutedigo al salir de un bloque decoacutedigo determinado independientemente de coacutemo salga

f = open(salidatxt)try linea = readline(f) println(linea)finally close(f)end

En este ejemplo la funcioacuten close siempre se ejecutaraacute

Bases de datosUna base de datos es un archivo que estaacute organizado para almacenar datos Lamayoriacutea de las bases de datos estaacuten organizadas como diccionarios en el sentidode que realizan asociaciones entre claves y valores La diferencia maacutes importanteentre un diccionario y una base de datos es que la base de datos se encuentra en

190 Capiacutetulo 14 Archivos

el disco (u otro almacenamiento permanente) de modo que su contenido seconserva despueacutes de que el programa haya finalizado

IntroAJulia proporciona una interfaz para GDBM (GNU dbm) que permite creary actualizar archivos de base de datos A modo de ejemplo se crea una base dedatos que contiene pies de foto para archivos de imagen

Abrir una base de datos es similar a abrir otros archivos

juliagt using IntroAJulia

juliagt bd = DBM(piedefoto c)DBM(ltpiedefotogt)

El modo c significa que la base de datos debe crearse si no existe El resultadoes un objeto de base de datos que se puede usar (para la mayoriacutea de lasoperaciones) como un diccionario

Cuando se crea un nuevo elemento GDBM actualiza el archivo de base de datos

juliagt bd[luismipng] = Foto de Luis MiguelFoto de Luis Miguel

Cuando accede a uno de los elementos GDBM lee el archivo

juliagt bd[luismipng]Foto de Luis Miguel

Si realiza otra asignacioacuten a una clave existente GDBM reemplaza el valoranterior

juliagt bd[luismipng] = Foto de Luis Miguel cantandoFoto de Luis Miguel cantandojuliagt bd[luismipng]Foto de Luis Miguel cantando

Algunas funciones que tienen un diccionario como argumento con claves yvalores no funcionan con objetos de base de datos No obstante la iteracioacuten conun bucle for siacute

for (clave valor) in bd println(clave valor)end

Al igual que con otros archivos debe cerrar la base de datos cuando haya

Bases de datos 191

terminado

juliagt close(bd)

SerializacioacutenUna limitacioacuten de GDBM es que las claves y los valores deben ser cadenas oconjuntos de bytes Si intenta utilizar cualquier otro tipo se produciraacute un error

Las funciones serialize y deserialize pueden ser uacutetiles Traducen casi cualquiertipo de objeto en un arreglo de bytes (un iobuffer) adecuado para elalmacenamiento en una base de datos y luego traducen los arreglos de bytesnuevamente en objetos

juliagt using Serialization

juliagt io = IOBuffer()

juliagt t = [1 2 3]

juliagt serialize(io t)24juliagt print(take(io))UInt8[0x37 0x4a 0x4c 0x0a 0x04 0x00 0x00 0x00 0x15 0x00 0x080xe2 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x02 0x00 0x000x00 0x00 0x00 0x00 0x00 0x03 0x00 0x00 0x00 0x00 0x00 0x000x00]

El formato no es intuitivo para nosotros pero es faacutecil de interpretar para Juliadeserialize reconstituye el objeto

juliagt io = IOBuffer()

juliagt t1 = [1 2 3]

juliagt serialize(io t1)24juliagt s = take(io)

juliagt t2 = deserialize(IOBuffer(s))

juliagt print(t2)[1 2 3]

serialize y deserialize escriben y leen desde un objeto iobuffer que representa unIO stream en memoria La funcioacuten take recupera el contenido del iobuffer como

192 Capiacutetulo 14 Archivos

un arreglo de bytes y reestablece el iobuffer a su estado inicial

Aunque el nuevo objeto tiene el mismo valor que el anterior no es (en general) elmismo objeto

juliagt t1 == t2truejuliagt t1 equiv t2false

En otras palabras la serializacioacuten y luego la deserializacioacuten tienen el mismoefecto que copiar el objeto

Esto se puede usar para almacenar valores que no sean cadenas en una base dedatos

OBSERVACIOacuteN

De hecho el almacenamiento de valores que no soncadenas en una base de datos es tan comuacuten que se haencapsulado en un paquete llamado JLD2 (consultehttpsgithubcomJuliaIOJLD2jl)

Objetos de ComandoLa mayoriacutea de los sistemas operativos proporcionan una interfaz de liacutenea decomandos tambieacuten conocida como shell Las shells generalmente proporcionancomandos para navegar por el sistema de archivos y ejecutar aplicaciones Porejemplo en Unix puede cambiar los directorios con cd mostrar el contenido deun directorio con ls e iniciar un navegador web escribiendo (por ejemplo) firefox

Cualquier programa que se pueda iniciar desde la shell tambieacuten puede iniciarsedesde Julia usando un objeto de comando

juliagt cmd = `echo hola``echo hola`

Las comillas invertidas se usan para delimitar el comando

La funcioacuten run ejecuta el comando

juliagt run(cmd)hola

hola es la salida del comando echo enviado a STDOUT La funcioacuten run devuelveun objeto de proceso y genera un ErrorException si el comando externo no se

Objetos de Comando 193

ejecuta correctamente

Si se desea leer la salida del comando externo se puede usar read en su lugar

juliagt a = read(cmd String)holan

Por ejemplo la mayoriacutea de los sistemas Unix tienen un comando llamadomd5sum o md5 que lee el contenido de un archivo y calcula una suma deverificacioacuten Puede leer sobre Md5 en httpsenwikipediaorgwikiMd5 Estecomando proporciona una manera eficiente de verificar si dos archivos tienen elmismo contenido La probabilidad de que diferentes contenidos produzcan lamisma suma de comprobacioacuten es muy pequentildea

Puede usar un objeto de comando para ejecutar md5 desde Julia y obtener elresultado

juliagt nombrearchivo = salidatxtsalidatxtjuliagt cmd = `md5 $nombrearchivo``md5 salidatxt`juliagt res = read(cmd String)ERROR IOError could not spawn `md5 salidatxt` no such file ordirectory (ENOENT)

Modulos

Supongamos que tenemos un archivo llamado wcjl con el siguiente coacutedigo

function contarlineas(nombrearchivo) conteo = 0 for linea in eachline(nombrearchivo) conteo += 1 end conteoend

print(contarlineas(wcjl))

Si ejecuta este programa se leen las liacuteneas de coacutedigo y se imprime el nuacutemero deliacuteneas en el archivo que es 9 Tambieacuten puede incluirlo en REPL de esta manera

juliagt include(wcjl)9

194 Capiacutetulo 14 Archivos

Los moacutedulos permiten crear espacios de trabajo separados es decir nuevosglobal scopes (aacutembitos de tipo global) Una sentencia tiene global scope si tieneefecto en todo el programa

Un moacutedulo comienza con la palabra reservada module y termina con end Al usarmoacutedulos se evitan los conflictos de nombres entre sus propias definiciones denivel superior y las que se encuentran en el coacutedigo de otra persona importpermite controlar queacute nombres de otros moacutedulos estaacuten visibles y exportespecifica cuaacuteles de sus nombres son puacuteblicos es decir aquellos que se puedenusar fuera del moacutedulo sin tener el prefijo del nombre del moacutedulo

module ContarLineas export contarlineas

function contarlineas(nombrearchivo) conteo = 0 for linea in eachline(nombrearchivo) conteo += 1 end conteo endend

El moacutedulo ContarLineas proporciona la funcioacuten contarlineas

juliagt using ContarLineas

juliagt contarlineas(wcjl)11

Ejercicio 14-1

Escriba este ejemplo en un archivo llamado wcjl incluacuteyalo en REPL (coninclude) y escriba using ContarLineas

AVISO

Si importa un moacutedulo que ya se ha importado Julia no hace nadaNo se vuelve a leer el archivo incluso si ha sido modificado

Si desea volver a cargar un moacutedulo debe reiniciar REPL Elpaquete Revise puede ayudarlo a no reiniciar tan seguido (veahttpsgithubcomtimholyRevisejl)

DepuracioacutenAl leer y escribir archivos el usuario puede tener problemas con los espacios enblanco Estos errores pueden ser difiacuteciles de depurar porque los espacios las

Depuracioacuten 195

tabulaciones y las nuevas liacuteneas son generalmente invisibles

juliagt s = 1 2t 3n 4

juliagt println(s)1 2 3 4

Las funciones integradas repr o dump pueden ser de ayuda Toman cualquierobjeto como argumento y devuelven una representacioacuten de tipo cadena delobjeto

1 2t 3n 4

juliagt repr(s)1 2t 3n 4juliagt dump(s)String 1 2t 3n 4

Esto puede ser uacutetil para la depuracioacuten

Otro problema con el que es faacutecil encontrarse es que en diferentes sistemasoperativos se usan diferentes caracteres para indicar el final de una liacuteneaAlgunos sistemas usan una nueva liacutenea representada por n Otros usan uncaraacutecter de retorno r Algunos usan ambos Si un archivo es usado en diferentessistemas estas inconsistencias podriacutean causar problemas

Para la mayoriacutea de los sistemas hay aplicaciones para convertir de un formato aotro Puede encontrarlas (y leer maacutes sobre este tema) enhttpsenwikipediaorgwikiNewline O por supuesto podriacutea escribir una ustedmismo

Glosariopersistente

Perteneciente a un programa que se ejecuta indefinidamente y mantiene almenos algunos de sus datos en almacenamiento permanente

archivo de textoUna secuencia de caracteres almacenados en almacenamiento permanentetal como en un disco duro

directorioUna coleccioacuten de archivos con nombre tambieacuten llamada carpeta

196 Capiacutetulo 14 Archivos

rutaUna cadena que identifica a un archivo

ruta relativaUna ruta que comienza en el directorio actual

ruta absolutaUna ruta que comienza en el directorio superior del sistema de archivos

capturar (catch)Evitar que una excepcioacuten haga terminar un programa utilizando lassentencias try catch finally

base de datosUn archivo cuyo contenido estaacute organizado como un diccionario con clavesque corresponden a valores

shellUn programa que permite a los usuarios escribir comandos y luegoejecutarlos iniciando otros programas

objeto de comandoUn objeto que representa un comando de shell Esto permite que unprograma de Julia ejecute comandos y lea los resultados

Ejercicios

Ejercicio 14-2

Escriba una funcioacuten llamada sed que tome como argumentos una cadena depatrones una cadena de reemplazo y dos nombres de archivo La funcioacuten debeleer el primer archivo y escribir el contenido en el segundo archivo (creaacutendolo sies necesario) Si la cadena de patrones aparece en alguacuten lugar del archivo debereemplazarse con la cadena de reemplazo

Si se produce un error al abrir leer escribir o cerrar los archivos su programadebe detectar la excepcioacuten imprimir un mensaje de error y terminar

Ejercicio 14-3

Si hizo Seccioacuten 12102 recordaraacute que debiacutea crear un diccionario que asociabauna cadena ordenada de letras al conjunto de palabras que se podiacutea deletrearcon esas letras Por ejemplo cuaderno estaba asociado al arreglo [cuadernoeducaron encuadro]

Escriba un moacutedulo que importe conjuntoanagramas y proporcione dos nuevas

Ejercicios 197

funciones almacenaranagramas que almacena el diccionario de anagramasusando JLD2 (vea httpsgithubcomJuliaIOJLD2jl) y leeranagramas que buscauna palabra y devuelve un arreglo de sus anagramas

Ejercicio 14-4

En una gran coleccioacuten de archivos MP3 puede haber maacutes de una copia de lamisma cancioacuten almacenada en diferentes directorios o con diferentes nombresde archivo El objetivo de este ejercicio es buscar duplicados

1 Escriba un programa que busque un directorio y todos sus subdirectoriosde forma recursiva y devuelva un arreglo de rutas completas para todos losarchivos con un sufijo dado (como mp3)

2 Para reconocer duplicados puede usar md5sum o md5 para calcular unasuma de verificacioacuten para cada archivo Si dos archivos tienen la mismasuma de verificacioacuten probablemente tengan el mismo contenido

3 Para verificarlo puede usar el comando de Unix diff

198 Capiacutetulo 14 Archivos

Capiacutetulo 15 Estructuras y ObjetosA esta altura ya debe saber coacutemo usar funciones para tener un coacutedigo maacutesorganizado y coacutemo usar los tipos integrados de Julia para organizar sus datos Elsiguiente paso es aprender a construir sus propios tipos para organizar tanto elcoacutedigo como los datos Este es un gran tema y por lo tanto tomaraacute un par decapiacutetulos abarcar todo

Tipos CompuestosSe han utilizado muchos tipos integrados en Julia y ahora se va a definir unnuevo tipo A modo de ejemplo se crea un tipo llamado Punto que representa unpunto en un espacio bidimensional

En notacioacuten matemaacutetica los puntos suelen escribirse entre pareacutentesis con unacoma que separa las coordenadas Por ejemplo representa el origen y representa el punto localizado unidades a la derecha y unidades hacia arribadel origen

Hay varias formas en que se podriacutean representar puntos del plano cartesiano enJulia

bull Almacenando las coordenadas por separado en dos variables x e y

bull Almacenando las coordenadas como elementos de un arreglo o tupla

bull Creando un nuevo tipo para representar puntos como objetos

Crear un nuevo tipo exige un poco maacutes de esfuerzo que las otras dos opcionespero tiene algunas ventajas como pronto se veraacute

Un tipo compuesto definido por el programador tambieacuten se denomina estructura(struct en ingleacutes) La definicioacuten de estructura de un punto se ve asiacute

struct Punto x yend

El encabezado indica que la nueva estructura se llama Punto El cuerpo definelos atributos o campos de la estructura La estructura de Punto tiene doscampos x e y

Una estructura es como una faacutebrica que crea objetos Para crear un punto sedebe llamar a Punto como si fuera una funcioacuten que tiene como argumentos losvalores de los campos Cuando Punto se usa como una funcioacuten se llamaconstructor

Tipos Compuestos 199

juliagt p = Punto(30 40)Punto(30 40)

El valor de retorno es una referencia a un objeto Punto el cual es asignado a p

La creacioacuten de un nuevo objeto se llama instanciacioacuten y el objeto creado es unainstancia del tipo

Cuando se imprime una instancia Julia dice a queacute tipo pertenece y cuaacuteles son losvalores de los atributos

Cada objeto es una instancia de alguacuten tipo por lo que objeto e instancia sonintercambiables No obstante en este capiacutetulo se utiliza instancia para indicarque se estaacute hablando de un tipo definido por el programador

Un diagrama de estado que muestra un objeto y sus atributos se denominadiagrama de objeto (ver Figura 20)

Figura 20 Diagrama de objeto

Las Estructuras son Inmutables

Puede obtener los valores de los campos utilizando la notacioacuten

juliagt x = px30juliagt py40

La expresioacuten px significa Vaya al objeto al que se apunta p y obtenga el valorde x En el ejemplo se asigna ese valor a una variable llamada x No hayconflicto entre la variable x y el atributo x

Puede usar esa notacioacuten de punto como parte de cualquier expresioacuten Porejemplo

juliagt distancia = sqrt(px^2 + py^2)50

Sin embargo las estructuras son inmutables por defecto y despueacutes de laconstruccioacuten los campos no pueden cambiar su valor

200 Capiacutetulo 15 Estructuras y Objetos

juliagt py = 10ERROR setfield immutable struct of type Punto cannot be changed

Esto puede parecer extrantildeo al principio pero tiene varias ventajas

bull Puede ser maacutes eficiente

bull No es posible violar las invariantes (requisitos que deberiacutean cumplirse entodos los objetos en todo momento) de los constructores de un tipocompuesto (ver Seccioacuten 174)

bull El coacutedigo que usa objetos inmutables puede ser maacutes faacutecil de entender

Estructuras MutablesDe ser necesario se pueden declarar tipos compuestos mutables con la palabrareservada mutable struct A continuacioacuten se muestra la definicioacuten de un puntomutable

mutable struct MPunto x yend

Puede asignar valores a una instancia de una estructura mutable utilizandonotacioacuten de punto ()

juliagt blanco = MPunto(00 00)MPunto(00 00)juliagt blancox = 3030juliagt blancoy = 4040

RectaacutengulosA veces decidir cuaacuteles deberiacutean ser los campos de un objeto es faacutecil pero enotros casos no Por ejemplo imagine que se quiere un tipo que represente unrectaacutengulo iquestQueacute campos usariacutea para especificar la ubicacioacuten y el tamantildeo de unrectaacutengulo Puede ignorar el aacutengulo Para simplificar las cosas suponga que elrectaacutengulo es vertical u horizontal

Hay al menos dos posibilidades

bull Puede especificar una esquina del rectaacutengulo (o el centro) el ancho y laaltura

Estructuras Mutables 201

bull Puede especificar dos esquinas opuestas

Es difiacutecil decir que una opcioacuten es mejor que la otra por lo que implementaremosla primera a modo de ejemplo

Representa un rectaacutengulo

atributos ancho alto esquinastruct Rectangulo ancho alto esquinaend

El texto escrito entre comillas triples es llamado cadena de documentacioacuten (odocstring) y permite documentar La documentacioacuten es el acto de comentarconvenientemente cada una de las partes que tiene el programa

En este ejemplo la cadena de documentacioacuten (o docstring) enumera losatributos Los atributos ancho y alto son nuacutemeros y esquina es un objeto Puntoque especifica la esquina inferior izquierda

Para representar un rectaacutengulo debe crear una instancia del tipo Rectangulo

juliagt origen = MPunto(00 00)MPunto(00 00)juliagt caja = Rectangulo(1000 2000 origen)Rectangulo(1000 2000 MPunto(00 00))

Figura 21 muestra el estado de este objeto Un objeto es embebido si es atributode otro objeto Debido a que el atributo esquina se refiere a un objeto mutablese dibuja fuera del objeto Rectangulo

Figura 21 Diagrama de objeto

Instancias como ArgumentosPodemos pasar una instancia como argumento de la manera habitual Porejemplo

202 Capiacutetulo 15 Estructuras y Objetos

function imprimirpunto(p) println(($(px) $(py)))end

imprimirpunto toma un Punto como argumento y lo muestra en notacioacutenmatemaacutetica Puede llamar a imprimirpunto con un argumento p

juliagt imprimirpunto(blanco)(30 40)

Ejercicio 15-1

Escriba una funcioacuten llamada distanciaentrepuntos que tome dos puntos comoargumentos y devuelva la distancia entre ellos

Si un objeto de estructura mutable se pasa a una funcioacuten como argumento lafuncioacuten puede modificar los campos del objeto Por ejemplo moverpunto tomaun objeto mutable Punto y dos nuacutemeros dx y dy los cuales suma a los atributos xe y de Punto respectivamente

function moverpunto(p dx dy) px += dx py += dy nothingend

Aquiacute hay un ejemplo que muestra como funciona

juliagt origen = MPunto(00 00)MPunto(00 00)juliagt moverpunto(origen 10 20)

juliagt origenMPunto(10 20)

Dentro de la funcioacuten p es un alias de origen por lo que cuando la funcioacutenmodifica p origen tambieacuten cambia

Al pasar un objeto inmutable Punto a moverpunto se produce un error

juliagt moverpunto(p 10 20)ERROR setfield immutable struct of type Punto cannot be changed

Sin embargo se puede modificar el valor de un atributo mutable de un objeto

Instancias como Argumentos 203

inmutable Por ejemplo moverrectangulo tiene como argumentos un objetoRectangulo y dos nuacutemeros dx y dy Esta funcioacuten usa moverpunto para mover laesquina del rectaacutengulo

function moverrectangulo(rect dx dy) moverpunto(rectesquina dx dy)end

Ahora p en moverpunto es un alias para rectesquina por lo que cuando p semodifica rectesquina tambieacuten cambia

juliagt cajaRectangulo(1000 2000 MPunto(00 00))juliagt moverrectangulo(caja 10 20)

juliagt cajaRectangulo(1000 2000 MPunto(10 20))

AVISO

No puede reasignar un atributo mutable de un objeto inmutable

juliagt cajaesquina = MPunto(10 20)ERROR setfield immutable struct of type Rectangulo cannotbe changed

Instancias como Valores de RetornoLas funciones pueden devolver instancias Por ejemplo encontrarcentro toma unRectangulo como argumento y devuelve un Punto que contiene las coordenadasdel centro del rectaacutengulo

function encontrarcentro(rect) Punto(rectesquinax + rectancho 2 rectesquinay + rectalto 2)end

La expresioacuten rectcornerx significa ldquoVaya al objeto al que rect apunta yseleccione el atributo llamado esquina Luego vaya a ese objeto y seleccione elatributo llamado x

A continucioacuten se observa un ejemplo que toma caja como argumento y asigna elPunto resultante a centro

juliagt centro = encontrarcentro(caja)Punto(510 1020)

204 Capiacutetulo 15 Estructuras y Objetos

CopiadoEl uso de alias puede hacer que un programa sea difiacutecil de leer ya que loscambios hechos en un lugar pueden tener efectos inesperados en otro lugar Esdifiacutecil estar al tanto de todas las variables a las que puede apuntar un objetodado

Copiar un objeto es muchas veces una alternativa a la creacioacuten de un alias Juliaprovee una funcioacuten llamada copy que puede duplicar cualquier objeto

juliagt p1 = MPunto(30 40)MPunto(30 40)juliagt p2 = deepcopy(p1)MPunto(30 40)juliagt p1 equiv p2falsejuliagt p1 == p2false

El operador equiv indica que p1 y p2 no son el mismo objeto lo cual es esperable Loque no es del todo esperable es que == no devuelva true aunque estos puntoscontengan los mismos datos Resulta que para los objetos mutables elcomportamiento predeterminado del operador == es el mismo que el operador=== es decir comprueba la identidad del objeto no la equivalencia del objetoEsto se debe a que Julia no sabe queacute deberiacutea considerarse equivalente para lostipos compuestos mutables Al menos no todaviacutea

Ejercicio 15-2

Cree una instancia de Punto haga una copia y verifique la equivalencia y laigualdad de ambas El resultado puede sorprenderlo pero explica por queacute elalias no es un problema para un objeto inmutable

DepuracioacutenAl comenzar a trabajar con objetos es probable que encuentre algunasexcepciones nuevas Si intenta acceder a un campo que no existe obtendraacute

juliagt p = Punto(30 40)Punto(30 40)juliagt pz = 10ERROR type Punto has no field z

Si no estaacute seguro del tipo de un objeto puede saberlo de la siguiente manera

Copiado 205

juliagt typeof(p)Punto

Tambieacuten puede usar isa para verificar si un objeto es una instancia de un tipoespeciacutefico

juliagt p isa Puntotrue

Si no estaacute seguro de si un objeto tiene un atributo particular puede usar lafuncioacuten fieldnames

juliagt fieldnames(Punto)(x y)

o la funcioacuten isdefined

juliagt isdefined(p x)truejuliagt isdefined(p z)false

El primer argumento puede ser cualquier objeto y el segundo argumento es elsiacutembolo seguido del nombre del atributo

Glosarioestructura

Un tipo compuesto

constructorUna funcioacuten con el mismo nombre que un tipo que crea instancias de estetipo

instanciaUn objeto que pertenece a un tipo

instanciarCrear un nuevo objeto

atributo o campoUn valor con nombre asociado un objeto

206 Capiacutetulo 15 Estructuras y Objetos

objeto embebidoUn objeto que se almacena como atributo de otro objeto

deep copy o copia profundaCopiar el contenido de un objeto y cualquier objeto embebido en eacutel y a suvez cualquier objeto embebido en ellos y asiacute sucesivamente Implementadopor la funcioacuten deepcopy

diagrama de objetoUn diagrama que muestra objetos sus atributos y valores de atributos

Ejercicios

Ejercicio 15-3

1 Escriba una definicioacuten de un tipo llamado Circulo que tenga atributos centroy radio y doacutende centro sea un objeto Punto y radio un nuacutemero

2 Cree una instancia de un objeto Circulo que represente a un ciacuterculo concentro en y radio 75

3 Escriba una funcioacuten llamada puntoencirculo que tome un objeto Circulo y unobjeto Punto y devuelva true si el punto se encuentra dentro o en el liacutemitedel ciacuterculo

4 Escriba una funcioacuten llamada rectencirculo que tome un objeto Circulo y unobjeto Rectangulo y devuelva true si el rectaacutengulo se encuentracompletamente dentro o en el liacutemite del ciacuterculo

5 Escriba una funcioacuten llamada sobreposicionrectcirc que tome un objetoCirculo y un objeto Rectangulo y devuelva true si alguna de las esquinas delrectaacutengulo cae dentro del ciacuterculo Una versioacuten maacutes desafiante es escribiruna funcioacuten que devuelva true si alguna parte del rectaacutengulo (nonecesariamente una esquina) cae dentro del ciacuterculo

Ejercicio 15-4

1 Escriba una funcioacuten llamada dibujarrect que tome como argumentos unobjeto turtle y un objeto Rectaacutengulo y use turtle para dibujar el rectaacutenguloConsulte el Capiacutetulo 4 para ver ejemplos que usen objetos Turtle

2 Escriba una funcioacuten llamada dibujarcirculo que tome como argumentos unobjeto Turtle y un objeto Circulo y dibuje el ciacuterculo

Ejercicios 207

Capiacutetulo 16 Estructuras y FuncionesAhora que se ha tratado coacutemo crear tipos compuestos el siguiente paso esescribir funciones que tomen objetos definidos por el programador comoparaacutemetros y que devuelvan otros como resultados En este capiacutetulo tambieacuten sepresenta el estilo de programacioacuten funcional y dos nuevas formas dedesarrollar programas

TiempoComo otro ejemplo de tipo compuesto se define una estructura llamada Horaque registra la hora del diacutea La definicioacuten de esta estructura se muestra acontinuacioacuten

Representa la hora del diacutea

atributos hora minuto segundostruct Hora hora minuto segundoend

Observacioacuten Time es una palabra reservada de Julia

juliagt tiempo = Hora(11 59 30)Hora(11 59 30)

El diagrama de objeto para el objeto Hora luce asiacute Figura 22

Figura 22 Diagrama de objeto

Ejercicio 16-1

Escriba una funcioacuten llamada imprimirhora que tome un objeto Hora y lo imprimacon el formato horaminutosegundo Printf de la macro printf del moacuteduloStdLib permite imprimir un nuacutemero entero con el formato 02d es decirutilizando al menos dos diacutegitos incluido un cero inicial si es necesario

208 Capiacutetulo 16 Estructuras y Funciones

Ejercicio 16-2

Escriba una funcioacuten booleana llamada estadespues que tome dos objetos Horat1 y t2 y devuelva true si la hora t1 estaacute despueacutes que t2 y false de lo contrarioDesafiacuteo no use sentencias if

Funciones PurasEn las siguientes secciones se escriben dos versiones de una funcioacuten que calculala suma de horas La primera versioacuten muestra un tipo de funcioacuten llamado funcioacutenpura y la segunda un tipo llamado modificador Ademaacutes estas versionespermitiraacuten mostrar un nuevo plan de desarrollo de programas llamado desarrollode prototipos una forma de abordar un problema complejo comenzando con unprototipo simple y lidiando gradualmente con las complicaciones

Este es un primer prototipo de la funcioacuten sumahora

function sumahora(t1 t2) Hora(t1hora + t2hora t1minuto + t2minuto t1segundo +t2segundo)end

La funcioacuten crea un nuevo objeto Hora inicializa sus atributos y devuelve unareferencia al nuevo objeto A esto se le llama funcioacuten pura porque no modificaninguno de los objetos que se le pasan como argumento y no tiene efectos (comomostrar un valor o tomar una entrada del usuario) maacutes que devolver un valor

Para probar esta funcioacuten se crean dos objetos Hora inicio que contiene la horade inicio de una peliacutecula como Roma y duracion que contiene la duracioacuten de lapeliacutecula que es dos horas y 15 minutos

sumahora calcula cuaacutendo se terminaraacute la peliacutecula

imprimirhora (generic function with 1 method)

juliagt inicio = Hora(9 50 0)

juliagt duracion = Hora(2 15 0)

juliagt finaliza = sumahora(inicio duracion)

juliagt imprimirhora(finaliza)116500

El resultado 116500 no es lo que se buscaba El problema es que esta funcioacuten

Funciones Puras 209

no considera los casos en los que el nuacutemero de segundos o minutos suma maacutesque sesenta Cuando esto ocurre debemos acarrear (como en una suma) lossegundos sobrantes a la columna de los minutos o los minutos extras a lacolumna de las horas He aquiacute una versioacuten corregida de la funcioacuten

function sumahora(t1 t2) segundo = t1segundo + t2segundo minuto = t1minuto + t2minuto hora = t1hora + t2hora if segundo gt= 60 segundo -= 60 minuto += 1 end if minuto gt= 60 minuto -= 60 hora += 1 end Hora(hora minuto segundo)end

Aunque esta funcioacuten es correcta es muy larga Maacutes adelante se exploraraacute unaalternativa maacutes corta

ModificadoresHay veces en las que es uacutetil que una funcioacuten modifique uno o maacutes de los objetosque recibe como paraacutemetros En ese caso los cambios son visibles en el nivel endonde se ubica la sentencia de llamada Estas funciones se llaman modificadores

La funcioacuten incrementar que agrega un nuacutemero dado de segundos a un objetoHora puede escribirse naturalmente como un modificador Aquiacute se muestra unprototipo de la funcioacuten

function incrementar(tiempo segundos) tiemposegundo += segundos if tiemposegundo gt= 60 tiemposegundo -= 60 tiempominute += 1 end if tiempominuto gt= 60 tiempominuto -= 60 tiempohora += 1 endend

La primera liacutenea realiza la suma de los segundos y las restantes se ocupan de los

210 Capiacutetulo 16 Estructuras y Funciones

casos especiales vistos anteriormente

iquestEs correcta esta funcioacuten iquestQueacute ocurre si el paraacutemetro segundos es muchomayor que sesenta

En tal caso no es suficiente con acarrear una vez debemos seguir hacieacutendolohasta que tiemposegundo sea menor que sesenta Una solucioacuten es sustituir lassentencias if por sentencias while Esta funcioacuten seriacutea correcta pero no es lasolucioacuten maacutes eficiente

Ejercicio 16-3

Escriba una versioacuten correcta de incrementar sin bucles

Todo lo que se pueda hacer con modificadores tambieacuten puede lograrse confunciones puras De hecho algunos lenguajes de programacioacuten solo permitenfunciones puras Hay ciertas evidencias de que los programas que usanfunciones puras son maacutes raacutepidos de desarrollar y menos propensos a errores quelos programas que usan modificadores Sin embargo a veces los modificadoresson uacutetiles y en algunos casos los programas funcionales (es decir con funcionespuras) tienden a ser menos eficientes

En general recomendamos que escriba funciones puras siempre que searazonable y recurra a los modificadores soacutelo si hay una ventaja convincente Esteenfoque podriacutea llamarse estilo de programacioacuten funcional

Ejercicio 16-4

Escriba una versioacuten pura de incrementar que cree y devuelva un nuevo objetoHora en vez de modificar el paraacutemetro

Desarrollo de prototipos frente a la planificacioacutenEl desarrollo de programas que veremos ahora se llama ldquodesarrollo deprototiposrdquo En cada una de las funciones anteriores escribimos un prototipoque realizaba el caacutelculo baacutesico y luego lo probamos sobre unos cuantos casoscorrigiendo los errores a medida que iban apareciendo

Este enfoque puede ser efectivo especialmente si auacuten no tiene un conocimientoprofundo del problema No obstante las correcciones incrementales puedengenerar coacutedigo innecesariamente complicado (que considere muchos casosespeciales) y poco confiable (es difiacutecil saber si ha encontrado todos los errores)

Una alternativa es el desarrollo planificado en el que la comprensioacuten delproblema en profundidad puede facilitar en gran medida la programacioacuten En elcaso de sumahora se puede ver un objeto Hora como iexclun nuacutemero de tres diacutegitosen base 60 (vea httpsenwikipediaorgwikiSexagesimal ) El atributo segundoes la ldquocolumna de unidadesrdquo el atributo minuto es la ldquocolumna de los sesentasrdquo y

Desarrollo de prototipos frente a la planificacioacuten 211

el atributo hora es la ldquocolumna de los tres mil seiscientosrdquo

Cuando se escribiacutea sumahora e incrementar efectivamente se estaba sumandoen base 60 por eso se tuvo que acarrear de una columna a la siguiente

Esta observacioacuten sugiere otro enfoque para el problema se pueden convertir losobjetos Hora en enteros y aprovechar el hecho de que la computadora saberealizar aritmeacutetica con enteros

La siguiente funcioacuten convierte un objeto Hora en un entero

function horaaentero(tiempo) minutos = tiempohora 60 + tiempominuto segundos = minutos 60 + tiemposegundoend

Ahora para convertir un entero en un objeto Hora (recuerde que divrem divideel primer argumento por el segundo y devuelve el cociente y el resto como unatupla)

function enteroahora(segundos) (minutos segundo) = divrem(segundos 60) hora minuto = divrem(minutos 60) Hora(hora minuto segundo)end

Puede que tenga que pensar un poco y realizar algunas pruebas paraconvencerse de que estas funciones son correctas Una forma de probarlas esverificar que horaaentero((enteroahora(x)) == x para muchos valores de x Estees un ejemplo de prueba de consistencia

Una vez que esteacute convencido puede usar estas funciones para reescribirsumahora

function sumahora(t1 t2) segundos = horaaentero(t1) + horaaentero(t2) enteroahora(segundos)end

Esta versioacuten es maacutes corta que la original y maacutes faacutecil de verificar

Ejercicio 16-5

Reescriba incrementar usando horaaentero y enteroahora

Convertir de base 60 a base 10 y viceversa es maacutes difiacutecil que solo trabajar con

212 Capiacutetulo 16 Estructuras y Funciones

los tiempos El cambio de base es maacutes abstracto pero la intuicioacuten humana paratratar con las horas es mejor

Si al usuario se le ocurre tratar los tiempos como nuacutemeros de base 60 e invierteun poco de tiempo en escribir las funciones de conversioacuten (horaaentero yenteroahora) obtiene un programa maacutes corto faacutecil de leer y depurar y confiable

El cambio de base tambieacuten hace que sea maacutes faacutecil antildeadir funcionalidadesposteriormente Por ejemplo imagine restar dos Horas para hallar el intervaloentre ellas El enfoque simple seriacutea implementar una resta con preacutestamo perousar funciones de conversioacuten seriacutea maacutes faacutecil y con mayor probabilidad correcto

Iroacutenicamente a veces hacer un poblema maacutes complejo (o maacutes general) lo hacemaacutes faacutecil porque hay menos casos especiales y por lo tanto el margen de errores menor

DepuracioacutenUn objeto Hora estaacute bien definido si los valores de minuto y segundo estaacuten entre0 y 60 (incluido 0 pero no 60) y si hora es positivo hora y minuto deben servalores enteros pero se podriacutea permitir que segundo sea fraccional

Los requisitos como estos se denominan invariantes porque siempre deben serverdaderos Dicho de otra manera si no son ciertos algo estaacute mal

Escribir coacutedigo para verificar invariantes puede ayudar a detectar errores yencontrar sus causas Por ejemplo podriacutea tener una funcioacuten como eshoravalidaque tome un objeto Hora y devuelva false si viola una invariante

function eshoravalida(tiempo) if tiempohora lt 0 || tiempominuto lt 0 || tiemposegundo lt 0 return false end if tiempominuto gt= 60 || tiemposegundo gt= 60 return false end trueend

Al comienzo de cada funcioacuten puede verificar los argumentos para asegurarse deque sean vaacutelidos

Depuracioacuten 213

function sumahora(t1 t2) if eshoravalida(t1) || eshoravalida(t2) error(objeto Hora en sumahora es invaacutelido) end segundos = horaaentero(t1) + horaaentero(t2) enteroahora(segundos)end

O podriacutea usar una macro assert que verifica un invariante dado y genera unaexcepcioacuten si falla

function sumahora(t1 t2) assert(eshoravalida(t1) ampamp eshoravalida(t2) objeto Hora en sumahoraes invaacutelido) segundos = horaaentero(t1) + horaaentero(t2) enteroahora(segundos)end

Las macros assert son uacutetiles porque permiten distinguir el coacutedigo que tratacondiciones normales del coacutedigo que verifica los errores

Glosariodesarrollo de prototipos

Una forma de desarrollar programas que involucra generar un prototipo delprograma hacer pruebas y corregir errores a medida que son encontrados

desarrollo planificadoUna forma de desarrollar programas que implica una profunda comprensioacutendel problema y maacutes planificacioacuten que desarrollo incremental o desarrollo deprototipos

funcioacuten puraUna funcioacuten que no modifica los objetos que recibe como paraacutemetros Lamayoriacutea de las funciones puras son productivas

modificadorUna funcioacuten que modifica uno o maacutes de los objetos que recibe comoparaacutemetros La mayoriacutea de los modificadores son nulos es decir entreganresultado nothing

estilo funcional de programacioacutenUn estilo de programacioacuten en el que la mayoriacutea de las funciones son puras

214 Capiacutetulo 16 Estructuras y Funciones

invarianteUna condicioacuten que nunca deberiacutea cambiar durante la ejecucioacuten de unprograma

Ejercicios

Ejercicio 16-6

Escriba una funcioacuten llamada multhora que tome un objeto Hora y un nuacutemero ydevuelva un nuevo objeto Hora que contenga el producto entre Hora original y elnuacutemero

Luego use multhora para escribir una funcioacuten que tome un objeto Hora querepresente el tiempo de duracioacuten de una carrera y un nuacutemero que represente ladistancia y devuelva un objeto Hora que represente el ritmo promedio (minutospor kiloacutemetro)

Ejercicio 16-7

Julia proporciona objetos de tiempo similares a los objetos Hora de este capiacutetulopero que tienen un amplio conjunto de funciones y operadores Lea ladocumentacioacuten en httpsdocsjulialangorgenv1stdlibDates

1 Escriba un programa que tome la fecha actual e imprima el diacutea de lasemana

2 Escriba un programa que tome como entrada una fecha de cumpleantildeos eimprima la edad del usuario y la cantidad de diacuteas horas minutos ysegundos hasta su proacuteximo cumpleantildeos

3 Para dos personas nacidas en diacuteas diferentes hay un diacutea en que una tiene eldoble de edad que la otra Ese es su Diacutea Doble Escriba un programa quetome dos cumpleantildeos y calcule su Diacutea doble

4 Desafiacuteo Escriba una versioacuten maacutes general que calcule el diacutea en que unapersona es veces mayor que la otra

Ejercicios 215

Capiacutetulo 17 Dispatch MuacuteltipleJulia permite escribir coacutedigo que puede funcionar con diferentes tipos Esto sellama programacioacuten geneacuterica

En este capiacutetulo se discutiraacute sobre las declaraciones de tipo en Julia Ademaacutes sepresentan los meacutetodos que son formas de implementar diferentescomportamientos en una funcioacuten dependiendo del tipo de sus argumentos Estoes conocido como dispatch muacuteltiple

Declaraciones de Tipo

El operador asocia anotaciones de tipo con expresiones y variables

juliagt (1 + 2) Float64ERROR TypeError in typeassert expected Float64 got a value of typeInt64juliagt (1 + 2) Int643

Esto ayuda a verificar que el programa funciona de la manera esperada

El operador tambieacuten se puede agregar al lado izquierdo de una asignacioacuten ocomo parte de una declaracioacuten

juliagt function devolverfloat() xFloat64 = 100 x enddevolverfloat (generic function with 1 method)juliagt x = devolverfloat()1000juliagt typeof(x)Float64

La variable x siempre es de tipo Float64 y su valor se convierte en un puntoflotante si es necesario

Tambieacuten se puede antildeadir una anotacioacuten de tipo al encabezado de una definicioacutende funcioacuten

216 Capiacutetulo 17 Dispatch Muacuteltiple

function sinc(x)Float64 if x == 0 return 1 end sin(x)(x)end

El valor de retorno de sinc siempre se convierte al tipo Float64

En Julia cuando se omiten los tipos los valores pueden ser de cualquier tipo(Any)

MeacutetodosEn Capiacutetulo 16 definimos una estructura llamada Hora y en Seccioacuten 161escribimos una funcioacuten llamada imprimirhora

using Printf

struct Hora hora Int64 minuto Int64 segundo Int64end

function imprimirhora(tiempo) printf(02d02d02d tiempohora tiempominuto tiemposegundo)end

Para mejorar el rendimiento se pueden (y deben) agregar las declaraciones detipo a los atributos en una definicioacuten de estructura

Para llamar a esta funcioacuten debe pasarle un objeto Hora como argumento

juliagt inicio = Hora(9 45 0)Hora(9 45 0)juliagt imprimirhora(inicio)094500

Para agregar un meacutetodo a la funcioacuten imprimirhora con el fin de que esta soloacepte como argumento un objeto Hora todo lo que hay que hacer es agregar seguido de Hora al argumento tiempo en la definicioacuten de funcioacuten

Meacutetodos 217

function imprimirhora(tiempoHora) printf(02d02d02d tiempohora tiempominuto tiemposegundo)end

Un meacutetodo es una definicioacuten de funcioacuten con una especificacioacuten imprimirhoratiene un argumento de tipo Hora

Llamar a la funcioacuten imprimirhora con un objeto Hora produce el mismo resultadoque antes

juliagt imprimirhora(inicio)094500

Se redefine el primer meacutetodo sin la anotacioacuten de tipo lo cual permite unargumento de cualquier tipo

function imprimirhora(tiempo) println(No seacute coacutemo imprimir el tiempo del argumento)end

Si se llama a la funcioacuten imprimirhora con un objeto diferente de Hora seobtendraacute

juliagt imprimirhora(150)No seacute coacutemo imprimir el tiempo del argumento

Ejercicio 17-1

Reescriba horaaentero y enteroahora (de Seccioacuten 164) especificando el tipo delos argumentos

enteroahora (generic function with 1 method)

Ejemplos AdicionalesAquiacute hay una versioacuten de la funcioacuten incrementar (Ejercicio 16-5 de Seccioacuten 163)reescrita especificando el tipo de los argumentos

function incrementar(tiempoHora segundosInt64) segundos += horaaentero(tiempo) enteroahora(segundos)end

218 Capiacutetulo 17 Dispatch Muacuteltiple

Tenga en cuenta que ahora incrementar es una funcioacuten pura no un modificador

Asiacute es como se llama a la funcioacuten incrementar

juliagt inicio = Hora(9 45 0)Hora(9 45 0)juliagt incrementar(inicio 1337)Hora(10 7 17)

Si se colocan los argumentos en el orden incorrecto se obtiene un error

juliagt incrementar(1337 inicio)ERROR MethodError no method matching incrementar(Int64 Hora)

La especificacioacuten del meacutetodo es incrementar(tiempoHora segundosInt64) noincrementar(segundosInt64 tiempoHora)

Al reescribir estadespues (Ejercicio 16-2 de Seccioacuten 163) para que solo acepteobjetos Hora se tiene

function estadespues(t1Hora t2Hora) (t1hora t1minuto t1segundo) gt (t2hora t2minuto t2segundo)end

Hace falta destacar que los argumentos opcionales permiten definir muacuteltiplesmeacutetodos Por ejemplo esta definicioacuten

function f(a=1 b=2) a + 2bend

se traduce en los siguientes tres meacutetodos

f(a b) = a + 2bf(a) = f(a 2)f() = f(1 2)

Estas expresiones son definiciones vaacutelidas de meacutetodos de Julia Esta es unanotacioacuten abreviada para definir funcionesmeacutetodos

ConstructoresUn constructor es una funcioacuten especial que se llama para crear un objeto Losmeacutetodos por defecto del constructor Hora tienen las siguientes especificaciones

Constructores 219

Hora(hora minuto segundo)Hora(horaInt64 minutoInt64 segundoInt64)

Tambieacuten se pueden agregar meacutetodos propios de constructores externos

function Hora(tiempoHora) Hora(tiempohora tiempominuto tiemposegundo)end

Este meacutetodo se llama constructor de copia porque el nuevo objeto Hora es unacopia de su argumento

Para imponer invariantes se necesitan meacutetodos de constructor interno

struct Hora hora Int64 minuto Int64 segundo Int64 function Hora(horaInt64=0 minutoInt64=0 segundoInt64=0) assert(0 le minuto lt 60 Minuto no estaacute entre 0 y 60) assert(0 le segundo lt 60 Segundo no estaacute entre 0 y 60) new(hora minuto segundo) endend

La estructura Hora tiene ahora 4 meacutetodos de constructor interno

Hora()Hora(horaInt64)Hora(horaInt64 minutoInt64)Hora(horaInt64 minutoInt64 segundoInt64)

Un meacutetodo de constructor interno siempre se define dentro del bloque de unadeclaracioacuten de tipo y tiene acceso a una funcioacuten especial llamada new que creaobjetos del tipo recieacuten declarado

AVISOSi se define alguacuten constructor interno el constructor por defectoya no estaacute disponible Se tienen que escribir expliacutecitamente todoslos constructores internos necesarios

Tambieacuten existe un meacutetodo sin argumentos de la funcioacuten local new

220 Capiacutetulo 17 Dispatch Muacuteltiple

mutable struct Hora hora Int64 minuto Int64 segundo Int64 function Hora(horaInt64=0 minutoInt64=0 segundoInt64=0) assert(0 le minuto lt 60 Minuto estaacute entre 0 y 60) assert(0 le segundo lt 60 Segundo estaacute entre 0 y 60) tiempo = new() tiempohora = hora tiempominuto = minuto tiemposegundo = segundo tiempo endend

Esto permite construir estructuras de datos recursivas es decir una estructuradonde uno de los atributos es la estructura misma En este caso la estructuradebe ser mutable ya que sus atributos se modifican despueacutes de la creacioacuten deinstancias

showshow es una funcioacuten especial que devuelve la representacioacuten de cadena de unobjeto A continuacioacuten se muestra el meacutetodo show para objetos Hora

using Printf

function Baseshow(ioIO tiempoHora) printf(io 02d02d02d tiempohora tiempominutotiemposegundo)end

Esta funcioacuten guarda como cadena de texto una hora dada en el archivo al que iohace referencia

El prefijo Base es necesario si se quiere agregar un nuevo meacutetodo a la funcioacutenBaseshow

Cuando se imprime un objeto Julia llama a la funcioacuten show (esto ocurre siemprey como agregamos un nuevo meacutetodo a la funcioacuten Baseshow entonces se muestraHora con el formato que queremos)

juliagt tiempo = Hora(9 45 0)094500

Al escribir un nuevo tipo compuesto casi siempre es preferible empezar

show 221

escribiendo un constructor externo puesto que facilita la creacioacuten de instanciasde objetos y show que es uacutetil para la depuracioacuten

Ejercicio 17-2

Escriba un meacutetodo de constructor externo para la clase Punto que tome x e ycomo paraacutemetros opcionales y los asigne a los atributos correspondientes

incrementar (generic function with 1 method)

Sobrecarga de OperadoresEs posible cambiar la definicioacuten de los operadores cuando se aplican a tiposdefinidos por el usuario Esto se hace definiendo meacutetodos del operador Porejemplo si se define un meacutetodo llamado + con dos argumentos Hora se puedeusar el operador + en los objetos Hora

Asiacute es como se veriacutea la definicioacuten

import Base+

function +(t1Hora t2Hora) segundos = horaaentero(t1) + horaaentero(t2) enteroahora(segundos)end

La sentencia import agrega el operador + al aacutembito local (local scope) para quese puedan agregar meacutetodos

A continuacioacuten se muestra coacutemo usar este operador para objetos Hora

juliagt inicio = Hora(9 45)094500juliagt duracion = Hora(1 35 0)013500juliagt inicio + duracion112000

Al aplicar el operador + a objetos Hora Julia invoca el meacutetodo recieacuten agregadoCuando REPL muestra el resultado Julia invoca a show iexclHay muchas cosasocurriendo pero que no se observan

Ampliar el comportamiento de los operadores de modo que funcionen con tiposdefinidos por el usuarioprogramador se denomina sobrecarga del operador

222 Capiacutetulo 17 Dispatch Muacuteltiple

Dispatch MuacuteltipleEn la seccioacuten anterior se sumaron dos objetos Hora Imagine que ahora se quieresumar un nuacutemero entero a un objeto Hora

function +(tiempoHora segundosInt64) incrementar(tiempo segundos)end

He aquiacute un ejemplo que usa el operador + con un objeto Hora y un entero

juliagt inicio = Hora(9 45)094500juliagt inicio + 1337100717

La suma es un operador conmutativo por lo que se debe agregar otro meacutetodo

function +(segundosInt64 tiempoHora) tiempo + segundosend

Y se obtiene el mismo resultado

juliagt 1337 + inicio100717

La eleccioacuten del meacutetodo a ejecutar cuando se aplica una funcioacuten se llamadispatch Julia permite que el proceso de dispatch elija a cuaacutel de los meacutetodos deuna funcioacuten llamar en funcioacuten del nuacutemero y tipo de los argumentos dados El usode todos los argumentos de una funcioacuten para elegir el meacutetodo que se debeinvocar se conoce como dispatch muacuteltiple

Ejercicio 17-3

Escriba los siguientes meacutetodos + para objetos Punto

bull Si ambos operandos son objetos Punto el meacutetodo deberiacutea devolver un nuevoobjeto Punto cuya coordenada x sea la suma de las coordenadas x de losoperandos De manera anaacuteloga haga lo mismo para la coordenada y

bull Si el primer o el segundo operando es una tupla el meacutetodo debe agregar elprimer elemento de la tupla a la coordenada x y el segundo elemento a lacoordenada y y devolver un nuevo objeto Punto con el resultado

Dispatch Muacuteltiple 223

Programacioacuten GeneacutericaEl dispatch muacuteltiple es uacutetil cuando es necesario pero (afortunadamente) nosiempre lo es A menudo puede evitarse escribiendo funciones que funcionencorrectamente para argumentos de diferentes tipos

Muchas de las funciones que se han visto para cadenas tambieacuten funcionan paraotros tipos de secuencia Por ejemplo en Seccioacuten 112 se usa histograma paracontar la cantidad de veces que cada letra aparece en una palabra

function histograma(s) d = Dict() for c in s if c notin keys(d) d[c] = 1 else d[c] += 1 end end dend

Esta funcioacuten tambieacuten funciona para listas tuplas e incluso diccionarios siemprey cuando los elementos de s sean hashables ya que asiacute pueden usarse comoclaves de d

juliagt t = (spam huevo spam spam tocino spam)(spam huevo spam spam tocino spam)juliagt histograma(t)DictAnyAny with 3 entries spam =gt 4 huevo =gt 1 tocino =gt 1

Las funciones que pueden tomar paraacutemetros de diferentes tipos se llamanpolimoacuterficas El polimorfismo puede facilitar la reutilizacioacuten del coacutedigo

Por ejemplo la funcioacuten integrada sum que suma los elementos de una secuenciafunciona siempre que los elementos de la secuencia permitan la suma

Como se antildeadioacute el meacutetodo + para los objetos Hora entonces se puede usar sumpara Hora

224 Capiacutetulo 17 Dispatch Muacuteltiple

juliagt t1 = Hora(1 7 2)010702juliagt t2 = Hora(1 5 8)010508juliagt t3 = Hora(1 5 0)010500juliagt sum((t1 t2 t3))031710

Si todas las operaciones realizadas dentro de la funcioacuten se pueden aplicar al tipola funcioacuten se puede aplicar al tipo

El mejor tipo de polimorfismo es el que no se busca cuando usted descubre queuna funcioacuten que habiacutea escrito se puede aplicar a un tipo para el que nunca lahabiacutea planeado

Interfaz e implementacioacutenUno de los objetivos del dispatch muacuteltiple es hacer que el software sea maacutes faacutecilde mantener lo que significa poder mantener el programa funcionando cuandootras partes del sistema cambian y modificar el programa para cumplir con losnuevos requisitos

Una teacutecnica de disentildeo que ayuda a lograr ese objetivo es mantener las interfacesseparadas de las implementaciones Esto significa que los meacutetodos que tienen unargumento con anotacioacuten de tipo no deberiacutean depender de coacutemo se representanlos atributos de ese tipo

Por ejemplo en este capiacutetulo se desarrolla una estructura que representa unahora del diacutea Los meacutetodos que tienen un argumento con anotacioacuten de este tipoincluyen horaaentero estadespues y +

Se pueden implementar esos meacutetodos de varias maneras Los detalles de laimplementacioacuten dependen de coacutemo se represente Hora En este capiacutetulo losatributos de un objeto Hora son hora minuto y segundo

Otra opcioacuten seriacutea reemplazar estos atributos con un solo entero que representeel nuacutemero de segundos desde la medianoche Esta implementacioacuten hariacutea quealgunas funciones como estadespues sean maacutes faacuteciles de escribir pero hace queotras sean maacutes difiacuteciles

Despueacutes de implementar un tipo puede descubrir una mejor implementacioacuten Siotras partes del programa estaacuten usando su tipo cambiar la interfaz puede llevarmucho tiempo y ser propenso a errores No obstante si hizo un buen disentildeoacute deinterfaz puede cambiar la implementacioacuten sin cambiar la interfaz lo quesignifica que otras partes del programa no tienen que cambiar

Interfaz e implementacioacuten 225

DepuracioacutenLlamar a una funcioacuten con los argumentos correctos puede ser difiacutecil cuando seespecifica maacutes de un meacutetodo para la funcioacuten Julia permite examinar lasespecificaciones de los meacutetodos de una funcioacuten

Para saber queacute meacutetodos estaacuten disponibles para una funcioacuten determinada puedeusar la funcioacuten methods

juliagt methods(imprimirhora) 2 methods for generic function imprimirhora[1] printtime(timeMyTime) in Main at REPL[3]2[2] printtime(time) in Main at REPL[4]2

En este ejemplo la funcioacuten imprimirhora tiene 2 meacutetodos uno con un argumentoHora y otro con un argumento Any

Glosarioanotacioacuten de tipo

El operador seguido de un tipo que indica que una expresioacuten o unavariable es de ese tipo

meacutetodoUna definicioacuten de un posible comportamiento de una funcioacuten

dispatchLa eleccioacuten de queacute meacutetodo ejecutar cuando se ejecuta una funcioacuten

especificacioacutenEl nuacutemero y tipo de argumentos de un meacutetodo que permite al dispatchseleccionar el meacutetodo maacutes especiacutefico de una funcioacuten durante la llamada afuncioacuten

constructor externoConstructor definido fuera de la definicioacuten de tipo para definir meacutetodosuacutetiles para crear un objeto

constructor internoConstructor definido dentro de la definicioacuten de tipo para imponerinvariantes o para construir objetos recursivos

constructor por defectoConstructor interno que estaacute disponible cuando el usuario no defineconstructores internos

226 Capiacutetulo 17 Dispatch Muacuteltiple

constructor de copiaMeacutetodo de constructor externo de un tipo que tiene como uacutenico argumentoun objeto del tipo Crea un nuevo objeto que es una copia del argumento

sobrecarga de operadoresAmpliar el comportamiento de los operadores como ++ de modo quetrabajen con tipos definidos por el usuario

dispatch muacuteltipleDispatch basado en todos los argumentos de una funcioacuten

programacioacuten geneacutericaEscribir coacutedigo que pueda funcionar con maacutes de un tipo

Ejercicios

Ejercicio 17-4

Cambie los atributos de Hora para que sea un solo nuacutemero entero querepresente los segundos desde la medianoche Luego modifique los meacutetodosdefinidos en este capiacutetulo para que funcionen con la nueva implementacioacuten

Ejercicio 17-5

Escriba una definicioacuten para un tipo llamado Canguro con un atributo llamadocontenidodemarsupio de tipo Arreglo y los siguientes meacutetodos

bull Un constructor que inicialice contenidodemarsupio a un arreglo vaciacuteo

bull Un meacutetodo llamado ponerenmarsupio que tome un objeto Canguro y unobjeto de cualquier tipo y lo agregue a contenidodemarsupio

bull Un meacutetodo show que devuelva una representacioacuten de cadena del objetoCanguro y el contenido del marsupio

Pruebe su coacutedigo creando dos objetos Canguro asignaacutendolos a variablesllamadas cangu y ro y luego agregando ro al contenido del marsupio de cangu

Ejercicios 227

Capiacutetulo 18 SubtiposEn el capiacutetulo anterior se presentoacute el dispatch muacuteltiple y los meacutetodospolimoacuterficos Al no especificar el tipo de los argumentos de un meacutetodo este sepuede invocar con argumentos de cualquier tipo Ahora se veraacute coacutemo especificarun subconjunto de tipos permitidos en las especificaciones de un meacutetodo

En este capiacutetulo se explica el concepto de subtipo usando tipos que representannaipes mazos de naipes y manos de poacuteker

Si usted nunca ha jugado poacuteker puede leer sobre eacutel en httpseswikipediaorgwikiPC3B3quer aunque no es necesario ya que se explicaraacute todo lonecesario para los ejercicios

NaipesHay cincuenta y dos naipes en una baraja inglesa cada uno de los cualespertenece a uno de los cuatro palos y tiene un valor Los palos son Picas (spades)Corazones (hearts) Diamantes (diams) y Treacuteboles (clubs) Los valores son As (A) 2 3 4 5 67 8 9 10 Jota (J) Reina (Q) y Rey (K) Dependiendo del tipo de juego el valordel As puede ser mayor que al Rey o inferior al 2

Si queremos definir un nuevo objeto para representar un naipe son obvios losatributos que deberiacutea tener valor y palo Lo que no es tan obvio es el tipo que sedebe dar a estos atributos Una opcioacuten es usar cadenas de caracteres quecontengan palabras como Picas para los palos y Reina para los valores Unproblema de esta implementacioacuten es que no seriacutea faacutecil comparar naipes para vercuaacutel tiene mayor valor o palo

Una alternativa es usar nuacutemeros enteros para codificar los valores y palos Eneste contexto codificar significa definir una asociacioacuten entre nuacutemeros y paloso entre nuacutemeros y valores Este tipo de codificacioacuten no estaacute relacionada concifrar o traducir a un coacutedigo secreto (eso seriacutea cifrado)

Por ejemplo esta tabla muestra una correspondencia entre palos y coacutedigos(nuacutemeros) enteros

bull spades 4

bull hearts 3

bull diams 2

bull clubs 1

Este coacutedigo facilita la comparacioacuten de naipes los palos maacutes altos se asignan a losnuacutemeros maacutes altos por lo tanto podemos comparar los palos al comparar suscoacutedigos

228 Capiacutetulo 18 Subtipos

Estamos usando el siacutembolo para dejar en claro que estas asignaciones no sonparte de Julia Forman parte del disentildeo del programa pero no aparecenexpliacutecitamente en el coacutedigo

La definicioacuten de estructura de Naipe se ve asiacute

struct Naipe palo Int64 valor Int64 function Naipe(paloInt64 valorInt64) assert(1 le palo le 4 el palo no estaacute entre 1 y 4) assert(1 le valor le 13 el valor no estaacute entre 1 y 13) new(palo valor) endend

Para crear un Naipe se debe llamar a Naipe con el palo y el valor del naipedeseado

juliagt reina_de_diamantes = Naipe(2 12)Naipe(2 12)

Variables GlobalesPara poder imprimir los objetos Naipe de una manera que sea faacutecil de leer senecesita establecer una correspondencia entre los coacutedigos enteros y suscorrespondientes palos y valores Una manera natural de hacer esto es conarreglos de cadenas

const nombres_palo = [clubs diams hearts spades]const nombres_valor = [A 2 3 4 5 6 7 8 9 10J Q K]

Las variables nombres_palo y nombres_valor son variables globales Ladeclaracioacuten const significa que la variable solo se puede asignar una vez Estoresuelve el problema de rendimiento de las variables globales

Ahora se puede implementar un meacutetodo show apropiado

function Baseshow(ioIO naipeNaipe) print(io nombres_valor[naipevalor] nombres_palo[naipepalo])end

La expresioacuten nombres_valor[naipevalor] significa use el atributo valor delobjeto naipe como iacutendice en el arreglo nombres_valor y seleccione la cadena

Variables Globales 229

correspondiente

Con los meacutetodos que se tienen hasta ahora se pueden crear e imprimir naipes

juliagt Naipe(3 11)Jhearts

Comparacioacuten de naipesPara los tipos integrados existen operadores relacionales (lt gt == etc) quecomparan valores y determinan cuaacutendo uno es mayor menor o igual a otro Paralos tipos definidos por el usuario se puede sustituir el comportamiento de estosoperadores si se proporciona un meacutetodo llamado lt

El orden correcto de los naipes no es obvio Por ejemplo iquestcuaacutel es mejor el 3 deTreacuteboles o el 2 de Diamantes Uno tiene un valor mayor pero el otro tiene unpalo mayor Para hacer que los naipes sean comparables se debe decidir queacute esmaacutes importante valor o palo

La respuesta puede depender del tipo de juego pero para simplificar las cosasse establece la eleccioacuten arbitraria de que el palo es maacutes importante por lo quetodas los treacuteboles superan a todos los diamantes y asiacute sucesivamente

Con esa decisioacuten tomada se puede escribir lt

import Baselt

function lt(c1Naipe c2Naipe) (c1palo c1valor) lt (c2palo c2valor)end

Ejercicio 18-1

Escriba un meacutetodo lt para objetos Hora Puede usar comparacioacuten de tuplas ocomparacioacuten de enteros

Prueba unitariaUna prueba unitaria permite verificar el correcto funcionamiento de su coacutedigocomparando los resultados obtenidos con los esperados Esto puede ser uacutetil paraverificar que su coacutedigo funciona correctamente despueacutes de haberlo modificado ytambieacuten es una forma de predefinir el comportamiento correcto de su coacutedigodurante el desarrollo

Se pueden realizar pruebas unitarias simples con las macros test

230 Capiacutetulo 18 Subtipos

juliagt using Test

juliagt test Naipe(1 4) lt Naipe(2 4)Test Passedjuliagt test Naipe(1 3) lt Naipe(1 4)Test Passed

test devuelve Test Passed (Prueba aprobada) si la expresioacuten que sigue estrue Test Failed (Prueba fallida) si es false y Error Result (Resultado deerror) si no se pudo evaluar

MazosAhora que ya tenemos Naipes el proacuteximo paso es definir Mazos Como un mazoestaacute compuesto de naipes naturalmente cada Mazo contendraacute un arreglo denaipes como atributo

A continuacioacuten se muestra una definicioacuten para Mazo El constructor crea elatributo naipes y genera la baraja estaacutendar de cincuenta y dos naipes

struct Mazo naipes ArrayNaipe 1end

function Mazo() mazo = Mazo(Naipe[]) for palo in 14 for valor in 113 push(mazonaipes Naipe(palo valor)) end end mazoend

La forma maacutes faacutecil de poblar el mazo es mediante un bucle anidado El bucleexterior enumera los palos desde 1 hasta 4 El bucle interior enumera los valoresdesde 1 hasta 13 Cada iteracioacuten crea un nuevo Naipe con el palo y valor actualy lo agrega a mazonaipes

Este es un meacutetodo show para Mazo

Mazos 231

function Baseshow(ioIO mazoMazo) for naipe in mazonaipes print(io naipe ) end println()end

Asiacute es como se ve el resultado

juliagt Mazo()Aclubs 2clubs 3clubs 4clubs 5clubs 6clubs 7clubs 8clubs 9clubs 10clubs Jclubs Qclubs Kclubs Adiams 2diams 3diams 4diams 5diams 6diams 7diams 8diams 9diams 10diams JdiamsQdiams Kdiams Ahearts 2hearts 3hearts 4hearts 5hearts 6hearts 7hearts 8hearts 9hearts 10hearts Jhearts Qhearts Khearts Aspades 2spades 3spades 4spades 5spades 6spades 7spades 8spades 9spades10spades Jspades Qspades Kspades

Antildeadir Eliminar Barajar y OrdenarPara repartir los naipes se debe tener una funcioacuten que elimine un naipe delmazo y lo devuelva La funcioacuten pop proporciona una forma conveniente derealizar esto

function Basepop(mazoMazo) pop(mazonaipes)end

Como pop elimina el uacuteltimo naipe en el arreglo se estaacute repartiendo desde elextremo inferior del mazo

Para antildeadir un naipe se puede usar la funcioacuten push

function Basepush(mazoMazo naipeNaipe) push(mazonaipes naipe) mazoend

Un meacutetodo como este que usa otro meacutetodo sin hacer mucho maacutes se llamaenchapado La metaacutefora proviene de la carpinteriacutea donde un enchapado es unacapa fina de madera de alta calidad que se pega a la superficie de una pieza demadera de baja calidad para mejorar su apariencia

En este caso push es un meacutetodo fino que expresa una operacioacuten de arreglosadecuada para los mazos Mejora la apariencia o interfaz de la implementacioacuten

Tambieacuten podemos escribir un meacutetodo llamado shuffle (barajar en ingleacutes) usandola funcioacuten Randomshuffle

232 Capiacutetulo 18 Subtipos

using Random

function Randomshuffle(mazoMazo) shuffle(mazonaipes) mazoend

Ejercicio 18-2

Escriba una funcioacuten llamada sort (ordenar en ingleacutes) que use la funcioacuten sortpara ordenar las cartas en un Mazo sort usa el meacutetodo isless que definimospara determinar el orden

Tipos Abstractos y SubtiposSe busca que un tipo represente una mano es decir los naipes que tiene unjugador Una mano es similar a un mazo ambos estaacuten compuestos de unconjunto de naipes y ambos requieren de operaciones tales como agregar yeliminar una carta

Una mano es diferente de un mazo en ciertos aspectos ya que existen ciertasoperaciones sobre una mano que no tendriacutean sentido sobre un mazo Porejemplo en el poker se debe comparar una mano con otra para ver quieacuten ganaEn bridge se necesita calcular el puntaje de la mano para asiacute poder hacer lasubasta

Por lo tanto hace falta una forma de agrupar los tipos concretos que estaacutenrelacionados En Julia esto se hace definiendo un abstract type (tipo abstracto eningleacutes) que sea padre de Mazo y Mano A esto se le llama crear subtipos

Se llama al tipo abstracto ConjuntoDeCartas

abstract type ConjuntoDeCartas end

Se puede crear un nuevo tipo abstracto con la palabra reservada abstract typeDe manera opcional se puede especificar un tipo padre de una estructuracolocando despueacutes del nombre de esta el siacutembolo lt seguido del nombre de untipo abstracto existente

Cuando no se proporciona un supertipo el supertipo por defecto es Any es decirun tipo abstracto predefinido del que todos los objetos son instancias y del quetodos los tipos son subtipos

Ahora se puede expresar que Mazo es un hijo de ConjuntoDeCartas

Tipos Abstractos y Subtipos 233

struct Mazo lt ConjuntoDeCartas naipes ArrayNaipe 1end

function Mazo() mazo = Mazo(Naipe[]) for palo in 14 for valor in 113 push(mazonaipes Naipe(palo valor)) end end mazoend

El operador isa comprueba si un objeto es de un tipo dado

juliagt mazo = Mazo()

juliagt mazo isa ConjuntoDeCartastrue

Una mano tambieacuten es un ConjuntoDeCartas

struct Mano lt ConjuntoDeCartas naipes ArrayNaipe 1 etiqueta Stringend

function Mano(etiquetaString=) Mano(Naipe[] etiqueta)end

En lugar de llenar la mano con 52 naipes nuevos el constructor de Manoinicializa naipes a un arreglo vaciacuteo Se puede etiquetar a la Mano pasando unargumento opcional al constructor

juliagt mano = Mano(nueva mano)Mano(Naipe[] nueva mano)

Tipos Abstractos y FuncionesAhora podemos expresar las operaciones que tienen en comuacuten Mazo y Mano alser funciones que tienen como argumento a ConjuntoDeCartas

234 Capiacutetulo 18 Subtipos

function Baseshow(ioIO cdcConjuntoDeCartas) for naipe in cdcnaipes print(io naipe ) endend

function Basepop(cdcConjuntoDeCartas) pop(cdcnaipes)end

function Basepush(cdcConjuntoDeCartas naipeNaipe) push(cdcnaipes naipe) nothingend

Se puede usar pop y push para repartir una carta

juliagt mazo = Mazo()Aclubs 2clubs 3clubs 4clubs 5clubs 6clubs 7clubs 8clubs 9clubs 10clubs Jclubs Qclubs Kclubs Adiams 2diams 3diams 4diams 5diams 6diams 7diams 8diams 9diams 10diams JdiamsQdiams Kdiams Ahearts 2hearts 3hearts 4hearts 5hearts 6hearts 7hearts 8hearts 9hearts 10hearts Jhearts Qhearts Khearts Aspades 2spades 3spades 4spades 5spades 6spades 7spades 8spades 9spades10spades Jspades Qspades Kspadesjuliagt shuffle(mazo)10clubs 9hearts 7spades 2spades Ahearts 4clubs Jhearts 2diams 6clubs Qclubs 8diams 8hearts 3hearts 7clubs 3diams 2clubs Jclubs 8clubs 9diams 6spades 3spades 5spades Adiams Aclubs10hearts 4spades Qhearts Jdiams Kspades 10diams Khearts Kclubs 5clubs 5hearts 5diams 10spades 7diams 3clubs 9spades Aspades 2hearts 7hearts 9clubs Qdiams 6hearts 8spades Jspades 4diamsQspades 6diams Kdiams 4heartsjuliagt naipe = pop(mazo)4heartsjuliagt push(mano naipe)

A continuacioacuten se encapsula este coacutedigo en una funcioacuten llamada mover

function mover(cdc1ConjuntoDeCartas cdc2ConjuntoDeCartas nInt) assert 1 le n le length(cs1naipes) for i in 1n naipe = pop(cdc1) push(cdc2 naipe) end nothingend

mover toma tres argumentos dos objetos ConjuntoDeCartas y el nuacutemero decartas a repartir Modifica ambos objetos ConjuntoDeCartas y devuelve nothing

En algunos juegos las cartas se mueven de una mano a otra o de una mano almazo Puede usar mover para cualquiera de estas operaciones cdc1 y cdc2pueden ser un Mazo o una Mano

Tipos Abstractos y Funciones 235

Diagramas de tiposHasta ahora se han visto diagramas de pila que muestran el estado de unprograma y diagramas de objetos que muestran los atributos de un objeto y susvalores Estos diagramas son como una foto sacada durante la ejecucioacuten de unprograma por lo que cambian a medida que se ejecuta el programa

Tambieacuten son muy detallados en algunos casos demasiado detallados Undiagrama de tipos es una representacioacuten maacutes abstracta de la estructura de unprograma En vez de mostrar objetos individuales muestra los tipos y lasrelaciones entre ellos

Hay varias formas de relacioacuten entre tipos

bull Los objetos de un tipo concreto pueden contener referencias a objetos deotro tipo Por ejemplo cada Rectaacutengulo contiene una referencia a un Puntoy cada Mazo contiene referencias a un conjunto de Naipes Este tipo derelacioacuten se llama TIENE-UN como por ejemplo un Rectaacutengulo tiene unPunto

bull Un tipo concreto puede tener un tipo abstracto como supertipo Estarelacioacuten se llama ES-UN como por ejemplo una Mano es unConjuntoDeCartas

bull Un tipo puede depender de otro si los objetos de un tipo toman objetos delsegundo tipo como paraacutemetros o usan objetos del segundo tipo como partede un caacutelculo Este tipo de relacioacuten se llama dependencia

Figura 23 Diagrama de tipo

Cada una de las flechas superiores representa una relacioacuten ES-UN En este casoindica que Mano tiene como supertipo a ConjuntoDeCartas

Cada una de las flechas inferiores representa una relacioacuten TIENE-UN en estecaso un Mazo tiene referencias a objetos Naipe

El asterisco () cerca de la flecha es una multiplicidad e indica cuaacutentos Naipestiene un Mazo Una multiplicidad puede ser un nuacutemero simple como 52 unrango como 57 o un asterisco lo cual indica que un Mazo puede tener cualquiernuacutemero de Naipes

236 Capiacutetulo 18 Subtipos

No hay dependencias en este diagrama Normalmente se mostrariacutean con unaflecha achurada Si hay muchas dependencias a veces se omiten

Un diagrama maacutes detallado podriacutea mostrar que un Mazo en realidad contiene unarreglo de Naipes pero los tipos integrados como arreglos y diccionariosgeneralmente no se incluyen en los diagramas de tipos

DepuracioacutenUtilizar subtipos puede dificultar la depuracioacuten ya que al llamar a una funcioacutencon un objeto como argumento puede ser complicado determinar queacute meacutetodo seinvocaraacute

Al escribir una funcioacuten que funciona con objetos Mano se busca que funcionecon todo tipo de Manos como ManoDePoker ManoDeBridge etc Si el usuarioinvoca un meacutetodo como sort podriacutea obtener el meacutetodo definido para un tipoabstracto Mano pero si existiera un meacutetodo sort que tuviera como argumentocualquiera de estos subtipos de Mano obtendriacutea esa versioacuten Estecomportamiento suele ser algo bueno pero puede ser confuso

function Basesort(manoMano) sort(manonaipes)end

Si usted no estaacute seguro del flujo de ejecucioacuten de un programa la solucioacuten maacutessimple es agregar sentencias de impresioacuten al inicio de sus meacutetodos maacutesrelevantes Si shuffle imprimiera un mensaje como Ejecutando shuffle en Mazodurante la ejecucioacuten del programa seriacutea posible rastrear el flujo de ejecucioacuten

Una mejor alternativa es la macro which

juliagt which sort(mano)sort(manoMano) in Main at REPL[5]1

Entonces el meacutetodo sort de mano es el que tiene como argumento un objeto detipo Mano

Una sugerencia para el disentildeo del programa cuando anula un meacutetodo lainterfaz del nuevo meacutetodo deberiacutea ser la misma que la anterior Deberiacutea tomarlos mismos paraacutemetros devolver el mismo tipo y obedecer las mismascondiciones previas y posteriores Si sigue esta regla cualquier funcioacuten disentildeadapara funcionar con una instancia de un supertipo como un ConjuntoDeCartastambieacuten funcionaraacute con instancias de sus subtipos Mazo y Mano

Si viola esta regla llamada principio de sustitucioacuten de Liskov su coacutedigocolapsaraacute como un castillo de naipes (jeje)

Depuracioacuten 237

La funcioacuten supertype permite encontrar el supertipo directo de un tipo

juliagt supertype(Mazo)ConjuntoDeCartas

Encapsulado de DatosLos capiacutetulos anteriores muestran un plan de desarrollo que podriacuteamos llamardisentildeo orientado a tipos Se identifican los objetos necesarios como PuntoRectaacutengulo y Hora y se definen estructuras para representarlos En cada casohay una correspondencia obvia entre el objeto y alguna entidad en el mundo real(o al menos en el mundo matemaacutetico)

A veces no es tan obvio saber queacute objetos se necesitan y coacutemo estos debeninteractuar En ese caso se necesita un plan de desarrollo diferente Lo mismoque ocurre con interfaces de funciones por encapsulado y generalizacioacuten ocurrecon interfaces de tipo por encapsulado de datos

El anaacutelisis de Markov de Seccioacuten 138 es un buen ejemplo Si descarga el coacutedigodesde httpsgithubcomBenLauwensThinkJuliajlblobmastersrcsolutionschap13jl veraacute que se usan dos variables globales sufijos y prefijo las cuales seleen y escriben desde varias funciones

sufijos = Dict()prefijos = []

Debido a que estas variables son globales solo se puede ejecutar un anaacutelisis a lavez Si se leen dos textos sus prefijos y sufijos se agregariacutean a las mismasestructuras de datos (lo que generariacutea un texto interesante)

Para ejecutar muacuteltiples anaacutelisis y mantenerlos separados se puede encapsular elestado de cada anaacutelisis en un objeto Asiacute es como se veriacutea

struct Markov orden Int64 sufijos DictTupleStringVarargString ArrayString 1 prefijo ArrayString 1end

function Markov(ordenInt64=2) new(orden DictTupleStringVarargString ArrayString 1()ArrayString 1())end

A continuacioacuten se transforman las funciones en meacutetodos Por ejemplo para

238 Capiacutetulo 18 Subtipos

procesarpalabra

function procesarpalabra(markovMarkov palabraString) if length(markovprefijo) lt markovorden push(markovprefijo palabra) return end get(markovsufijos (markovprefijo) ArrayString 1()) push(markovsufijos[(markovprefijo)] palabra) popfirst(markovprefijo) push(markovprefijo palabra)end

Transformar un programa asiacute (cambiando el disentildeo sin cambiar elcomportamiento) es otro ejemplo de refactorizacioacuten (vea Seccioacuten 47)

Este ejemplo sugiere el siguiente plan de desarrollo para disentildear tipos

bull Comience escribiendo funciones que lean y escriban variables globales(cuando sea necesario)

bull Una vez que el programa esteacute funcionando busque asociaciones entre lasvariables globales y las funciones que las usan

bull Encapsule variables relacionadas como atributos de una estructura

bull Transforme las funciones asociadas en meacutetodos que tengan comoargumentos objetos del nuevo tipo

Exercise 18-3

Descargue el coacutedigo de Markov de httpsgithubcomBenLauwensThinkJuliajlblobmastersrcsolutionschap13jl y siga los pasos descritos anteriormente paraencapsular las variables globales como atributos de una nueva estructurallamada Markov

Glosariocodificar

Representar un conjunto de valores utilizando otro conjunto de valoresgenerando una asociacioacuten entre ellos

prueba unitariaManera estandarizada de probar que el coacutedigo estaacute correcto

enchapadoUn meacutetodo o funcioacuten que mejora la interfaz de otra funcioacuten sin hacermuchos caacutelculos

Glosario 239

crear subtiposLa capacidad de definir una jerarquiacutea de tipos relacionados

tipo abstractoUn tipo que puede ser padre de otro tipo

tipo concretoUn tipo que se puede construir

subtipoUn tipo que tiene como padre un tipo abstracto

supertipoUn tipo abstracto que es el padre de otro tipo

relacioacuten ES-UNUna relacioacuten entre un subtipo y su supertipo

relacioacuten TIENE-UNUna relacioacuten entre dos tipos donde las instancias de un tipo contienenreferencias a instancias del otro

dependenciaUna relacioacuten entre dos tipos donde las instancias de un tipo usan instanciasdel otro tipo pero no las almacenan como atributos

diagrama de tiposUn diagrama que muestra los tipos en un programa y las relaciones entreellos

multiplicidadUna notacioacuten en un diagrama de tipo que muestra para una relacioacutenTIENE-UN cuaacutentas referencias hay a instancias de otra clase

encapsulado de datosUn plan de desarrollo de programas que implica hacer un prototipo que usevariables globales y una versioacuten final que convierta las variables globales enatributos de instancia

Ejercicios

Ejercicio 18-4

Para el siguiente programa dibuje un diagrama de tipos que muestre estos tiposy las relaciones entre ellos

240 Capiacutetulo 18 Subtipos

abstract type PadrePingPong end

struct Ping lt PadrePingPong pong PadrePingPongend

struct Pong lt PadrePingPong pings ArrayPing 1 function Pong(pings=ArrayPing 1()) new(pings) endend

function agregarping(pongPong pingPing) push(pongpings ping) nothingend

pong = Pong()ping = Ping(pong)agregarping(pong ping)

Ejercicio 18-5

Escriba un meacutetodo llamado repartir que tome tres paraacutemetros un Mazo elnuacutemero de manos y el nuacutemero de naipes por mano Deberiacutea crear el nuacutemeroapropiado de objetos Mano repartir el nuacutemero apropiado de naipes por mano ydevolver un arreglo de Manos

Ejercicio 18-6

Las siguientes son las posibles manos en el poacuteker en orden de valor creciente yprobabilidad decreciente

parejaDos cartas del mismo nuacutemero

doble parejaDos pares de cartas del mismo nuacutemero

triacuteoTres cartas del mismo nuacutemero

escaleraCinco cartas consecutivas (los ases pueden ser considerados altos o bajospor lo tanto As-2-3-4-5 es escalera 10-Jota-Reina-Rey-As tambieacuten pero

Ejercicios 241

Reina-Rey-As-2-3 no)

colorCinco cartas del mismo palo

fullTres cartas iguales en su valor maacutes otras dos iguales en su valor

poacutekerCuatro cartas iguales en su valor

escalera de colorCinco cartas consecutivas del mismo palo

El objetivo de este ejercicio es estimar la probabilidad de tener cada una de estasmanos

1 Agregue meacutetodos llamados tienepareja tienedoblepareja etc quedevuelvan true o false seguacuten si la mano cumple o no con los criteriosrelevantes Su coacutedigo deberiacutea funcionar correctamente para manos quecontengan cualquier nuacutemero de naipes (aunque 5 y 7 son los tamantildeos maacutescomunes)

2 Escriba un meacutetodo llamado clasificar que descubra la clasificacioacuten de mayorvalor para una mano y defina el atributo etiqueta con esta clasificacioacuten Porejemplo una mano de 7 cartas que contiene un color y una pareja debeetiquetarse como color

3 Cuando esteacute convencido de que sus meacutetodos de clasificacioacuten estaacutenfuncionando correctamente estime las probabilidades de las distintasmanos Escriba una funcioacuten que baraje un mazo de naipes la divida endiferentes manos clasifique las manos y cuente la cantidad de veces queaparecen varias clasificaciones

4 Imprima una tabla de las clasificaciones y sus probabilidades Ejecute suprograma con un nuacutemero cada vez mayor de manos hasta que los valores desalida converjan con un grado razonable de precisioacuten Compare susresultados con los valores en httpsenwikipediaorgwikiHand_rankings

242 Capiacutetulo 18 Subtipos

Capiacutetulo 19 Extra SintaxisUno de los objetivos de este libro es ensentildearle lo justo y necesario de Julia Seexplica una sola forma de hacer las cosas y en ocasiones se deja como ejercicioal lector una segunda manera

Ahora se veraacuten algunos temas que se han dejado de lado pero que son uacutetilesJulia proporciona una serie de caracteriacutesticas que no son realmente necesarias(se puede escribir un buen coacutedigo sin ellas) pero a veces permiten escribir uncoacutedigo maacutes conciso legible yo eficiente

En este capiacutetulo y el siguiente se discute aquello que se ha omitido en loscapiacutetulos anteriores

bull maacutes sintaxis

bull funciones tipos y macros disponibles directamente de Base

bull funciones tipos y macros de la Biblioteca Estaacutendar (Standard Library)

Tuplas con nombreEs posible colocarle nombre a los componentes de una tupla creando una tuplacon nombre

juliagt x = (a=1 b=1+1)(a = 1 b = 2)juliagt xa1

En las tuplas con nombre se puede acceder a los atributos con su nombreutilizando la sintaxis de punto (xa)

FuncionesLas funciones en Julia tambieacuten se pueden definir mediante una sintaxiscompacta de la siguiente forma

juliagt f(xy) = x + yf (generic function with 1 method)

Funciones Anonimas

Podemos definir una funcioacuten sin especificar su nombre

Tuplas con nombre 243

juliagt x -gt x^2 + 2x - 11 (generic function with 1 method)juliagt function (x) x^2 + 2x - 1 end3 (generic function with 1 method)

Estos son ejemplos de funciones anoacutenimas Las funciones anoacutenimasgeneralmente se usan como argumento de otra funcioacuten

juliagt using Plots

juliagt plot(x -gt x^2 + 2x - 1 0 10 xlabel=x ylabel=y)

Figura 24 muestra el resultado del comando plot (graficar en ingleacutes)

Figura 24 Plot

Argumentos con nombre

Tambieacuten se puede poner nombre a los argumentos de una funcioacuten

juliagt function migrafico(x y style=continua width=1 color=negro) endmigrafico (generic function with 1 method)juliagt migrafico(010 010 style=dotted color=blue)

Los argumentos con nombre en una funcioacuten se especifican despueacutes de un punto ycoma en la especificacioacuten pero al llamar a la funcioacuten se pueden utilizar solocomas

244 Capiacutetulo 19 Extra Sintaxis

Clausuras

Una clausura es una teacutecnica que permite que una funcioacuten capture una variabledefinida fuera del aacutembito de la funcioacuten

juliagt foo(x) = ()-gtxfoo (generic function with 1 method)

juliagt bar = foo(1)1 (generic function with 1 method)

juliagt bar()1

En este ejemplo la funcioacuten foo devuelve una funcioacuten anoacutenima que tiene acceso alargumento x de la funcioacuten foo bar apunta a la funcioacuten anoacutenima y devuelve elvalor del argumento de foo

BloquesUn bloque es una forma de agrupar varias sentencias Un bloque comienza con lapalabra reservada begin y termina con end

En Capiacutetulo 4 se presentoacute la macro svg

ὂ = Turtle()svg begin forward(ὂ 100) turn(ὂ -90) forward(ὂ 100)end

En este ejemplo la macro svg tiene un uacutenico argumento un bloque queagrupa 3 llamadas a funciones

Bloques let

Un bloque let es uacutetil para crear nuevas ligaduras (o bindings) es decir variableslocales que pueden apuntar a valores

Bloques 245

juliagt x y z = -1 -1 -1

juliagt let x = 1 z show x y z endx = 1y = -1ERROR UndefVarError z not definedjuliagt show x y zx = -1y = -1z = -1

En el ejemplo la primera macro show muestra la variable local x la variableglobal y y la variable local indefinida z Las variables globales se mantienenintactas

Bloques do

En Seccioacuten 142 se cierra el archivo despueacutes de terminar de escribir en eacutel Estose puede hacer automaacuteticamente usando un Bloque do

juliagt datos = El Cid convoca a sus vasallosneacutestos se destierran coneacutelnEl Cid convoca a sus vasallosneacutestos se destierran con eacutelnjuliagt open(salidatxt w) do fout write(fout datos) end61

En este ejemplo fout es el archivo stream utilizado para la salida

Esto es equivalente a

juliagt f = fout -gt begin write(fout datos) end3 (generic function with 1 method)juliagt open(f salidatxt w)61

La funcioacuten anoacutenima se utiliza como primer argumento de la funcioacuten open

246 Capiacutetulo 19 Extra Sintaxis

function open(fFunction args) io = open(args) try f(io) finally close(io) endend

Un bloque do puede capturar variables de su aacutembito envolvente (enclosedscope) Por ejemplo la variable datos en el ejemplo anterior de open do escapturada desde el aacutembito externo

Estructuras de control

Operador ternario

El operador ternario puede utilizarse en vez de una sentencia if-elseif Estasentencia se usa cuando se necesita elegir entre diferentes expresiones con valoruacutenico

juliagt a = 150150juliagt a 2 == 0 println(par) println(impar)par

La expresioacuten que va antes de es una expresioacuten de condicioacuten Si la condicioacuten estrue se evaluacutea la expresioacuten que va antes de De lo contrario se evaluacutea laexpresioacuten que va despueacutes de

Evaluacioacuten de cortocircuito

Los operadores ampamp y || realizan una evaluacioacuten de cortocircuito es decir seevaluacutea el siguiente argumento solo cuando es necesario para determinar el valorfinal

Por ejemplo una funcioacuten factorial recursiva podriacutea definirse asiacute

function fact(nInteger) n gt= 0 || error(n debe ser no negativo) n == 0 ampamp return 1 n fact(n-1)end

Estructuras de control 247

Tarea (o Corrutina)

Una tarea es una estructura de control que puede ceder el control de formacooperativa sin hacer return En Julia una tarea puede implementarse como unafuncioacuten con un objeto Channel como primer argumento Se usa un channel parapasar valores de la funcioacuten a la sentencia que la llama

El teacutermino cooperativo alude a que los programas deben cooperar para quetodo el esquema de programacioacuten funcione

La secuencia de Fibonnaci se puede generar mediante una tarea

function fib(cChannel) a = 0 b = 1 put(c a) while true put(c b) (a b) = (b a+b) endend

put almacena valores en un objeto channel y take lee valores desde eacutel

juliagt fib_gen = Channel(fib)

juliagt take(fib_gen)0juliagt take(fib_gen)1juliagt take(fib_gen)1juliagt take(fib_gen)2juliagt take(fib_gen)3

El constructor Channel crea la tarea La funcioacuten fib se suspende despueacutes de cadallamada a put y se reanuda al llamar a take Por razones de rendimiento sealmacenan varios valores de la secuencia en el objeto channel durante un ciclode reanudacioacutensuspensioacuten

Un objeto channel tambieacuten se puede usar como iterador

248 Capiacutetulo 19 Extra Sintaxis

juliagt for val in Channel(fib) print(val ) val gt 20 ampamp break end0 1 1 2 3 5 8 13 21

Tipos

Tipos Primitivos

Un tipo concreto compuesto por bits se llama tipo primitivo A diferencia de lamayoriacutea de los lenguajes en Julia se puede declarar nuestros propios tiposprimitivos Los tipos primitivos estaacutendar se definen de la misma manera

primitive type Float64 lt AbstractFloat 64 endprimitive type Bool lt Integer 8 endprimitive type Char lt AbstractChar 32 endprimitive type Int64 lt Signed 64 end

El nuacutemero en las sentencias especifica cuaacutentos bits son necesarios

El siguiente ejemplo crea un tipo primitivo Byte y un constructor

juliagt primitive type Byte 8 end

juliagt Byte(valUInt8) = reinterpret(Byte val)Bytejuliagt b = Byte(0x01)Byte(0x01)

La funcioacuten reinterpret se usa para almacenar los bits de un entero sin signo con8 bits (UInt8) en el byte

Tipos Parameacutetricos

El sistema de tipos de Julia es parameacutetrico lo que significa que los tipos puedentener paraacutemetros

Los paraacutemetros de un tipo se colocan despueacutes del nombre del tipo entre llaves

struct PuntoTltReal xT yTend

Tipos 249

Con esto se define un nuevo tipo parameacutetrico PuntoTltReal que contiene doscoordenadas de tipo T que puede ser cualquier tipo que tenga Real comosupertipo

juliagt Punto(00 00)PuntoFloat64(00 00)

Ademaacutes de los tipos compuestos los tipos abstractos y los tipos primitivostambieacuten pueden tener paraacutemetros

OBSERVACIOacuteN

Para mejorar el rendimiento es totalmenterecomendable tener tipos concretos como atributos deuna estructura por lo que esta es una buena manera dehacer que Punto sea raacutepido y flexible

Union de Tipo

Una union de tipo es un tipo parameacutetrico abstracto que puede actuar comocualquiera de los tipos de sus argumentos

juliagt EnteroOCadena = UnionInt64 StringUnionInt64 Stringjuliagt 150 EnteroOCadena150juliagt Julia EnteroOCadenaJulia

Una unioacuten de tipos es en la mayoriacutea de los lenguajes informaacuteticos unaconstruccioacuten interna para trabajar con tipos Sin embargo Julia pone adisposicioacuten esta caracteriacutestica para sus usuarios ya que permite generar uncoacutedigo eficiente (cuando la unioacuten es entre pocos tipos) Esta caracteriacutestica otorgauna gran flexibilidad para controlar el dispatch

Meacutetodos

Meacutetodos Parameacutetricos

Las definiciones de meacutetodos tambieacuten pueden tener paraacutemetros de tipo quelimiten su especificacioacuten

250 Capiacutetulo 19 Extra Sintaxis

juliagt espuntoentero(pPuntoT) where T = (T === Int64)espuntoentero (generic function with 1 method)juliagt p = Punto(1 2)PuntoInt64(1 2)juliagt espuntoentero(p)true

Objetos Similares a Funciones

Cualquier objeto arbitrario de Julia puede hacerse invocable Tales objetosinvocables a veces se denominan funtores

struct PolinomioR coefVectorRend

function (pPolinomio)(x) val = pcoef[end] for coef in pcoef[end-1-11] val = val x + coef end valend

Para evaluar el polinomio simplemente debemos llamarlo

juliagt p = Polinomio([110100])PolinomioInt64([1 10 100])juliagt p(3)931

ConstructoresLos tipos parameacutetricos se pueden construir expliacutecita o impliacutecitamente

juliagt Punto(12) T implicitoPuntoInt64(1 2)juliagt PuntoInt64(1 2) T explicitoPuntoInt64(1 2)juliagt Punto(125) T implicitoERROR MethodError no method matching Punto(Int64 Float64)

Se generan constructores internos y externos por defecto para cada T

Constructores 251

struct PuntoTltReal xT yT PuntoT(xy) where TltReal = new(xy)end

Punto(xT yT) where TltReal = PuntoT(xy)

y tanto x como y deben ser del mismo tipo

Cuando x e y son de tipos diferentes se puede definir el siguiente constructorexterno

Punto(xReal yReal) = Punto(promote(xy))

La funcioacuten promote se detalla en Seccioacuten 1982

Conversioacuten y PromocioacutenJulia tiene un sistema para convertir argumentos de diferentes tipos a un tipocomuacuten Esto es llamado promocioacuten y aunque no es automaacutetico se puede realizarfaacutecilmente

Conversioacuten

Un valor se puede convertir de un tipo a otro

juliagt x = 1212juliagt typeof(x)Int64juliagt convert(UInt8 x)0x0cjuliagt typeof(ans)UInt8

Se pueden agregar nuestros propios meacutetodos convert

juliagt Baseconvert(TypePuntoT xArrayT 1) where TltReal =Punto(x)

juliagt convert(PuntoInt64 [1 2])PuntoInt64(1 2)

252 Capiacutetulo 19 Extra Sintaxis

Promocioacuten

Promocioacuten es la conversioacuten de valores de diferentes tipos a un solo tipo comuacuten

juliagt promote(1 25 3)(10 25 30)

Generalmente los meacutetodos para la funcioacuten promote no se definen directamentesino que se usa la funcioacuten auxiliar promot_rule para especificar las reglas de lapromocioacuten

promote_rule(TypeFloat64 TypeInt32) = Float64

MetaprogramacioacutenUn coacutedigo de Julia se puede representar como una estructura de datos del mismolenguaje Esto permite que un programa escriba y manipule su propio coacutedigo

Expresiones

Cada programa de Julia comienza como una cadena

juliagt prog = 1 + 21 + 2

El siguiente paso es analizar cada cadena en un objeto llamado expresioacutenrepresentado por el tipo de Julia Expr

juliagt ex = Metaparse(prog)(1 + 2)juliagt typeof(ex)Exprjuliagt dump(ex)Expr head Symbol call args ArrayAny((3)) 1 Symbol + 2 Int64 1 3 Int64 2

La funcioacuten dump muestra objetos expr con anotaciones

Las expresiones se pueden construir directamente con el prefijo entrepareacutentesis o usando un bloque quote

Metaprogramacioacuten 253

juliagt ex = quote 1 + 2 end

eval

Julia puede evaluar un objeto de expresioacuten usando la funcioacuten eval

juliagt eval(ex)3

Cada moacutedulo tiene su propia funcioacuten eval que evaluacutea las expresiones de suaacutembito

AVISO Generalmente si un coacutedigo tiene muchas llamadas a eval significaque algo estaacute mal eval se considera malo

Macros

Las macros pueden incluir coacutedigo generado en un programa Una macro asociauna tupla de objetos Expr directamente con una expresioacuten compilada

Aquiacute hay una macro simple

macro contenedorvariable(contenedor elemento) return esc(($(Symbol(contenedorelemento)) = $contenedor[$elemento]))end

Las macros se llaman anteponiendo (arroba) a su nombre La llamada a lamacro contenedorvariable letras 1 se reemplaza por

(letras1 = letras[1])

macroexpand contenedorvariable letras 1 returns this expression which isextremely useful for debugging

Este ejemplo ilustra coacutemo una macro puede acceder al nombre de susargumentos algo que una funcioacuten no puede hacer Se debe escapar de laexpresioacuten de retorno con esc porque debe resolverse en el entorno de la macrollamada

254 Capiacutetulo 19 Extra Sintaxis

NOTA

iquestPor queacute usar Macros

Las macros generan e incluyen fragmentos de coacutedigopersonalizado durante el tiempo de anaacutelisis es decir antes deejecutar el programa completo

Funciones Generadas

La macro generated crea coacutedigo especializado para meacutetodos dependiendo deltipo de los argumentos

generated function cuadrado(x) println(x) (x x)end

El cuerpo devuelve una expresioacuten citada como una macro

Para la sentencia que llama la funcioacuten generada se comporta como una funcioacutennormal

juliagt x = cuadrado(2) nota la salida es de la instruccioacuten println ()que estaacute en el cuerpoInt64juliagt x ahora imprimimos x4juliagt y = cuadrado(spam)Stringjuliagt yspamspam

Datos FaltantesLos datos faltantes se pueden representar a traveacutes del objeto missing que es lainstancia uacutenica del tipo Missing

Los arreglos pueden contener datos que faltan missing values en ingleacutes

juliagt a = [1 missing]2-element ArrayUnionMissing Int641 1 missing

El tipo de dicho arreglo es UnionMissing T doacutende T es el tipo de los valoresque realmente tenemos en el arreglo

Datos Faltantes 255

Las funciones de reduccioacuten devuelven missing cuando se invocan con arreglosque contienen valores que faltan

juliagt sum(a)missing

En este caso se puede usar la funcioacuten skipmissing para omitir los valores quefaltan

juliagt sum(skipmissing([1 missing]))1

Llamar a Coacutedigo de C y FortranSe escribe mucho coacutedigo en C o Fortran Reutilizar un coacutedigo que ya ha sidoprobado generalmente es mejor que escribir su propia versioacuten en otro lenguajeJulia puede llamar directamente a las bibliotecas C o Fortran existentesutilizando la sintaxis ccall

En Seccioacuten 146 se presentoacute una interfaz de Julia de la biblioteca GDBM defunciones de base de datos La biblioteca estaacute escrita en C Para cerrar la base dedatos se debe hacer una llamada a la funcioacuten close(db)

Baseclose(dbmDBM) = gdbm_close(dbmhandle)

function gdbm_close(handlePtrCvoid) ccall((gdbm_close libgdbm) Cvoid (PtrCvoid) handle)end

Un objeto dbm tiene un atributo handle de tipo PtrCvoid Este atributocontiene un puntero de C que apunta a la base de datos Para cerrar la base dedatos debe llamarse a la funcioacuten de C gdbm_close teniendo como uacutenicoargumento el puntero C apuntando a la base de datos sin valor de retorno Juliahace esto directamente con la funcioacuten ccall que tiene como argumentos

bull una tupla que consiste en un siacutembolo que contiene el nombre de la funcioacutenque queremos llamar gdbm_close y la libreriacutea compartida especificadacomo una cadena +libgdm

bull el tipo de retorno Cvoid

bull una tupla de tipos de argumentos (PtrCvoid)

bull los valores del argumento handle

Una visioacuten completa de la libreriacutea GDBM se puede encontrar como ejemplo enlas fuentes de ThinkJulia

256 Capiacutetulo 19 Extra Sintaxis

Glossaryclausura

Funcioacuten que captura variables del aacutembito en doacutende estaacute definida

bloque letBloque de asignacioacuten de nuevas ligaduras variables

funcioacuten anoacutenimaFuncioacuten definida sin nombre

tupla con nombreTupla con componentes con nombre

argumentos con nombreArgumentos identificados por su nombre en vez de solo por la posicioacuten queocupan

bloque doConstruccioacuten usada para definir y llamar a una funcioacuten anoacutenima parecida aun bloque de coacutedigo normal

operador ternarioOperador de estructura de control que toma tres operandos una condicioacutenuna expresioacuten que se ejecutaraacute si la condicioacuten devuelve true y una expresioacutenque se ejecutaraacute si la condicioacuten devuelve false

evaluacioacuten de cortocircuitoEvaluacioacuten de un operador booleano para el que se ejecuta o evaluacutea elsegundo argumento solo si el primero no es suficiente para determinar elvalor de la expresioacuten

tareas (corrutina)Caracteriacutestica de las estructuras de control que permite suspender yreanudar caacutelculos de manera flexible

tipo primitivoTipo concreto cuyos datos estaacuten compuestos de bits

unioacuten de tiposTipo que incluye todas las instancias de cualquiera de sus tipos deparaacutemetros como objetos

Glossary 257

tipo parameacutetricoTipo que tiene paraacutemetros

funtorObjeto con un meacutetodo asociado para que sea invocable

conversioacutenPermite convertir un valor de un tipo a otro

promocioacutenConversioacuten de valores de diferentes tipos a un solo tipo comuacuten

expresioacutenTipo de Julia que contiene una construccioacuten de lenguaje

macroForma de incluir el coacutedigo generado en el cuerpo final de un programa

funciones generadasFunciones capaces de generar coacutedigo especializado seguacuten el tipo de losargumentos

datos faltantesInstancias que representan datos sin valor

258 Capiacutetulo 19 Extra Sintaxis

Capiacutetulo 20 Extra Base y Libreriacutea EstaacutendarJulia tiene todo lo necesario El moacutedulo Base contiene las funciones tipos ymacros maacutes uacutetiles los cuales estaacuten disponibles directamente en Julia

Julia tambieacuten posee una gran cantidad de moacutedulos especializados en suBiblioteca Estaacutendar (moacutedulos para fechas computacioacuten distribuida aacutelgebralineal perfiles nuacutemeros aleatorios entre otros) Las funciones los tipos y lasmacros definidos en la Biblioteca Estaacutendar deben importarse antes de poderusarse

bull import _Module_ importa el modulo y _Modulefn_(x) llama a la funcioacuten _fn_

bull using _Module_ importa todas las funciones tipos y macros exportadas de_Module_

Ademaacutes es posible agregar maacutes funciones a una gran cantidad de paquetes(httpsjuliaobservercom)

Este capiacutetulo no es un reemplazo de la documentacioacuten oficial de Julia Soacutelo sedan algunos ejemplos para ilustrar lo que es posible hacer sin ser exhaustivoLas funciones ya vistas no estaacuten incluidas Se puede encontrar una explicacioacutenmaacutes completa en httpsdocsjulialangorg

Midiendo el RendimientoHemos visto que algunos algoritmos funcionan mejor que otros fibonnaci enSeccioacuten 116 es mucho maacutes raacutepido que fib en Seccioacuten 67 La macro timepermite cuantificar la diferencia

juliagt fib(1)1juliagt fibonacci(1)1juliagt time fib(40) 0567546 seconds (5 allocations 176 bytes)102334155juliagt time fibonacci(40) 0000012 seconds (8 allocations 1547 KiB)102334155

time imprime el tiempo que tardoacute en ejecutarse la funcioacuten el nuacutemero deasignaciones (allocations) y la memoria asignada antes de devolver el resultadoLa funcioacuten fibonacci que guarda resultados previos es mucho maacutes raacutepida peronecesita maacutes memoria

Midiendo el Rendimiento 259

El teorema No free lunch dice que no existe un uacutenico modelo que funcionemejor en todos los casos

OBSERVACIOacuteN

Para comparar dos algoritmos estos debenimplementarse como funciones Una funcioacuten en Julia secompila la primera vez que se ejecuta por lo tanto sedebe excluir la primera vez que se llama a estasfunciones al medir el rendimiento De lo contrariotambieacuten se mediriacutea el tiempo de compilacioacuten

El paquete BenchmarkTools (httpsgithubcomJuliaCIBenchmarkToolsjl) proporciona la macro btime querealiza una evaluacioacuten comparativa de la maneracorrecta iexclAsiacute que uacutesela

Colecciones y Estructuras de DatosEn Seccioacuten 136 se usan diccionarios para encontrar las palabras que apareciacuteanen un documento y que no apareciacutean en un arreglo de palabras La funcioacuten quese escribioacute tomaba d1 que conteniacutea las palabras del documento como claves yd2 que conteniacutea el arreglo de palabras Y devolviacutea un diccionario que conteniacutealas claves de d1 que no estaban en d2

function resta(d1 d2) res = Dict() for clave in keys(d1) if clave notin keys(d2) res[clave] = nothing end end resend

En todos estos diccionarios los valores son nothing porque nunca son usadosCon esto se estaacute desperdiciando espacio de almacenamiento

Julia ofrece otro tipo integrado llamado conjunto que se comporta como unacoleccioacuten de claves de diccionario sin valores Agregar elementos a un conjuntoes raacutepido y tambieacuten lo es verificar si un elemento forma parte de eacutel Ademaacutes losconjuntos proporcionan funciones y operadores para calcular operaciones deconjuntos

Por ejemplo la resta de conjuntos estaacute disponible como una funcioacuten llamadasetdiff Entonces reescribiendo resta

260 Capiacutetulo 20 Extra Base y Libreriacutea Estaacutendar

function resta(d1 d2) setdiff(d1 d2)end

El resultado es un conjunto en vez de un diccionario

Algunos de los ejercicios en este libro se pueden hacer de manera eficiente yconcisa con conjuntos Por ejemplo a continuacioacuten se muestra una solucioacuten pararepetido de Seccioacuten 10157 que usa un diccionario

function repetido(t) d = Dict() for x in t if x isin d return true end d[x] = nothing end falseend

Cuando un elemento aparece por primera vez se agrega al diccionario Si elmismo elemento aparece nuevamente la funcioacuten devuelve true

Usando conjuntos podemos escribir la misma funcioacuten

function repetido(t) length(Set(t)) lt length(t)end

Un elemento solo puede aparecer en un conjunto una vez por lo que si unelemento en t aparece maacutes de una vez el conjunto seraacute maacutes pequentildeo que t Si nohay elementos repetidos el conjunto tendraacute el mismo tamantildeo que t

Tambieacuten podemos usar conjuntos para hacer algunos de los ejercicios deCapiacutetulo 9 Por ejemplo aquiacute hay una versioacuten de usasolo con un bucle

function usasolo(palabra disponibles) for letra in palabra if letra notin disponibles return false end end trueend

Colecciones y Estructuras de Datos 261

usasolo comprueba si todas las letras en palabra estaacuten en disponibles Podemosreescribir esta funcioacuten

function usasolo(palabra disponibles) Set(palabra) sube Set(disponibles)end

El operador sube (subseteq TAB) verifica si un conjunto es un subconjunto deotro incluida la posibilidad de que sean iguales lo cual es cierto si todas lasletras en palabra aparecen en disponibles

Exercise 20-1

Reescriba la funcioacuten evita de Capiacutetulo 9 usando conjuntos

MatemaacuteticasTambieacuten se pueden usar nuacutemeros complejos en Julia La constante global im estaacuteasociada al nuacutemero complejo que representa la raiacutez cuadrada principal de

Ahora se puede verificar la identidad de Euler

juliagt ℯ^(imπ)+100 + 12246467991473532e-16im

El siacutembolo ℯ (euler TAB) es la base de los logaritmos naturales

Se puede analizar la naturaleza compleja de las funciones trigonomeacutetricas

Se puede probar esta foacutermula para diferentes valores de

juliagt x = 0012π000162juliagt cos(x) == 05(ℯ^(imx)+ℯ^(-imx))true

Aquiacute se muestra otro ejemplo del operador punto Julia tambieacuten permite usarvalores numeacutericos con identificadores (siacutembolos leacutexicos que nombran entidadescomo π) como en 2π

262 Capiacutetulo 20 Extra Base y Libreriacutea Estaacutendar

CadenasEn Capiacutetulo 8 y Capiacutetulo 9 se realizan algunas buacutesquedas en cadenas AdemaacutesJulia puede usar expresiones regulares (o regexes) compatibles con Perl lo quefacilita la tarea de encontrar patrones complejos en cadenas

La funcioacuten usasolo se puede implementar como una expresioacuten regular

function usasolo(palabra disponibles) r = Regex([^$(disponibles)]) occursin(r palabra)end

La expresioacuten regular busca un caraacutecter que no estaacute en la cadena disponible yoccursin devuelve true si el patroacuten se encuentra en palabra

juliagt usasolo(banana abn)truejuliagt usasolo(bananas abn)false

Las expresiones regulares tambieacuten se pueden construir como literales de cadenano estaacutendar con el prefijo r

juliagt match(r[^abn] banana)

juliagt m = match(r[^abn] bananas)RegexMatch(s)

En este caso la interpolacioacuten de cadenas no estaacute permitida La funcioacuten matchdevuelve nothing si no se encuentra el patroacuten de lo contrario devuelve un objetoregexmatch

Podemos extraer la siguiente informacioacuten de un objeto regexmatch

bull La subcadena que coincide mmatch

bull Las subcadenas que coinciden en forma de arreglo de cadenas mcaptures

bull La primera posicioacuten en la que se encuentra el patroacuten moffset

bull Las posiciones de las subcadenas que coinciden en forma de arreglomoffsets

Cadenas 263

juliagt mmatchsjuliagt moffset7

Las expresiones regulares son extremadamente poderosas y el manual de PERLhttpperldocperlorgperlrehtml explica coacutemo realizar hasta las buacutesquedas maacutesextrantildeas

ArreglosEn el Capiacutetulo 10 se usa un objeto de arreglo unidimensional con un iacutendice paraacceder a sus elementos Sin embargo en Julia las matrices sonmultidimensionales

Se puede crear una matriz de ceros de 2 por 3

juliagt z = zeros(Float64 2 3)2times3 ArrayFloat642 00 00 00 00 00 00juliagt typeof(z)ArrayFloat642

El tipo de esta matriz es un arreglo que contiene nuacutemeros de punto flotante Estamatriz es de 2 dimensiones

La funcioacuten size devuelve una tupla con el nuacutemero de elementos en cadadimensioacuten

juliagt size(z)(2 3)

La funcioacuten ones construye una matriz con elementos de valor unitario

juliagt s = ones(String 1 3)1times3 ArrayString2

El elemento de valor unitario de una cadena es una cadena vaciacutea

264 Capiacutetulo 20 Extra Base y Libreriacutea Estaacutendar

AVISO

s no es un arreglo unidimensional

juliagt s == [ ]false

s es un vector fila y [ ] es un vector columna

Se puede crear una matriz usando espacios para separar elementos en una fila ypunto y coma para separar filas

juliagt a = [1 2 3 4 5 6]2times3 ArrayInt642 1 2 3 4 5 6

Se pueden usar corchetes para modificar elementos de una matriz

juliagt z[12] = 11juliagt z[23] = 11juliagt z2times3 ArrayFloat642 00 10 00 00 00 10

Se pueden usar porciones en cada dimensioacuten para seleccionar un subgrupo deelementos

juliagt u = z[2end]2times2 ArrayFloat642 10 00 00 10

El operador aplica una operacioacuten en todas las dimensiones

juliagt ℯ^(imu)2times2 ArrayComplexFloat642 0540302+0841471im 10+00im 10+00im 0540302+0841471im

Arreglos 265

InterfacesJulia especifica algunas interfaces informales para definir comportamientos esdecir meacutetodos con un objetivo especiacutefico Cuando se extienden estos meacutetodospara un tipo los objetos de ese tipo se pueden usar para construir estoscomportamientos

Si parece un pato nada como un pato y grazna como un pato entoncesprobablemente sea un pato

En Seccioacuten 67 implementamos la funcioacuten fib que devuelve el elemento -eacutesimode la secuencia de Fibonnaci

Recorrer los valores de una coleccioacuten lo cual recibe el nombre de iteracioacuten esuna interfaz de este tipo Se puede crear un iterador que devuelva la secuenciade Fibonacci

struct FibonacciTltReal endFibonacci(dDataType) = dltReal Fibonaccid() error(No Real type)

Baseiterate(FibonacciT) where TltReal = (zero(T) (one(T) one(T)))Baseiterate(FibonacciT stateTupleT T) where TltReal =(state[1] (state[2] state[1] + state[2]))

Se implementa un tipo parameacutetrico Fibonacci sin atributos un constructorexterno y dos meacutetodos iterate Se llama al primer meacutetodo iterate para inicializarel iterador y este devuelve una tupla que consta de un primer valor 0 y unestado El estado en este caso es una tupla que contiene el segundo y el tercervalor 1 y 1

Se llama al segundo meacutetodo iterate para obtener el siguiente valor de lasecuencia de Fibonacci y devuelve una tupla que tiene como primer elemento elsiguiente valor y como segundo elemento el estado que es una tupla con los dosvalores siguientes

Ahora se puede usar Fibonacci en un bucle for

juliagt for e in Fibonacci(Int64) e gt 100 ampamp break print(e ) end0 1 1 2 3 5 8 13 21 34 55 89

Parece sacado debajo de la manga pero la explicacioacuten es simple Un bucle for enJulia

266 Capiacutetulo 20 Extra Base y Libreriacutea Estaacutendar

for i in iter bodyend

se traduce en

next = iterate(iter)while next == nothing (i state) = next body next = iterate(iter state)end

Este es un ejemplo de coacutemo una interfaz bien definida permite que unaimplementacioacuten use todas las funciones disponibles en esta interfaz

Moacutedulo Interactive UtilitiesYa se ha visto el moacutedulo InteractiveUtils en Seccioacuten 1810 La macro which essolo una de las tantas opciones

La biblioteca LLVM transforma el coacutedigo de Julia en coacutedigo de maacutequina envarios pasos Podemos visualizar la salida de cada etapa

Aquiacute se muestra un ejemplo simple

function sumacuadrada(aFloat64 bFloat64) a^2 + b^2end

El primer paso es mirar el coacutedigo de bajo nivel (lowered code)

juliagt using InteractiveUtils

juliagt code_lowered sumacuadrada(30 40)CodeInfo(1 1 = Coreapply_type(BaseVal 2) 2 = (1)() 3 = Baseliteral_pow(^ a 2) 4 = Coreapply_type(BaseVal 2) 5 = (4)() 6 = Baseliteral_pow(^ b 5) 7 = 3 + 6 return 7)

Moacutedulo Interactive Utilities 267

La macro code_lowered devuelve un arreglo de una representacioacuten intermediadel coacutedigo que utiliza el compilador para generar coacutedigo optimizado

El siguiente paso antildeade informacioacuten del tipo

juliagt code_typed sumacuadrada(30 40)CodeInfo(1 1 = Basemul_float(a a)Float64 2 = Basemul_float(b b)Float64 3 = Baseadd_float(1 2)Float64 return 3) =gt Float64

El tipo de resultados intermedios y el valor de retorno se infiere correctamente

Esta representacioacuten del coacutedigo se transforma en coacutedigo LLVM

juliagt code_llvm sumacuadrada(30 40) none1 within `sumacuadradadefine double julia_sumacuadrada_6080(double double) top none2 within `sumacuadrada intfuncsjl296 within `literal_pow floatjl405 within ` 2 = fmul double 0 0 3 = fmul double 1 1 floatjl401 within `+ 4 = fadd double 2 3 ret double 4

Y finalmente se genera el coacutedigo de maacutequina

268 Capiacutetulo 20 Extra Base y Libreriacutea Estaacutendar

juliagt code_native sumacuadrada(30 40) text none2 within `sumacuadrada intfuncsjl296 within `literal_pow floatjl405 within ` vmulsd xmm0 xmm0 xmm0 vmulsd xmm1 xmm1 xmm1 floatjl401 within `+ vaddsd xmm1 xmm0 xmm0 retq nopl (rax)

DepuracioacutenLas macros Logging son una alternativa al andamiaje con sentencias deimpresioacuten

juliagt warn iexclOh vosotros los que entraacuteis abandonad la depuracioacuten conprintf Warning iexclOh vosotros los que entraacuteis abandonad la depuracioacuten conprintf Main REPL[1]1

Las sentencias de depuracioacuten (debug) no tienen que eliminarse del coacutedigo Porejemplo en contraste con el warn anterior

juliagt debug La suma de algunos valores $(sum(rand(100)))

debug por defecto no produce salida En este caso sum(rand(100)) nunca seevaluaraacute a menos que debug logging esteacute habilitado

El nivel de logging puede seleccionarse mediante la variable de entornoJULIA_DEBUG

$ JULIA_DEBUG=all julia -e debug La suma de algunos valores$(sum(rand(100))) Debug La suma de algunos valores 47116520814555024 Main none1

Aquiacute hemos utilizado all para obtener toda la informacioacuten de depuracioacuten perotambieacuten se puede optar por generar salida solo para un archivo o moacuteduloespeciacutefico

Depuracioacuten 269

Glosarioregex

Expresioacuten regular una secuencia de caracteres que definen un patroacuten debuacutesqueda

matrizArreglo bidimensional

representacioacuten intermediaEstructura de datos utilizada internamente por un compilador pararepresentar el coacutedigo fuente

coacutedigo de maacutequinaInstrucciones que pueden ser ejecutadas directamente por la unidad centralde procesamiento de una computadora

debug loggingAlmacenar mensajes de depuracioacuten en un registro (log)

270 Capiacutetulo 20 Extra Base y Libreriacutea Estaacutendar

Capiacutetulo 21 DepuracioacutenAl depurar es necesario distinguir entre los diferentes tipos de errores pararastrearlos maacutes raacutepidamente

bull Los errores de sintaxis se descubren cuando el inteacuterprete traduce el coacutedigofuente a coacutedigo de bytes Estos errores indican que hay una falla en laestructura del programa Por ejemplo omitir la palabra reservada end alfinal de un bloque de funciones genera el mensaje ERROR LoadErrorsyntax incomplete function requires end

bull Los errores en tiempo de ejecucioacuten se presentan si algo falla mientras seejecuta el programa La mayoriacutea de los mensajes de error en tiempo deejecucioacuten indican doacutende ocurrioacute el error y queacute funciones se estabanejecutando Ejemplo Una recursioacuten infinita eventualmente causa el error entiempo de ejecucioacuten ERROR StackOverflowError

bull Los errores semaacutenticos ocurren cuando un programa se ejecuta sin generarmensajes de error pero no hace lo que deberiacutea Por ejemplo una expresioacutenpuede no evaluarse en el orden esperado generando un resultadoincorrecto

El primer paso en la depuracioacuten es averiguar el tipo de error al que se enfrentaAunque las siguientes secciones estaacuten organizadas por tipo de error algunasteacutecnicas son aplicables en maacutes de una situacioacuten

Errores de SintaxisLos errores de sintaxis suelen ser faacuteciles de corregir una vez se descubre cuaacutelesson Desafortunadamente muchas veces los mensajes de error no son uacutetiles Losmensajes maacutes comunes son

ERROR LoadError syntax incomplete premature end of input

y

ERROR LoadError syntax unexpected =

los cuales no son muy informativos

Por otro lado el mensaje indica en queacute parte del programa se produjo elproblema En realidad indica doacutende Julia notoacute que habiacutea un problema que no esnecesariamente doacutende estaacute el error A veces el error es anterior a la ubicacioacutendel mensaje de error generalmente en la liacutenea anterior

Si estaacute programando incrementalmente el usuario deberiacutea tener casi localizadoel error ya que estaraacute en la uacuteltima liacutenea que agregoacute

Si estaacute copiando coacutedigo de un libro comience comparando su coacutedigo con el

Errores de Sintaxis 271

coacutedigo del libro y verifique cada letra Al mismo tiempo recuerde que el libropuede contener errores por lo que si ve algo que parece un error de sintaxis esposible que lo sea

Aquiacute hay algunas formas de evitar los errores de sintaxis maacutes comunes

1 Aseguacuterese de no estar usando una palabra reservada de Julia en un nombrede variable

2 Compruebe que tiene la palabra reservada end al final de cada sentenciacompuesta incluyendo los bloques for while if y function

3 Aseguacuterese de que las cadenas tengan su par de comillas de apertura ycierre Aseguacuterese de que todas las comillas sean comillas rectas y no otrotipo de comillas

4 Si tiene cadenas que ocupan varias liacuteneas con triples comillas aseguacuterese deque ha terminado la cadena correctamente Una cadena sin terminar puedeprovocar un error invalid token al final de su programa o puede hacer quela siguiente parte del programa sea tratada como una cadena hasta llegar ala siguiente cadena iexclEl segundo caso podriacutea no presentar mensaje de error

5 Un pareacutentesis sin cerrar mdash( or [mdash hace que Julia continuacutee con la liacuteneasiguiente como parte de la sentencia actual Generalmente se produce unerror casi inmediatamente en la siguiente liacutenea

6 Verifique el claacutesico error que se produce al ocupar = en lugar de == dentrode un condicional

7 Si tiene caracteres que no son ASCII en el coacutedigo (incluidas cadenas ycomentarios) esto podriacutea causar un problema aunque Julia generalmentemaneja caracteres no ASCII Tenga cuidado si pega texto de una paacutegina webu otra fuente

Si nada funciona pase a la siguiente seccioacuten hellip

Sigo haciendo cambios y no hay diferencia

Si el REPL dice que hay un error y usted no lo ve podriacutea deberse a que usted y elREPL no estaacuten viendo el mismo coacutedigo Verifique su entorno de programacioacutenpara asegurarse de que el programa que estaacute editando es el que Julia estaacutetratando de ejecutar

Si no estaacute seguro intente poner un error de sintaxis obvio y deliberado alcomienzo del programa Ahora ejecuacutetelo de nuevo Si REPL no encuentra elnuevo error no estaacute ejecutando el nuevo coacutedigo

Estas son algunas de las posibles razones

bull Editoacute el archivo y olvidoacute guardar los cambios antes de ejecutarlonuevamente Algunos entornos de programacioacuten hacen esto por usted pero

272 Capiacutetulo 21 Depuracioacuten

otros no

bull Cambioacute el nombre del archivo pero auacuten estaacute ejecutando el archivo con elnombre anterior

bull Algo en su entorno de desarrollo estaacute configurado incorrectamente

bull Si estaacute escribiendo un moacutedulo y estaacute usando using aseguacuterese de no darle asu moacutedulo el mismo nombre que uno de los moacutedulos estaacutendar de Julia

bull Si estaacute usando using para importar un moacutedulo recuerde que debe reiniciarREPL cuando modifique el coacutedigo en el moacutedulo Si vuelve a importar elmoacutedulo no ocurre nada

Si se queda atascado y no puede darse cuenta de lo que estaacute sucediendo unenfoque es comenzar de nuevo con un nuevo programa como iexclHola Mundo yasegurarse de que puede ejecutar este programa ya conocido Luego puedeagregar gradualmente las piezas del programa original al nuevo

Errores en Tiempo de EjecucioacutenUna vez que su programa es sintaacutecticamente correcto Julia puede leerlo y almenos comenzar a ejecutarlo iquestQueacute podriacutea salir mal

Mi programa no hace absolutamente nada

Este problema es comuacuten cuando su archivo consta de funciones y clases pero enrealidad no llama a ninguna funcioacuten para iniciar la ejecucioacuten Esto puede serintencional si soacutelo se busca importar este moacutedulo para suministrar clases yfunciones

Si no es intencional aseguacuterese de que haya una llamada a la funcioacuten en elprograma y aseguacuterese de que el flujo de ejecucioacuten pase por esta llamada (veaSeccioacuten 21223)

Mi programa se congela

Si un programa se detiene y parece no estar haciendo nada estaacute congeladoGeneralmente eso significa que estaacute atrapado en un bucle infinito o en unarecursioacuten infinita

bull Si hay un bucle en particular que le resulta sospechoso de poder provocar elproblema agregue una sentencia de impresioacuten justo antes del bucle quediga entrando al bucle y otra inmediatamente posterior que diga saliendodel bucle

Ejecute el programa Si recibe el primer mensaje y no el segundo tiene unbucle infinito Vea Seccioacuten 21221

bull La mayoriacutea de las veces una recursioacuten infinita haraacute que el programa se

Errores en Tiempo de Ejecucioacuten 273

ejecute por un rato y luego produzca un error ERROR LoadErrorStackOverflowError Si eso sucede vea Seccioacuten 21222

Si no obtiene este error pero sospecha que hay un problema con un meacutetodoo funcioacuten recursiva igual puede utilizar las teacutecnicas de Seccioacuten 21222

bull Si ninguno de esos pasos funciona comience a probar otros bucles y otrasfunciones y meacutetodos recursivos

bull Si esto no funciona quizaacutes es porque usted no entiende el flujo de ejecucioacutende su programa Vea Seccioacuten 21223

Bucle Infinito

Si cree tener un bucle infinito y cree saber cuaacutel es antildeada una sentencia deimpresioacuten que imprima los valores de las variables de la condicioacuten al final delbucle junto con el valor de la condicioacuten

Por ejemplo

while x gt 0 ampamp y lt 0 hacer algo con x hacer algo con y debug variables x y debug condicion x gt 0 ampamp y lt 0end

Ahora cuando ejecute el programa en modo de depuracioacuten veraacute el valor de lasvariables y la condicioacuten en cada iteracioacuten En la uacuteltima iteracioacuten la condicioacutendebe ser false Si el ciclo continuacutea podraacute ver los valores de x e y y podraacuteaveriguar por queacute no se actualizan correctamente

Recursioacuten Infinita

La mayoriacutea de las veces una recursioacuten infinita hace que el programa se ejecutedurante un tiempo y luego produzca un error

ERROR LoadError StackOverflowError

Si sospecha que una funcioacuten o un meacutetodo estaacute causando una recursioacuten infinitacomience por asegurarse de que hay un caso base En otras palabras deberiacuteahaber una condicioacuten que haga que la funcioacuten devuelva un valor sin hacer otrallamada recursiva Si no necesita revisar el algoritmo y encontrar ese caso base

Si hay un caso base pero el programa no parece llegar hasta eacutel antildeada unasentencia de impresioacuten al inicio de la funcioacuten que imprima los paraacutemetrosAhora cuando ejecute el programa veraacute el valor de los paraacutemetros cada vez quese llame la funcioacuten Si los paraacutemetros no se acercan al caso base eso le daraacute

274 Capiacutetulo 21 Depuracioacuten

alguna idea de por queacute no lo hace

Flujo de Ejecucioacuten

Si no estaacute seguro del flujo de ejecucioacuten en su programa antildeada sentencias deimpresioacuten al principio de cada funcioacuten con mensajes como ldquoentrando a la funcioacutenfunrdquo donde fun sea el nombre de la funcioacuten

Ahora cuando ejecute el programa se imprimiraacute una mensaje en cada funcioacuten amedida que estas sean llamadas

Cuando ejecuto el programa recibo una excepcioacuten

Si algo sale mal durante la ejecucioacuten Julia imprime un mensaje que incluye elnombre de la excepcioacuten la liacutenea del programa donde sucedioacute el problema y untrazado inverso

El trazado inverso identifica la funcioacuten que se estaacute ejecutando y la funcioacuten que lallamoacute y luego la funcioacuten que llamoacute a esa y asiacute sucesivamente En otras palabrastraza la ruta de las llamadas a las funciones que le llevaron a donde seencuentra Tambieacuten incluye los nuacutemeros de las liacuteneas de su archivo doacutendesuceden todas esas llamadas

El primer paso es examinar el lugar del programa donde ocurrioacute el error y ver sipuede adivinar lo que sucedioacute Estos son algunos de los errores en tiempo deejecucioacuten maacutes comunes

ArgumentErrorUno de los argumentos para llamar a una funcioacuten no tiene la formaesperada

BoundsErrorSe estaacute tratando de acceder a un elemento de un arreglo fuera de los liacutemitesde indexacioacuten

DomainErrorEl argumento de una funcioacuten o constructor no pertenece al dominio vaacutelido

DivideErrorSe intentoacute dividir un entero por 0

EOFErrorNo habiacutea maacutes datos disponibles para leer desde un archivo o stream

InexactErrorNo se puede convertir a un tipo

Errores en Tiempo de Ejecucioacuten 275

KeyErrorSe estaacute tratando de acceder o eliminar un elemento inexistente de un objetoAbstractDict (Dict) o Set

MethodErrorNo existe un meacutetodo con la especificacioacuten de tipo requerida en la funcioacutengeneacuterica dada Alternativamente no existe un meacutetodo uacutenico maacutes especiacutefico

OutOfMemoryErrorUna operacioacuten asignoacute demasiada memoria para que el sistema o elrecolector de basura opere correctamente

OverflowErrorEl resultado de una expresioacuten es demasiado grande para el tipo especificadoy se produce un desbordamiento

StackOverflowErrorUna llamada a funcioacuten trata de usar maacutes espacio que el que estaacute disponibleen la pila de llamadas Esto generalmente ocurre cuando una llamada serepite infinitamente

StringIndexErrorSe produjo un error al intentar acceder a un iacutendice invaacutelido de una cadena

SystemErrorFalloacute una llamada al sistema y se muestra un mensaje de error

TypeErrorError de asercioacuten de tipo o error producido al llamar a una funcioacutenintegrada con un tipo de argumento incorrecto

UndefVarErrorUn siacutembolo en el entorno (o aacutembito) actual no estaacute definido

Puse tantas sentencias de impresioacuten que me ahogo eninformacioacuten

Uno de los problemas de usar sentencias print en la depuracioacuten es que puedeterminar ahogado por tanta informacioacuten Hay dos formas de resolver estosimplificar la salida o simplificar el programa

Para simplificar la salida puede eliminar o comentar (convertir en comentariosno evaluados coacutemo oacuterdenes del programa) las sentencias print que no sean uacutetileso combinarlas Tambieacuten puede dar a la salida un formato que la haga maacutescomprensible

276 Capiacutetulo 21 Depuracioacuten

Para simplificar el programa puede hacer varias cosas Primero puede reducir laescala del problema en el que estaacute trabajando el programa Por ejemplo si estaacutebuscando algo en una lista buacutesquelo en una lista pequentildea Si el programa aceptaentradas del usuario ingrese la entrada maacutes simple que provoque el problema

Segundo puede limpiar el programa Elimine el coacutedigo muerto y reorganice elprograma para hacerlo tan legible como sea posible Por ejemplo si sospechaque el problema estaacute en una parte del programa con un anidamiento (nesting)muy profundo pruebe a reescribir esa parte con una estructura maacutes simple Sisospecha de una funcioacuten muy larga trate de dividirla en funciones maacutes pequentildeasy prueacutebelas separadamente

Generalmente el proceso de encontrar el caso de prueba miacutenimo lleva el usuarioa encontrar el error Si encuentra que un programa funciona en una situacioacutenpero no en otra eso le daraacute una pista sobre lo que estaacute sucediendo

De forma parecida reescribir una porcioacuten de coacutedigo puede ayudarle a encontrarerrores sutiles Si realiza un cambio que cree que no deberiacutea afectar elprograma pero lo hace entonces eso puede darle una pista

Errores SemaacutenticosEn cierto modo los errores semaacutenticos son los maacutes difiacuteciles de corregir ya que elinteacuterprete no entrega informacioacuten sobre lo que estaacute mal Soacutelo usted sabe lo quese supone que debe hacer el programa

El primer paso es hacer una conexioacuten entre el coacutedigo y el comportamiento queestaacute viendo Necesita una hipoacutetesis sobre lo que realmente estaacute haciendo elprograma Una de las dificultades que nos encontramos es la alta velocidad delos computadores

A menudo seriacutea deseable ralentizar el programa a una velocidad humana Eltiempo que lleva colocar unas sentencias print en los lugares adecuados sueleser menor que el que lleva configurar un depurador poner y quitar puntos deinterrupcioacuten y ldquohacer avanzarrdquo al programa hasta donde se produce el error

Mi programa no funciona

Deberiacutea hacerse estas preguntas

bull iquestHay algo que se supone que deberiacutea hacer el programa pero que nosucede Busque la seccioacuten del coacutedigo que realiza esa funcioacuten y aseguacuterese deque se ejecuta cuando deberiacutea

bull iquestOcurre algo que no deberiacutea Busque el coacutedigo en su programa que realizaesa funcioacuten y vea si se ejecuta cuando no debe

bull iquestHay alguna seccioacuten del coacutedigo que cause un efecto que no esperabaAseguacuterese de que entiende el coacutedigo en cuestioacuten especialmente si incluye

Errores Semaacutenticos 277

funciones o meacutetodos de otros moacutedulos de Julia Lea la documentacioacuten de lasfunciones a las que llama Prueacutebelas escribiendo casos de prueba simples ycomprobando sus resultados

Para programar necesitaraacute tener un modelo mental de coacutemo funcionan losprogramas Si escribe un programa que no hace lo que esperaba de eacutel muchasveces el problema no estaraacute en el programa sino en su modelo mental

La mejor manera de corregir su modelo mental es dividiendo el programa en suscomponentes (normalmente en funciones y meacutetodos) y probando cadacomponente de forma independiente Una vez que encuentre la discrepanciaentre su modelo y la realidad podraacute solucionar el problema

Por supuesto deberiacutea ir haciendo y probando componentes a medida quedesarrolla el programa Si encuentra un problema soacutelo habriacutea que revisar unapequentildea cantidad de coacutedigo nuevo

Tengo una expresioacuten grande y peliaguda y no hace lo queespero

Estaacute bien escribir expresiones complejas mientras sean legibles pero pueden serdifiacuteciles de depurar Suele ser una buena idea dividir una expresioacuten compleja enuna serie de asignaciones de variables temporales

Por ejamplo

agregarcarta(juegomanos[i] sacarcarta(juegomanos[encontrarvecino(juegoi)]))

Puede reescribirse como

vecino = encontrarvecino(juego i)cartaseleccionada = sacarcarta(juegomanos[vecino])agregarcarta(juegomanos[i] cartaseleccionada)

La versioacuten expliacutecita es maacutes faacutecil de leer porque los nombres de variables nosentregan documentacioacuten adicional y es maacutes faacutecil de depurar porque se puedencomprobar los tipos de las variables intermedias y mostrar sus valores

Otro problema que puede suceder con las expresiones grandes es que el ordende evaluacioacuten puede no ser el que usted esperaba Por ejemplo si estaacutetraduciendo la expresioacuten a Julia podriacutea escribir

y = x 2 π

Esto no es correcto ya que la multiplicacioacuten y la divisioacuten tienen la misma

278 Capiacutetulo 21 Depuracioacuten

precedencia y se evaluacutean de izquierda a derecha De este modo la anteriorexpresioacuten calcula

Una buena forma de depurar expresiones es antildeadir pareacutentesis para que seaexpliacutecito el orden de evaluacioacuten

y = x (2 π)

Siempre que no esteacute seguro del orden de evaluacioacuten utilice pareacutentesis Elprograma no soacutelo seraacute correcto (en el sentido de que hace lo que usted quiere)sino que ademaacutes seraacute maacutes legible para otras personas que no hayan memorizadolas reglas de precedencia y que lean el coacutedigo

Tengo una funcioacuten que no devuelve lo que esperaba

Si tiene una sentencia return con una expresioacuten compleja no tendraacute laoportunidad de imprimir el valor de retorno antes de retornar De nuevo puedeusar una variable temporal Por ejemplo en lugar de

return sacarpares(juegomanos[i])

podriacutea escribir

contar = sacarpares(juegomanos[i])return contar

Ahora ya tiene la oportunidad de mostrar el valor de count antes de retornar

Estoy atascado de verdad y necesito ayuda

Primero intente alejarse del computador durante unos minutos Trabajar con uncomputador puede provocar estos efectos

bull Frustracioacuten yo furia

bull Creencias supersticiosas (ldquoel computador me odiardquo) y pensamiento maacutegico(ldquoel programa soacutelo funciona cuando me pongo la gorra hacia atraacutesrdquo)

bull Programar dando palos de ciego (el empentildeo de programar escribiendo todoslos programas posibles y eligiendo el que hace lo correcto)

Si se encuentra afectado por alguno de estos siacutentomas levaacutentese y deacute un paseoCuando esteacute calmado piense en el programa iquestQueacute es lo que hace iquestCuaacutelespueden ser las causas de tal comportamiento iquestCuaacutendo fue la uacuteltima vez que suprograma funcionaba y queacute fue lo siguiente que hizo

A veces lleva tiempo encontrar un error Muchas veces encontramos errores

Errores Semaacutenticos 279

cuando estamos lejos del computador y divagamos Algunos de los mejoreslugares para encontrar errores son los trenes las duchas y la cama justo antesde quedarse dormido

No de verdad necesito ayuda

Sucede Incluso los mejores programadores se atascan de vez en cuando A vecestrabaja durante tanto tiempo en un programa que no puede ver el error Lo quenecesita es un par de ojos nuevos

Antes de llamar a alguien aseguacuterese de estar preparado Su programa deberiacuteaser tan simple como sea posible y usted deberiacutea estar trabajando con la entradamiacutenima que provoca el error Deberiacutea tener sentencias print en los lugaresadecuados (y lo que dicen deberiacutea ser comprensible) y deberiacutea tambieacuten entenderel problema lo bastante bien como para describirlo de manera concisa

Cuando llame a alguien para que le ayude aseguacuterese de darle la informacioacuten quenecesitan

bull Si hay un mensaje de error iquestcuaacutel es y queacute parte del programa sentildeala

bull iquestQueacute fue lo uacuteltimo que hizo antes de que apareciera el error iquestCuaacuteles sonlas uacuteltimas liacuteneas de coacutedigo que escribioacute o cuaacutel es el nuevo caso de pruebaque falla

bull iquestQueacute ha intentado hasta ahora y queacute ha averiguado

Cuando encuentre el error toacutemese un momento para pensar acerca de lo quepodriacutea haber hecho para encontrarlo maacutes raacutepido La siguiente vez que vea algoparecido seraacute capaz de encontrar el error antes

Recuerde el objetivo no es solo hacer que el programa funcione El objetivo esaprender coacutemo hacer funcionar el programa

280 Capiacutetulo 21 Depuracioacuten

Apeacutendice A Entrada de UnicodeLa siguiente tabla muestra algunos de los muchos caraacutecteres Unicode quepueden ingresarse mediante abreviaciones similares a aquellas utilizadas enLatex en el REPL de Julia (y en muchos otros entornos de edicioacuten)

Caraacutecter Tab completionsequence

representacioacuten ASCII

sup2 ^2₁ _1₂ _2ἴ appleἴ bananaὂ camelἵ pearὂ turtlecap capequiv equiv ===

ℯ eulerisin in in

ge ge gt=

le le lt=

ne ne =

notin notinπ pi pi

sube subseteqε varepsilon

Apeacutendice A Entrada de Unicode 281

Apeacutendice B JuliaBoxJuliaBox permite ejecutar Julia en su navegador Ingrese a la paacuteginahttpswwwjuliaboxcom inicie sesioacuten y comience a usar el entorno Jupyter

La pantalla inicial se muestra en Figura 25 El botoacuten new (nuevo) permite lacreacioacuten de un notebook de Julia un archivo de texto (text file) una carpeta(folder) o una sesioacuten de terminal (terminal session)

En una sesioacuten de terminal el comando julia inicia REPL como se muestra enFigura 26

La interfaz del notebook permite mezclar texto (en modo Markdown) y coacutedigocon su respectiva salida Figura 27 muestra un ejemplo

Puedes encontrar maacutes documentacioacuten en el sitio web de Jupyterhttpjupyterorgdocumentation

Figura 25 Pantalla inicial

282 Apeacutendice B JuliaBox

Figura 26 Sesioacuten de terminal

Apeacutendice B JuliaBox 283

Figura 27 Notebook

284 Apeacutendice B JuliaBox

Apeacutendice C Cambios de ThinkJuliaEste libro es una traduccioacuten de ThinkJulia que estaacute disponible bajo la LicenciaCreative Commons Atribucioacuten-NoComercial 30 No portada Esta licenciarequiere que los trabajos derivados (como este libro) enumeren los cambiosrealizados en relacioacuten a la fuente

Las diferencias de este libro respecto a ThinkJulia incluyen lo siguiente

bull Traduccioacuten del ingleacutes al espantildeol

bull Se cambiaron muchas frases idiomaacuteticas que no seriacutean familiares para loshispanohablantes (Se cayoacute el centavo)

bull En vez de usar el texto de la novela Emma en el Capiacutetulo 13 se usa eltexto de Don Quijote

bull Debido a que OrsquoReilly no financioacute la traduccioacuten algunas de las referencias aOrsquoReilly en el prefacio fueron eliminadas

Apeacutendice C Cambios de ThinkJulia 285

Index 126 57=

veacutease ne 57

veacutease cadena vaciacutea 101

veacutease comillas triples 51hellip (comillas)

veacutease comillas 11

veacutease comentario 22$

veacutease interpolacioacuten de cadenas102

161veacutease operador moacutedulo 56

ampamp 247 57 21 21 (asterisco)

operador de multiplicacioacutenveacutease asterisco 9

+ 21+ (operador de suma)

veacutease suma 9+= 127 (coma)

no usar en enterosveacutease coma 11

- 21- (operador de resta)

veacutease subtraction 9 200 201 265

veacutease operador punto 128 21 (operador de divisioacuten)

veacutease division 10 206 253 244 25 265 64lt 57lt=

veacutease le 57=

veacutease sentencia de asignacioacuten 17== 105 205 57 75===

veacutease equiv 131=gt 142gt 57gt=

veacutease ge 57

veacutease help 51 247 254assert 214code_llvm 268code_lowered 267code_native 268code_typed 268contenedorvariable 254debug 269generated 255macroexpand 254printf 187show 73svg 43test 230time 259warn 269which 237 267[]

veacutease slice operator 125[]

veacutease operador corchete 97n 196r 196t 175 196] 42^ 21 21^ (circunflejo)

operador de exponenciacioacutenveacutease circunflejo 10

_ (guioacuten bajo)en enteros

veacutease guioacuten bajo (_) 11``

286 Index

veacutease comillas invertidas 193

veacutease llaves 142|| 247 57divide 161

veacutease operador divisioacuten entera 56hellip 161isin

veacutease in 104notin 115cap 177ne 57equiv 131 205le 57ge 57sube 262

Aabreviaturas tipo LaTeX 18abs 71 92abspath 188abstract type 233 233 240ack 83actualizacioacuten 94acumulador 127 137 174algoritmo 93 95alias 133 138 167 203 205ambas 105analizar 32andamiaje 154 73 83anidado 122anotacioacuten de tipo 226anular 177 184Any 123 142 217anaacutelisis de Markov 179anaacutelisis de sintaxis 12 15append 126arc 49archivo de texto 196arco 49 53areacirculo 74ArgumentError 27 275 64argumento 27 30 32 33 38argumento opcional 131 176argumentos con nombre 244 257argumentos opcionales 138

Arreglo 123arreglo 122 137 166arreglo vaciacuteo 122 124asignacioacuten 160 191 24asignacioacuten aumentada 137asignacioacuten de tupla 160 164asignacioacuten en tupla 168asignacioacuten muacuteltiple 86 94asterisco ()

operador de multiplicacioacuten 9atributo 199 206

Bbandera 151 155Base 243 259base de datos 191 197begin 245benchmarking 182 184Biblioteca Estaacutendar 243bloque 245bloque do 257bloque let 257Bool 57borrarprimero 133BoundsError 107 160 275break 89bucle 44 52 88bucle infinito 273 88 95bugs

veacutease errores 15Byte 249buacutesqueda 102 103 109 109 115 155buacutesqueda de biseccioacuten 178buacutesqueda inversa 155

Ccadena 166 97 97

concatenacioacutenveacutease concatenar 21

repeticioacutenveacutease repeticioacuten 22

cadena vaciacutea 101 108cadenas 10 14calculadora 26campo

veacutease atributo 199

Index 287

Canguro 227capturar 197capturar una excepcion 190Car Talk 120 157 169carpeta

veacutease directorio actual 188caraacutecter guioacuten bajo 18Caraacutecter Unicode 17caraacutecter Unicode 30 72caso base 63 66caso especial 119 120catch 190ccall 256cd 193Channel 248Char 112 97cifrado Ceacutesar 112Circulo 207circunflejo (^)

operador de exponenciacioacuten 10clasificar 242clausura 257clave 142 154close 113 187 192codificacioacuten UTF-8 108 99codificar 228 239coinciden 164cola 135collect 130 146 163coma ()

no usar en enteros 11coma final 158comentario 22 25comillas 30comillas (hellip)

entre 11comillas invertidas 193comillas triples 51comparacioacuten de cadenas 105componentes leacutexicos 11 15composicioacuten 29 33 39 74concatenacioacuten de cadenas 25concatenar 21 34concatenar_dos 34condicional alternativa 71condicional anidada 59 66

condicional encadenada 59 66condicioacuten 58 66conjetura de Collatz 89conjuntoanagramas 198ConjuntoDeCartas 233const 153 229constructor 199 206 219 251

copiaveacutease constructor de copia

220externo

veacutease constructor externo220

internoveacutease constructor interno

220constructor de copia 220 227constructor externo 220 226constructor interno 220 226constructor por defecto 226contador 104 109ContarLineas 195contarlineas 194conteo 109continue 90conversioacuten 252 258conversioacuten de tipo 27convert 252copia 125copiar 193 205copodenieve 69corchetes 142 265cos 33cuadrado 46cuatroveces 40cuenta regresiva 61cuentaregresiva 88cuerpo 30 38curva de Koch 69ciacuterculo 47 50coacutedigo ASCII 108 97coacutedigo de maacutequina 268coacutedigo muerto 277 71 82

Ddatos faltantes 255 258

288 Index

DBM 191de Cervantes

Miguel 174debug logging 269 270declaracioacuten 151 156decremento 88 94deepcopy 205 206 207definicioacuten circular 76definicioacuten de funcioacuten 29 38definicioacuten recursiva 76deleteat 130delimitador 131 138dependencia 236 240depuracioacuten 106 119 135 153 154

167 182 196 205 213 22623 269 37 52 65 72 81 93

emociones de la manejando las13

veacutease errores (bugs) probando15

depuracioacuten del pato de goma 183 184depuracioacuten experimental 37depuracioacuten por biseccioacuten 93desarrollo de prototipos 209 211 214desarrollo incremental 72 82desarrollo planificado 212 214deserialize 192desplazarpalabra 112 156determiniacutestico 172 183devolverfloat 216diaframa de estado 123diagrama

estadoveacutease diagrama de estado 17

graacutefico de llamadasveacutease graacutefico de llamadas

149objeto

veacutease diagrama de objeto200

pilaveacutease diagrama de pila 34

tiposveacutease diagrama de tipos 236

diagrama de estado 131 132 149166 166 17 24 86

diagrama de objeto 200 202 207diagrama de pila 134 34 39 62 68

78diagrama de tipos 236 240dibujarcirculo 207dibujarrect 207diccionario 142 154Dict 142Dijkstra

Edsger W 119dimensioacuten 264directorio 188 196disentildeo orientado a tipos 238dispatch 223 226dispatch muacuteltiple 223 227dispersar 168dispersioacuten 162distancia 72distanciaentrepuntos 203DivideError 275divisioacuten

operador de divisioacuten () 10divisioacuten entera 65divrem 161do 246docstring 202 51 53DomainError 275dosveces 40Doyle

Arthur Conan 37dump 196 253

Eeachindex 124eachline 114 194ejecucioacuten alternativa 58ejecutar 19 24elemento 122 137else 58elseif 59embebido 202emoji 97 99enbiseccion 141encabezado 30 38encapsulacioacuten 47encapsulado 53

Index 289

encapsulado de dato 238encapsulado de datos 240enchapado 232 239encontrarcentro 204end 101 124 190 195 199 245 30

44 58 98enteroahora 212 218entrelazan 141enumerate 164EOFError 275equivalente 132 138error 147 213

BaseEOFError 275KeyError 143StringIndexError 99SystemError 189

CoreArgumentError 27BoundsError 107DivideError 275DomainError 275InexactError 275MethodError 98OutOfMemoryError 276OverflowError 276StackOverflowError 63TypeError 216UndefVarError 34

semaacutenticoveacutease error semaacutentico 23

sintaxisveacutease error de sintaxis 18

tiempo de ejecucioacutenveacutease error de tiempo de

ejecucioacuten 23error de forma 168error de sintaxis 18 23 25 271 29error de tiempo de ejecucioacuten 23 25error en tiempo de ejecucioacuten 271 34error semaacutentico 23 25 271errores (bugs) 13

veacutease depuracioacuten 15errores de forma 167ES-UN 236esabecedaria 115 117

esanagrama 140esc 254escogerdelhistograma 173esdivisible 75eshoravalida 213espalindromo 110 118 84especificacioacuten 218 226 250espotencia 84esreverso 106 119estadespues 209 219estaordenada 140estilo de programacioacuten funcional 211estilo funcional de programacioacuten 214estimarpi 96estriangulo 68estructura 11 15estructura de dato 168estructuras de datos 167estructuras de datos recursivas 221eval 254 95evalbucle 96evaluacioacuten de cortocircuito 247 257evaluar 19 24evita 115 262evitar 114excepcioacuten

veacutease error de tiempo deejecucioacuten 23

exp 29export 195Expr 253expresioacuten 18 24 253 258expresioacuten booleana 57 66extension

jl 19extrema 161

Ffact 247 77 80 81factorial 78false 57faltantes 255fib 79Fibonacci 266fibonnaci 149 79file stream 113 119

290 Index

filter 174filtro 128 138finally 190findall 148findfirst 104findnext 104firstindex 99float 27flujo de ejecucioacuten 273 32 39 71 77

81 88for 44formateando 187formatting 154forward 42fractal 69funccioacuten

definida por el programadorconjuntoanagramas 198

funciondefinida por el programador

aacuterea 70funciones generadas 255 258funcioacuten 27 29 38

Baseabs 71abspath 188append 126buacutesqueda 109ccall 256coinciden 164collect 130conteo 109convert 252cos 33deepcopy 205 206deleteat 130divrem 161dump 196eachindex 124eachline 114enumerate 164error 147esc 254exp 29extrema 161factorial 78

filter 174findall 148firstindex 99float 27get 145get 156include 194insert 130isdefined 206isdir 188isequal 148isfile 189isletter 171ispath 188iterate 266join 131joinpath 189keys 143length 40log 28log10 28lpad 121match 263max 162maximum 161min 162minimum 161new 220nextind 99occursin 263ones 264open 113parse 27pop 129popfirst 129print 41promote 252promote_rule 253push 125pushfirst 130put 248pwd 188rand 140readdir 189readline 113 64reinterpret 249

Index 291

repr 196reverse 167reverse 167run 193setdiff 260show 36sin 28size 264sizeof 99skipmissing 256sort 126sort 126splice 129split 130sqrt 28string 28sum 127supertype 238take 192 248time 67trunc 27tupla 158uppercase 104values 144vcat 134walkdir 189write 186zeros 264zip 163

ContarLineascontarlineas 195

Coreeval 254 95

definida por el programadorack 83ambas 105areacirculo 74borrarprimero 133buacutesqueda 102clasificar 242cola 135concatenar_dos 34contarlineas 194copodenieve 69cuadrado 46cuatroveces 40

cuenta regresiva 61ciacuterculo 47desplazarpalabra 112devolverfloat 216dibujarcirculo 207dibujarrect 207distancia 72distanciaentrepuntos 203dosveces 40enbiseccion 141encontrarcentro 204enteroahora 212esabecedaria 115esanagrama 140escogerdelhistograma 173esdivisible 75eshoravalida 213espalindromo 84espotencia 84esreverso 106estadespues 209estaordenada 140estimarpi 96estriangulo 68evalbucle 96evita 114fact 77fib 79findfirst 104findnext 104histograma 145horaaentero 212imprimircuadricula 41imprimirdosveces 32imprimirhist 146imprimirhora 208imprimirmascomun 176imprimirpalabra 40imprimirpunto 202imprimirtodo 161incrementar 210interior 139interior 139invertirdic 148justificar_a_la_derecha 39koch 69

292 Index

leeranagramas 198mascomun 175masfrecuente 168mcd 85medio 84minmax 161miraiz 95mover 235moverpunto 203multhora 215noborrarprimero 135notiene_e 114palabraalazar 178palabrasdiferentes 175palabrastotales 174par inverso 141polyline 49poliacutegono 47ponerenmarsupio 227primera 84printn 62probarraiz 95procesararchivo 173procesarlinea 173procesarpalabra 239puntoencirculo 207recorrer 189rectencirculo 207recursioacuten 63repartir 241repetido 140repetirletras 30resta 177sed 197seq 89sinc 216sobreposicionrectcirc 207solomayusculas 128sumaacumulada 139sumaanidada 139sumacuadrada 267sumahora 209sumartodo 162tienedoblepareja 242tienepareja 242todoenmayusculas 127

ultima 84usasolo 115usatodo 115valorabsoluto 70verificarfermat 67

definido por el programadorimprimirletras 29

IntroAJuliaforward 42pendown 43penup 43turn 43

Metaparse 253 95

Plotsgraficar 185 244

programmer-definedarco 49

Randomshuffle 232

Serializacioacutendeserialize 192serialize 192

funcioacuten Ackermann 83funcioacuten anoacutenima 244 257funcioacuten booleana 75funcioacuten de Ackermann 156funcioacuten definida por el programador

29 33funcioacuten exponencial

veacutease exp 29funcioacuten factorial 77funcioacuten gamma 80funcioacuten hash 155funcioacuten logaritmo

veacutease log 28funcioacuten matemaacutetica 28funcioacuten nula 35 39funcioacuten productiva 35 39 70funcioacuten pura 209 214funcioacuten raiacutez

veacutease sqrt 28funcioacuten recursiva 61funcioacuten trigonomeacutetrica 28funcioacuten typeof 10function 29

Index 293

funtor 251 258

GGDBM 191generalizacioacuten 47 53get 145get 156 174global 151 99graficar 185graacutefico de llamada 155graacutefico de llamadas 149guardian 81guardiaacuten 83guioacuten bajo (_)

en enteros 11

Hhash 149hash table 144hashable 149 155help 51histograma 145 224Holmes

Sherlock 37Hora 208 217horaaentero 212 218

Iidentidad de Euler 262ideacutentico 132 138if 58im 262immutable 102 108 158 167 200implementacioacuten 144 155 225import 195 259imprimircuadricula 41imprimirdosveces 32imprimirhist 146imprimirhora 208 217imprimirletras 29imprimirmascomun 176imprimirpalabra 40imprimirpunto 202imprimirtodo 161in 100 124 143 156 44include 194

incrementar 218incrementar 210incremento 88 94indentacioacuten 46indicador 64

en REPL 14 9indice 98InexactError 275informaacuteticos habilidades de

veacutease programacioacuten 7inicializacioacuten 94initializacioacuten 87input 113insert 130 136instancia 200 206instanciacioacuten 200instanciar 206instrucciones

veacutease sentencias 7Int 112InteractiveUtils 237 267interfaz 225 266 48 53interior 139interior 139intermediate representation 270interpolacioacuten de cadenas 102 109

187 263IntroAJulia 42invariante 213 215invertirdic 148IOBuffer 192isa 206 234 80isdefined 206isdir 188isequal 148isfile 189isletter 171 174ispath 188item 122 142 154iteracioacuten 191 86 88 94iterador 163 168 266iterate 266

Jjoin 131joinpath 189

294 Index

Juliaejecutando 8

JuliaBox 19 8notebook graacutefico 42

justificar_a_la_derecha 39

KKeyError 143 276keys 143keyword

elseveacutease else 58

importveacutease import 259

koch 69

LLaTeX-like abbreviations 281leeranagramas 198lemario 113length 143 40 84 98lenguaje de programacioacuten 11 15lenguaje de programacioacuten completo 76lenguaje formal 11 15lenguaje natural 11 14ley de Zipf 184Linux 38lista anidada 137Llamada a funcioacuten 27 38llaves 142 249LLVM code 268log 28log10 28lookup 147lowercase 174lpad 121

Mmachine code 270macro 254 258 43

Baseassert 214debug 269generated 255macroexpand 254show 73

time 259warn 269

definida por el programadorcontenedorvariable 254

InteractiveUtilscode_llvm 268code_lowered 267code_native 268code_typed 268which 237

Luxorsvg 43

Printfprintf 187

Testtest 230

Mano 234map 128mapeo 138 142 154marco 34 39 62Markov 238mascomun 175masfrecuente 168match 263matemaacuteticas

operadores aritmeacuteticos 9matrix 264 270max 162maximum 161mayuacutescula 127Mazo 231mcd 85md5 194md5sum 194medio 84mensaje de error 23MethodError 101 159 162 219 276

98min 162minimum 161minmax 161miraiz 95Missing 255modelo mental 278modificador 210 214modo interactivo 19 24 36

Index 295

modo script 19 24 36module 195

ContarLineasveacutease ContarLineas 195

InteractiveUtilsveacutease InteractiveUtils 237

Randomveacutease Random 232

Testveacutease Test 230

modulo 42 52veacutease IntroAJulia 42

mover 235moverpunto 203MPunto 201multhora 215multiplicidad 236 240mutable 123 133 167mutable struct 201meacutetodo 217 226meacutetodo de Newton 91meacutetodos 226moacutedulo

Plotsveacutease Plots 184 244

Serializacioacutenveacutease Serializacioacuten 192

Nnada 39Naipe 229new 220nextind 99noborrarprimero 135norma Unicode 108 97notacioacuten de punto

veacutease 200nothing 177 36 36 70notiene_e 114 115nuacutemeros complejos 262

Oobjeto 131 138objeto de comando 193 197objeto de funcioacuten 38 40objeto embebido 207

objeto zip 163 168occursin 263ones 264open 113 186 246operacioacuten con cadenas 21operacioacuten de reduccioacuten 127 138operador

Base= 57 56+= 127 128lt 57lt= 57== 57gt 57gt= 57 247[] 125[] 97in 104isa 206 234divide 56isin 104notin 115cap 177ne 57equiv 131le 57ge 57sube 262

cadenas 21operador corchete 101 101 122 123

159 191 97operador de divisioacuten entera 56operador de exponenciacioacuten (^) 10operador de multiplicacioacuten () 9operador de resta (-) 9operador de suma (+) 9operador loacutegico 57 66operador moacutedulo 56 65operador porcioacuten 125 135 159operador punto 128 137operador relacional 159 57 66operador ternario 257

veacutease 247

296 Index

operadores 14 9aritmeacuteticos 9

operadores aritmeacuteticos 9operando 24orden alfabeacutetico 105orden de operaciones 21OutOfMemoryError 276output

sentencia de impresioacuten 14 9OverflowError 276

Ppalabra clave 18 24palabra reservada

abstract type 233begin 245break 89catch 190const 153 229continue 90do 246elseif 59export 195final 30finally 190for 44function 30global 151if 58import 195in 44module 195mutable struct 201quote 253return 62struct 199tipo primitivo 249try 190using 42while 88

palabraalazar 178palabrasdiferentes 175palabrastotales 174paliacutendromo 84PAPOMUDAS 21paquete 42 52

par clave-valor 142 154 165par inverso 141Paradoja del cumpleantildeos 140pares de metaacutetesis 169parse 253 64 95paraacutemetro 32 34 38pareacutentesis 158 164 21 27

vaciacuteos 30pendown 43penup 43persistente 186 196pi 17 28pista 150 155 156 170plan de desarrollo de programa 117

211 239 50 53 82plot 244Plots 184 244polimorfismo 225polimoacuterfica 224polygon 49polyline 49poliacutegono 47Poncela

Enrique Jardiel 114ponerenmarsupio 227pop 129 232 234popfirst 129 133porcioacuten 108 109 265postcondicioacuten 52 53 81precedencia del operador 25precondicioacuten 52 53 81prefijo 179primera 84Principal 35principio de sustitucioacuten de Liskov 237print 187 41println 187 41printn 62probarraiz 95procesararchivo 173procesarlinea 173procesarpalabra 239programacioacuten de caminata aleatoria

183programacioacuten geneacuterica 227programas 14 7

Index 297

promocioacuten 253 258promote 252 253promote_rule 253Proyecto Gutenberg 171prueba de consistencia 154prueba de cordura 154prueba unitaria 230 239pseudoaleatorio 172 184Ptr 256Punto 199 222puntoencirculo 207push 125 130 134 136 141 232

234pushfirst 130 136put 248pwd 188

Qquote 253

Rrama 59 66rand 140 172Random 232read 194readdir 189readline 113 64 90reasignacioacuten 151 204recopila 161recorrer 189recorrido 106 108 124 99Rectangulo 202rectencirculo 207recursividad 61recursioacuten 117 63 66 68 76 86 88recursioacuten infinita 274 63 67 80recursos en liacutenea

JuliaBox 8reduccioacuten a un problema previamente

resuelto 120reduccioacuten a un problema resuelto

previamente 117reducible 170reducir el tamantildeo 153refactorizacioacuten 239 50 53referencia 133 138 200

Regex 263regex 263 270RegexMatch 263reinterpret 249relacioacuten ES-UN 240relacioacuten TIENE-UN 240repartir 241repeticioacuten 22 34

veacutease iteracioacuten 8repetido 140 156 261repetirletras 30repetition 43REPL 281REPL (Read-Eval-Print Loop) 14 8replace 174repr 196representacioacuten intermedia 268resolucioacuten de problemas 14 7resta 177 260return 62reunir 168reverse 167 175reverse lookup 147reverse 167run 193ruta 188 197ruta absoluta 188 197ruta relativa 188 197

Ssangriacutea 30 60script 19 24secuencia 108 97 97secuencias de secuencias 166sed 197semaacutentica 25sentencia 19 24sentencia break 89 94sentencia compuesta 58 66sentencia condicional 58 66 76sentencia continue 90 95sentencia de asignacioacuten 123 17 86sentencia de asignacioacuten aumentada

127sentencia de depuracioacuten 269sentencia de impresioacuten 14

298 Index

funcioacuten println 9sentencia for 100 114 117 124 163

165 191 266 44 86 88sentencia global 152 155sentencia if 58sentencia print 81 94sentencia return 62 66 70sentencia try 190sentencia using 42 52sentencia while 117 88 94 99separador 175seq 89Serializacioacuten 192serialize 192Set 260setdiff 260shell 193 197show 221 227 229 234 36shuffle 232sin 28 32sinc 216singleton 148 155sintaxis 11 15sintaxis de punto 129 138 243size 264sizeof 99skipmissing 256slice 101sobrecarga de operadores 227sobrecarga del operador 222sobreposicionrectcirc 207solomayusculas 128sort 126 137 146 167 175sort 126 136 136 167 233splice 129split 130 160 174sqrt 28 73square 47StackOverflowError 274 276 63 80stacktrace 63String 97string 187 263 28StringIndexError 276 99strip 136struct 199 206subtipo 233 233 240 240

sufijo 179sum 127 162 224suma de verificacioacuten 194sumaacumulada 139sumaanidada 139sumacuadrada 267sumahora 209 213sumartodo 162supertipo 233 240supertype 238SVG picture 43Symbol 206SystemError 189 276

Ttabla hash 155take 192 248tarea 248 257teorema de Pitaacutegoras 72tesis de Turing 76Test 230TIENE-UN 236tienedoblepareja 242tienepareja 242Time 208time 67tipo 199 233

BaseAny 123 142Array 123Bool 57Channel 248Char 97Dict 142Expr 253IOBuffer 192Missing 255nothing 36Ptr 256Regex 263RegexMatch 263Set 260Symbol 206Tuple 158UInt8 249Union 250

Index 299

DatesTime 208

definida por el programadorByte 249Canguro 227Circulo 207ConjuntoDeCartas 233Fibonacci 266Hora 208Mano 234Markov 238Mazo 231MPunto 201Naipe 229Punto 199Rectangulo 202

IntroAJuliaDBM 191

LuxorTurtle 42

tipo compuesto 199tipo compuesto mutable 201tipo concreto 233 240tipo de punto flotante (Float64) 10 14tipo entero (Int64) 10 14tipo parameacutetrico 258tipo primitivo 249 257tipos 10 14

Float64veacutease tipo de punto flotante

10Int64

veacutease tipo entero 10String

veacutease cadenas 10tipos de datos

veacutease tipos 10todoenmayusculas 127 129Torvalds

Linus 38transitorio 186trazado inverso 35 39true 57trunc 27try 190tupla 158 158 166 167

tupla con nombre 243 257Tuple 158Turing

Alan 76turn 43Turtle 42TypeError 216 276typeof 122 158 205

UUInt8 249ultima 84UndefVarError 152 276 34 35 87Unicode character 281Union 250union de tipo 250unioacuten de tipos 257update 87uppercase 104usasolo 115 116 261 263usatodo 115 116using 259 42

Vvalor 131 142 154 17valor de retorno 27 39valor por defecto 184valor predeterminado 176valorabsoluto 70valores 10 14values 144variable 131 17 24

local 34variable de entorno 269variable global 151 155 229variable global constante 153 156variable local 34 38variable temporal 279 70 75 82vcat 134 136verificar 154verificar automaacuteticamente 154verificarfermat 67voto de confianza 78

Wwalkdir 189

300 Index

while 88write 186

Zzeros 264zip 163 165 167 167

Aacuteaacutembito 195aacuterea 70

Iacuteiacutendice 108 123

Uacuteuacuteltimo teorema de Fermat 67

Ππ

veacutease pi 17

ℯ 262

Index 301

  • Introduccioacuten a la Programacioacuten en Julia
  • Tabla de Contenido
  • Licencia
  • Dedicatoria
  • Prefacio
  • Capiacutetulo 1 El camino de la programacioacuten
  • Capiacutetulo 2 Variables expresiones y sentencias
  • Capiacutetulo 3 Funciones
  • Capiacutetulo 4 Estudio de Caso Disentildeo de Interfaz
  • Capiacutetulo 5 Condicionales y recursividad
  • Capiacutetulo 6 Funciones productivas
  • Capiacutetulo 7 Iteracioacuten
  • Capiacutetulo 8 Cadenas
  • Capiacutetulo 9 Estudio de Caso Juego de Palabras
  • Capiacutetulo 10 Arreglos
  • Capiacutetulo 11 Diccionarios
  • Capiacutetulo 12 Tuplas
  • Capiacutetulo 13 Estudio de Caso Seleccioacuten de Estructura de Datos
  • Capiacutetulo 14 Archivos
  • Capiacutetulo 15 Estructuras y Objetos
  • Capiacutetulo 16 Estructuras y Funciones
  • Capiacutetulo 17 Dispatch Muacuteltiple
  • Capiacutetulo 18 Subtipos
  • Capiacutetulo 19 Extra Sintaxis
  • Capiacutetulo 20 Extra Base y Libreriacutea Estaacutendar
  • Capiacutetulo 21 Depuracioacuten
  • Apeacutendice A Entrada de Unicode
  • Apeacutendice B JuliaBox
  • Apeacutendice C Cambios de ThinkJulia
  • Index
Page 4: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar

DedicatoriaPara Emeline Arnaud y Tibo

2 Dedicatoria

PrefacioEn enero de 2018 comenceacute a preparar un curso de programacioacuten pensado paraestudiantes que no tuvieran experiencia previa en programacioacuten Queriacutea usarJulia como lenguaje de programacioacuten y descubriacute que no existiacutea ninguacuten libro paraaprender a programar que usara Julia como primer lenguaje de programacioacutenHay tutoriales maravillosos que explican los conceptos clave de Julia peroninguno de ellos se dedicaba lo suficiente a ensentildear a pensar como programador

Conociacutea el libro Think Python de Allen Downey el cual contiene todos loselementos clave para aprender a programar correctamente Sin embargo estelibro se basa en el lenguaje de programacioacuten Python Mi primer borrador delcurso fue una mezcla de muchas referencias pero a medida que trabajaba eneste el contenido comenzoacute a parecerse cada vez maacutes a los capiacutetulos de ThinkPython Pronto la idea de desarrollar mi curso como base para trasladar eselibro a Julia se hizo realidad

Todo el material estaba disponible en un repositorio de GitHub en forma denotebooks de Jupyter Despueacutes de publicar un mensaje en el sitio Discourse deJulia sobre el progreso de mi curso los comentarios fueron abrumadoresAparentemente un libro sobre conceptos baacutesicos de programacioacuten con Juliacomo primer lenguaje de programacioacuten era algo que faltaba en el universo deJulia Contacteacute a Allen para ver si podiacutea iniciar oficialmente la versioacuten de ThinkPython para Julia y su respuesta fue inmediata ldquoiexcladelanterdquo me puso encontacto con su editor de OrsquoReilly Media y ahora un antildeo despueacutes estoy haciendolos retoques finales a este libro

Fue un camino difiacutecil En Agosto de 2018 se lanzoacute Julia v10 y como todos miscolegas programadores de Julia tuve que hacer una migracioacuten del coacutedigo Todoslos ejemplos en el libro se prueban durante la conversioacuten de los archivos fuente aarchivos ASCIIDoc compatibles con OrsquoReilly Tanto la cadena de herramientascomo el coacutedigo de los ejemplos teniacutean que ser compatibles con Julia v10Afortunadamente no hay cursos en Agostohellip

Espero que disfrutes al trabajar con este libro y que te ayude a aprender aprogramar y pensar como informaacutetico al menos un poco

Ben Lauwens

iquestPor queacute JuliaJulia fue lanzado originalmente en 2012 por Alan Edelman Stefan Karpinski JeffBezanson y Viral Shah Es un lenguaje de programacioacuten gratuito y de coacutedigoabierto

La eleccioacuten de un lenguaje de programacioacuten es siempre subjetiva Para miacute lassiguientes caracteriacutesticas de Julia son decisivas

iquestPor queacute Julia 3

bull Julia estaacute desarrollado como un lenguaje de programacioacuten de altorendimiento

bull Julia usa enviacuteo muacuteltiple (ldquomultiple dispatchrdquo en ingleacutes) que le permite alprogramador elegir entre diferentes patrones de programacioacuten de acuerdoa la aplicacioacuten

bull Julia es un lenguaje de tipo dinaacutemico que se puede usar faacutecilmente de formainteractiva

bull Julia tiene una sintaxis de alto nivel que es faacutecil de aprender

bull Julia es un lenguaje de programacioacuten con tipos opcionales cuyos tipos dedatos (definidos por el usuario) hacen que el coacutedigo sea claro y robusto

bull Julia tiene una biblioteca estaacutendar extendida ademaacutes estaacuten disponiblesnumerosos paquetes de terceros

Julia es un lenguaje de programacioacuten uacutenico ya que resuelve el problema de losdos idiomas No se necesita de ninguacuten otro lenguaje de programacioacuten paraescribir coacutedigo de alto rendimiento Esto no significa que ocurraautomaacuteticamente Es responsabilidad del programador optimizar el coacutedigo quegenere cuellos de botella aunque esto puede hacerse directamente en Julia

iquestA quieacuten estaacute dirigido este libroEste libro es para cualquier persona que quiera aprender a programar No serequieren conocimientos formales previos

Los nuevos conceptos se introducen gradualmente y los temas maacutes avanzados sedescriben en capiacutetulos posteriores

Introduccioacuten a Julia puede ser usado como un curso de un semestre de nivelsecundario o universitario

Convenciones utilizadas en este libroEn este libro se siguen las siguientes convenciones tipograacuteficas

CursivaIndica nuevos teacuterminos URL direcciones de correo electroacutenico nombres dearchivo y extensiones de archivo

Ancho constanteSe utiliza para mostrar coacutedigo de programas asiacute como dentro de lospaacuterrafos para referirse a elementos del programa como nombres devariables o funciones bases de datos tipos de datos variables de entornosentencias y palabras reservadas

4 Prefacio

Ancho constante en negrita

Muestra comandos u otro texto que el usuario debe escribir

Ancho constante en cursivaMuestra el texto que debe reemplazarse con valores proporcionados por elusuario o por valores determinados por el contexto

OBSERVACIOacuteN Esto indica consejo o sugerencia

NOTA Esto es una nota general

AVISO Esto indica una advertencia o precaucioacuten

Usando los coacutedigos de ejemploTodo el coacutedigo utilizado en este libro estaacute disponible en un repositorio de Git enGitHub httpsgithubcomJuliaIntroIntroAJuliajl Si no estaacute familiarizado conGit es un sistema de control de versiones que le permite realizar seguimiento alos archivos que componen un proyecto Una coleccioacuten de archivos controladospor Git se denomina ldquorepositoriordquo GitHub es un servicio de hosting queproporciona almacenamiento para repositorios de Git y una interfaz webconveniente

El siguiente paquete puede ser de utilidad y se puede agregar directamente aJulia Simplemente escriba add httpsgithubcomJuliaIntroIntroAJuliajlen el REPL en modo Pkg

La forma maacutes faacutecil de ejecutar un coacutedigo de Julia es yendo a httpsjuliaboxcome iniciar una sesioacuten de prueba gratuita Es posible utilizar tanto las interfacesREPL como de notebooks Si desea tener Julia instalada localmente en sucomputadora puede descargar JuliaPro de Julia Computing gratuitamenteConsiste en una versioacuten reciente de Julia el IDE de Juno basado en Atom y variospaquetes de Julia preinstalados Si es maacutes aventurero puede descargar Juliadesde httpsjulialangorg instale el editor que prefiera por ejemplo Atom oVisual Studio Code activando los complementos para su integracioacuten de Julia Enel caso de una instalacioacuten local tambieacuten puede agregar el paquete IJulia que lepermite ejecutar un notebook de Jupyter en su computadora

AgradecimientosRealmente quiero agradecer a Allen por escribir Think Python y permitirmetrasladar este libro a Julia iexclTu entusiasmo es contagioso

Tambieacuten me gustariacutea agradecer a los revisores teacutecnicos de este libro quehicieron muchas sugerencias uacutetiles Tim Besard Bart Janssens y David P

Usando los coacutedigos de ejemplo 5

Sanders

Gracias a Melissa Potter de OrsquoReilly Media por hacer de este un mejor libro Meobligaste a hacer las cosas bien y hacer que este libro sea lo maacutes originalposible

Gracias a Matt Hacker de OrsquoReilly Media que me ayudoacute con la cadena deherramientas Atlas y algunos problemas al destacar la sintaxis

Gracias a todos los estudiantes que trabajaron con una versioacuten temprana de estelibro y a todos los colaboradores (enumerados a continuacioacuten) que enviaroncorrecciones y sugerencias

Lista de ColaboradoresSi tiene una sugerencia o correccioacuten abra un issue en GitHub Si se realiza uncambio basado en sus comentarios seraacute agregado a la lista de contribuyentes (amenos que solicite ser omitido)

Aviacutesenos con queacute versioacuten del libro estaacute trabajando y en queacute formato Si incluyeal menos parte de la oracioacuten en la que aparece el error eso facilita la buacutesquedaLos nuacutemeros de paacutegina y seccioacuten tambieacuten son uacutetiles pero no es tan faacutecil trabajarcon ellos iexclGracias

bull Scott Jones sentildealoacute el cambio de nombre de Void a Nothing y con esto secomenzoacute la migracioacuten a Julia v10

bull Robin Deits encontroacute algunos errores tipograacuteficos en el Capiacutetulo 2

bull Mark Schmitz sugirioacute destacar la sintaxis

bull Zigu Zhao encontroacute algunos errores en el Capiacutetulo 8

bull Oleg Soloviev detectoacute un error en la url al agregar el paquete ThinkJulia

bull Aaron Ang encontroacute algunos problemas de representacioacuten y nomenclatura

bull Sergey Volkov encontroacute un enlace caiacutedo en el Capiacutetulo 7

bull Sean McAllister sugirioacute mencionar el excelente paquete BenchmarkTools

bull Carlos Bolech envioacute una larga lista de correcciones y sugerencias

bull Krishna Kumar corrigioacute el ejemplo de Markov en el Capiacutetulo 18

6 Prefacio

Capiacutetulo 1 El camino de la programacioacutenEl objetivo de este libro es ensentildearle a pensar como un informaacutetico Esta manerade pensar combina las mejores caracteriacutesticas de las matemaacuteticas la ingenieriacutea ylas ciencias naturales Los informaacuteticos al igual que los matemaacuteticos usanlenguajes formales para expresar ideas (especiacuteficamente caacutelculos) De manerasimilar a los ingenieros disentildean estructuras ensamblan componentes paraformar sistemas evaluando los costos y beneficios entre las alternativasAdemaacutes observan el comportamiento de sistemas complejos elaboran hipoacutetesisy prueban predicciones como los cientiacuteficos

La habilidad maacutes importante para un informaacutetico es la resolucioacuten de problemasEsto implica ser capaz de formular problemas encontrar soluciones creativasexpresando una solucioacuten de forma clara y precisa Como resultado el proceso deaprender a programar es una excelente oportunidad para practicar habilidadesde resolucioacuten de problemas Es por ello que este capiacutetulo se llama El camino dela programacioacuten

Por una parte aprenderaacute a programar que es una habilidad muy uacutetil por siacutemisma Pero ademaacutes la programacioacuten se constituiraacute como un medio para un finA medida que avancemos este fin seraacute maacutes claro

iquestQueacute es un programa

Un programa es una secuencia de instrucciones que especifica coacutemo hacer uncaacutelculo El caacutelculo puede ser de naturaleza matemaacutetica tal como resolver unsistema de ecuaciones o encontrar las raiacuteces de un polinomio pero tambieacutenpuede ser un caacutelculo simboacutelico como buscar y reemplazar texto en undocumento o bien algo graacutefico tal como procesar una imagen o reproducir unvideo

Los detalles difieren para cada lenguaje pero algunas instrucciones baacutesicasaparecen en casi todos los lenguajes

EntradaInputSe obtienen datos a traveacutes del teclado un archivo una red u otrodispositivo

SalidaOutputLos datos se muestran por pantalla se guardan en un archivo se enviacutean atraveacutes de la red etc

MatemaacuteticasSe realizan operaciones matemaacuteticas baacutesicas como la suma y lamultiplicacioacuten

iquestQueacute es un programa 7

Ejecucioacuten condicionalSe verifican ciertas condiciones y se ejecuta el coacutedigo apropiado

RepeticioacutenSe realiza alguna accioacuten repetidamente generalmente con alguna variacioacuten

Aunque no lo crea eso es todo lo que se debe hacer Cada programa que hausado sin importar su complejidad estaacute construido basaacutendose en instruccionesque se asemejan a estas De esta manera la programacioacuten puede entendersecomo el proceso de dividir una tarea compleja y larga en pequentildeas subtareas losuficientemente simples como para realizarse con una de estas instruccionesbaacutesicas

Ejecutando Julia

Uno de los desafiacuteos al comenzar a utilizar Julia es su instalacioacuten ademaacutes delsoftware relacionado Si estaacute familiarizado con su sistema operativo y se sientecoacutemodo con la interfaz de liacutenea de comandos no tendraacute problemas No obstantepara los principiantes puede ser difiacutecil aprender sobre administracioacuten de sistemay programacioacuten al mismo tiempo

Para evitar ese problema se recomienda que comience ejecutando Julia en unnavegador Maacutes tarde cuando se sienta coacutemodo con Julia se haraacuten sugerenciaspara instalar Julia en su ordenador

En el navegador puede ejecutar Julia en JuliaBox No se requiere instalacioacutensimplemente abra su navegador y entre a la paacutegina de JuliaBox inicie sesioacuten ycomience a programar (consulte Apeacutendice B)

Julia REPL (de ReadndashEvalndashPrint Loop que se traduce en Bucle de Leer-Evaluar-Imprimir) es un programa que lee y ejecuta coacutedigo de Julia Puede iniciar REPLabriendo un terminal en JuliaBox y escribiendo julia en la liacutenea de comandoCuando comienza deberiacutea ver una salida como esta

_ _ _ _(_)_ | Documentation httpsdocsjulialangorg (_) | (_) (_) | _ _ _| |_ __ _ | Type for help ] for Pkg help | | | | | | | _` | | | | |_| | | | (_| | | Version 152 (2020-09-23) _ |___|_|_|___| | Official httpsjulialangorg release|__ |

juliagt

Las primeras liacuteneas contienen informacioacuten sobre el REPL por lo que esto puede

8 Capiacutetulo 1 El camino de la programacioacuten

mostrarse diferente en su computadora Debe verificar que la versioacuten sea almenos 100

El uacuteltima liacutenea es un indicador sentildealando que el REPL estaacute listo para que seingrese una instruccioacuten Si escribe una liacutenea de coacutedigo y presiona Enter la REPLmuestra el resultado

juliagt 1 + 12

Los fragmentos de coacutedigo se pueden copiar y pegar textualmente incluido elindicador juliagt y cualquier salida

Ahora ya estaacute listo para comenzar De aquiacute en adelante ya sabraacute coacutemo iniciar laREPL de Julia y ejecutar su coacutedigo

El primer programaTradicionalmente el primer programa que se escribe en un nuevo lenguaje sellama ldquoiexclHola mundordquo porque todo lo que hace es mostrar las palabras ldquoiexclHolamundordquo En Julia se ve asiacute

juliagt println(iexclHola mundo)iexclHola mundo

Este es un ejemplo de una sentencia de impresioacuten aunque en realidad noimprime nada en papel Muestra un resultado en la pantalla

Las comillas en el programa marcan el principio y el final del texto que semostraraacute y no apareceraacuten en el resultado

Los pareacutentesis indican que println es una funcioacuten Se estudiaraacuten funciones enCapiacutetulo 3

Operadores aritmeacuteticos

Despueacutes de nuestro programa ldquoiexclHola mundordquo el siguiente paso es laaritmeacutetica Julia tiene operadores los cuales son siacutembolos que representancaacutelculos como la suma y la multiplicacioacuten

Los operadores + - y realizan las operaciones de suma resta y multiplicacioacutenrespectivamente como se muestra en los siguientes ejemplos

El primer programa 9

juliagt 40 + 242juliagt 43 - 142juliagt 6 742

El operador realiza la divisioacuten

juliagt 842420

Quizaacutes se pregunte por queacute el resultado es 420 en vez de 42 Esto seraacuteexplicado en la siguiente seccioacuten

Finalmente el operador ^ realiza la potencicioacuten es decir eleva un nuacutemero a unapotencia

juliagt 6^2 + 642

Valores y tipos

Un valor es uno de los elementos baacutesicos con los que trabaja un programa talcomo una letra o un nuacutemero Algunos de los valores que hemos visto hasta ahorason 2 420 y Hola Mundo

Estos valores pertenecen a diferentes tipos 2 es un entero (integer en ingleacutes)420 es un nuacutemero de punto flotante (floating-point number en ingleacutes) y HolaMundo es una cadena de caracteres (string en ingleacutes) llamada asiacute porque lasletras que contiene estaacuten unidas

Si no estaacute seguro del tipo de un valor el REPL puede ayudarle

juliagt typeof(2)Int64juliagt typeof(420)Float64juliagt typeof(iexclHola mundo)String

Los enteros pertenecen al tipo Int64 las cadenas pertenecen a String y losnuacutemeros de punto flotante pertenecen a Float64

10 Capiacutetulo 1 El camino de la programacioacuten

iquestQueacute pasa con los valores 2 y 420 Parecen nuacutemeros pero estaacuten entrecomillas como si fueran cadenas Estos valores tambieacuten son cadenas

juliagt typeof(2)Stringjuliagt typeof(420)String

Si se quiere escribir un nuacutemero de grandes dimensiones se podriacutea caer en lacostumbre de usar comas para separar sus cifras como por ejemplo 1000000Este no es un entero vaacutelido en Julia aunque siacute es vaacutelido

juliagt 1000000(1 0 0)

iexclEsto no es lo que se podriacutea esperar Julia entiende 1000000 como unasecuencia de enteros separados por comas Maacutes adelante aprenderemos maacutessobre este tipo de secuencias

Sin embargo puede obtener el resultado esperado usando 1_000_000

Lenguajes formales y naturales

Los lenguajes naturales son los lenguajes hablados como el espantildeol el ingleacutes oel franceacutes no fueron disentildeados por personas (aunque las personas intentanimponerles un orden) sino que evolucionaron naturalmente

Los lenguajes formales son lenguajes disentildeados por personas para propoacutesitosespeciacuteficos Por ejemplo la notacioacuten que usan los matemaacuteticos es un lenguajeformal particularmente uacutetil para denotar relaciones entre nuacutemeros y siacutembolosLos quiacutemicos usan un lenguaje formal para representar la estructura quiacutemica delas moleacuteculas Los lenguajes de programacioacuten tambieacuten son lenguajes formales yhan sido disentildeados para expresar caacutelculos

Los lenguajes formales tienden a dictar reglas estrictas de sintaxis quegobiernan la estructura de las sentencias Por ejemplo en matemaacuteticas lasentencia tiene la sintaxis correcta pero no En quiacutemica esuna foacutermula sintaacutecticamente correcta pero no lo es

Las reglas de sintaxis pueden ser de dos tipos correspondientes a componentesleacutexicos y a estructura Los componentes leacutexicos son los elementos baacutesicos dellenguaje como palabras nuacutemeros y elementos quiacutemicos Uno de los problemascon es que no es un componente leacutexico vaacutelido en matemaacuteticas (al menos

Lenguajes formales y naturales 11

hasta donde conocemos) Del mismo modo no es vaacutelido porque no existeninguacuten elemento con la abreviatura

El segundo tipo de reglas de sintaxis se refiere a la forma en que se combinan loscomponentes leacutexicos La ecuacioacuten no es vaacutelida porque aunque y soncomponentes leacutexicos vaacutelidos no se puede tener uno justo despueacutes el otro Delmismo modo en una foacutermula quiacutemica el subiacutendice se coloca despueacutes del nombredel elemento no antes

Esta es un oracioacuten en espa$ol bien estructurada con cmponentes leacutexicos novaacutelidos Esta oracioacuten leacutexicos todos componentes los tiene pero estructura una novaacutelida con

Cuando se lee una oracioacuten en espantildeol o en un lenguaje formal se tiene quedescubrir la estructura (aunque en un lenguaje natural se haceinconscientemente) Este proceso se llama parsing o anaacutelisis de sintaxis

Aunque los lenguajes formales y naturales tienen muchas caracteriacutesticas encomuacutenmdashcomponentes leacutexicos estructura y sintaxismdashexisten algunas diferencias

AmbiguumledadLos lenguajes naturales estaacuten llenos de ambiguumledades este problema esabordado mediante el uso del contexto y otra informacioacuten Los lenguajesformales estaacuten disentildeados para ser casi completamente precisos lo quesignifica que cualquier declaracioacuten tiene exactamente un significadoindependientemente del contexto

RedundanciaPara compensar la ambiguumledad y reducir los malentendidos los lenguajesnaturales emplean mucha redundancia Como resultado a menudo sonverbosos Los lenguajes formales son menos redundantes y maacutes concisos

MetaacuteforaLos lenguajes naturales estaacuten llenos de modismos y metaacuteforas Si se diceldquoCaiacute en la cuentardquo probablemente no haya una cuenta y nada que se caiga(este modismo significa que alguien entendioacute algo despueacutes de un periacuteodo deconfusioacuten) Por otro lado los lenguajes formales significan exactamente loque expresan

Debido a que todo el mundo crece hablando lenguajes naturales a veces esdifiacutecil adaptarse a los lenguajes formales La diferencia entre lenguaje formal ynatural es como la diferencia entre la poesiacutea y la prosa

PoesiacuteaLas palabras se usan por sus sonidos y significados El poema en conjuntocrea un efecto o una respuesta emocional La ambiguumledad no soacutelo es comuacutensino a menudo deliberada

12 Capiacutetulo 1 El camino de la programacioacuten

ProsaEl significado literal de las palabras es maacutes importante y la estructuraaporta significado La prosa es maacutes faacutecil de analizar que la poesiacutea pero amenudo sigue siendo ambigua

ProgramasEl significado de un programa computacional es inequiacutevoco y literal ypuede entenderse por completo mediante el anaacutelisis de los componentesleacutexicos y de estructura

Los lenguajes formales son maacutes densos que los naturales por lo que lleva maacutestiempo leerlos Ademaacutes la estructura es importante por lo que no siempre esmejor leer de arriba a abajo y de izquierda a derecha En cambio aprenderaacute aanalizar el programa mentalmente identificando los componentes leacutexicos einterpretando la estructura Finalmente los detalles son importantes Pequentildeoserrores de ortografiacutea y puntuacioacuten que pueden pasar desapercibidos en loslenguajes naturales pueden hacer una gran diferencia en un lenguaje formal

Depuracioacuten

Los programadores cometen errores Los errores de programacioacuten se denominanbugs y el proceso para rastrearlos se denomina debugging o depuracioacuten

La programacioacuten y especialmente la depuracioacuten pueden provocar emocionesnegativas Frente a un error difiacutecil de solucionar puede sentir enojo verguumlenzaoacute cansancio

Existe evidencia de que las personas responden naturalmente a lascomputadoras como si fueran personas Cuando trabajan bien se los consideracompantildeeros de equipo y cuando son obstinados o groseros se los trata de lamisma manera que a personas groseras y obstinadas [1]

Prepararse para estas reacciones puede ayudarlo a lidiar con ellas Un enfoquees pensar en la computadora como un empleado con ciertas fortalezas como lavelocidad y la precisioacuten y debilidades particulares como la falta de empatiacutea y laincapacidad para comprender el panorama general

Su trabajo es ser un buen gerente debe encontrar formas de aprovechar lasfortalezas y mitigar las debilidades Ademaacutes debe encontrar formas de usar susemociones para involucrarse con el problema sin dejar que sus reaccionesinterfieran con su capacidad para trabajar de manera efectiva

Aprender a depurar puede ser frustrante pero es una habilidad valiosa que esuacutetil para muchas actividades maacutes allaacute de la programacioacuten Al final de cadacapiacutetulo hay una seccioacuten como esta con algunas sugerencias para ladepuracioacuten iexclEspero que le sean de ayuda

Depuracioacuten 13

Glosarioresolucioacuten de problemas

El proceso de formular un problema encontrar una solucioacuten y expresarla

programaUna secuencia de instrucciones que especifica un caacutelculo

REPLUn programa que de manera reiterada lee una entrada la ejecuta y generaresultados

indicadorCaracteres mostrados por el REPL para indicar que estaacute listo para recibirinformacioacuten de entrada de parte del usuario

sentencia de impresioacuten (print)Una instruccioacuten que hace que el REPL de Julia muestre un valor en lapantalla

operadorUn siacutembolo que representa un caacutelculo simple como la suma lamultiplicacioacuten o la concatenacioacuten de cadenas

valorUna de las unidades baacutesicas de datos como un nuacutemero o cadena quemanipula un programa

tipoUna categoriacutea de valores Los tipos que se han visto hasta ahora sonenteros (Int64) nuacutemeros de punto flotante (Float64) y cadenas (String)

enteroUn tipo que representa nuacutemeros enteros

punto flotanteUn tipo que representa nuacutemeros con un punto decimal

cadenaUn tipo que representa secuencias de caracteres

lenguaje naturalCualquier lenguaje hablado que evoluciona naturalmente

14 Capiacutetulo 1 El camino de la programacioacuten

lenguaje formalCualquier lenguaje disentildeado para fines especiacuteficos como la representacioacutende ideas matemaacuteticas o programas de computadora Todos los lenguajes deprogramacioacuten son lenguajes formales

sintaxisLas reglas que gobiernan la estructura de un programa

componente leacutexicoUno de los elementos baacutesicos de la estructura de un programa anaacutelogo auna palabra en un lenguaje natural

estructuraLa manera en que los componentes leacutexicos se combinan

anaacutelisis de sintaxisExaminar un programa y analizar la estructura sintaacutectica

bugUn error en un programa

depuracioacutendebuggingEl proceso de buacutesqueda y correccioacuten de errores

Ejercicios

OBSERVACIOacuteNEs una buena idea leer este libro frente a unacomputadora para hacer los ejemplos y ejerciciosconforme avance

Ejercicio 1-1

Siempre que esteacute experimentando con algo nuevo debe intentar cometererrores Por ejemplo en el programa ldquoiexclHola mundordquo iquestQueacute sucede si omite unade las comillas iquestQueacute pasa si omite ambas iquestQueacute ocurre si escribe mal println

Este tipo de ejercicios le ayuda a recordar lo que leyoacute tambieacuten le ayuda aprogramar porque puede saber queacute significan los mensajes de error Es mejorcometer errores ahora y a propoacutesito en lugar de despueacutes y accidentalmente

1 En un comando print iquestQueacute sucede si omite uno de los pareacutentesis o ambos

2 Si estaacute intentando imprimir un string iquestQueacute sucede si omite una de lascomillas o ambas

3 Se puede usar un signo menos para escribir un nuacutemero negativo como -2

Ejercicios 15

iquestQueacute sucede si pone un signo + antes de un nuacutemero iquestQueacute pasa con 2++2

4 En notacioacuten matemaacutetica los ceros a la izquierda son correctos como en 02iquestQueacute pasa si intenta esto en Julia

5 iquestQueacute sucede si tiene dos valores sin operador entre ellos

Ejercicio 1-2

Inicie el REPL de Julia y uacuteselo como una calculadora

1 iquestCuaacutentos segundos hay en 42 minutos y 42 segundos

2 iquestCuaacutentas millas hay en 10 kiloacutemetros

OBSERVACIOacuteN Hay 161 kiloacutemetros en una milla

3 Si corre una carrera de 10 kiloacutemetros en 37 minutos y 48 segundos iquestCuaacuteles su ritmo promedio (tiempo por milla en minutos y segundos) iquestCuaacutel es suvelocidad promedio en millas por hora

[1] Reeves Byron and Clifford Ivar Nass 1996 ldquoThe Media Equation How People Treat ComputersTelevision and New Media Like Real People and Placesrdquo Chicago IL Center for the Study of Language andInformation New York Cambridge University Press

16 Capiacutetulo 1 El camino de la programacioacuten

Capiacutetulo 2 Variables expresiones y sentenciasUna de las caracteriacutesticas maacutes poderosas de un lenguaje de programacioacuten es lacapacidad de manipular variables Una variable es un nombre que hacereferencia a un valor

Sentencias de asignacioacuten

Una sentencia de asignacioacuten crea una nueva variable y le asigna un valor

juliagt mensaje = Y ahora algo completamente diferenteY ahora algo completamente diferentejuliagt n = 1717juliagt π_val = 31415926535897933141592653589793

Este ejemplo realiza tres asignaciones La primera asigna una cadena a unanueva variable llamada mensaje la segunda le asigna el entero 17 a la variable nla tercera asigna el valor (aproximado) de π (pi TAB) a la variable π_val

Una forma comuacuten de representar variables en papel es escribir el nombre de lavariable con una flecha apuntando a su valor Este tipo de figura se llamaldquodiagrama de estadordquo porque muestra en queacute estado se encuentra cada una delas variables La Figura 1 Figura 1 muestra el resultado del ejemplo anterior

Figura 1 Diagrama de estado

Nombres de variablesLos programadores generalmente eligen nombres representativos para susvariables es decir nombres que explican para queacute se usa o queacute contiene lavariable

Los nombres de las variables pueden ser tan largos como se desee Puedencontener casi todos los caracteres Unicode (consulte Seccioacuten 81) pero nopueden comenzar con un nuacutemero Es vaacutelido usar letras mayuacutesculas pero locomuacuten es usar solo minuacutesculas para nombres de variables

Los caracteres Unicode se pueden ingresar mediante autocompletado portabulacioacuten de las abreviaturas tipo LaTeX en el REPL de Julia

El caraacutecter guioacuten bajo _ puede formar parte del nombre de una variable

Sentencias de asignacioacuten 17

Generalmente se usa como separador en nombres con varias palabras como porejemplo en tu_nombre ovelocidad_aerodinamica_de_una_golondrina_sin_cargamento

Si se le da un nombre invaacutelido a una variable aparece un error de sintaxis

juliagt 76trombones = un gran desfileERROR syntax 76 is not a valid function argument name (ERRORsintaxis 76 no es un nombre de argumento de funcioacuten vaacutelido)juliagt mas = 1000000ERROR syntax extra token after end of expression (ERROR sintaxiscomponente leacutexico adicional despueacutes del final de la expresioacuten)juliagt struct = Quiacutemica avanzadaERROR syntax unexpected = (ERROR sintaxis = inesperado)

76trombones es un nombre de variable invaacutelido porque comienza con un nuacutemeroTambieacuten es invaacutelido mas porque contiene el caraacutecter invaacutelido Pero iquestCuaacutel esel error en struct

Resulta que struct es una de las palabras reservadas de Julia Julia usa laspalabras reservadas para reconocer la estructura del programa por ello nopueden usarse como nombres de variables

Julia tiene las siguientes palabras reservadas

abstract type baremodule begin break catchconst continue do else elseifend export finally for functionglobal if import importall inlet local macro module mutable structprimitive type quote return try usingstruct where while

No es necesario memorizar esta lista En la mayoriacutea de los entornos dedesarrollo las palabras reservadas se muestran en un color diferente por lotanto si intenta usar una como nombre de variable lo sabraacute

Expresiones y sentenciasUna expresioacuten es una combinacioacuten de valores variables y operadores Un valor ouna variable por siacute solos se consideran una expresioacuten por lo que las siguientesexpresiones son vaacutelidas

18 Capiacutetulo 2 Variables expresiones y sentencias

juliagt 4242juliagt n17juliagt n + 2542

Cuando escribe una expresioacuten en el indicador el REPL la evaluacutea lo que significaque encuentra el valor de la expresioacuten En este ejemplo n tiene el valor 17previamente asignado y n+25 retorna el valor 42

Una sentencia es una unidad de coacutedigo que tiene un efecto tal como crear unavariable o mostrar un valor

juliagt n = 1717juliagt println(n)17

La primera liacutenea es una sentencia de asignacioacuten ya que asigna un valor a n Lasegunda liacutenea es una sentencia de impresioacuten que muestra el valor de n

Cuando escribe una sentencia REPL la ejecuta es decir hace lo que dice lasentencia

Modo scriptHasta ahora se ha ejecutado Julia en modo interactivo lo que significa que se hainteractuado directamente con el REPL Este modo es una buena manera decomenzar pero si estaacute trabajando con varias liacuteneas de coacutedigo puede resultarincoacutemodo

Una alternativa es guardar el coacutedigo en un archivo de oacuterdenes o script y luegoutilizar Julia en modo script para ejecutarlo Por convencioacuten los scripts de Juliatienen nombres que terminan con la extensioacuten jl

Si sabe coacutemo crear y ejecutar un script en su computadora estaacute listo paracomenzar De lo contrario es recomendable usar JuliaBox nuevamente Abra unarchivo de texto escriba el script y guaacuterdelo con la extensioacuten jl El script sepuede ejecutar en una terminal con el comando julia nombre_del_scriptjl

Debido a que Julia proporciona ambos modos puede probar liacuteneas de coacutedigo enmodo interactivo antes de colocarlos en un script Auacuten asiacute tenga enconsideracioacuten que existen diferencias entre el modo interactivo y el modo scriptque pueden generar confusioacuten

Por ejemplo si estaacute utilizando Julia como una calculadora puede escribir

Modo script 19

juliagt millas = 262262juliagt millas 16142182

La primera liacutenea asigna un valor a millas y muestra el valor La segunda liacutenea esuna expresioacuten por lo que el REPL la evaluacutea y muestra el resultado Gracias alcoacutedigo anterior sabemos que una maratoacuten tiene unos 42 kiloacutemetros

Pero si escribe el mismo coacutedigo en un script y lo ejecuta no obtendraacute ninguacutenresultado En el modo script una expresioacuten por siacute sola no tiene ninguacuten efectovisible Julia evaluacutea la expresioacuten pero no muestra el valor a menos que se loindique

millas = 262println(millas 161)

Al principio este comportamiento puede ser confuso

Un script generalmente contiene una secuencia de sentencias Si hay maacutes de unasentencia los resultados aparecen de uno a la vez a medida que se ejecutan lassentencias

Por ejemplo el script

println(1)x = 2println(x)

produce la salida

12

Notar que la sentencia de asignacioacuten x = 2 no tiene salida

Ejercicio 2-1

Para comprobar que ha comprendido lo recientemente explicado escriba lassiguientes sentencias en el REPL de Julia y vea lo que hace cada una

5x = 5x + 1

20 Capiacutetulo 2 Variables expresiones y sentencias

Ahora coloque las mismas sentencias en un script y ejecuacutetelo iquestCuaacutel es elresultado Modifique el script transformando cada expresioacuten en una sentencia deimpresioacuten y luego ejecuacutetelo de nuevo

Orden de operacionesCuando una expresioacuten contiene maacutes de un operador el orden de evaluacioacutendepende de las reglas de precedencia Julia sigue la convencioacuten matemaacutetica parael orden de evaluacioacuten de los operadores matemaacuteticos El acroacutenimo PAPOMUDASes una forma uacutetil de recordar estas reglas

bull PAreacutentesis tienen la mayor precedencia y se pueden utilizar para forzar laevaluacioacuten de una expresioacuten en el orden que se desee Dado que lasexpresiones entre pareacutentesis se evaluacutean primero 2(3-1) es 4 y (1+1)^(5-2) es 8 Tambieacuten puede usar pareacutentesis para hacer una expresioacuten maacutes faacutecilde leer como en (minuto100)60 incluso si no cambia el resultado

bull POtenciacioacuten tiene la siguiente precedencia maacutes alta por lo que 1+2^3 es9 no 27 y 23^2 es 18 no 36

bull MUltiplicacioacuten y Divisioacuten tienen mayor precedencia que la Adicioacuten ySustraccioacuten Entonces 23-1 es 5 no 4 y 6+42 es 8 no 5

bull Los operadores con la misma precedencia se evaluacutean de izquierda a derecha(excepto potencias) Entonces en la expresioacuten grados2π la divisioacuten ocurreprimero y el resultado se multiplica por π Para dividir entre puede usarpareacutentesis escribir grados2π o grados2π

OBSERVACIOacuteNNo se esfuerce demasiado en recordar el orden de lasoperaciones Si el orden no es evidente mirando laexpresioacuten use pareacutentesis para que siacute lo sea

Operaciones con cadenasEn general no se pueden realizar operaciones matemaacuteticas con cadenas aunquelas cadenas puedan parecer nuacutemeros por lo que lo siguiente es invaacutelido

2 - 1huevos faacuteciltercero + talismaacuten

No obstante hay dos excepciones y ^

El operador realiza concatenacioacuten de cadenas lo que significa que une lascadenas de extremo a extremo Por ejemplo

Orden de operaciones 21

juliagt primer_str = autoautojuliagt segundo_str = moacutevilmoacuteviljuliagt primer_str segundo_strautomoacutevil

El operador ^ tambieacuten funciona con cadenas generando repeticiones Porejemplo Spam^3 es SpamSpamSpam Si uno de los valores es una cadena elotro tiene que ser un nuacutemero entero

De manera anaacuteloga este uso de y ^ tambieacuten tiene sentido en la multiplicacioacuten ypotencia Asiacute como 4^3 es equivalente a 444 esperamos que el Spam^3 sea lomismo que el SpamSpamSpam y lo es

ComentariosA medida que los programas se hacen maacutes largos y complejos se vuelven maacutesdifiacuteciles de leer Los lenguajes formales son densos y a menudo es difiacutecil leer elcoacutedigo y entender queacute estaacute haciendo o por queacute

Por esta razoacuten es una buena idea agregar notas a sus programas para explicaren lenguaje natural lo que estaacute haciendo el programa Estas notas se llamancomentarios y comienzan con el siacutembolo

calcula el porcentaje de hora que ha transcurridoporcentaje = (minuto 100) 60

En este caso el comentario aparece soacutelo en una liacutenea Tambieacuten puede ponercomentarios al final de una liacutenea

porcentaje = (minuto 100) 60 porcentaje de una hora

Todo desde el hasta el final de la liacutenea se ignora y no tiene ninguacuten efecto en laejecucioacuten del programa

Los comentarios son maacutes uacutetiles cuando documentan caracteriacutesticas no obvias delcoacutedigo Es razonable suponer que el lector puede averiguar queacute hace el coacutedigopor lo tanto es maacutes uacutetil explicar por queacute

Este comentario es inuacutetil porque es redundante con el coacutedigo

v = 5 asigna 5 a v

Este comentario contiene informacioacuten uacutetil que no estaacute presente en el coacutedigo

22 Capiacutetulo 2 Variables expresiones y sentencias

v = 5 velocidad en metrossegundo

OBSERVACIOacuteNLos nombres de las variables tienen que ser descriptivospara asiacute reducir la necesidad de comentarios pero notan largos como para dificultar la lectura del coacutedigo

DepuracioacutenSe pueden producir tres tipos de errores en un programa errores de sintaxiserrores en tiempo de ejecucioacuten y errores semaacutenticos Es uacutetil distinguirlos pararastrearlos maacutes raacutepidamente

Error de sintaxisldquoSintaxisrdquo se refiere a la estructura de un programa y las reglas sobre esaestructura Por ejemplo los pareacutentesis deben presentarse de a pares por loque (1+2) es vaacutelido pero 8) es un error de sintaxis

Si hay un error de sintaxis en cualquier parte de su programa Julia muestraun mensaje de error y se cierra no pudiendo ejecutar el programa Durantesus primeras semanas como programador puede pasar mucho tiemporastreando errores de sintaxis A medida que gane experiencia cometeraacutemenos errores y los encontraraacute maacutes raacutepido

Error en tiempo de ejecucioacutenEl segundo tipo de error es el error en tiempo de ejecucioacuten llamado asiacuteporque aparece durante la ejecucioacuten del programa Estos errores tambieacutense denominan excepciones porque generalmente indican que ha sucedidoalgo excepcional (y malo)

Los errores en tiempo de ejecucioacuten son raros en los programas simples queveraacute en los primeros capiacutetulos por lo que puede pasar un tiempo antes deque encuentre uno

Error semaacutenticoEl tercer tipo de error es ldquosemaacutenticordquo es decir relacionado con elsignificado Si hay un error semaacutentico en su programa este se ejecutaraacute singenerar mensajes de error pero no haraacute lo que se desea sino que haraacute otracosa Especiacuteficamente haraacute lo que usted le dijo que hiciera (y no lo queusted desea que realice)

Identificar errores semaacutenticos puede ser complicado porque requiere que setrabaje a la inversa analizando la salida del programa para intentar descubrirqueacute estaacute haciendo

Depuracioacuten 23

Glosariovariable

Un nombre que hace referencia a un valor

asignacioacutenUna sentencia que asigna un valor a una variable

diagrama de estadoUna representacioacuten graacutefica de un conjunto de variables y los valores a losque hace referencia

palabra claveUna palabra reservada que se utiliza para definir la sintaxis y estructura deun programa no puede usar palabras reservadas como if function ywhile como nombres de variables

operandoUno de los valores sobre los que opera un operador

expresioacutenUna combinacioacuten de variables operadores y valores que representa un solovalor como resultado

evaluarSimplificar una expresioacuten realizando operaciones para obtener un solo valor

sentenciaUna seccioacuten de coacutedigo que representa un comando o accioacuten Hasta ahoralas sentencias que hemos visto son asignaciones e impresiones

ejecutarEjecutar una sentencia y hacer lo que eacutesta dice

modo interactivoUna forma de utilizar el REPL de Julia escribiendo coacutedigo en el indicador

modo scriptUna forma de usar Julia para leer coacutedigo desde un script y ejecutarlo

scriptUn programa almacenado en un archivo

24 Capiacutetulo 2 Variables expresiones y sentencias

precedencia del operadorReglas que rigen el orden en que se evaluacutean las expresiones que involucranmuacuteltiples operadores matemaacuteticos y operandos

concatenarUnir dos cadenas de extremo a extremo

comentarioInformacioacuten en un programa que estaacute destinada a otros programadores (ocualquier persona que lea el coacutedigo fuente) y que no tiene efecto en laejecucioacuten del programa

error de sintaxisUn error en un programa que hace que sea imposible de analizar (y por lotanto imposible de ejecutar)

error en tiempo de ejecucioacuten o excepcioacutenUn error que se detecta mientras se ejecuta el programa

semaacutenticaEl significado de un programa

error semaacutenticoEs un error en un programa que provoca que se haga algo diferente a loque el programador pretendiacutea

Ejercicios

Ejercicio 2-2

Repitiendo el consejo del capiacutetulo anterior cada vez que aprenda algo nuevodebe probarlo en el modo interactivo y cometer errores a propoacutesito para ver elresultado

1 Hemos visto que n=42 es vaacutelido iquestQueacute pasa con 42=n

2 iquestY con x=y=1

3 En algunos lenguajes cada sentencia termina con un punto y coma iquestQueacutesucede si pone un punto y coma al final de una sentencia en Julia

4 iquestQueacute pasa si pone un punto al final de una sentencia

5 En notacioacuten matemaacutetica puede multiplicar x e y de esta manera x y iquestQueacutepasa si intenta eso en Julia iquestY queacute sucede con 5x

Ejercicios 25

Ejercicio 2-3

Practique usando el REPL de Julia como una calculadora

1 El volumen de una esfera con radio es iquestCuaacutel es el volumen de unaesfera con radio 5

2 Supongamos que el precio de venta de un libro es de $2495 pero laslibreriacuteas obtienen un descuento del 40 El enviacuteo cuesta $3 por la primeracopia y 75 centavos por cada copia adicional iquestCuaacutel es el costo total al pormayor de 60 copias

3 Si una persona sale de casa a las 652 am y corre 1 milla a un ritmorelajado (815 minutos por milla) luego 3 millas maacutes raacutepido (712 minutospor milla) y 1 milla a ritmo relajado nuevamente iquestA queacute hora llega a casapara desayunar

26 Capiacutetulo 2 Variables expresiones y sentencias

Capiacutetulo 3 FuncionesEn el contexto de la programacioacuten una funcioacuten es una secuencia de sentenciasque ejecuta una operacioacuten deseada y tiene un nombre Cuando se define unafuncioacuten se especifica su nombre y secuencia de sentencias Una vez hecho estose puede llamar a la funcioacuten por su nombre

Llamada a funcioacuten

Ya se ha visto un ejemplo de una llamada a funcioacuten

juliagt println(iexclHola Mundo)iexclHola Mundo

El nombre de esta funcioacuten es println La expresioacuten entre pareacutentesis se llamaargumento de la funcioacuten

Es comuacuten decir que una funcioacuten toma un argumento y devuelve un resultadoEl resultado tambieacuten se llama valor de retorno

Julia tiene funciones integradas que convierten valores de un tipo a otro Lafuncioacuten parse toma una cadena y si es posible la convierte en cualquier tipo denuacutemero en caso contrario arroja error

juliagt parse(Int64 32)32juliagt parse(Float64 314159)314159juliagt parse(Int64 Hola)ERROR ArgumentError invalid base 10 digit H in Hola

(ERROR ArgumentError base invaacutelida de 10 diacutegitos H en Hola)

trunc puede convertir valores de punto flotante a enteros pero no redondea sinoque trunca

juliagt trunc(Int64 399999)3juliagt trunc(Int64 -23)-2

float convierte nuacutemeros enteros en nuacutemeros de punto flotante

Llamada a funcioacuten 27

juliagt float(32)320

Finalmente string convierte el argumento en una cadena

juliagt string(32)32juliagt string(314159)314159

Funciones matemaacuteticasEn Julia la mayoriacutea de las funciones matemaacuteticas conocidas estaacuten disponiblesdirectamente

proporcioacuten = potencia_de_sentildealpotencia_de_ruidodecibelios = 10log10(proporcioacuten)

Este primer ejemplo utiliza la funcioacuten log10 para calcular la proporcioacuten entresentildeal y ruido en decibelios (suponiendo que potencia_de_sentildeal ypotencia_de_ruido estaacuten definidos) Tambieacuten existe la funcioacuten log que calcula ellogaritmo natural

radianes = 07altura = sin(radianes)

Este segundo ejemplo encuentra la razoacuten seno (en ingleacutes sine) de la variableradianes El nombre de esta variable es una pista de que la funcioacuten sin y las otrasfunciones trigonomeacutetricas (cos tan etc) toman argumentos en radianes Paraconvertir grados a radianes se debe dividir por 180 y multiplicar por

juliagt grados=4545juliagt radianes=grados180π07853981633974483juliagt sin(radianes)07071067811865475

El valor de la variable π es una aproximacioacuten de punto flotante de con unaprecisioacuten de aproximadamente 16 diacutegitos

Si sabe de trigonometriacutea puede verificar el resultado anterior comparaacutendolo conla raiacutez cuadrada de dos dividido por dos

28 Capiacutetulo 3 Funciones

juliagt sqrt(2) 207071067811865476

ComposicioacutenHasta ahora hemos analizado los elementos de un programa (variablesexpresiones y sentencias) de forma aislada sin mencionar coacutemo se combinan

Una de las caracteriacutesticas maacutes uacutetiles de los lenguajes de programacioacuten es sucapacidad para combinar pequentildeos bloques de coacutedigo Por ejemplo elargumento de una funcioacuten puede ser cualquier tipo de expresioacuten incluidosoperadores aritmeacuteticos

x = sin(grados3602π)

E incluso llamadas a funciones

x = exp(log(x + 1))

Casi en cualquier lugar donde se pueda colocar un valor se puede colocar unaexpresioacuten arbitraria con una excepcioacuten el lado izquierdo de una sentencia deasignacioacuten debe ser un nombre de variable Cualquier otra expresioacuten en el ladoizquierdo genera un error de sintaxis (se veraacuten excepciones a esta regla maacutesadelante)

2

juliagt minutos = horas 60 bien120juliagt horas 60 = minutos malERROR syntax 60 is not a valid function argument name

(ERROR sintaxis 60 no es un nombre de argumento de funcioacuten vaacutelido)

Agregar nuevas funcionesHasta ahora solo hemos usado las funciones integradas en Julia pero tambieacuten esposible agregar nuevas funciones Una definicioacuten de funcioacuten especifica el nombrede una nueva funcioacuten y la secuencia de sentencias que se ejecutan cuando sellama a la funcioacuten A continuacioacuten se muestra un ejemplo

Composicioacuten 29

function imprimirletras() println(Juguemos en el bosque) println(mientras el lobo no estaacute)end

function es una palabra reservada que indica que esta es una definicioacuten defuncioacuten El nombre de la funcioacuten es imprimirletras Las reglas para losnombres de funciones son las mismas que para los nombres de variables puedencontener casi todos los caracteres Unicode (consulte Seccioacuten 81) pero el primercaraacutecter no puede ser un nuacutemero No puede usar una palabra reservada comonombre de una funcioacuten y debe evitar tener una variable y una funcioacuten con elmismo nombre

Los pareacutentesis vaciacuteos despueacutes del nombre indican que esta funcioacuten no tieneargumentos

La primera liacutenea de una definicioacuten de funcioacuten se llama encabezado el resto sellama cuerpo El cuerpo termina con la palabra reservada end y puede contenertodas las sentencias que desee Para facilitar la lectura el cuerpo de la funcioacutendeberiacutea tener sangriacutea

Las comillas deben ser comillas rectas () generalmente ubicadas junto a latecla Enter en el teclado Las comillas inglesas (ldquordquo)no son vaacutelidas en Julia

Si escribe una definicioacuten de funcioacuten en modo interactivo Julia REPL inserta unasangriacutea para informarle que la definicioacuten no estaacute completa

juliagt function imprimirletras() println(Juguemos en el bosque)

Para finalizar la funcioacuten debe escribir end

La sintaxis para llamar a la nueva funcioacuten es la misma que para las funcionesintegradas en Julia

juliagt imprimirletras()Juguemos en el bosquemientras el lobo no estaacute

Una vez definida una funcioacuten puede usarla dentro de otra funcioacuten Por ejemplopara repetir el estribillo anterior se podriacutea escribir una funcioacuten llamadarepetirletras

30 Capiacutetulo 3 Funciones

function repetirletras() imprimirletras() imprimirletras()end

Y luego llamar a repetirletras

juliagt repetirletras()Juguemos en el bosquemientras el lobo no estaacuteJuguemos en el bosquemientras el lobo no estaacute

Definiciones y usosAl unir los fragmentos de coacutedigo de la seccioacuten anterior todo el programa se veasiacute

function imprimirletras() println(Jueguemos en el bosque) println(mientras el lobo no estaacute)end

funcioacuten repetirletras() imprimirletras() imprimirletras()end

repetirletras()

Este programa contiene dos definiciones de funcioacuten imprimirletras yrepetirletras Las definiciones de funcioacuten se ejecutan al igual que otrassentencias pero su ejecucioacuten crea nuevas funciones Las sentencias dentro de lafuncioacuten no se ejecutan hasta que se llama a la funcioacuten y la definicioacuten de lafuncioacuten no genera salida

Como es de esperar debe crear una funcioacuten antes de poder ejecutarla En otraspalabras la definicioacuten de la funcioacuten tiene que ejecutarse antes de que se llame ala funcioacuten

Ejercicio 3-1

Mueva la uacuteltima liacutenea de este programa a la parte superior de modo que lallamada a funcioacuten aparezca antes de las definiciones Ejecute el programa y veaqueacute mensaje de error obtiene

Definiciones y usos 31

Ahora mueva la llamada a funcioacuten hacia abajo y coloque la definicioacuten deimprimirletras despueacutes de la definicioacuten de repetirletras iquestQueacute sucede cuandoejecuta este programa

Flujo de ejecucioacutenPara asegurarse de que una funcioacuten sea definida antes de su primer uso debeconocer el orden en que se ejecutan las instrucciones lo que se denomina flujode ejecucioacuten

La ejecucioacuten siempre comienza con la primera sentencia del programa Lassentencias se ejecutan una a la vez en orden descendente

Las definiciones de funcioacuten no alteran el flujo de ejecucioacuten del programa pero sedebe recordar que las sentencias dentro de la funcioacuten no se ejecutan hasta quese llama a la funcioacuten

Una llamada a funcioacuten es como un desviacuteo en el flujo de ejecucioacuten En lugar depasar a la siguiente sentencia el flujo salta al cuerpo de la funcioacuten ejecuta lassentencias que estaacuten alliacute y luego regresa para continuar el coacutedigo donde lo dejoacute

Esto suena bastante simple hasta que se tiene en cuenta que una funcioacuten puedellamar a otra Mientras se estaacute ejecutando una funcioacuten el programa podriacutea tenerque ejecutar las sentencias de otra funcioacuten Luego mientras ejecuta esa nuevafuncioacuten iexclel programa podriacutea tener que ejecutar otra funcioacuten maacutes

Afortunadamente Julia es capaz de hacer el seguimiento de sus movimientos asiacuteque cada vez que una funcioacuten termina el programa retoma la funcioacuten que lallamoacute justo donde la dejoacute Cuando llega al final del programa la ejecucioacutentermina

En resumen cuando lee un programa no siempre debe leer de arriba haciaabajo A veces tiene maacutes sentido seguir el flujo de ejecucioacuten

Paraacutemetros y argumentosAlgunas de las funciones que se han visto requieren argumentos Por ejemplo lafuncioacuten cos necesita un nuacutemero como argumento Algunas funciones toman maacutesde un argumento por ejemplo parse toma dos un nuacutemero y una cadena

Dentro de la funcioacuten los argumentos se asignan a variables llamadasparaacutemetros A continuacioacuten se muestra un ejemplo de definicioacuten de funcioacuten quetoma un argumento

32 Capiacutetulo 3 Funciones

function imprimirdosveces(juan) println(juan) println(juan)end

Esta funcioacuten asigna el argumento a un paraacutemetro llamado juan Cuando se llamaa la funcioacuten esta imprime el valor del paraacutemetro (cualquiera que sea) dos veces

Esta funcioacuten funciona con cualquier valor que se pueda imprimir

juliagt imprimirdosveces(Correo no deseado)Correo no deseadoCorreo no deseadojuliagt imprimirdosveces(42)4242juliagt imprimirdosveces(π)π = 31415926535897 π = 31415926535897

Las mismas reglas de composicioacuten que se aplican a las funciones integradastambieacuten se aplican a las funciones definidas por el programador por lo quepodemos usar cualquier tipo de expresioacuten como argumento paraimprimirdosveces

juliagt imprimirdosveces(Correo no deseado ^4)Correo no deseado Correo no deseado Correo no deseado Correo no deseadoCorreo no deseado Correo no deseado Correo no deseado Correo no deseadojuliagt imprimirdosveces(cos(π))-10-10

El argumento se evaluacutea antes de llamar a la funcioacuten por lo que en los ejemploslas expresiones Correo no deseado ^4 y cos(π) solo se evaluacutean una vez

Tambieacuten puede usar una variable como argumento

juliagt michael = La vida es bellaLa vida es bellajuliagt imprimirdosveces(michael)La vida es bellaLa vida es bella

El nombre de la variable que pasamos como argumento (michael) no tiene nadaque ver con el nombre del paraacutemetro (juan) Para la funcioacuten imprimirdosveces

Paraacutemetros y argumentos 33

todos los paraacutemetros se llaman juan sin importar el nombre de la variable quepasemos como argumento (en este caso michael)

Las variables y los paraacutemetros son localesCuando se crea una variable dentro de una funcioacuten esta es local es decir soloexiste dentro de la funcioacuten Por ejemplo

function concatenar_dos(parte1 parte2) concat = parte1 parte2 imprimirdosveces(concat)end

Esta funcioacuten toma dos argumentos los concatena e imprime el resultado dosveces Aquiacute hay un ejemplo

juliagt linea1 = Hola holaHola holajuliagt linea2 = adioacutes adioacutesadioacutes adioacutesjuliagt concatenar_dos(liacutenea1 liacutenea2)Hola hola adioacutes adioacutesHola hola adioacutes adioacutes

Cuando concatenar_dos termina la variable concat es destruida Si intentamosimprimirla obtendremos un error

juliagt println(concat)ERROR UndefVarError concat not defined

Los paraacutemetros tambieacuten son locales Por ejemplo fuera de la funcioacutenimprimirdosveces no existe juan

Diagramas de pilaPara seguir la pista de queacute variables se usan en queacute lugares es uacutetil dibujar undiagrama de pila Al igual que los diagramas de estado los diagramas de pilamuestran el valor de cada variable pero tambieacuten muestran la funcioacuten a la quepertenece cada una

Cada funcioacuten se representa por un marco Un marco es un recuadro con elnombre de una funcioacuten a un costado y los paraacutemetros y variables de la funcioacutendentro El diagrama de pila para el ejemplo anterior se muestra en Figura 2

34 Capiacutetulo 3 Funciones

Figura 2 Diagrama de pila

Los marcos se ordenan de tal manera que cada funcioacuten llama a la funcioacuteninmediatamente inferior En este ejemplo imprimirdosveces fue llamado porconcatenar_dos y concatenar_dos fue llamado por Main que es un nombreespecial para la funcioacuten de maacutes alto nivel Cuando se crea una variable afuera decualquier funcioacuten pertenece a Main

Cada paraacutemetro se refiere al mismo valor que su argumento correspondienteEntonces parte1 tiene el mismo valor que linea1 parte2 tiene el mismo valorque linea2 y juan tiene el mismo valor que concat

Si se produce un error durante una llamada a funcioacuten Julia imprime el nombrede la funcioacuten el nombre de la funcioacuten que la llamoacute el nombre de la funcioacuten que asu vez llamoacute a esta otra y asiacute sucesivamente hasta llegar a la funcioacuten de maacutes altonivel Main

Por ejemplo si intenta acceder a concat desde imprimirdosveces obtendraacute unUndefVarError

ERROR UndefVarError concat not definedStacktrace [1] imprimirdosveces at REPL[1]gt2 [inlined] [2] concatenar_dos(String String) at REPL[2]gt3

Esta lista de funciones se llama trazado inverso Indica en queacute archivo deprograma se produjo el error en queacute liacutenea y queacute funciones se estaban ejecutandoen ese momento Tambieacuten muestra la liacutenea de coacutedigo que causoacute el error

El orden de las funciones en el trazado inverso es el opuesto del orden de losrecuadros en el diagrama de pila La funcioacuten que se estaacute ejecutando actualmenteestaacute en la parte superior

Funciones productivas y funciones nulasAlgunas de las funciones que hemos utilizado como las funciones matemaacuteticasdevuelven resultados A este tipo de funciones se les llamaraacute funcionesproductivas a falta de un nombre mejor Otras funciones comoimprimirdosveces realizan una accioacuten pero no devuelven un valor Estas sellaman funciones nulas

Funciones productivas y funciones nulas 35

Cuando se llama a una funcioacuten productiva casi siempre se quiere hacer algo conel resultado por ejemplo asignarlo a una variable o usarlo como parte de unaexpresioacuten

x = cos(radianes)aurea = (sqrt(5)+1)2

Cuando se llama a una funcioacuten en modo interactivo Julia muestra el resultado

juliagt sqrt(5)223606797749979

Pero en un script si se llama a una funcioacuten productiva iexclel valor de retorno sepierde para siempre

sqrt(5)

Output

223606797749979

Este script calcula la raiacutez cuadrada de 5 pero como no almacena ni muestra elresultado no es muy uacutetil

Las funciones nulas pueden mostrar algo en la pantalla o tener alguacuten otro efectopero no tienen un valor de retorno Si asigna el resultado a una variableobtendraacute un valor especial llamado nothing (nada en ingleacutes)

juliagt resultado = imprimirdosveces(Bing)BingBingjuliagt show(resultado)nothing

Para imprimir el valor nothing debe usar la funcioacuten show que es como la funcioacutenprint pero permite el valor nothing

El valor nothing no es lo mismo que la cadena nothing Es un valor especial quetiene su propio tipo

juliagt typeof (nothing)Nothing

Las funciones que hemos escrito hasta ahora son nulas Comenzaremos a escribir

36 Capiacutetulo 3 Funciones

funciones productivas en unos pocos capiacutetulos

iquestPor queacute se necesitan funcionesPuede que no esteacute claro por queacute vale la pena dividir un programa en funcionesHay varias razones

bull Crear una nueva funcioacuten le brinda la oportunidad de darle nombre a ungrupo de sentencias lo que hace que su programa sea maacutes faacutecil de leer ydepurar

bull Las funciones pueden hacer que un programa sea maacutes corto al eliminarcoacutedigo repetitivo Ademaacutes si realiza un cambio solo tiene que hacerlo en unsolo lugar

bull Dividir un programa largo en funciones le permite depurar las partes de unaen una y luego unirlas

bull Las funciones bien disentildeadas pueden ser uacutetiles para muchos programasUna vez que escribe y depura una puede reutilizarla

bull En Julia las funciones pueden mejorar mucho el rendimiento

DepuracioacutenUna de las habilidades maacutes importantes que adquiriraacute es la depuracioacuten Aunquepuede ser frustrante la depuracioacuten es una de las partes maacutes intelectualmentegratificantes desafiantes e interesantes de la programacioacuten

La depuracioacuten puede ser vista como un trabajo de detective El programador seenfrenta a pistas y tiene que inferir los procesos y eventos que generaron losresultados que ve

La depuracioacuten tambieacuten es como una ciencia experimental Una vez que se tieneuna idea de lo que estaacute mal se modifica el programa y se intenta nuevamente Sila hipoacutetesis era correcta se puede predecir el resultado de la modificacioacuten y asiacuteestar un paso maacutes cerca de un programa totalmente funcional Si la hipoacutetesis eraincorrecta se tiene que encontrar una nueva Como Sherlock Holmes sentildealoacute

Cuando todo aquello que es imposible ha sido eliminado lo que quede pormuy improbable que parezca es la verdad

mdash A Conan Doyle El signo de los cuatro

Para algunas personas la programacioacuten y la depuracioacuten son lo mismo Es decirla programacioacuten es el proceso de depurar gradualmente un programa hasta quehaga lo que desea Lo ideal es comenzar con un programa que funcione y hacer

iquestPor queacute se necesitan funciones 37

pequentildeas modificaciones depuraacutendolas a medida que avanza

Por ejemplo Linux es un sistema operativo que contiene millones de liacuteneas decoacutedigo pero comenzoacute como un programa simple que Linus Torvalds usoacute paraexplorar el chip Intel 80386 Seguacuten Larry Greenfield Uno de los proyectosanteriores de Linus fue un programa que cambiariacutea entre imprimir AAAA yBBBB Esto luego evolucionoacute a Linux (The Linux Usersrsquo Guide Beta Version1)

Glosariofuncioacuten

secuencia de sentencias que ejecuta una operacioacuten deseada y tiene unnombre Las funciones pueden tomar o no argumentos y pueden producir ono un resultado

definicioacuten de funcioacutenUna sentencia que crea una nueva funcioacuten especificando su nombreparaacutemetros y las sentencias que contiene

objeto de funcioacutenUn valor creado por una definicioacuten de funcioacuten El nombre de la funcioacuten esuna variable que se refiere a un objeto de funcioacuten

encabezadoLa primera liacutenea de una definicioacuten de funcioacuten

cuerpoSecuencia de sentencias dentro de una definicioacuten de funcioacuten

paraacutemetroUn nombre usado dentro de una funcioacuten para referirse al valor pasado comoargumento

Llamada a funcioacutenUna sentencia que ejecuta una funcioacuten Compuesta por el nombre de lafuncioacuten seguido por la lista de argumentos que usa entre pareacutentesis

argumentoValor que se le pasa a una funcioacuten cuando se la llama Este valor se asignaal paraacutemetro correspondiente en la funcioacuten

variable localUna variable definida dentro de una funcioacuten Una variable local solo puedeusarse dentro de su funcioacuten

38 Capiacutetulo 3 Funciones

valor de retornoEl resultado de una funcioacuten Si se utiliza una llamada a funcioacuten como unaexpresioacuten el valor de retorno es el valor de la expresioacuten

funcioacuten productivaUna funcioacuten que devuelve un valor

funcioacuten vaciacuteaUna funcioacuten que siempre devuelve nothing

nothingUn valor especial devuelto por las funciones nulas

composicioacutenUsar una expresioacuten como parte de una expresioacuten maacutes grande o unasentencia como parte de una sentencia maacutes grande

flujo de ejecucioacutenEl orden en que las sentencias se ejecutan

diagrama de pilaUna representacioacuten graacutefica de una pila de funciones sus variables y losvalores a los que se refieren

marcoUn recuadro que en un diagrama de pila representa una llamada de funcioacutenContiene las variables locales y los paraacutemetros de la funcioacuten

trazado inversoUna lista de las funciones que se estaacuten ejecutando las cuales son impresascuando ocurre una excepcioacuten

Ejercicios

OBSERVACIOacuteN Estos ejercicios deben realizarse utilizando soacutelo lo quese ha tratado hasta ahora

Ejercicio 3-2

Escriba una funcioacuten llamada justificar_a_la_derecha que tome una cadena s comoparaacutemetro y que imprima la cadena con suficientes espacios en blanco para quela uacuteltima letra de la cadena se encuentre en la columna 70 de la pantalla

using IntroAJulia

Ejercicios 39

justificar_a_la_derecha(Celia)

OBSERVACIOacuteN

Use concatenacioacuten de cadenas y repeticioacuten AdemaacutesJulia tiene integrada una funcioacuten llamada length quedevuelve la longitud de una cadena por lo que el valorde length(Celia) es 5

Ejercicio 3-3

Un objeto de funcioacuten es un valor que se puede asignar a una variable o serpasado como argumento Por ejemplo dosveces es una funcioacuten que toma unobjeto de funcioacuten como argumento y lo llama dos veces

function dosveces(f) f() f()end

A continuacioacuten se muestra un ejemplo que usa dosveces para llamar a unafuncioacuten llamada imprimirgato dos veces

function imprimirpalabra() println(palabra)end

dosveces(imprimirpalabra)

1 Escriba este ejemplo en un script y prueacutebelo

2 Modifique dosveces para que tome dos argumentos un objeto de funcioacuten yun valor y que llame a la funcioacuten dos veces pasando el valor comoargumento

3 Copie la definicioacuten de imprimirdosveces mencionada antes en este capiacutetuloa su secuencia de comandos

4 Use la versioacuten modificada de dosveces para llamar a imprimirdosveces dosveces pasando palabra como argumento

5 Defina una nueva funcioacuten llamada cuatroveces que tome un objeto defuncioacuten y un valor y que llame a la funcioacuten cuatro veces pasando el valorcomo paraacutemetro Debe haber solo dos sentencias en el cuerpo de estafuncioacuten no cuatro

40 Capiacutetulo 3 Funciones

Ejercicio 3-4

1 Escriba la funcioacuten imprimircuadricula que dibuje una cuadriacutecula como lasiguiente

juliagt imprimircuadricula()+ - - - - + - - - - +| | || | || | || | |+ - - - - + - - - - +| | || | || | || | |+ - - - - + - - - - +

1 Escriba una funcioacuten que dibuje una cuadriacutecula similar con cuatro filas ycuatro columnas

Creacuteditos Este ejercicio se basa en un ejercicio en Oualline Practical CProgramming Third Edition OrsquoReilly Media 1997

OBSERVACIOacuteN

Para imprimir maacutes de un valor por liacutenea se puedeimprimir una secuencia de valores separados por comas

println (+ -)

La funcioacuten print no avanza a la siguiente liacutenea

print(+)println(-)

El resultado de estas sentencias es + - en la mismaliacutenea El resultado de una siguiente sentencia deimpresioacuten comenzariacutea en la siguiente liacutenea

Ejercicios 41

Capiacutetulo 4 Estudio de Caso Disentildeo de InterfazEste capiacutetulo presenta un segundo estudio de caso que muestra el proceso dedisentildear funciones que trabajen en conjunto

Se presentan graacuteficos turtle que es una forma de crear dibujos a traveacutes de laprogramacioacuten Los graacuteficos turtle no estaacuten incluidos en la Biblioteca Estaacutendarpor lo que se debe agregar el moacutedulo IntroAJulia a su configuracioacuten de Julia

Los ejemplos de este capiacutetulo se pueden ejecutar en un notebook graacutefico enJuliaBox el cual combina coacutedigo texto formateado matemaacuteticas y multimedia enun solo documento (vea Apeacutendice B)

TurtlesUn modulo es un archivo que contiene una coleccioacuten de funciones relacionadasJulia proporciona algunos moacutedulos en su Biblioteca Estaacutendar Ademaacutes es posibleagregar maacutes funciones a una gran cantidad de paquetes(httpsjuliaobservercom)

Los paquetes se pueden instalar en REPL ingresando al modo Pkg REPL con latecla ]

(v12) pkggt add httpsgithubcomJuliaIntroIntroAJuliajl

Esto puede demorar un poco

Antes de que podamos usar las funciones de un moacutedulo tenemos que importarlocon una sentencia using

juliagt using IntroAJulia

juliagt ὂ = Turtle()LuxorTurtle(00 00 true 00 (00 00 00))

El moacutedulo IntroAJulia proporciona una funcioacuten llamada Turtle (tortuga enespantildeol) que crea un objeto LuxorTurtle el cual es asignado a una variablellamada ὂ (turtle TAB)

Una vez que crea una tortuga puede llamar a una funcioacuten para moverla y asiacutehacer un dibujo con ella Por ejemplo para mover la tortuga hacia adelante(forward en ingleacutes)

42 Capiacutetulo 4 Estudio de Caso Disentildeo de Interfaz

svg begin forward(ὂ 100)end

Figura 3 Haciendo avanzar a la tortuga

La palabra reservada svg ejecuta una macro que dibuja una imagen SVG Lasmacros son una caracteriacutestica importante pero avanzada de Julia

Los argumentos de forward son la tortuga y una distancia en piacutexeles por lo queel tamantildeo real depende de su pantalla

Tambieacuten es posible hacer girar a la tortuga con la funcioacuten turn Los argumentosde esta funcioacuten son la tortuga y un aacutengulo en grados

Ademaacutes cada tortuga estaacute sosteniendo un laacutepiz que puede estar hacia arriba ohacia abajo si el laacutepiz estaacute hacia abajo la tortuga deja un rastro cuando semueve Figura 3 muestra el rastro dejado por la tortuga Las funciones penup ypendown significan laacutepiz hacia arriba y laacutepiz hacia abajo

Para dibujar un aacutengulo recto modifique la llamada a la macro

ὂ = Turtle()svg begin forward(ὂ 100) turn(ὂ -90) forward(ὂ 100)end

Ejercicio 4-1

Ahora modifique la macro para que dibuje un cuadrado iexclNo sigas hasta haberloterminado

Repeticioacuten Simple

Es probable que haya escrito algo como esto

Repeticioacuten Simple 43

ὂ = Turtle()svg begin forward(ὂ 100) turn(ὂ -90) forward(ὂ 100) turn(ὂ -90) forward(ὂ 100) turn(ὂ -90) forward(ὂ 100)end

Se puede hacer lo mismo de manera maacutes concisa con una sentencia for

juliagt for i in 14 println(iexclHola) endiexclHolaiexclHolaiexclHolaiexclHola

Este es el uso maacutes simple de la sentencia for aunque se veraacuten maacutes usos despueacutesEacutesto deberiacutea ser suficiente para reescribir su programa que dibuja un cuadradoNo continuacutee hasta que lo haga

Aquiacute hay una sentencia for que dibuja un cuadrado

ὂ = Turtle()svg begin for i in 14 forward(ὂ 100) turn(ὂ -90) endend

La sintaxis de una sentencia for es similar a la definicioacuten de una funcioacuten Tieneun encabezado y un cuerpo que termina con la palabra reservada end El cuerpopuede contener el nuacutemero de sentencias que desee

Una sentencia for tambieacuten es llamada bucle porque el flujo de ejecucioacuten recorreel cuerpo y luego vuelve a la parte superior En este caso ejecuta el cuerpocuatro veces

Esta versioacuten es en realidad un poco diferente del coacutedigo anterior que dibujaba uncuadrado porque hace otro giro despueacutes de dibujar el uacuteltimo lado del cuadradoEl giro adicional lleva maacutes tiempo pero simplifica el coacutedigo si se hace lo mismo

44 Capiacutetulo 4 Estudio de Caso Disentildeo de Interfaz

en cada iteracioacuten del ciclo Esta versioacuten tambieacuten tiene el efecto de dejar a latortuga nuevamente en la posicioacuten inicial mirando hacia la direccioacuten inicial

EjerciciosLos siguientes ejercicios usan tortugas Son divertidos pero tambieacuten tienen untrasfondo Mientras trabaja en ellos piense cuaacutel es ese trasfondo

OBSERVACIOacuteNLas siguientes secciones muestran las soluciones paraestos ejercicios asiacute que no mire hasta que hayaterminado (o al menos lo haya intentado)

Ejercicio 4-2

Escriba una funcioacuten llamada cuadrado que tome como paraacutemetro a un turtle tDeberiacutea usar este turtle para dibujar un cuadrado

Ejercicio 4-3

Escriba una llamada a funcioacuten que pase t como argumento a cuadrado y luegovuelva a ejecutar la macro

Ejercicio 4-4

Agregue otro paraacutemetro llamado lon a cuadrado Modifique el cuerpo para quela longitud de los lados sea lon y luego modifique la llamada a funcioacutenagregando este segundo argumento Ejecute la macro nuevamente Pruebe conun rango de valores para lon

Ejercicio 4-5

Haga una copia de cuadrado y cambie su nombre a poliacutegono Agregue otroparaacutemetro llamado n y modifique el cuerpo para que dibuje un poliacutegono regularde -lados

OBSERVACIOacuteN Los aacutengulos exteriores de un poliacutegono regular de -ladosson grados

Ejercicio 4-6

Escriba una funcioacuten llamada ciacuterculo que tome un turtle t y un radio r comoparaacutemetros y que dibuje un ciacuterculo aproximado llamando a poliacutegono con unalongitud y nuacutemero de lados apropiados Pruebe su funcioacuten con un rango devalores de r

Ejercicios 45

OBSERVACIOacuteN Calcule la circunferencia del ciacuterculo y aseguacuterese de quelen n == circunferencia

Ejercicio 4-7

Haga una versioacuten maacutes general de circulo llamada arco que tome un paraacutemetroadicional angulo y que determine queacute fraccioacuten de un ciacuterculo dibujar angulo estaacuteen grados entonces cuando angulo= 360 arco deberiacutea dibujar un ciacuterculocompleto

EncapsulacioacutenEl primer ejercicio le pide que coloque el coacutedigo que permite dibujar uncuadrado en una definicioacuten de funcioacuten y que luego llame a la funcioacuten pasando aturtle como paraacutemetro Aquiacute hay una solucioacuten

function cuadrado(t) for i in 14 forward(t 100) turn(t -90) endendὂ = Turtle()svg begin cuadrado(ὂ)end

Las sentencias maacutes internas forward y turn tienen doble sangriacutea para mostrarque estaacuten dentro del bucle for que a su vez estaacute dentro de la definicioacuten defuncioacuten

Dentro de la funcioacuten t se refiere a la misma tortuga ὂ entonces turn(t -90)tiene el mismo efecto que turn(ὂ -90) En ese caso iquestpor queacute no llamar alparaacutemetro ὂ La razoacuten es que t puede ser cualquier tortuga no solo ὂ por loque podriacuteamos crear una segunda tortuga y pasarla como argumento a cuadrado

ὂ = Turtle()svg begin cuadrado(ὂ)end

Colocar una porcioacuten de coacutedigo en una funcioacuten se denomina encapsulacioacuten Unode los beneficios de la encapsulacioacuten es que al ponerle un nombre al coacutedigo estosirve como una especie de documentacioacuten Otra ventaja es que si reutiliza elcoacutedigo iexcles maacutes conciso llamar a una funcioacuten dos veces que copiar y pegar el

46 Capiacutetulo 4 Estudio de Caso Disentildeo de Interfaz

cuerpo

GeneralizacioacutenEl siguiente paso es agregar un paraacutemetro lon a cuadrado Aquiacute hay unasolucioacuten

function cuadrado(t lon) for i in 14 forward(t lon) turn(t -90) endendὂ = Turtle()svg begin cuadrado(ὂ 100)end

Agregar un paraacutemetro a una funcioacuten se llama generalizacioacuten porque hace que lafuncioacuten sea maacutes general en la versioacuten anterior el cuadrado siempre teniacutea elmismo tamantildeo en esta versioacuten puede ser de cualquier tamantildeo

El siguiente paso tambieacuten es una generalizacioacuten En vez de dibujar cuadradospoligono dibuja poliacutegonos regulares con cualquier nuacutemero de lados Aquiacute hay unasolucioacuten

function poligono(t n lon) angulo = 360 n for i in 1n forward(t lon) turn(t -angulo) endendὂ = Turtle()svg begin poligono(ὂ 7 70)end

Este ejemplo dibuja un poliacutegono de 7 lados con una longitud de 70 por lado

Disentildeo de InterfazEl siguiente paso es escribir circulo que toma un radio r como paraacutemetro Aquiacutehay una solucioacuten simple que usa poligono para dibujar un poliacutegono de 50 lados

Generalizacioacuten 47

function circulo(t r) circunferencia = 2 π r n = 50 lon = circunferencia n poligono(t n lon)end

La primera liacutenea calcula la circunferencia de un ciacuterculo con radio usando lafoacutermula n es el nuacutemero de segmentos de liacutenea de nuestra aproximacioacuten a unciacuterculo y lon es la longitud de cada segmento Por lo tanto poliacutegono dibuja unpoliacutegono de 50 lados que se aproxima a un ciacuterculo de radio r

Una limitante de esta solucioacuten es que n es constante lo que significa que paraciacuterculos muy grandes los segmentos de liacutenea son demasiado largos y paraciacuterculos pequentildeos perdemos tiempo dibujando segmentos muy pequentildeos Unasolucioacuten seriacutea generalizar la funcioacuten tomando n como paraacutemetro Esto le dariacutea alusuario (quien llama a ciacuterculo) maacutes control pero la interfaz seriacutea menos pulcra

La interfaz de una funcioacuten es un resumen de coacutemo se usa iquestcuaacuteles son losparaacutemetros iquestQueacute hace la funcioacuten iquestY cuaacutel es el valor de retorno Una interfazes pulcra si le permite al usuario que la llama hacer lo que quiera sin tener quelidiar con detalles innecesarios

En este ejemplo r pertenece a la interfaz porque especifica el ciacuterculo a dibujar nes menos apropiado porque se refiere a los detalles de coacutemo se debe representarel ciacuterculo

En lugar de saturar la interfaz es mejor elegir un valor apropiado de ndependiendo de la circunferencia

function circulo(t r) circunferencia = 2 π r n = trunc(circunferencia 3) + 3 lon = circunferencia n poligono(t n lon)end

Ahora el nuacutemero de segmentos es un nuacutemero entero cercano a circunferencia3por lo que la longitud de cada segmento es aproximadamente 3 que es losuficientemente pequentildeo como para que los ciacuterculos se vean bien pero losuficientemente grandes como para ser eficientes y aceptables para cualquierciacuterculo

Agregar 3 a n garantiza que el poliacutegono tenga al menos 3 lados

48 Capiacutetulo 4 Estudio de Caso Disentildeo de Interfaz

RefactorizacioacutenCuando se escribioacute circulo se pudo reutilizar poligono ya que un poliacutegono demuchos lados es una buena aproximacioacuten de un ciacuterculo Pero arco no es tanversaacutetil no se puede usar poligono o circulo para dibujar un arco

Una alternativa es comenzar con una copia de poligono y transformarla en arcoEl resultado podriacutea verse asiacute

function arco(t r angulo) arco_lon = 2 π r angulo 360 n = trunc(arco_lon 3) + 1 paso_lon = arco_lon n paso_angulo = angulo n for i in 1n forward(t paso_lon) turn(t -paso_angulo) endend

La segunda mitad de esta funcioacuten se parece a poligono pero no se puedereutilizar poligono sin cambiar la interfaz Se podriacutea generalizar poligono paratomar un angulo como tercer argumento iexclpero entonces poligono ya no seriacutea unnombre apropiado En su lugar se puede llamar a esta funcioacuten maacutes generalpolilinea

function polilinea(t n lon angulo) for i in 1n forward(t lon) turn(t -angulo) endend

Ahora se puede reescribir poligono y arco usando polilinea

Refactorizacioacuten 49

function poligono(t n lon) angulo = 360 n polilinea(t n lon angulo)end

function arco(t r angulo) arco_lon = 2 π r angulo 360 n = trunc(arco_lon 3) + 1 paso_lon = arco_lon n paso_angulo = angulo n polilinea(t n paso_lon paso_angulo)end

Finalmente se puede reescribir circulo usando arco

function circulo(t r) arco(t r 360)end

Este proceso que reorganiza un programa para mejorar las interfaces y facilitarla reutilizacioacuten del coacutedigo se denomina refactorizacioacuten En este caso se observaque habiacutea un coacutedigo similar en arco y poligono por lo que lo factorizamos enpolilinea

Si se hubiese planeado con anticipacioacuten se podriacutea haber escrito polilineaprimero y haber evitado la refactorizacioacuten pero a menudo no se sabe losuficiente al comienzo de un proyecto para disentildear todas las interfaces Una vezque se comienza a programar se comprende mejor el problema A vecesrefactorizar es una sentildeal de que se ha aprendido algo

Un Plan de DesarrolloUn plan de desarrollo de programa es un proceso para escribir programas Elproceso que se utiliza en este estudio de caso es encapsulacioacuten ygeneralizacioacuten Los pasos de este proceso son

1 Comience escribiendo un pequentildeo programa sin definiciones de funciones

2 Una vez que el programa funcione identifique una porcioacuten de coacutedigo quetenga un objetivo especiacutefico encapsule esta porcioacuten en una funcioacuten yasiacutegnele un nombre

3 Generalice la funcioacuten agregando los paraacutemetros apropiados

4 Repita los pasos 1ndash3 hasta que tenga un conjunto de funciones De serposible copie y pegue coacutedigo para evitar volver a escribir (y volver adepurar)

50 Capiacutetulo 4 Estudio de Caso Disentildeo de Interfaz

5 Busque oportunidades para mejorar el programa refactorizando Porejemplo si tiene un coacutedigo similar en varios lugares considere factorizarloen una funcioacuten general apropiada

Este proceso tiene algunos inconvenientes se exploraraacuten alternativas maacutesadelante pero puede ser uacutetil si no sabe de antemano coacutemo dividir el programaen funciones Este enfoque permite disentildear conforme se avanza

DocstringUn docstring es una cadena que va antes de una funcioacuten y que explica la interfaz(doc es la abreviatura de documentacioacuten) Aquiacute hay un ejemplo

polilinea(t n lon angulo)

Dibuja n segmentos de liacutenea de la longitud dada y conaacutengulo entre ellos (en grados) dado t es una tortugafunction polilinea(t n lon angulo) for i in 1n forward(t lon) turn(t -angulo) endend

Se puede acceder a la documentacioacuten en REPL o en un notebook escribiendo seguido del nombre de una funcioacuten o macro y presionando ENTER

helpgt polilineasearch

polilinea(t n lon angulo)

Dibuja n segmentos de liacutenea de la longitud dada y con aacutengulo entre ellos(en grados) dado t es una tortuga

Los docstring generalmente son cadenas de comillas triples tambieacuten conocidascomo cadenas de liacuteneas muacuteltiples ya que las comillas triples permiten que lacadena abarque maacutes de una liacutenea

Un docstring contiene la informacioacuten esencial que alguien necesitariacutea para usaresta funcioacuten Explica de manera concisa lo que hace la funcioacuten (sin entrar endetalles sobre coacutemo lo hace) Explica queacute efecto tiene cada paraacutemetro en elcomportamiento de la funcioacuten y de queacute tipo debe ser cada paraacutemetro (si no esobvio)

Docstring 51

OBSERVACIOacuteN

Escribir este tipo de documentacioacuten es una parteimportante del disentildeo de la interfaz Una interfaz biendisentildeada debe ser simple de explicar si tienedificultades para explicar una de sus funciones tal vez lainterfaz podriacutea mejorarse

DepuracioacutenUna interfaz es como un contrato entre una funcioacuten y el usuario El usuarioacepta proporcionar ciertos paraacutemetros y la funcioacuten acepta hacer cierto trabajo

Por ejemplo polilinea requiere cuatro argumentos t tiene que ser una tortuga ntiene que ser un nuacutemero entero lon deberiacutea ser un nuacutemero positivo y angulotiene que ser un nuacutemero en grados

Estos requisitos se llaman precondiciones porque se supone que son verdaderosantes de que la funcioacuten comience a ejecutarse Por el contrario las condicionesal final de la funcioacuten son postcondiciones Las postcondiciones incluyen el efectodeseado de la funcioacuten (como dibujar segmentos de liacutenea) y cualquier efectosecundario (como mover la tortuga o hacer otros cambios)

Las condiciones previas son responsabilidad del usuario Si el usuario viola unaprecondicioacuten (iexcldebidamente documentada) y la funcioacuten no funcionacorrectamente el error estaacute en el usuario no en la funcioacuten

Si se cumplen las precondiciones pero no las postcondiciones el error estaacute en lafuncioacuten Si sus pre y postcondiciones son claras pueden ayudar con ladepuracioacuten

Glosariomodulo

Un archivo que contiene una coleccioacuten de funciones relacionadas y otrasdefiniciones

paqueteUna biblioteca externa con maacutes funcionalidades

sentencia usingUna sentencia que lee un archivo de moacutedulo y crea un objeto de moacutedulo

bucleUna parte de un programa que puede ejecutarse repetidamente

52 Capiacutetulo 4 Estudio de Caso Disentildeo de Interfaz

encapsulacioacutenEl proceso de transformar una secuencia de sentencias en una definicioacuten defuncioacuten

generalizacioacutenEl proceso de reemplazar algo innecesariamente especiacutefico (como unnuacutemero) con algo maacutes general (como una variable o paraacutemetro)

interfazUna descripcioacuten de coacutemo usar una funcioacuten incluido el nombre y lasdescripciones de los argumentos y el valor de retorno

refactorizacioacutenEl proceso de modificar un programa para mejorar las interfaces de lasfunciones y otras cualidades del coacutedigo

plan de desarrollo de programaUn proceso para escribir programas

docstringUna cadena que aparece en la parte superior de una definicioacuten de funcioacutenpara documentar la interfaz de la funcioacuten

precondicioacutenUn requisito que debe cumplir el usuario antes de que comience unafuncioacuten

postcondicioacutenUn requisito que debe cumplir la funcioacuten antes de que finalice

Ejercicios

Ejercicio 4-8

Copie y pegue el coacutedigo de este capiacutetulo en un notebook

1 Dibuje un diagrama de pila que muestre el estado del programa mientrasejecuta circulo(ὂ radio) Puede hacer la aritmeacutetica a mano o agregarsentencias de impresioacuten al coacutedigo

2 La versioacuten de arco en Seccioacuten 47 no es muy precisa ya que la aproximacioacutenlineal del ciacuterculo siempre queda por afuera del ciacuterculo verdadero Comoresultado la tortuga termina a unos pocos piacutexeles del destino correcto Lasiguiente solucioacuten muestra una forma de reducir el efecto de este error Leael coacutedigo y vea si tiene sentido Si dibuja un diagrama es posible queentienda mejor coacutemo funciona

Ejercicios 53

arco(t r angulo)

Dibuja un arco con el radio y el aacutengulo dados

t tortuga r radio angulo aacutengulo subtendido por el arco en gradosfunction arco(t r angulo) arco_lon = 2 π r abs(angulo) 360 n = trunc(arco_lon 4) + 3 paso_lon = arco_lon n paso_angulo = angulo n

haciendo un ligero giro a la izquierda antes de comenzar se reduce el error causado por la aproximacioacuten lineal del arco turn(t -paso_angulo2) polilinea(t n paso_lon paso_angulo) turn(t paso_angulo2)end

Ejercicio 4-9

Escriba un conjunto de funciones generales que permitan dibujar flores como enFigura 4

Figura 4 Flores con Turtle

Ejercicio 4-10

Escriba un conjunto de funciones generales que puedan dibujar formas como enFigura 5

Figura 5 Poliacutegonos con Turtle

54 Capiacutetulo 4 Estudio de Caso Disentildeo de Interfaz

Ejercicio 4-11

Las letras del alfabeto se pueden construir a partir de un nuacutemero pequentildeo deelementos baacutesicos como liacuteneas verticales y horizontales y algunas curvasDisentildee un alfabeto que se pueda dibujar con un nuacutemero miacutenimo de elementosbaacutesicos y luego escriba funciones que dibujen las letras

Deberiacutea escribir una funcioacuten para cada letra con nombres dibujar_a dibujar_betc y colocar sus funciones en un archivo llamado letrasjl

Ejercicio 4-12

Lea sobre espirales en httpseswikipediaorgwikiEspiral luego escriba unprograma que dibuje una espiral de Arquiacutemedes como en Figura 6

Figura 6 Espiral de Arquiacutemedes

Ejercicios 55

Capiacutetulo 5 Condicionales y recursividadEl tema principal de este capiacutetulo es la sentencia if la cual permite ejecutardiferentes acciones dependiendo del estado del programa Inicialmente sepresentan dos nuevos operadores divisioacuten entera y moacutedulo

Divisioacuten entera y MoacuteduloEl operador divisioacuten entera divide (div TAB) divide dos nuacutemeros y redondea haciaabajo el resultado Por ejemplo suponga que la duracioacuten de una peliacutecula es de105 minutos Es posible que desee saber la duracioacuten en horas La divisioacutenconvencional devuelve un nuacutemero de punto flotante

juliagt minutos = 105105juliagt minutos 60175

No obstante las horas no se suelen escribir con decimales La divisioacuten enteradevuelve el nuacutemero entero de horas redondeado hacia abajo

juliagt horas = minutos divide 601

Para obtener el resto de la divisioacuten se puede restar una hora (en minutos) a laduracioacuten total de la peliacutecula

juliagt resto = minutos - horas 6045

Otra alternativa es usar el operador moacutedulo que divide dos nuacutemeros ydevuelve el resto

juliagt resto = minutos 6045

OBSERVACIOacuteN

El operador moacutedulo es maacutes uacutetil de lo que parecePermite verificar por ejemplo si un nuacutemero es divisiblepor otro si xy es cero entonces x es divisible por y

Ademaacutes puede extraer el (o los) diacutegito(s) maacutes a laderecha de un nuacutemero Por ejemplo x10 devuelve eldiacutegito maacutes a la derecha de un entero x (en base 10) Delmismo modo x100 devuelve los dos uacuteltimos diacutegitos

56 Capiacutetulo 5 Condicionales y recursividad

Expresiones booleanasUna expresioacuten booleana es una expresioacuten que es verdadera o falsa Lossiguientes ejemplos usan el operador == que compara dos operandos ydevuelve el valor true (verdadero en espantildeol) si son iguales y el valor false(falso) de lo contrario

juliagt 5 == 5truejuliagt 5 == 6false

true y false son valores especiales que pertenecen al tipo Bool no son cadenas

juliagt typeof(true)Booljuliagt typeof(false)Bool

El operador == es un operador relacional El resto de operadores relacionalesson

x = y x no es igual a y x ne y (ne TAB) x gt y x es mayor que y x lt y x es menor que y x gt= y x es mayor o igual que y x ge y (ge TAB) x lt= y x es menor o igual que y x le y (le TAB)

AVISO

Aunque estas operaciones probablemente le sean familiares lossiacutembolos de Julia son diferentes de los siacutembolos matemaacuteticos Unerror comuacuten es usar un solo signo igual (=) en vez de un doblesigno igual (== Recuerde que = es un operador de asignacioacuten y== es un operador relacional No existe =lt o =gt

Operadores LoacutegicosHay tres operadores loacutegicos ampamp (y) || (o) y (no) La semaacutentica (significado) deestos operadores es similar a su significado en espantildeol Por ejemplo xgt0 ampampxlt10 es verdadero solo si x es mayor que 0 y menor que 10

n2==0 || n3 == 0 es verdadero si una o ambas condiciones son verdaderases decir si el nuacutemero es divisible por 2 o por 3

Expresiones booleanas 57

Tanto ampamp como || se asocian en primer lugar con el objeto a su derecha pero ampamptiene preferencia por sobre ||

Finalmente el operador niega una expresioacuten booleana entonces (xgty) esverdadero si xgty es falso es decir si x es menor o igual que y

Ejecucioacuten CondicionalPara escribir programas uacutetiles generalmente se necesita verificar condiciones ycambiar el comportamiento del programa acorde a ellas Las sentenciascondicionales permiten llevar esto a cabo La forma maacutes simple es la sentencia if(si en ingleacutes)

if x gt 0 println(x es positivo)end

La expresioacuten booleana despueacutes de if se llama condicioacuten Si es verdadera seejecuta la instruccioacuten con sangriacutea Si no nada ocurre

Las sentencias if tienen la misma estructura que las definiciones de funcioacuten unencabezado seguido del cuerpo terminado con la palabra reservada end (enespantildeol fin) Las sentencias como esta se denominan sentencias compuestas

No hay liacutemite en el nuacutemero de sentencias que pueden aparecer en el cuerpo Aveces es uacutetil tener un cuerpo sin sentencias (por lo general como un marcadorde posicioacuten para el coacutedigo que auacuten no se ha escrito)

if x lt 0 TODO se necesita realizar alguna accioacuten con los valores negativosend

Ejecucioacuten alternativaUna segunda forma de la sentencia if es la ejecucioacuten alternativa en la que haydos posibilidades y la condicioacuten determina cuaacutel se ejecuta La sintaxis se ve asiacute

if x 2 == 0 println(x es par)else println(x es impar)end

Si el resto de x dividido por 2 es 0 entonces x es par y el programa muestra unmensaje acorde Si la condicioacuten es falsa se ejecuta el segundo conjunto de

58 Capiacutetulo 5 Condicionales y recursividad

sentencias Como la condicioacuten debe ser verdadera o falsa se ejecutaraacuteexactamente una de las alternativas Las alternativas se llaman ramas porqueson ramas en el flujo de ejecucioacuten

Condicionales encadenadasA veces hay maacutes de dos posibilidades y se necesitan maacutes de dos ramas Unamanera de expresar este coacutemputo es a traveacutes de una condicional encadenada

if x lt y println(x es menor que y)elseif x gt y println(x es mayor que y)else println(x e y son iguales)end

De nuevo soacutelo se ejecutaraacute una rama No hay liacutemite al nuacutemero de sentenciaselseif Si hay una sentencia else debe estar al final (aunque no es necesario queesteacute)

if alternativa == a dibujar_a()elseif alternativa == b dibujar_b()elseif alternativa == c dibujar_c()end

Cada condicioacuten se comprueba en orden Si la primera es falsa se comprueba lasiguiente y asiacute se sigue con las demaacutes Si una de ellas es verdadera se ejecuta larama correspondiente y la sentencia se termina Si es verdadera maacutes de unacondicioacuten soacutelo se ejecuta la primera rama verdadera

Condicionales anidadasUna condicional puede estar anidada (nested en ingleacutes) dentro de otraPodriacuteamos haber escrito el ejemplo de la seccioacuten anterior de la siguiente manera

Condicionales encadenadas 59

if x == y println(x e y son iguales)else if x lt y println(x es menor a y) else println(x es mayor a y) endend

La condicional externa contiene dos ramas La primera rama contiene unasentencia simple La segunda rama contiene otra sentencia if que tiene dosramas propias Estas dos ramas son ambas sentencias simples aunque podriacuteanser sentencias condicionales

Aunque la sangriacutea no obligatoria de las sentencias hace evidente su estructuralas condicionales anidadas muy pronto se vuelven difiacuteciles de leer Se recomiendaevitarlas cuando pueda

Los operadores loacutegicos a menudo proporcionan una forma de simplificar lassentencias condicionales anidadas Por ejemplo es posible reescribir el siguientecoacutedigo usando un solo condicional

if 0 lt x if x lt 10 println(x es un nuacutemero positivo de un solo diacutegito) endend

La sentencia print soacutelo se ejecuta si conseguimos superar ambas condicionalesde modo que se puede obtener el mismo efecto con el operador ampamp

if 0 lt x ampamp x lt 10 println(x es un nuacutemero positivo de un solo diacutegito)end

Para este tipo de condicioacuten Julia proporciona una sintaxis maacutes concisa

if 0 lt x lt 10 println(x es un nuacutemero positivo de un solo diacutegito)end

60 Capiacutetulo 5 Condicionales y recursividad

RecursividadEstaacute permitido que una funcioacuten llame a otra y tambieacuten que una funcioacuten se llamea siacute misma Puede no parecer uacutetil pero siacute lo es como puede verse en la siguientefuncioacuten

function cuentaregresiva(n) if n le 0 println(Despegue) else print(n ) cuentaregresiva(n-1) endend

Si n es 0 o negativo muestra la palabra Despegue En otro caso muestra elvalor n y luego llama a la funcioacuten cuentaregresiva pasaacutendole n-1 comoargumento

iquestQueacute sucede si llamamos a una funcioacuten como esta

juliagt cuentaregresiva(3)3 2 1 Despegue

La ejecucioacuten de cuentaregresiva empieza con n = 3 y como n es mayor que 0muestra el valor 3 y luego se llama a siacute mismahellip

 La ejecucioacuten de cuentaregresiva empieza con n = 2 y como n es mayor que 0   muestra el valor 2 y luego se llama a siacute mismahellip

  La ejecucioacuten de cuentaregresiva empieza con n = 1 y como n es mayor que0    muestra el valor 1 y luego se llama a siacute mismahellip

   La ejecucioacuten de cuentaregresiva empieza con n = 0 y como n no es mayorque 0     muestra la palabra Despegue y luego termina

  La cuentaregresiva cuyo argumento es n = 1 termina

 La cuentaregresiva cuyo argumento es n = 2 termina

La cuentaregresiva cuyo argumento es n = 3 termina

Y volvemos a Main

Una funcioacuten que se llama a siacute misma es una funcioacuten recursiva y el proceso deejecucioacuten se llama recursividad

Recursividad 61

Como otro ejemplo se puede escribir una funcioacuten que imprima una cadena veces

function printn(s n) if n le 0 return end println(s) printn(s n-1)end

Si n lt= 0 se usa la sentencia return para salir de la funcioacuten El flujo de laejecucioacuten vuelve inmediatamente a la sentencia de llamada a funcioacuten y no seejecutan las liacuteneas restantes de la funcioacuten

El resto de la funcioacuten es similar a cuenta regresiva muestra s y luego se llama asiacute misma para mostrar s veces maacutes de modo que el nuacutemero de lineasmostradas es es decir

Para ejemplos simples como este es maacutes faacutecil usar un ciclo for Se mostraraacutenejemplos que son difiacuteciles de escribir con un ciclo for y faacuteciles de escribir conrecursividad

Diagramas de pila para funciones recursivasEn Seccioacuten 39 se usoacute un diagrama de pila para representar el estado de unprograma durante una llamada de funcioacuten El mismo tipo de diagrama puede serde utilidad para interpretar una funcioacuten recursiva

Cada vez que se llama a una funcioacuten Julia crea un marco que contiene lasvariables locales de la funcioacuten y los paraacutemetros En una funcioacuten recursiva puedehaber maacutes de un marco en el diagrama de pila al mismo tiempo

Figura 7 Diagrama de pila

Figura 7 muestra un diagrama de pila para cuentaregresiva utilizando n=3

Como siempre la parte superior de la pila es el marco para Main Estaacute vaciacuteopues no se crearon variables en Main ni tampoco se pasaron argumentos

62 Capiacutetulo 5 Condicionales y recursividad

Los cuatro marcos de cuentaregresiva tienen diferentes valores del paraacutemetro nLa parte inferior del diagrama de pila donde n = 0 es llamado caso base Nohace una llamada recursiva asiacute que no hay maacutes marcos

Ejercicio 5-1

Como ejercicio dibuje un diagrama de pila para printn llamada con s = Hola yn = 2 Luego escriba una funcioacuten llamada hacer_n que tome como argumentosuna funcioacuten y un nuacutemero n y que luego llame a la funcioacuten dada veces

Recursioacuten infinitaSi una recursioacuten nunca alcanza un caso base continuacutea haciendo llamadasrecursivas para siempre y el programa nunca termina Esto se conoce comorecursioacuten infinita y generalmente no es una buena idea Aquiacute hay un coacutedigo conuna recursioacuten infinita

function recursion() recursion()end

En la mayoriacutea de los entornos de programacioacuten un programa con recursioacuteninfinita realmente no se ejecuta para siempre Julia entrega un mensaje de errorcuando se alcanza la profundidad de recursioacuten maacutexima

juliagt recursion()ERROR StackOverflowErrorStacktrace [1] recursion() at REPL[1]2 (repeats 80000 times)

Este stacktrace es un poco maacutes grande que el que vimos en el capiacutetulo anteriorCuando se produce el error iexclhay 80000 marcos de recursion en el diagrama depila

Si por accidente encuentra una recursioacuten infinita en su coacutedigo revise su funcioacutenpara confirmar que hay un caso base que no realiza una llamada recursiva Sihay un caso base verifique si realmente puede ocurrir

Entrada por tecladoLos programas que se han escrito hasta ahora no aceptan entradas del usuarioSimplemente hacen lo mismo cada vez

Julia tiene una funcioacuten incorporada llamada readline que detiene el programa yespera a que el usuario escriba algo Cuando el usuario presiona RETURN oENTER el programa se reanuda y readline devuelve lo que el usuario escribioacute

Recursioacuten infinita 63

como una cadena

juliagt text = readline()iquestQueacute estaacute esperandoiquestQueacute estaacute esperando

Antes de recibir una entrada por teclado del usuario es una buena idea imprimirun mensaje que le diga al usuario queacute escribir

juliagt print(iquestCuaacutel es su nombre ) readline()iquestCuaacutel es su nombre iexclArturo Rey de los BretonesiexclArturo Rey de los Bretones

Un punto y coma permite colocar varias sentencias en la misma liacutenea En elREPL solo la uacuteltima sentencia devuelve su valor

Si espera que el usuario escriba un nuacutemero entero puede intentar convertir elvalor de retorno a Int64

juliagt println(iquestCuaacutentos dejaron su casa su tierra o su posesioacuten)numero = readline()iquestCuaacutentos dejaron su casa su tierra o su posesioacuten115115juliagt parse(Int64 numero)115

Pero si el usuario no escribe una cadena de diacutegitos obtendraacute un error

juliagt println(iquestCuaacutentos dejaron su casa su tierra o su posesioacuten)numero = readline()iquestCuaacutentos dejaron su casa su tierra o su posesioacutenMaacutes de ciento quince sonMaacutes de ciento quince sonjuliagt parse(Int64 speed)ERROR ArgumentError invalid base 10 digit M in Maacutes de ciento quinceson[]

Veremos queacute hacer con este tipo de error maacutes adelante

DepuracioacutenCuando se produce un error de sintaxis o de tiempo de ejecucioacuten el mensaje deerror contiene mucha informacioacuten lo cual puede ser abrumador Las partes maacutes

64 Capiacutetulo 5 Condicionales y recursividad

uacutetiles suelen ser

bull Queacute tipo de error fue

bull Doacutende ocurrioacute tal error

Los errores de sintaxis suelen ser faacuteciles de encontrar y hay algunos trucos Engeneral los mensajes de error indican doacutende se descubrioacute el problema pero elerror real podriacutea estar antes en el coacutedigo a veces en una liacutenea anterior

Lo mismo aplica para los errores de tiempo de ejecucioacuten Suponga que estaacutetratando de calcular una relacioacuten sentildealruido en decibelios La foacutermula es

En Julia se podriacutea escribir algo como esto

intensidad_sentildeal = 9intensidad_ruido = 10relacion = intensidad_sentildeal divide intensidad_ruidodecibeles = 10 log10(relacion)print(decibeles)

Obteniendo

-Inf

Este no es el resultado que esperaacutebamos

Para encontrar el error puede ser uacutetil imprimir el valor de la variable relacionque resulta ser 0 El problema estaacute en la liacutenea 3 que usa la divisioacuten entera enlugar de la divisioacuten de punto flotante

AVISOEl usuario debe tomarse el tiempo de leer los mensajes de errorcuidadosamente pero no se debe asumir que todo lo que dicen escorrecto

GlosarioDivisioacuten entera

Un operador denotado por divide que divide dos nuacutemeros y redondea haciaabajo (hacia el infinito negativo) a un entero

operador moacuteduloUn operador denotado con el signo de porcentaje () que se utiliza conenteros y devuelve el resto cuando un nuacutemero se divide por otro

Glosario 65

expresioacuten booleanaUna expresioacuten cuyo valor es verdadero o falso

operador relacionalUno de los operadores que compara sus operandos == ne (=) gt lt ge(gt=) and le (lt=)

operador loacutegicoUno de los operadores que combina expresiones booleanas ampamp (and) ||(or) and (not)

sentencia condicionalUna sentencia que controla el flujo de ejecucioacuten dependiendo de algunacondicioacuten

condicioacutenLa expresioacuten booleana en una sentencia condicional que determina queacuterama se ejecuta

sentencia compuestaUna sentencia que consta de un encabezado y un cuerpo El cuerpo terminacon la palabra reservada end

ramaUna de las secuencias alternativas de sentencias en una sentenciacondicional

condicional encadenadaUna sentencia condicional con una serie de ramas alternativas

condicional anidadaUna sentencia condicional que aparece en una de las ramas de otrasentencia condicional

sentencia returnUna sentencia que hace que una funcioacuten finalice de inmediato y que vuelvaa la sentencia de llamada a funcioacuten

recursividad o recursioacutenEl proceso de llamar a la funcioacuten que se estaacute ejecutando actualmente

caso baseUna rama condicional en una funcioacuten recursiva que no realiza una llamadarecursiva

66 Capiacutetulo 5 Condicionales y recursividad

recursioacuten infinitaUna recursioacuten que no tiene un caso base o que nunca llega a eacutelEventualmente una recursioacuten infinita provoca un error de tiempo deejecucioacuten

Ejercicios

Ejercicio 5-2

La funcioacuten time devuelve el tiempo medio de Greenwich actual en segundosdesde la eacutepoca que es un tiempo arbitrario utilizado como punto de referenciaEn sistemas UNIX la eacutepoca es el 1 de enero de 1970

juliagt time()1603600382165353e9

Escriba un script que lea la hora actual y la convierta a una hora del diacutea enhoras minutos y segundos maacutes el nuacutemero de diacuteas transcurridos desde la eacutepoca

Ejercicio 5-3

El uacuteltimo teorema de Fermat dice que no hay enteros positivos and tal que

para cualquier valor de mayor que 2

1 Escriba una funcioacuten llamada verificarfermat que tome cuatroparaacutemetrosmdasha b c y nmdash y que verifique si el teorema de Fermat es vaacutelidoSi n es mayor que 2 y a^n + b^n == c^n el programa deberiacutea imprimiriexclSanto cielo Fermat estaba equivocado De lo contrario el programadeberiacutea imprimir No eso no funciona

2 Escriba una funcioacuten que solicite al usuario ingresar valores para a b c y nque los convierta en enteros y que use verificarfermat para verificar siviolan el teorema de Fermat

Ejercicio 5-4

Si tiene tres barras estas podriacutean o no formar un triaacutengulo Por ejemplo si unade las barras tiene 12 centiacutemetros de largo y las otras dos tienen un centiacutemetrode largo no es posible que las barras pequentildeas puedan juntarse al medio Paracualquier triacuteo de longitudes hay una prueba simple para ver si es posible formarun triaacutengulo

Ejercicios 67

OBSERVACIOacuteN

Si cualquiera de las tres longitudes es mayor que lasuma de las otras dos entonces no se puede formar untriaacutengulo De lo contrario se puede (Si la suma de doslongitudes es igual a la tercera forman lo que se llamaun triaacutengulo degenerado)

1 Escriba una funcioacuten llamada estriangulo que tome tres enteros comoargumentos y que imprima ldquoSiacuterdquo o ldquoNordquo dependiendo de si se puede o noformar un triaacutengulo a partir de barras de las longitudes dadas

2 Escriba una funcioacuten que solicite al usuario ingresar tres longitudes debarras las convierta en enteros y use estriangulo para verificar si las barrascon las longitudes dadas pueden formar un triaacutengulo

Ejercicio 5-5

iquestCuaacutel es el resultado del siguiente programa Dibuje un diagrama de pila quemuestre el estado del programa cuando imprima el resultado

function recursion(n s) if n == 0 println(s) else recursion(n-1 n+s) endend

recursion(3 0)

1 iquestQueacute pasariacutea si se llamara a esta funcioacuten asiacute recursion(-1 0)

2 Escriba un documento que explique todo lo que alguien necesitariacutea saberpara usar esta funcioacuten (y nada maacutes)

Los siguientes ejercicios utilizan el moacutedulo IntroAJulia descrito en Capiacutetulo 4

Ejercicio 5-6

Lea la siguiente funcioacuten y vea si puede averiguar queacute hace (vea los ejemplos enCapiacutetulo 4) Luego ejecuacutetelo y vea si lo hizo bien

68 Capiacutetulo 5 Condicionales y recursividad

function dibujar(t distancia n) if n == 0 return end angulo = 50 adelante(t distancian) girar(t -angulo) dibujar(t distancia n-1) girar(t 2angulo) dibujar(t distancia n-1) girar(t -angulo) adelante(t -distancian)end

Ejercicio 5-7

Figura 8 Una curva de Koch

La curva de Koch es un fractal que luce como Figura 8 Para dibujar una curva deKoch con longitud todo lo que tiene que hacer es

1 Dibuje una curva de Koch con longitud

2 Gire a la izquierda 60 grados

3 Dibuje una curva de Koch con longitud

4 Gire a la derecha 120 grados

5 Dibuje una curva de Koch con longitud

6 Gire a la izquierda 60 grados

7 Dibuje una curva de Koch con longitud

La excepcioacuten es cuando es menor que 3 en ese caso puede dibujar una liacutenearecta con una longitud

1 Escribe una funcioacuten llamada koch que tome una tortuga y una longitudcomo paraacutemetros y que use la tortuga para dibujar una curva de Koch con lalongitud dada

2 Escriba una funcioacuten llamada copodenieve que dibuje tres curvas de Kochpara hacer el contorno de un copo de nieve

3 La curva de Koch se puede generalizar de varias maneras ConsultehttpsenwikipediaorgwikiKoch_snowflake para ver ejemplos eimplementar su favorito

Ejercicios 69

Capiacutetulo 6 Funciones productivasMuchas de las funciones de Julia que se han utilizado como las funcionesmatemaacuteticas producen valores de retorno Todas las funciones que se hanescrito hasta ahora son nulas es decir tienen un efecto (como imprimir un valor)pero devuelven el valor nothing En este capiacutetulo se ensentildea a escribir funcionesproductivas

Valores de retornoLlamar a una funcioacuten genera un valor de retorno que generalmente se asigna auna variable o se usa como parte de una expresioacuten

e = exp(10)altura = radio sin(radio)

Las funciones que se han escrito hasta ahora son nulas Coloquialmentehablando no tienen valor de retorno de manera formal su valor de retorno esnothing En este capiacutetulo (finalmente) se van a escribir funciones productivas Elprimer ejemplo es area que devuelve el aacuterea de un ciacuterculo dado un radio

function area(radio) a = π radio^2 return aend

Se ha visto la sentencia return antes pero en una funcioacuten productiva la sentenciareturn incluye una expresioacuten Esta sentencia significa Retorne inmediatamentede esta funcioacuten y use la siguiente expresioacuten como valor de retorno La expresioacutendada puede ser arbitrariamente complicada Asiacute pues se podriacutea haber escritoesta funcioacuten maacutes concisamente

function area(radio) π radio^2end

El valor devuelto por una funcioacuten es el valor de la uacuteltima expresioacuten evaluadaque por defecto es la uacuteltima expresioacuten en el cuerpo de la definicioacuten de lafuncioacuten

Por otro lado las variables temporales como a y las sentencias return expliacutecitaspueden facilitar la depuracioacuten

A veces es uacutetil tener muacuteltiples sentencias return una en cada rama de unasentencia condicional

70 Capiacutetulo 6 Funciones productivas

function valorabsoluto(x) if x lt 0 return -x else return x endend

Dado que estas sentencias return estaacuten en una condicional alternativa solo seejecuta una

En cuanto se ejecuta una sentencia return la funcioacuten termina sin ejecutarninguna de las sentencias siguientes El coacutedigo que aparece despueacutes de lasentencia return o en cualquier otro lugar al que el flujo de ejecucioacuten nuncallegaraacute se llama coacutedigo muerto

En una funcioacuten productiva es una buena idea asegurarse que cualquier posiblerecorrido del programa llegue a una sentencia return Por ejemplo

function valorabsoluto(x) if x lt 0 return -x end if x gt 0 return x endend

Esta versioacuten no es correcta porque si x es igual a 0 ninguna de las condicioneses verdadera y la funcioacuten termina sin alcanzar una sentencia return Si el flujo deejecucioacuten llega al final de la funcioacuten el valor de retorno es nothing queclaramente no es el valor absoluto de 0

juliagt show(valorabsoluto(0))nothing

OBSERVACIOacuteN Julia tiene una funcioacuten incorporada llamada abs quecalcula los valores absolutos

Ejercicio 6-1

Escriba la funcioacuten comparar que tome dos valores x y y y que devuelva 1 si x gty 0 si x == y y -1 si x lt y

Valores de retorno 71

Desarrollo incrementalConforme vaya escribiendo funciones maacutes extensas puede empezar a dedicarmaacutes tiempo a la depuracioacuten

Para lidiar con programas de complejidad creciente se sugiere una teacutecnicallamada desarrollo incremental El objetivo del desarrollo incremental es evitarlargas sesiones de depuracioacuten antildeadiendo y probando solamente pequentildeasporciones de coacutedigo cada vez

Por ejemplo suponga que desea encontrar la distancia entre dos puntos dadospor las coordenadas y Por el teorema de Pitaacutegoras la distancia es

El primer paso es considerar queacute aspecto tendriacutea la funcioacuten distancia en Julia Enotras palabras iquestcuaacuteles son las entradas (paraacutemetros) y cuaacutel es la salida (valor deretorno)

En este caso las entradas son los dos puntos que se pueden representar usandocuatro nuacutemeros El valor devuelto es la distancia que es un nuacutemero de puntoflotante

He aquiacute una primera versioacuten de la funcioacuten

function distancia(x₁ y₁ x₂ y₂) 00end

Obviamente esta versioacuten de la funcioacuten no calcula distancias sino que siempredevuelve cero Aun asiacute es correcta sintaacutecticamente hablando y se ejecutaraacute loque implica que se puede probar antes de hacerla maacutes compleja Los nuacutemeros desubiacutendice estaacuten disponibles en la codificacioacuten de caracteres Unicode (_1 TAB_2 TAB etc)

Para probar la nueva funcioacuten se llama con una muestra de valores

distance(1 2 4 6)

Se eligen estos valores de tal forma que la distancia horizontal sea igual a 3 y ladistancia vertical sea igual a 4 y de esa manera el resultado es 5 (la hipotenusadel triaacutengulo 3-4-5) Cuando se comprueba una funcioacuten es uacutetil conocer larespuesta correcta

Hasta el momento se ha podido confirmar que la funcioacuten es sintaacutecticamentecorrecta por lo que se puede empezar a agregar liacuteneas de coacutedigo El paso loacutegico

72 Capiacutetulo 6 Funciones productivas

siguiente es encontrar las diferencias y En la siguiente versioacuten de lafuncioacuten se almacenaraacuten estos valores en variables temporales y se mostraraacuten conel macro show

function distancia(x₁ y₁ x₂ y₂) dx = x₂ - x₁ dy = y₂ - y₁ show dx dy 00end

Si la funcioacuten trabaja bien las salidas deben ser dx = 3 y dy = 4 Si es asiacute se sabeque la funcioacuten estaacute obteniendo los paraacutemetros correctos y realizando el primercaacutelculo correctamente Si no entonces soacutelo hay unas pocas liacuteneas que revisar

A continuacioacuten se calcula la suma de los cuadrados de dx y dy

function distancia(x₁ y₁ x₂ y₂) dx = x₂ - x₁ dy = y₂ - y₁ dsup2 = dx^2 + dy^2 show dsup2 00end

De nuevo se quiere ejecutar el programa en esta etapa y comprobar la salida(que deberiacutea ser 25) Los nuacutemeros en superiacutendice tambieacuten estaacuten disponibles (^2TAB) Finalmente se puede usar sqrt para calcular y devolver el resultado

function distancia(x₁ y₁ x₂ y₂) dx = x₂ - x₁ dy = y₂ - y₁ dsup2 = dx^2 + dy^2 sqrt(dsup2)end

Si esto funciona correctamente ya se habriacutea terminado Si no se podriacutea mostrarel valor de la variable resultado antes de la sentencia de retorno

La versioacuten final de la funcioacuten no muestra nada cuando se ejecuta soacutelo retorna unvalor Las sentencias print son uacutetiles para la depuracioacuten pero una vez que elprograma esteacute funcionando correctamente se deben eliminar El coacutedigoeliminado se llama andamiaje porque es uacutetil para construir el programa pero noes parte del producto final

Al principio deberiacutea antildeadir solamente una o dos liacuteneas de coacutedigo cada vez

Desarrollo incremental 73

Conforme vaya ganando experiencia puede que se encuentre escribiendo ydepurando fragmentos mayores de coacutedigo Sin embargo el proceso de desarrolloincremental puede ahorrarle mucho tiempo de depuracioacuten

Los aspectos clave del proceso son

1 Iniciar con un programa que funcione y hacerle pequentildeos cambiosincrementales En cualquier momento si hay un error sabraacute exactamentedoacutende estaacute

2 Usar variables temporales para guardar valores intermedios para que puedamostrarlos y verificarlos

3 Una vez que el programa esteacute funcionando tal vez prefiera eliminar partedel andamiaje o consolidar muacuteltiples sentencias en expresiones compuestaspero soacutelo si eso no hace que el programa sea difiacutecil de leer

Ejercicio 6-2

Use la teacutecnica de desarrollo incremental para escribir una funcioacuten llamadahipotenusa que retorne el largo de la hipotenusa de un triaacutengulo rectaacutengulo dadoel largo de las otras dos aristas Registre cada etapa del proceso de desarrollo

ComposicioacutenAhora como usted esperariacutea se puede llamar a una funcioacuten desde otra Comoejemplo se escribe una funcioacuten que tome dos puntos el centro del ciacuterculo y unpunto del periacutemetro y calcule el aacuterea del ciacuterculo

Suponga que el punto central estaacute almacenado en las variables xc y yc y que elpunto del periacutemetro lo estaacute en xp y yp El primer paso es hallar el radio delciacuterculo que es la distancia entre los dos puntos La funcioacuten distancia que realizaesta tarea seriacutea

radio = distancia(xc yc xp yp)

El siguiente paso es encontrar el aacuterea del ciacuterculo usando este radio De nuevo seusa una de las funciones definidas previamente

resultado = area(radio)

Envolviendo todo en una funcioacuten se obtiene

74 Capiacutetulo 6 Funciones productivas

function areacirculo(xc yc xp yp) radio = distancia(xc yc xp yp) resultado = area(radio) return resultadoend

Las variables temporales radio y resultado son uacutetiles para el desarrollo y ladepuracioacuten pero una vez que el programa estaacute funcionando se puede hacer maacutesconciso componiendo las llamadas a funcioacuten

function areacirculo(xc yc xp yp) area(distancia(xc yc xp yp))end

Funciones BooleanasLas funciones pueden devolver valores booleanos lo que a menudo esconveniente para ocultar complicadas comprobaciones dentro de funciones Porejemplo

function esdivisible(x y) if x y == 0 return true else return false endend

Es comuacuten dar a las funciones booleanas nombres que suenan como preguntasque tienen como respuesta un si oacute un no esdivisible devuelve true o false paraindicar si x es o no divisible por y

Por ejemplo

juliagt esdivisible(6 4)falsejuliagt esdivisible(6 3)true

El resultado del operador == es booleano por lo tanto se puede escribir lafuncioacuten de una manera maacutes concisa devolviendo el resultado directamente

Funciones Booleanas 75

function esdivisible(x y) x y == 0end

Las funciones booleanas se usan a menudo en las sentencias condicionales

if esdivisible(x y) println(x es divisible por y)end

Puede parecer tentador escribir algo como

if esdivisible(x y) == true println(x es divisible por y)end

pero la comparacioacuten extra con true es innecesaria

Ejercicio 6-3

Escriba la funcioacuten entremedio(xyz) que devuelva true si x le y le z o false enotro caso

Maacutes recursividadSolo se ha cubierto una pequentildea parte de Julia pero le puede interesar saber queesta parte ya es un lenguaje de programacioacuten completo lo que significa quecualquier coacutemputo puede expresarse en este lenguaje Cualquier programa quese haya escrito podriacutea reescribirse usando solo lo que ha aprendido hasta ahora(en realidad necesitariacutea algunos comandos para controlar dispositivos como elmouse discos etc pero eso es todo)

Probar esta afirmacioacuten es un ejercicio no trivial realizado por primera vez porAlan Turing uno de los primeros cientiacuteficos de la computacioacuten (algunosargumentariacutean que era matemaacutetico pero muchos de los primeros cientiacuteficosinformaacuteticos comenzaron como matemaacuteticos) En consecuencia esto se conocecomo la Tesis de Turing Para una discusioacuten maacutes completa (y precisa) de la Tesisde Turing se recomienda el libro de Michael Sipser Introduccioacuten a la Teoriacutea de laComputacioacuten

Para darle una idea de lo que puede hacer con las herramientas que haaprendido hasta ahora se evaluacutean algunas funciones matemaacuteticas definidasrecursivamente Una definicioacuten recursiva es similar a una definicioacuten circular enel sentido de que la definicioacuten contiene una referencia a lo que estaacute siendodefinido Una definicioacuten verdaderamente circular no es muy uacutetil

76 Capiacutetulo 6 Funciones productivas

vorpalUn adjetivo usado para describir algo que es vorpal

Si esta definicioacuten apareciese en el diccionario la persona que la leyera podriacuteamolestarse Por otro lado si se busca la definicioacuten de la funcioacuten factorialdenotada con el siacutembolo se encuentra encontrar algo como esto

Esta definicioacuten dice que el factorial de 0 es 1 y el factorial de cualquier otrovalor es multiplicado por el factorial de

Entonces es 3 veces que es 2 veces que es 1 vez Es decir es igual a3 por 2 por 1 por 1 que es 6

Si se puede escribir una definicioacuten recursiva se puede escribir un programa deJulia para evaluarlo El primer paso es decidir cuaacuteles deberiacutean ser losparaacutemetros En este caso debe quedar claro que factorial toma valores enteros

function fact(n) end

Si el argumento es 0 la funcioacuten debe devolver 1

function fact(n) if n == 0 return 1 endend

De lo contrario y esto es lo interesante se tiene que hacer una llamada recursivapara encontrar el factorial de n-1 y luego multiplicarlo por n

function fact(n) if n == 0 return 1 else recursion = fact(n-1) resultado = n recursion return resultado endend

El flujo de ejecucioacuten de este programa es similar al flujo de cuentaregresiva enSeccioacuten 58 Si llamamos a fact con el valor 3

Maacutes recursividad 77

Como 3 no es 0 se toma la segunda rama y se calcula el factorial de n-1 hellip

 Como 2 no es 0 se toma la segunda rama y se calcula el factorial de n-1 hellip

  Como 1 no es 0 se toma la segunda rama y se calcula el factorial de + n-1 +hellip

   Como 0 es igual a 0 se toma la primera rama y devuelve 1 sin realizar      maacutes llamadas recursivas

  El valor de retorno 1 se multiplica por n que es 1 y se devuelve elresultado

 El valor de retorno 1 se multiplica por n que es 2 y se devuelve el resultado

El valor de retorno 2 se multiplica por n que es 3 y el resultado 6 se convierteen el valor de retorno de la llamada a funcioacuten que inicioacute todo el proceso

Figura 9 Diagrama de pila

Figura 9 muestra coacutemo se ve el diagrama de pila para esta secuencia dellamadas a funciones

Los valores de retorno se pasan de nuevo a la pila En cada marco el valor deretorno es el valor de resultado que es el producto de n y recursion

En el uacuteltimo marco las variables locales recursion y resultado no existen porquela rama que las crea no se ejecuta

OBSERVACIOacuteN Julia tiene la funcioacuten factorial para calcular el factorialde un nuacutemero entero

Voto de confianzaSeguir el flujo de ejecucioacuten es una forma de leer programas pero puede llegar aser abrumador Una alternativa es lo que se conoce como el voto deconfianza(en ingleacutes leap of faith) Cuando llega a una llamada de funcioacuten enlugar de seguir el flujo de ejecucioacuten asume que la funcioacuten funcionacorrectamente y devuelve el resultado correcto

De hecho ya se estaacute dando este voto de confianza cuando se usan funciones

78 Capiacutetulo 6 Funciones productivas

integradas de Julia Cuando se llaman a cos o exp no se examinan los cuerpos deesas funciones Simplemente se asume que funcionan porque las personas quelas escribieron eran buenos programadores

Lo mismo ocurre cuando el usuario llama a una de sus propias funciones Porejemplo en Seccioacuten 64 se escribe una funcioacuten llamada esdivisible quedetermina si un nuacutemero es divisible por otro Una vez que se confirme que estafuncioacuten es correcta mdashal examinar y probar el coacutedigomdash se puede usar la funcioacutensin mirar nuevamente el cuerpo

Lo mismo aplica a los programas recursivos Cuando llegue a la llamadarecursiva en lugar de seguir el flujo de ejecucioacuten debe suponer que la llamadarecursiva funciona (devuelve el resultado correcto) y luego preguntarseSuponiendo que pueda encontrar el factorial de iquestse puede calcular elfactorial de Estaacute claro que es posible multiplicando por

Por supuesto es un poco extrantildeo suponer que la funcioacuten funciona correctamentecuando no ha terminado de escribirla iexclpero por eso se llama voto de confianza

Un Ejemplo MaacutesDespueacutes de los factoriales el ejemplo maacutes comuacuten de una funcioacuten matemaacuteticadefinida de manera recursiva es fibonacci que tiene la siguiente definicioacuten (verhttpsenwikipediaorgwikiFibonacci_number)

Traducido a Julia se ve asiacute

function fib(n) if n == 0 return 0 elseif n == 1 return 1 else return fib(n-1) + fib(n-2) endend

Si intenta seguir el flujo de ejecucioacuten en esta funcioacuten incluso para valoresbastante pequentildeos de n su cabeza podriacutea estallar Dando un voto de confianzaes decir asumiendo que las dos llamadas recursivas funcionan correctamenteentonces estaacute claro que se obtiene el resultado correcto al sumarlas

Un Ejemplo Maacutes 79

Tipos de Comprobacioacuten

iquestQueacute pasa si se llama a fact con 15 como argumento

juliagt fact(15)ERROR StackOverflowErrorStacktrace [1] fact(Float64) at REPL[3]2

Parece una recursioacuten infinita iquestComo es esto posible La funcioacuten tiene un casobase (cuando n == 0) Pero si n no es un nuacutemero entero es posible perderse elcaso base y hacer recursioacuten para siempre

En la primera llamada recursiva el valor de n es 05 En la siguiente es -05 Apartir de ahiacute se vuelve maacutes pequentildeo (maacutes negativo) pero nunca seraacute 0

Existen dos opciones Se puede intentar generalizar la funcioacuten factorial paratrabajar con nuacutemeros de punto flotante o se puede hacer que fact verifique eltipo del argumento La primera opcioacuten se llama funcioacuten gamma y estaacute un pocomaacutes allaacute del alcance de este libro En este libro se proseguiraacute con la segunda

Se puede usar el operador integrado isa para verificar el tipo de argumentoTambieacuten podemos asegurarnos de que el argumento sea positivo

function fact(n) if (n isa Int64) error(El factorial uacutenicamente estaacute definido para nuacutemerosenteros) elseif n lt 0 error(El factorial no estaacute definido para enteros negativos) elseif n == 0 return 1 else return n fact(n-1) endend

El primer caso base se hace cargo de nuacutemeros no enteros y el segundo deenteros negativos En ambos casos el programa imprime un mensaje de error ydevuelve nothing para indicar que algo salioacute mal

juliagt fact(fred)ERROR El factorial uacutenicamente estaacute definido para nuacutemeros enterosjuliagt fact(-2)ERROR El factorial no estaacute definido para enteros negativos

80 Capiacutetulo 6 Funciones productivas

Si se superan ambas verificaciones se sabe que n es positivo o cero por lo quees posible probar que la recursioacuten termina

Este programa muestra un patroacuten a veces llamado guardian Los dos primeroscondicionales actuacutean como guardianes protegiendo el coacutedigo que sigue de losvalores que pueden causar un error Los guardianes hacen posible demostrar queel coacutedigo es correcto

En Seccioacuten 145 se exploraraacute una alternativa maacutes flexible para imprimir unmensaje de error generar una excepcioacuten

DepuracioacutenDividir un coacutedigo extenso en pequentildeas funciones crea naturalmente puntos decontrol para la depuracioacuten Si un programa no estaacute funcionando existen tresposibilidades a considerar

bull Hay algo incorrecto en los argumentos de la funcioacuten se viola una condicioacutenprevia

bull Hay algo incorrecto en la funcioacuten se viola una condicioacuten posterior

bull Hay algo incorrecto en el valor de retorno o la forma en que se estaacuteutilizando

Para descartar la primera posibilidad puede agregar una sentencia de impresioacutenal comienzo de la funcioacuten para mostrar los valores de los paraacutemetros (y tal vezsus tipos) o bien escribir liacuteneas de coacutedigo que verifiquen las condiciones previasde manera expliacutecita

Si los paraacutemetros estaacuten bien agregue una sentencia de impresioacuten antes de cadasentencia return y muestre el valor de retorno Si es posible verifique elresultado a mano Considere tambieacuten llamar a la funcioacuten con valores quefaciliten la verificacioacuten del resultado (como en Seccioacuten 62)

Si la funcioacuten parece estar funcionando revise la llamada a la funcioacuten paraasegurarse de que el valor de retorno se estaacute utilizando correctamente (iexcloincluso si se estaacute utilizando)

Agregar sentencias de impresioacuten al principio y al final de una funcioacuten puedeayudar a que el flujo de ejecucioacuten sea maacutes transparente Por ejemplo aquiacute hayuna versioacuten de fact con sentencias de impresioacuten

Depuracioacuten 81

function fact(n) espacio = ^ (4 n) println(espacio factorial n) if n == 0 println(espacio devolviendo 1) return 1 else recursion = fact(n-1) resultado = n recursion println(espacio devolviendo resultado) return resultado endend

espacio es una cadena de caracteres de espacios que permite generar sangriacutea enla salida

juliagt fact(4) factorial 4 factorial 3 factorial 2 factorial 1factorial 0devolviendo 1 devolviendo 1 devolviendo 2 devolviendo 6 devolviendo 2424

Si estaacute confundido con el flujo de ejecucioacuten este tipo de salida puede ser uacutetilDesarrollar un buen andamiaje toma tiempo pero un poco de andamiaje puedeahorrar al usuario mucha depuracioacuten

Glosariovariable temporal

Variable usada para almacenar un valor intermedio en un caacutelculo complejo

coacutedigo muertoParte de un programa que nunca puede ser ejecutado a menudo porqueaparece despueacutes de una sentencia return

desarrollo incrementalPlan de desarrollo de un programa que intenta evitar la depuracioacutenagregando y probando solamente una pequentildea porcioacuten de coacutedigo a la vez

82 Capiacutetulo 6 Funciones productivas

andamiajeCoacutedigo que se usa durante el desarrollo de un programa pero que no esparte de la versioacuten final del mismo

guardiaacutenUn patroacuten de programacioacuten que usa una sentencia condicional paraverificar y manejar circunstancias que pueden causar un error

Ejercicios

Ejercicio 6-4

Dibuje un diagrama de pila para el siguiente programa iquestQueacute imprime elprograma

function b(z) prod = a(z z) println(z prod) prodend

function a(x y) x = x + 1 x yend

function c(x y z) total = x + y + z cuadrado = b(total)^2 cuadradoend

x = 1y = x + 1println(c(x y+3 x+y))

Ejercicio 6-5

La funcioacuten de Ackermann se define

Vea httpsenwikipediaorgwikiAckermann_function Escriba una funcioacutenllamada ack que evaluacutee la funcioacuten de Ackermann Use su funcioacuten para evaluarack(3 4) que deberiacutea ser 125 iquestQueacute sucede para valores mayores de m y n

Ejercicios 83

Ejercicio 6-6

Un paliacutendromo es una palabra que se escribe igual en un sentido que en otrocomo ana y radar De manera recursiva una palabra es un paliacutendromo si laprimera y la uacuteltima letra son iguales y lo que estaacute entre ellas es un paliacutendromo

Las siguientes funciones toman un argumento de tipo cadena y devuelven laprimera letra la uacuteltima y las intermedias

function primera(palabra) primera = firstindex(palabra) palabra[primera]end

function ultima(palabra) ultima = lastindex(palabra) palabra[ultima]end

function medio(palabra) primera = firstindex(palabra) ultima = lastindex(palabra) palabra[nextind(palabra primera) prevind(palabra ultima)]end

Se veraacute coacutemo funcionan en Capiacutetulo 8

1 Pruebe estas funciones iquestQueacute sucede si llama a la funcioacuten medio con unacadena de dos letras iquestY con una cadena de una letra iquestQueacute pasa con lacadena vaciacutea que no contiene letras

2 Escriba una funcioacuten llamada espalindromo que tome un argumento de tipocadena y devuelva true si es un paliacutendromo y false de lo contrario Recuerdeque puede usar la funcioacuten integrada length para verificar la longitud de unacadena

Ejercicio 6-7

Un nuacutemero es una potencia de si es divisible por y es una potencia de Escriba una funcioacuten llamada espotencia que tome los paraacutemetros a y b ydevuelva true si a es una potencia de b

OBSERVACIOacuteN Tendraacute que pensar en el caso base

Ejercicio 6-8

El maacuteximo comuacuten divisor (MCD) de y es el nuacutemero maacutes grande que los divide

84 Capiacutetulo 6 Funciones productivas

a ambos con resto 0

Una forma de encontrar el MCD de dos nuacutemeros se basa en la observacioacuten deque si es el resto cuando se divide por entonces mcd(a b) = mcd(b r)Como caso base podemos usar mcd(a 0) = a

Escriba una funcioacuten llamada mcd que tome los paraacutemetros a y b y devuelva sumaacuteximo divisor comuacuten

Creacuteditos Este ejercicio se basa en un ejemplo del libro Estructura einterpretacioacuten de programas informaacuteticos de Abelson y Sussman

Ejercicios 85

Capiacutetulo 7 IteracioacutenEste capiacutetulo se centra en la iteracioacuten que es la capacidad de ejecutarrepetidamente un bloque de sentencias Se han visto dos tipos de iteracioacutenusando recursioacuten en Seccioacuten 58 y usando ciclos for en Seccioacuten 42 En estecapiacutetulo veremos otro tipo maacutes usando sentencias while Primeramente seintroduciraacuten algunos teacuterminos sobre asignacioacuten de variables

Asignacioacuten muacuteltiplePuede que ya haya descubierto que estaacute permitido realizar maacutes de unaasignacioacuten a la misma variable Una nueva asignacioacuten hace que la variableexistente se refiera a un nuevo valor (y deje de referirse al viejo valor)

juliagt x = 55juliagt x = 77

La primera vez que se muestra x su valor es 5 y la segunda vez su valor es 7

Figura 10 Diagrama de estado

Figura 10 muestra el aspecto de una asignacioacuten muacuteltiple en un diagrama deestado

Es necesario aclarar algo que puede causar confusioacuten Puesto que Julia usa elsigno igual (=) para la asignacioacuten es tentador interpretar una sentencia a = bcomo una sentencia de igualdad Pero esta interpretacioacuten es incorrecta

Para empezar la igualdad es simeacutetrica y la asignacioacuten no lo es Por ejemplo enmatemaacuteticas si entonces Pero en Julia la sentencia a = 7 es vaacutelida y 7= a no lo es

Ademaacutes en matemaacuteticas una sentencia de igualdad es verdadera o falsasiempre Si ahora entonces siempre seraacute igual a En Julia una sentenciade asignacioacuten puede hacer que dos variables sean iguales pero no tienen porqueacute quedarse asiacute

86 Capiacutetulo 7 Iteracioacuten

juliagt a = 55juliagt b = a a y b son iguales5juliagt a = 3 a y b ya no son iguales3juliagt b5

La tercera liacutenea cambia el valor de a pero no cambia el valor de b por lo tanto yadejan de ser iguales

AVISO

Reasignar variables puede ser uacutetil pero se debe tener precaucioacutenSi los valores cambian frecuentemente la reasignacioacuten puedehacer que el coacutedigo sea difiacutecil de leer y depurar

Estaacute permitido definir una funcioacuten con el mismo nombre de unavariable definida anteriormente

Actualizacioacuten de variablesUna de las formas maacutes comunes de asignacioacuten muacuteltiple es la actualizacioacutendoacutende el nuevo valor de la variable depende del anterior

juliagt x = x + 18

Esto significa ldquotome el valor actual de x suacutemele uno y despueacutes actualice x con elnuevo valorrdquo

Si intenta actualizar una variable que no existe obtendraacute un error puesto queJulia evaluacutea la expresioacuten del lado derecho antes de asignar un valor a x

juliagt y = y + 1ERROR UndefVarError y not defined

Antes de actualizar una variable tiene que inicializarla usualmente con unaasignacioacuten simple

juliagt y = 00juliagt y = y + 11

Actualizar una variable sumaacutendole 1 se denomina un incremento y restaacutendole 1

Actualizacioacuten de variables 87

se llama un decremento

La Sentencia whileLas computadoras se usan a menudo para automatizar tareas repetitivasRealizar repetidamente tareas ideacutenticas o similares sin cometer errores es algoque las computadoras hacen bien y que los seres humanos hacen limitadamenteLa ejecucioacuten repetida de un conjunto de sentencias se llama iteracioacuten

Ya se han visto dos funciones cuentaregresiva y printn que iteran usandorecursividad Por ser la iteracioacuten tan comuacuten Julia proporciona variascaracteriacutesticas que la hacen maacutes faacutecil Una es la sentencia for que se vio enSeccioacuten 42 a la cual se volveraacute maacutes adelante

Otra caracteriacutestica es la sentencia while Aquiacute hay una versioacuten decuentaregresiva que muestra el uso de la sentencia while

function cuentaregresiva(n) while n gt 0 print(n ) n = n - 1 end println(iexclDespegue)end

Casi podriacutea leer la sentencia while como si fuera Espantildeol La funcioacuten anteriorsignifica ldquoMientras n sea mayor que 0 continuacutee mostrando el valor de n y luegoreduciendo el valor de n en 1 Cuando llegue a 0 muestre la palabra iexclDespegueldquo

Maacutes formalmente el flujo de ejecucioacuten de una sentencia while es el siguiente

1 Se determina si la condicioacuten es verdadera o falsa

2 Si es falsa se sale de la sentencia while y continuacutea la ejecucioacuten con lasiguiente sentencia

3 Si es verdadera ejecuta cada una de las sentencias en el cuerpo y regresa alpaso 1

Este tipo de flujo se llama bucle porque el tercer paso vuelve a la parte superior

El cuerpo del bucle deberiacutea cambiar el valor de una o maacutes variables de maneraque en alguacuten momento la condicioacuten sea falsa y el bucle termine En casocontrario el bucle se repetiraacute indefinidamente lo cual se llama bucle infinitoUna interminable fuente de diversioacuten para los informaacuteticos es la observacioacuten deque las instrucciones del champuacute ldquoEnjabone enjuague repitardquo son un bucleinfinito

88 Capiacutetulo 7 Iteracioacuten

En el caso de cuentaregresiva podemos probar que el bucle termina si n es ceroo negativo el ciclo termina En otro caso el valor de n se hace maacutes pequentildeocada vez que pasa por el bucle asiacute en cierto momento se llega a 0

En otros casos no es tan faacutecil decirlo Por ejemplo

function seq(n) while n = 1 println(n) if n 2 == 0 n is par n = n 2 else n is impar n = n3 + 1 end endend

La condicioacuten de este bucle es n = 1 de manera que el bucle continuaraacute hastaque n sea 1 que haraacute que la condicioacuten sea falsa

Cada vez que pasa por el bucle el programa muestra como salida el valor de n yluego comprueba si es par o impar Si es par el valor de n se divide por dos Si esimpar el valor de n se sustituye por n3 + 1 Por ejemplo si el argumento pasadoa la funcioacuten seq es 3 los valores resultantes n son 3 10 5 16 8 4 2 1

Puesto que n a veces aumenta y a veces disminuye no hay una prueba obvia deque n alcance alguna vez el valor 1 o de que el programa vaya a terminar Paraalgunos valores particulares de n se puede probar que siacute termina Por ejemplosi el valor de inicio es una potencia de dos entonces el valor de n seraacute par cadavez que se pasa por el bucle hasta que llegue a 1 El ejemplo anterior producedicha secuencia si se inicia con 16

Lo diacuteficil es preguntarse si se puede probar que este programa termina paratodos los valores positivos de n Hasta ahora nadie ha sido capaz de probar quelo hace o iexclque no lo hace (Vea httpseswikipediaorgwikiConjetura_de_Collatz)

Ejercicio 7-1

Reescribe la funcioacuten printn de Seccioacuten 58 utilizando iteracioacuten en vez derecursioacuten

breakA veces no se sabe que un ciclo debe terminar hasta que se llega al cuerpo Enese caso se puede usar la sentencia break para salir del bucle

break 89

Por ejemplo suponga que se desea recibir entradas del usuario hasta que esteescriba listo Podriacuteamos escribir

while true print(gt ) linea = readline() if line == listo break end println(linea)endprintln(iexclListo)

La condicioacuten del bucle es true que siempre es verdadero por lo que el bucle seejecuta hasta que llega a la sentencia break

En cada iteracioacuten se le pide al usuario (con el siacutembolo gt ) una entrada Si elusuario escribe listo la sentencia break sale del bucle De lo contrario elprograma repite lo que escriba el usuario y vuelve a la parte superior del bucleA continuacioacuten se muestra coacutemo funciona este programa

gt no listono listogt listoiexclListo

Esta forma de escribir bucles while es comuacuten porque permite verificar lacondicioacuten en cualquier parte del bucle (no solo en la parte superior) y puedeexpresar la condicioacuten de teacutermino de manera afirmativa (detenerse cuando estosuceda) en vez de negativamente (continuar hasta que esto suceda)

continueLa sentencia break permite terminar el bucle Cuando aparece una sentenciacontinue dentro de un bucle se regresa al comienzo del bucle ignorando todoslas sentencias que quedan en la iteracioacuten actual del bucle e inicia la siguienteiteracioacuten Por ejemplo

for i in 110 if i 3 == 0 continue end print(i )end

Output

90 Capiacutetulo 7 Iteracioacuten

1 2 4 5 7 8 10

Si i es divisible por 3 la sentencia continue detiene la iteracioacuten actual ycomienza la siguiente iteracioacuten Solo se imprimen los nuacutemeros en el rango de 1 a10 no divisibles por 3

Raiacuteces CuadradasLos bucles son comuacutenmente utilizados en programas que calculan resultadosnumeacutericos y que comienzan con una respuesta aproximada que es iterativamentemejorada

Por ejemplo una forma de calcular raiacuteces cuadradas es el meacutetodo de NewtonSuponga que desea conocer la raiacutez cuadrada de Si comienza con casi cualquierestimacioacuten puede calcular una mejor aproximacioacuten con la siguiente foacutermula

Por ejemplo si es 4 y es 3

juliagt a = 44juliagt x = 33juliagt y = (x + ax) 221666666666666665

El resultado estaacute maacutes cerca de la respuesta correcta ( ) Si se repite elproceso con la nueva estimacioacuten se acerca auacuten maacutes

juliagt x = y21666666666666665juliagt y = (x + ax) 220064102564102564

Despueacutes de algunas actualizaciones la estimacioacuten es casi exacta

Raiacuteces Cuadradas 91

juliagt x = y20064102564102564juliagt y = (x + ax) 220000102400262145juliagt x = y20000102400262145juliagt y = (x + ax) 220000000000262146

En general no se sabe de antemano cuaacutentos pasos se necesitan para llegar a larespuesta correcta pero se sabe que se ha llegado a ella cuando la estimacioacutendeja de cambiar

juliagt x = y20000000000262146juliagt y = (x + ax) 220juliagt x = y20juliagt y = (x + ax) 220

Cuando y == x ya se pueden detener los coacutemputos A continuacioacuten se muestraun ciclo que comienza con una estimacioacuten inicial x la cual mejora hasta que dejade cambiar

while true println(x) y = (x + ax) 2 if y == x break end x = yend

Para la mayoriacutea de los valores de a esto funciona bien aunque en general no serecomienda probar igualdad entre nuacutemeros de punto flotante Los nuacutemeros depunto flotante son aproximadamente correctos la mayoriacutea de los nuacutemerosracionales como e irracionales como no pueden ser representadosexactamente con un Float64

En lugar de verificar si x e y son exactamente iguales es maacutes seguro usar lafuncioacuten integrada abs para calcular el valor absoluto o la magnitud de ladiferencia entre ellos

92 Capiacutetulo 7 Iteracioacuten

if abs(y-x) lt ε breakend

Donde ε (varepsilon TAB) toma un valor como 00000001 que determina coacutemode cerca es suficientemente cerca

AlgoritmosEl meacutetodo de Newton es un ejemplo de un algoritmo un proceso mecaacutenico quepermite resolver una categoriacutea de problemas (en este caso el caacutelculo de raiacutecescuadradas)

Para comprender queacute es un algoritmo podriacutea ayudar empezar con algo que no esun algoritmo Cuando aprendioacute a multiplicar nuacutemeros de un solo diacutegitoprobablemente memorizoacute la tabla de multiplicar En efecto memorizoacute 100soluciones especiacuteficas Ese tipo de conocimiento no es un algoritmo

Pero si fuera perezoso podriacutea haber aprendido algunos trucos Por ejemplopara encontrar el producto de y 9 puede escribir como el primer diacutegito y

como el segundo diacutegito Este truco es una solucioacuten general para multiplicarcualquier nuacutemero de un solo diacutegito por 9 iexclEsto siacute es un algoritmo

Del mismo modo las teacutecnicas que aprendioacute para la suma con ldquollevamos tantordquo laresta con ldquopedimos prestado tantordquo y la divisioacuten ldquolarga o con galera o de casitardquoson todas ellas algoritmos Una de las caracteriacutesticas de los algoritmos es que norequieren inteligencia para realizarlos Son procesos mecaacutenicos donde cada pasose sigue de acuerdo con un conjunto simple de reglas

Ejecutar algoritmos es aburrido pero disentildearlos es interesante intelectualmentedesafiante y constituyen una parte central de la informaacutetica

Algunas de las cosas que las personas hacen naturalmente sin dificultad oconscientemente son las maacutes difiacuteciles de expresar en algoritmos Comprender ellenguaje natural es un buen ejemplo Todo el mundo lo hace pero hasta ahoranadie ha podido explicar coacutemo se hace al menos no en forma de algoritmo

DepuracioacutenA medida que comience a escribir programas maacutes extensos es posible que pasemaacutes tiempo depurando Maacutes coacutedigo significa maacutes posibilidades de cometer unerror y maacutes lugares doacutende se pueden esconder los errores

Una forma de reducir el tiempo de depuracioacuten es depurar por biseccioacuten Porejemplo si hay 100 liacuteneas en su programa y las revisa una a la vez seriacutean 100revisiones

Algoritmos 93

Es mejor tratar de dividir el problema en dos Busque en la mitad del programa oun valor intermedio que pueda verificar Agregue una sentencia de impresioacuten (oalgo que permita verificar) y ejecute el programa

Si esta verificacioacuten es incorrecta debe haber un problema en la primera mitaddel programa Si es correcta el problema estaacute en la segunda mitad

Cada vez que realiza una verificacioacuten como esta reduce a la mitad el nuacutemero deliacuteneas que debe revisar Despueacutes de seis pasos (que es mucho menos que 100) sereduciriacutea a una o dos liacuteneas de coacutedigo al menos en teoriacutea

En la praacutectica no siempre se conoce doacutende estaacute la mitad del programa y nosiempre es posible verificarlo No tiene sentido contar liacuteneas y encontrar el puntomedio exacto En su lugar piense en los lugares del programa donde puedehaber errores y en los lugares donde es faacutecil verificar Luego elija un lugar endonde usted crea que las posibilidades de encontrar un error antes o despueacutes deesta verificacioacuten son maacutes o menos las mismas

Glosarioasignacioacuten muacuteltiple

Asignar un nuevo valor a una variable que ya existe

actualizacioacutenAsignacioacuten donde el nuevo valor de la variable depende del antiguo

inicializacioacutenAsignacioacuten que le da un valor inicial a una variable que seraacute actualizada

incrementoActualizacioacuten que incrementa el valor de la variable (usualmente en 1)

decrementoActualizacioacuten que disminuye el valor de la variable (usualmente en 1)

iteracioacutenEjecucioacuten repetida de un conjunto de sentencias usando una funcioacutenrecursiva o un bucle

sentencia whileSentencia que permite iteraciones controladas por una condicioacuten

sentencia breakSentencia que permite salir de un bucle

94 Capiacutetulo 7 Iteracioacuten

sentencia continueSentencia localizada dentro de un bucle que obliga a iniciar una nuevaiteracioacuten desde el inicio del bucle

bucle infinitoUn bucle cuya condicioacuten de teacutermino no es satisfecha

algoritmoProceso general para resolver una categoriacutea de problemas

Ejercicios

Ejercicio 7-2

Copie el bucle de Seccioacuten 76 e inseacutertelo en una funcioacuten llamada miraiz que tomea como paraacutemetro elija un valor razonable de x y devuelva una estimacioacuten de laraiacutez cuadrada de a

Para probarla escriba una funcioacuten llamada probarraiz que imprima una tablacomo esta

a mysqrt sqrt diff- ------ ---- ----10 10 10 0020 1414213562373095 14142135623730951 2220446049250313e-1630 17320508075688772 17320508075688772 0040 20 20 0050 223606797749979 223606797749979 0060 2449489742783178 2449489742783178 0070 26457513110645907 26457513110645907 0080 282842712474619 28284271247461903 4440892098500626e-1690 30 30 00

La primera columna es un nuacutemero a la segunda columna es la raiacutez cuadrada dea calculada con miraiz la tercera columna es la raiacutez cuadrada calculada con lafuncioacuten integrada sqrt y la cuarta columna es el valor absoluto de la diferenciaentre las dos estimaciones

Exercise 7-3

La funcioacuten integrada Metaparse toma una cadena y la transforma en unaexpresioacuten Esta expresioacuten se puede evaluar en Julia con la funcioacuten Coreeval Porejemplo

Ejercicios 95

juliagt expr = Metaparse(1+23)(1 + 2 3)juliagt eval(expr)7juliagt expr = Metaparse(sqrt(π))(sqrt(π))juliagt eval(expr)17724538509055159

Escriba una funcioacuten llamada evalbucle que iterativamente solicite una entrada alusuario tome la entrada resultante la evaluacutee usando eval y pase posteriormentea imprimir el resultado Debe continuar hasta que el usuario ingrese listo y luegodevolver el valor de la uacuteltima expresioacuten que evaluoacute

Exercise 7-4

El matemaacutetico Srinivasa Ramanujan encontroacute una serie infinita que puede usarsepara generar una aproximacioacuten numeacuterica de

Escriba una funcioacuten llamada estimarpi que utilice esta foacutermula para calcular ydevolver una estimacioacuten de π Debe usar un ciclo while para calcular losteacuterminos de la suma hasta que el uacuteltimo teacutermino sea menor que 1e-15 (que es lanotacioacuten de Julia para ) Puede verificar el resultado comparaacutendolo con π

96 Capiacutetulo 7 Iteracioacuten

Capiacutetulo 8 CadenasLas cadenas son diferentes de los nuacutemeros enteros flotantes y booleanos Unacadena es una secuencia es decir una coleccioacuten ordenada de valores En estecapiacutetulo se veraacute coacutemo acceder a los caracteres que forman una cadena y seconoceraacuten algunas funciones integradas en Julia relacionadas con cadenas

CaracteresLos hispanohablantes estaacuten familiarizados con algunos caracteres tales como lasletras del alfabeto (A B C hellip) los nuacutemeros y los signos de puntuacioacuten comunesEstos caracteres estaacuten estandarizados en el coacutedigo ASCII (Coacutedigo EstaacutendarEstadounidense para el Intercambio de Informacioacuten)

Por supuesto hay muchos otros caracteres utilizados en idiomas distintos delespantildeol que no estaacuten en el coacutedigo ASCII tales como aquellos usados en losidiomas griego aacuterabe chino hebreo hindi japoneacutes y coreano

Definir queacute es un caraacutecter es altamente complejo La norma Unicode permiteabordar este problema y se considera como el estaacutendar definitivo para ello Estanorma funciona asignando un nuacutemero uacutenico para cada caraacutecter a nivel global

Un valor Char representa un uacutenico caraacutecter y estaacute entre comillas simples

juliagt xx ASCIIUnicode U+0078 (category Ll Letter lowercase)juliagt ἴἴ Unicode U+1F34C (category So Symbol other)juliagt typeof(x)Char

Incluso los emojis son parte del estaacutendar Unicode (banana TAB)

Una Cadena es una SecuenciaUna cadena es una secuencia de caracteres Se puede acceder a un caraacutecter conel operador corchete

juliagt fruta = bananabananajuliagt letra = fruta[1]b ASCIIUnicode U+0062 (category Ll Letter lowercase)

La segunda sentencia selecciona el caraacutecter nuacutemero 1 de fruta y la asigna a lavariable letra

Caracteres 97

La expresioacuten entre corchetes se llama indice El iacutendice indica el caraacutecter de lasecuencia a obtener (de ahiacute el nombre)

La indexacioacuten en Julia es base 1 es decir el primer elemento de cualquier objetoindexado con enteros estaacute en el iacutendice 1 y el uacuteltimo en el iacutendice end

juliagt fruta[end]a ASCIIUnicode U+0061 (category Ll Letter lowercase)

Como iacutendice se pueden usar expresiones que contengan variables y operadores

juliagt i = 11juliagt fruta[i+1]a ASCIIUnicode U+0061 (category Ll Letter lowercase)juliagt fruta[end-1]n ASCIIUnicode U+006E (category Ll Letter lowercase)

No obstante el valor del iacutendice tiene que ser un nuacutemero entero De lo contrariose obtiene

juliagt letra = fruta[15]ERROR MethodError no method matching getindex(String Float64)

lengthlength es una funcioacuten integrada que devuelve el nuacutemero de caracteres de unacadena

juliagt frutas = ἴ ἴ ἵἴ ἴ ἵjuliagt len = length(frutas)5

Para obtener la uacuteltima letra de una cadena puede sentirse tentado a probar algocomo esto

juliagt last = frutas[len] ASCIIUnicode U+0020 (category Zs Separator space)

Pero con esto no se obtiene el resultado esperado

Las cadenas se codifican usando codificacioacuten UTF-8 UTF-8 es una codificacioacutende longitud variable lo que significa que no todos los caracteres estaacuten

98 Capiacutetulo 8 Cadenas

codificados con el mismo nuacutemero de bytes

La funcioacuten sizeof devuelve el nuacutemero de bytes de una cadena

juliagt sizeof(ἴ)4

Dado que un emoji estaacute codificado en 4 bytes y la indexacioacuten de cadenas estaacutebasada en bytes el quinto elemento de frutas es un ESPACIO

Esto significa que no todos los iacutendices de byte de una cadena UTF-8 sonnecesariamente iacutendices vaacutelidos para un caraacutecter Si en una cadena se indexa conun iacutendice de bytes no vaacutelido se genera un error

juliagt frutas[2]ERROR StringIndexError(ἴ ἴ ἵ 2)

En el caso de frutas el caraacutecter ἴ es un caraacutecter de cuatro bytes por lo que losiacutendices 2 3 y 4 no son vaacutelidos y el iacutendice del siguiente caraacutecter es 5 el siguienteiacutendice vaacutelido se puede calcular con nextind(frutas 1) el subsiguiente connextind(frutas5) y asiacute sucesivamente

RecorridoMuchos caacutelculos implican procesar una cadena caraacutecter por caraacutecter A menudoempiezan por el principio seleccionan cada caraacutecter por turno hacen algo con eacutely continuacutean hasta el final Este patroacuten de proceso se llama recorrido Una formade escribir un recorrido es con una sentencia while

indice = firstindex(frutas)while indice lt= sizeof(frutas) letra = frutas[indice] println(letra) global indice = nextind(frutas indice)end

Este bucle recorre la cadena y muestra cada letra en una liacutenea distinta Lacondicioacuten del bucle es index lt= sizeof(fruta) de modo que cuando el iacutendice esmayor al nuacutemero de bytes en la cadena la condicioacuten es falsa y no se ejecuta elcuerpo del bucle

La funcioacuten firstindex devuelve el primer iacutendice de bytes vaacutelido La palabrareservada global antes de indice indica que queremos reasignar la variableindice definida en Main (ver Seccioacuten 117)

Recorrido 99

Ejercicio 8-1

Escriba una funcioacuten que tome una cadena como argumento y que muestre lasletras desde la uacuteltima a la primera una por liacutenea

Otra forma de escribir un recorrido es con un bucle for

for letra in frutas println(letra)end

Cada vez que se recorre el bucle se asigna a la variable letra el siguientecaraacutecter de la cadena El bucle continuacutea hasta que no quedan maacutes caracteres

El ejemplo siguiente muestra coacutemo usar la concatenacioacuten (multiplicacioacuten decadenas) y un bucle for para generar una serie abecedaria (es decir una seriecon elementos en orden alfabeacutetico) Por ejemplo en el libro de Robert McCloskeyMake Way for Ducklings los nombres de los patitos son Jack Kack Lack MackNack Ouack Pack y Quack Este bucle muestra esos nombres en orden

prefijos = JKLMNOPQsufijo = ack

for letra in prefijos println(letra sufijo)end

Output

JackKackLackMackNackOackPackQack

Por supuesto esto no es del todo correcto porque ldquoOuackrdquo y ldquoQuackrdquo no estaacutencorrectamente escritos

Ejercicio 8-2

Modifique este programa para solucionar este error

100 Capiacutetulo 8 Cadenas

Porciones de CadenasA la subcadena de una cadena se le llama porcioacuten La seleccioacuten de una porcioacuten essimilar a la seleccioacuten de un caraacutecter

juliagt str = Julio Cesar

juliagt str[15]Julio

El operador [nm] devuelve la parte de la cadena desde el n-eacutesimo byte hasta elm-eacutesimo Por lo tanto se siguen las mismas reglas que para la indexacioacuten simple

La palabra reservada end se puede usar para indicar al uacuteltimo byte de la cadena

juliagt str[7end]Cesar

Si el primer iacutendice es mayor que el segundo el resultado es una cadena vaciacutearepresentada por dos comillas

juliagt str[87]

Una cadena vaciacutea no contiene caracteres y tiene una longitud de 0 pero apartede eso es igual a cualquier otra cadena

Ejercicio 8-3

Continuando este ejemplo iquestqueacute cree que significa str[] Pruebe y veraacute

Las Cadenas son InmutablesEs tentador usar el operador [] en el lado izquierdo de una asignacioacuten con laintencioacuten de cambiar un caraacutecter en una cadena Por ejemplo

juliagt saludo = iexclHola mundoiexclHola mundojuliagt saludo[3] = JERROR MethodError no method matching setindex(String CharInt64)

Nota del traductor De acuerdo con la codificacioacuten de caracteres en utf-8 o latin-

Porciones de Cadenas 101

1 el caraacutecter de exclamacioacuten lsquoiexclrsquo en la variable saludo ocupa dos posiciones deahiacute que la letra lsquoHrsquo esteacute localizada en el iacutendice 3

La razoacuten del error es que las cadenas son inmutables lo que significa que no sepuede cambiar una cadena existente Lo maacuteximo que se puede hacer es crearuna nueva cadena que sea una variacioacuten de la original

juliagt saludo = iexclJ saludo[4end]iexclJola mundo

Este ejemplo concatena la apertura del signo de exclamacioacuten y una nuevaprimera letra a una porcioacuten de saludo Esta operacioacuten no tiene efecto sobre lacadena original

Interpolacioacuten de CadenasConstruir cadenas usando concatenacioacuten puede ser un poco engorroso Paradisminuir la necesidad de las llamadas a string o multiplicaciones repetidas Juliapermite la interpolacioacuten de cadenas usando $

juliagt saludo = iexclHolaiexclHolajuliagt paraquien = mundomundojuliagt $saludo $(paraquien)iexclHola mundo

Esto es maacutes entendible y conveniente que la concatenacioacuten de cadenas saludo paraquien

La expresioacuten inmediatamente siguiente a $ se toma como la expresioacuten cuyo valorse va a interpolar en la cadena Por lo tanto puede interpolar cualquierexpresioacuten en una cadena usando pareacutentesis

juliagt 1 + 2 = $(1 + 2)1 + 2 = 3

Buacutesqueda

iquestQueacute hace la siguiente funcioacuten

102 Capiacutetulo 8 Cadenas

function busqueda(palabra letra) indice = primerindice(palabra) while indice lt= sizeof(palabra) if palabra[indice] == letra return indice end indice = nextind(palabra indice) end -1end

En cierto sentido la funcioacuten buacutesqueda es lo contrario del operador [] En lugarde tomar un iacutendice y extraer el caraacutecter correspondiente toma un caraacutecter yencuentra el iacutendice donde aparece el caraacutecter Si el caraacutecter no se encuentra lafuncioacuten devuelve -1

Este es el primer ejemplo de una sentencia return dentro de un bucle Sipalabra[indice] == letra la funcioacuten devuelve inmediatamente el iacutendiceescapando del bucle prematuramente

Si el caraacutecter no aparece en la cadena entonces el programa sale del buclenormalmente y devuelve -1

Este patroacuten de computacioacuten se llama a veces un recorrido eureka porque tanpronto como encontramos lo que buscamos podemos gritar ldquoiexclEureka rdquo y dejarde buscar

Ejercicio 8-4

Modifique la funcioacuten busqueda para que tenga un tercer paraacutemetro el iacutendice depalabra donde deberiacutea comenzar a buscar

Iterando y contandoEl siguiente programa cuenta el nuacutemero de veces que aparece la letra a en unacadena

palabra = bananacontador = 0for letra in palabra if letra == a global contador = contador + 1 endendprintln(contador)

Iterando y contando 103

Este programa es otro ejemplo del patroacuten de computacioacuten llamado conteo Lavariable contador se inicializa en 0 y se incrementa cada vez que encuentra laletra a Cuando termina el bucle contador contiene el resultado (el nuacutemero totalde letras a)

Ejercicio 8-5

Coloque este coacutedigo en una funcioacuten llamada conteo y generaliacutecelo de tal maneraque tome como argumentos una cadena y una letra

Luego vuelva a escribir la funcioacuten para que en vez de revisar toda la cadenautilice la funcioacuten busqueda de tres paraacutemetros de la seccioacuten anterior

Libreriacutea con cadenasJulia tiene funciones integradas que realizan una variedad de operaciones uacutetilesen cadenas Por ejemplo la funcioacuten uppercase toma una cadena y devuelve unanueva cadena con todas las letras mayuacutesculas

juliagt uppercase(iexclHola mundo)iexclHOLA MUNDO

Existe una funcioacuten llamada findfirst que es notablemente similar a la funcioacutenbusqueda que escribimos

juliagt findfirst(a banana)22

La funcioacuten findfirst es maacutes general que la funcioacuten creada puede encontrarsubcadenas no solo caracteres

juliagt findfirst(na banana)34

Por defecto findfirst empieza la buacutesqueda al comienzo de la cadena pero lafuncioacuten findnext toma un tercer argumento el indice donde deberiacutea comenzar

juliagt findnext(na banana 4)56

El operador isinEl operador isin (in TAB) es un operador booleano que toma un caraacutecter y unacadena y devuelve true si el primero aparece en el segundo

104 Capiacutetulo 8 Cadenas

juliagt a isin banana a en bananatrue

Por ejemplo la siguiente funcioacuten imprime todas las letras de palabra1 quetambieacuten aparecen en palabra2

function ambas(palabra1 palabra2) for letra in palabra1 if letra isin palabra2 print(letra ) end endend

Una buena eleccioacuten de nombres de variables permite que Julia se pueda leercomo el espantildeol Este bucle puede leerse como para (cada) letra en (la primera)palabra si (la) letra es un elemento de (la segunda) palabra imprima (la) letra

Esto es lo que se obtiene si se compara manzanas y naranjas

juliagt ambas(manzanas naranjas)a n a n a s

Comparacioacuten de CadenasLos operadores de comparacioacuten trabajan sobre cadenas Para ver si dos cadenasson iguales

palabra = Pintildeaif palabra == banana println(iexclTenemos bananas)end

Otras operaciones de comparacioacuten son uacutetiles para ordenar alfabeacuteticamentepalabras

if palabra lt banana println(Su palabra $palabra va antes de banana)elseif word gt banana println(Su palabra $palabra va antes de banana)else println(iexclTenemos bananas)end

Comparacioacuten de Cadenas 105

Julia no maneja las letras mayuacutesculas y minuacutesculas del mismo modo que sonmanejadas en cualquier lengua hablada Todas las letras mayuacutesculas van antesde las letras minuacutesculas seguacuten el estaacutendar de codificacioacuten Por lo tanto

Su palabra Pintildea va antes de banana

OBSERVACIOacuteNUna forma comuacuten de abordar este problema es convertirlas cadenas a un formato estaacutendar como por ejemplo aminuacutesculas antes de realizar la comparacioacuten

DepuracioacutenCuando se usan iacutendices para recorrer los valores en una secuencia es difiacutecilacceder al principio y al final del recorrido Aquiacute hay una funcioacuten que comparados palabras y devuelve true si una de las palabras es el reverso de la otra perocontiene dos errores

function espalindroma(palabra1 palabra2) if length(palabra1) = length(palabra2) return false end i = firstindex(palabra1) j = lastindex(palabra2) while j gt= 0 j = prevind(palabra2 j) if palabra1[i] = palabra2[j] return false end i = nextind(palabra1 i) end trueend

La primera sentencia if verifica si las palabras tienen la misma longitud Si no sedevuelve false inmediatamente De lo contrario para el resto de la funcioacuten sepuede suponer que las palabras tienen la misma longitud Este es un ejemplo delpatroacuten guardiaacuten

i y j son iacutendices i recorre palabra1 de derecha a izquierda mientras que j recorrepalabra2 de izquierda a derecha Si dos letras no coinciden se devuelve falseinmediatamente Si el ciclo termina y todas las letras coinciden se devuelve true

La funcioacuten lastindex devuelve el uacuteltimo iacutendice de bytes vaacutelido de una cadena yprevind el iacutendice vaacutelido anterior a un caraacutecter

Si se prueba esta funcioacuten con las palabras amor y roma se espera el valor de

106 Capiacutetulo 8 Cadenas

retorno true pero se obtiene false

juliagt espalindroma(amor roma)false

Para depurar este tipo de error primeramente se imprimen los valores de losiacutendices

espalindroma (generic function with 1 method)

Ahora al ejecutar el programa se obtiene maacutes informacioacuten

juliagt espalindroma(amor roma)i = 1j = 3false

En la primera iteracioacuten del bucle el valor de j es 3 pero tendriacutea que ser 4 Estose puede solucionar trasladando la liacutenea j = prevind (palabra2 j) al final del ciclowhile

Si se soluciona ese error y se ejecuta el programa nuevamente se obtiene

espalindroma (generic function with 1 method)

juliagt espalindroma(amor roma)i = 1j = 4i = 2j = 3i = 3j = 2i = 4j = 1i = 5j = 0ERROR BoundsError attempt to access String at index [5]

Esta vez se ha producido un BoundsError El valor de i es 5 que estaacute fuera delrango de la cadena amor

Depuracioacuten 107

Ejercicio 8-6

Ejecute el programa en papel cambiando los valores de i y j durante cadaiteracioacuten Encuentre y arregle el segundo error en esta funcioacuten

Glosariosecuencia

Una coleccioacuten ordenada de valores donde cada valor se identifica medianteun iacutendice entero

coacutedigo ASCIICoacutedigo de caracteres estaacutendar para el intercambio de informacioacuten

norma UnicodeUn estaacutendar en la industria informaacutetica para la codificacioacuten representacioacuteny manejo consistentes de texto en la mayoriacutea de los sistemas de escrituradel mundo

iacutendiceUn valor entero usado para seleccionar un miembro de un conjuntoordenado como puede ser un caraacutecter de una cadena En Julia los iacutendicescomienzan en 1

codificacioacuten UTF-8Una codificacioacuten de caracteres de longitud variable capaz de codificar todoslos 1112064 puntos de coacutedigo vaacutelidos en Unicode utilizando de uno a cuatrobytes de 8 bits

recorrerIterar sobre los elementos de un conjunto realizando una operacioacuten similaren cada uno de ellos

porcioacutenUna parte de una cadena especificada mediante un rango de iacutendices

cadena vaciacuteaUna cadena sin caracteres y longitud 0 representada por dos comillas

immutableLa propiedad de una secuencia que hace que a sus elementos no se lespueda asignar nuevos valores

interpolacioacuten de cadenasEl proceso de evaluar una cadena que contiene uno o maacutes marcadores de

108 Capiacutetulo 8 Cadenas

posicioacuten produciendo un resultado en el que los marcadores de posicioacuten sereemplazan con sus valores correspondientes

buacutesquedaUn patroacuten de recorrido que se detiene cuando encuentra lo que estaacutebuscando

contadorUna variable utilizada para contar algo generalmente inicializada en cero yluego incrementada

Ejercicios

Ejercicio 8-7

Lea la documentacioacuten de las funciones relacionadas con cadenas enhttpsdocsjulialangorgenv1manualstrings Es posible que desee probaralgunas de ellas para asegurarse de comprender coacutemo funcionan strip y replaceson particularmente uacutetiles

La documentacioacuten utiliza una sintaxis que puede ser confusa Por ejemplo ensearch(cadenaAbstractString caracterChars [comienzoInteger]) loscorchetes indican argumentos opcionales Por lo tanto cadena y caracter sonobligatorios pero comienzo es opcional

Ejercicio 8-8

Hay una funcioacuten integrada llamada count que es similar a la funcioacuten en Seccioacuten89 Lea la documentacioacuten de esta funcioacuten y uacutesela para contar el nuacutemero deletras a en banana

Ejercicio 8-9

Una porcioacuten de cadena puede tomar un tercer iacutendice El primero especifica elinicio el tercero el final y el segundo el tamantildeo del paso es decir el nuacutemero deespacios entre caracteres sucesivos Un tamantildeo de paso de 2 significa cada uncaracter 3 significa cada dos etc

juliagt fruta = bananabananajuliagt fruta[126]bnn

Un tamantildeo de paso de -1 recorre la palabra hacia la izquierda por lo que laporcioacuten [end-11] genera una cadena invertida

Ejercicios 109

Use esto para escribir una versioacuten de una liacutenea de coacutedigo de espalindroma deSeccioacuten 6113

Exercise 8-10

Las siguientes funciones estaacuten destinadas a verificar si una cadena contieneletras minuacutesculas pero algunas de ellas son incorrectas Para cada funcioacutendescriba queacute hace realmente la funcioacuten (suponiendo que el paraacutemetro es unacadena)

110 Capiacutetulo 8 Cadenas

function cualquierminuscula1(s) for c in s if islowercase(c) return true else return false end endend

function cualquierminuscula2(s) for c in s if islowercase(c) return true else return false end endend

function cualquierminuscula3(s) for c in s bandera = islowercase(c) end flagend

function cualquierminuscula4(s) bandera = false for c in s bandera = bandera || islowercase(c) end flagend

function cualquierminuscula5(s) for c in s if islowercase(c) return false end end trueend

Exercise 8-11

Un cifrado Ceacutesar es una forma simple de cifrado que implica desplazar cada letraun nuacutemero fijo de lugares Desplazar una letra significa reemplazarla por otra

Ejercicios 111

letra que se encuentra un nuacutemero fijo de posiciones maacutes adelante en el alfabetoEs posible desplazarse hasta el principio del abecedario si fuera necesario Deesta manera con un desplazamiento de 3 A es D y con un desplazamiento de1 Z es A

Para desplazar una palabra desplace cada letra en la misma cantidad Porejemplo con un desplazamiento de 6 ABCDEF es GHIJKL y con undesplazamiento de -6 BCDE es VWXY En la peliacutecula 2001 Una odisea delespacio la computadora de la nave se llama HAL que es IBM desplazada por -1

Escriba una funcioacuten llamada desplazarpalabra que tome una cadena y un nuacutemeroentero como paraacutemetros y devuelva una nueva cadena que contenga las letrasde la cadena original desplazadas por la cantidad dada

OBSERVACIOacuteN

Es posible que desee utilizar la funcioacuten integrada Intque convierte un caraacutecter en un coacutedigo numeacuterico yChar que convierte los coacutedigos numeacutericos encaracteres Las letras del alfabeto estaacuten codificadas enorden alfabeacutetico por ejemplo

juliagt Int(c) - Int(a)2

Porque c es la tercera letra del alfabeto Pero cuidadolos coacutedigos numeacutericos para las letras mayuacutesculas sondiferentes

juliagt Char(Int(A) + 32)a ASCIIUnicode U+0061 (category Ll Letterlowercase)

Algunos chistes ofensivos en Internet estaacuten codificados en ROT13 que es uncifrado Ceacutesar con desplazamiento 13 Si no se ofende faacutecilmente encuentre ydecodifice algunos de ellos

112 Capiacutetulo 8 Cadenas

Capiacutetulo 9 Estudio de Caso Juego de PalabrasEste capiacutetulo presenta un segundo estudio de caso que consiste en resolverpuzzles buscando palabras que tengan ciertas propiedades Por ejemplo sebuscaraacuten palabras cuyas letras aparezcan en orden alfabeacutetico Ademaacutes sepresentaraacute otra forma de desarrollar programas la reduccioacuten a un problemapreviamente resuelto

Leer listas de palabrasPara los ejercicios de este capiacutetulo se necesita una lista de palabras en espantildeolHay muchas listas de palabras disponibles en la Web pero la maacutes adecuada paranuestro propoacutesito es una de las listas de palabras recopiladas y contribuidas aldominio puacuteblico por Ismael Olea (see httpoleaorgproyectoslemarios) Estalista de 87900 palabras se encuentra en la paacutegina de Olea con el nombre dearchivo lemario-general-del-espanoltxt Tambieacuten es posible descargar una copiadesde httpsgithubcomJuliaIntroIntroAJuliajlblobmasterdatapalabrastxt

Este archivo es un archivo de texto simple por lo que puede ser abierto con uneditor de texto o leiacutedo con Julia La funcioacuten integrada open toma el nombre delarchivo como paraacutemetro y devuelve un objeto archivo que puede ser usado parala lectura del archivo

IOStream(ltfilehometravisbuildJuliaIntroIntroAJuliajlsrcdatapalabrastxtgt)

juliagt fin = open(palabrastxt)IOStream(ltfile palabrastxtgt)

fin es un objeto archivo que puede ser utilizado como entrada y cuando se dejade utilizar debe cerrarse con close(fin)

Julia tiene integradas varias funciones de lectura entre ellas readline que lee loscaracteres del archivo hasta que llega a un salto de liacutenea devolviendo elresultado como una cadena

juliagt readline(fin)a

La primera palabra en esta lista particular es a que indica direccioacuten intervalode tiempo finalidad entre otros

El objeto archivo lleva registro de doacutende quedoacute por uacuteltima vez por lo que sillama a readline nuevamente se obtendraacute la siguiente palabra

Leer listas de palabras 113

juliagt readline(fin)a-

La siguiente palabra es a- que es un prefijo que indica privacioacuten

Tambieacuten se puede usar un archivo como parte de un bucle for El siguienteprograma lee palabrastxt e imprime cada palabra una por liacutenea

for line in eachline(palabrastxt) println(line)end

Ejercicios

Ejercicio 9-1

Escriba un programa que lea palabrastxt e imprima solo las palabras con maacutes de20 caracteres (sin contar espacios en blanco)

Ejercicio 9-2

En 1927 Enrique Jardiel Poncela publicoacute cinco historias cortas omitiendo encada una de ellas una vocal Estas historias incluyen El Chofer Nuevonarracioacuten escrita sin la letra a y Un marido sin vocacioacuten sin la letra e Dadoque la letra e es la maacutes frecuente del espantildeol esto no es faacutecil de lograr

De hecho es difiacutecil pensar oraciones que no utilicen esta letra Intentarlo escomplicado pero con la praacutectica se vuelve maacutes faacutecil

Bueno volviendo al tema importante

Escriba una funcioacuten llamada notiene_e que devuelva true si una palabra dada notiene la letra e

Modifique su programa de la seccioacuten anterior para que imprima solo las palabrasque no tienen e y que ademaacutes calcule el porcentaje de palabras en la lista queno tengan e

Ejercicio 9-3

Escriba una funcioacuten llamada evitar que tome como argumentos una palabra yuna cadena de letras prohibidas y que devuelva true si la palabra no usaninguna de las letras prohibidas

Modifique su programa de la seccioacuten anterior para solicitar al usuario queingrese una cadena de letras prohibidas y que luego imprima el nuacutemero de

114 Capiacutetulo 9 Estudio de Caso Juego de Palabras

palabras que no contengan ninguna de ellas iquestEs posible encontrar unacombinacioacuten de 5 letras prohibidas que excluya la menor cantidad de palabras

Ejercicio 9-4

Escriba una funcioacuten llamada usasolo que tome una palabra y una cadena deletras y que devuelva true si la palabra contiene solo letras de la lista iquestPuedehacer una oracioacuten usando solo las letras oneacmil Aparte de iquestEl camino

Ejercicio 9-5

Escriba una funcioacuten llamada usatodo que tome una palabra y una cadena deletras y que devuelva true si la palabra usa todas las letras requeridas al menosuna vez iquestCuaacutentas palabras usan todas las vocales aeiou

Ejercicio 9-6

Escriba una funcioacuten llamada esabecedaria que devuelva true si las letras de unapalabra aparecen en orden alfabeacutetico iquestCuaacutentas palabras de este tipo hay

BuacutesquedaTodos los ejercicios en la seccioacuten anterior tienen algo en comuacuten se puedenresolver con el patroacuten de buacutesqueda El ejemplo maacutes simple es

function notiene_e(palabra) for letra in palabra if letra == e return false end end trueend

El bucle for recorre los caracteres de palabra Si encontramos la letra e puededevolver inmediatamente false de lo contrario hay que pasar a la siguiente letraSi se sale del bucle normalmente eso significa que no se encontroacute una e por loque la funcioacuten devuelve true

Esta funcioacuten podriacutea ser escrita de manera maacutes concisa usando el operador notin(notin TAB) pero se comienza con esta versioacuten porque muestra la loacutegica delpatroacuten de buacutesqueda

evita es una versioacuten maacutes general de notiene_e pero tiene la misma estructura

Buacutesqueda 115

function evita(palabra prohibidas) for letra in palabra if letter isin prohibidas return false end end trueend

Se devuelve false tan pronto como se encuentre una letra prohibida si llegamosal final del ciclo se devuelve true

usasolo es similar excepto que el sentido de la condicioacuten se invierte

function usasolo(palabra disponibles) for letra in palabra if letra notin disponibles return false end end trueend

En vez de un conjunto de letras prohibidas se tiene un conjunto de letrasdisponibles Si se encuentra una letra en palabra que no estaacute en disponible sedevuelve false

usatodo es similar excepto que se invierte el papel de la palabra y la cadena deletras

function usatodo(palabra requeridas) for letra in requeridas if letra notin palabra return false end end trueend

En lugar de recorrer las letras de la palabra el bucle recorre las letrasrequeridas Si alguna de las letras requeridas no aparece en la palabra sedevuelve false

Si se pensara como un informaacutetico se reconoceriacutea que usatodo es una instanciade un problema previamente resuelto y se podriacutea haber escrito

116 Capiacutetulo 9 Estudio de Caso Juego de Palabras

function usatodo(palabra requeridas) usasolo(requeridas palabra)end

Este es un ejemplo de una forma de desarrollar programas llamada reduccioacuten aun problema resuelto previamente lo que significa que se reconoce el problemaen el que se estaacute trabajando como una instancia de un problema ya resuelto y seaplica la solucioacuten existente

Bucle con iacutendicesLas funciones de la seccioacuten anterior fueron escritas con ciclos for porque solo senecesitaban los caracteres en las cadenas y no hubo necesidad de trabajar conlos iacutendices

Para esabecedaria tenemos que comparar letras adyacentes lo cual es un pococomplicado con un ciclo for

function esabecedaria(palabra) i = firstindex(palabra) previa = palabra[i] j = nextind(palabra i) for c in palabra[jend] if c lt previa return false end previa = c end trueend

Otra alternativa es usar recursividad

function esabecedaria(palabra) if length(palabra) lt= 1 return true end i = firstindex(palabra) j = nextind(palabra i) if palabra[i] gt palabra[j] return false end esabecedaria(palabra[jend])end

Una tercera opcioacuten es usar un ciclo while

Bucle con iacutendices 117

function esabecedaria(palabra) i = firstindex(palabra) j = nextind(palabra 1) while j lt= sizeof(palabra) if palabra[j] lt palabra[i] return false end i = j j = nextind(palabra i) end trueend

El ciclo comienza en i=1 y j=nextind(palabra 1) y termina cuandojgtsizeof(palabra) En cada iteracioacuten se compara el caraacutecter ieacutesimo (que sepuede considerar como el caraacutecter actual) con el caraacutecter jeacutesimo (que se puedeconsiderar como el siguiente)

Si el siguiente caraacutecter es menor (va antes en el alfabeto) que el actual entoncesla palabra no tiene sus letras en orden alfabeacutetico y se devuelve false

Si se llega al final del ciclo sin encontrar letras que imposibiliten el ordenalfabeacutetico entonces la palabra pasa la prueba Para convencerse de que el ciclotermina correctamente considere como ejemplo la palabra Abel

A continuacioacuten se muestra una versioacuten de espalindromo que usa dos iacutendices unocomienza al principio de la palabra y aumenta su valor y el otro comienza al finaly disminuye su valor

function espalindromo(palabra) i = firstindex(palabra) j = lastindex(palabra) while iltj if palabra[i] = palabra[j] return false end i = nextind(palabra i) j = prevind(palabra j) end trueend

O podriacuteamos reducir este problema a uno previamente resuelto y escribir

118 Capiacutetulo 9 Estudio de Caso Juego de Palabras

function espalindromo(palabra) isreverse(palabra palabra)end

Usando esreverso de Seccioacuten 813

DepuracioacutenComprobar el correcto funcionamiento de los programas es difiacutecil Las funcionesde este capiacutetulo son relativamente faacuteciles de probar porque se pueden verificarlos resultados a mano Aun asiacute es casi imposible elegir un conjunto de palabrasque permitan evaluar todos los posibles errores

Tomando notiene_e como ejemplo hay dos casos obvios que verificar laspalabras que tienen una e deberiacutean devolver false y las palabras que nodeberiacutean devolver true No deberiacutean haber problemas para encontrar un ejemplode cada uno

Dentro de cada caso hay algunos subcasos menos obvios Entre las palabras quetienen una e se deben probar las palabras con una e al principio al final y almedio Ademaacutes se deben probar palabras largas cortas y muy cortas como unacadena vaciacutea La cadena vaciacutea es un ejemplo de un caso especial no obviodonde pueden originarse errores

Ademaacutes de las instancias de prueba generadas tambieacuten puede probar suprograma con una lista de palabras como palabrastxt Al escanear el resultadoes posible que pueda detectar errores pero tenga cuidado puede detectar untipo de error (palabras que no deberiacutean incluirse pero lo estaacuten) y no otro(palabras que deberiacutean incluirse pero no lo estaacuten)

Por lo general las pruebas pueden ayudarlo a encontrar errores pero no es faacutecilgenerar un buen conjunto de instancias de prueba e incluso si lo hace no puedeestar seguro de que su programa sea correcto Seguacuten un informaacutetico muyfamoso

Las pruebas de programa se pueden usar para mostrar la presencia deerrores iexclpero nunca para mostrar su ausencia

mdash Edsger W Dijkstra

Glosarioobjeto archivo o file stream

Un valor que representa un archivo abierto

Depuracioacuten 119

reduccioacuten a un problema previamente resueltoUna manera de resolver un problema expresaacutendolo como una instancia deun problema previamente resuelto

caso especialUna instancia de prueba que es atiacutepica o no obvia (y por lo tanto menosprobable que se maneje correctamente)

Ejercicios

Ejercicio 9-7

Esta pregunta se basa en un Puzzle que se transmitioacute en el programa de radioCar Talk (httpswwwcartalkcompuzzlerbrowse)

Se tiene una secuencia de nuacutemeros y se desea saber cuaacutel es el siguiente Losnuacutemeros son 4 6 12 18 30 42 60 y luego X

Pista 1 Todos los nuacutemeros de la secuencia son pares Pista 2 El nuacutemero queva despueacutes del que estoy buscando es 102

iquestCuaacutel es el nuacutemero

Primero piense el patroacuten que busca y luego escriba un programa que le permitaencontrar el nuacutemero que sigue este patroacuten que se encuentra entre 60 y 102

Ejercicio 9-8

A continuacioacuten se muestra otro puzzle de Car Talk (httpswwwcartalkcompuzzlerbrowse)

120 Capiacutetulo 9 Estudio de Caso Juego de Palabras

Estaba conduciendo por la autopista el otro diacutea y vi mi odoacutemetro Como lamayoriacutea de los odoacutemetros muestra seis diacutegitos y solo en kiloacutemetros enterosEntonces si mi automoacutevil tuviera un kilometraje de 300000 por ejemploseriacutea 3-0-0-0-0-0

Ahora lo que vi ese diacutea fue muy interesante Noteacute que los uacuteltimos 4 diacutegitoseran palindroacutemicos es decir se leiacutean igual hacia adelante que hacia atraacutesPor ejemplo 5-4-4-5 es un paliacutendromo por lo que mi odoacutemetro podriacuteahaberse leiacutedo 3-1-5-4-4-5

Un kiloacutemetro despueacutes los uacuteltimos 5 nuacutemeros fueron palindroacutemicos Porejemplo podriacutea haberse leiacutedo 3-6-5-4-5-6 Un kiloacutemetro despueacutes de eso los 4nuacutemeros del medio eran palindroacutemicos iquestYhellip estaacutes listo para esto iexclUnkiloacutemetro despueacutes los 6 eran palindroacutemicos

La pregunta es iquestqueacute nuacutemero estaba en el odoacutemetro cuando mireacute porprimera vez

Escriba un programa de Julia que pruebe todos los nuacutemeros de seis diacutegitos eimprima cualquier nuacutemero que satisfaga estos requisitos

Ejercicio 9-9

Aquiacute hay otro puzzle de Car Talk que puede resolver con una buacutesqueda(httpswwwcartalkcompuzzlerbrowse)

Hace poco visiteacute a mi madre y nos dimos cuenta de que los dos diacutegitos quecomponen mi edad cuando se invertiacutean daban como resultado su edad Porejemplo si tiene 73 antildeos yo tengo 37 Nos preguntamos con queacute frecuenciaesto ha sucedido a lo largo de los antildeos pero nos desviamos de otros temas ynunca obtuvimos una respuesta

Cuando llegueacute a casa descubriacute que los diacutegitos de nuestras edades han sidoreversibles seis veces hasta ahora Tambieacuten descubriacute que si teniacuteamos suertevolveriacutea a suceder en unos antildeos y si tenemos mucha suerte sucederiacutea unavez maacutes despueacutes de eso En otras palabras habriacutea sucedido 8 vecesEntonces la pregunta es iquestcuaacutentos antildeos tengo ahora

Escriba un programa de Julia que busque soluciones para este puzzle

OBSERVACIOacuteN Puede encontrar la funcioacuten lpad uacutetil

Ejercicios 121

Capiacutetulo 10 ArreglosEste capiacutetulo presenta uno de los tipos maacutes uacutetiles de Julia los arreglos Tambieacutense trataraacuten objetos y lo que puede suceder cuando se tiene maacutes de un nombrepara el mismo objeto

Un arreglo es una secuenciaAl igual que una cadena de texto un arreglo es una secuencia de valores En unacadena los valores son caracteres en un arreglo pueden ser de cualquier tipoLos valores en un arreglo se denominan elementos o a veces items

Hay varias formas de crear un nuevo arreglo la maacutes sencilla es encerrar loselementos entre corchetes ([ ])

[10 20 30 40][abadejo falsiacutea estrambote]

El primer ejemplo es un arreglo de cuatro enteros El segundo es un arreglo detres cadenas de texto Los elementos de un arreglo no tienen por queacute ser delmismo tipo El siguiente arreglo contiene una cadena un nuacutemero de puntoflotante un entero y otro arreglo

[spam 20 5 [10 20]]

Se dice que un arreglo dentro de otro arreglo estaacute anidado

Un arreglo que no contiene elementos se llama arreglo vaciacuteo y se puede crearuno con corchetes vaciacuteos []

Como es de esperar se pueden asignar valores de arreglos a variables

juliagt quesos = [Cheddar Edam Gouda]

juliagt numeros = [42 123]

juliagt vacio = []

juliagt print(quesos numeros vacio)[Cheddar Edam Gouda] [42 123] Any[]

La funcioacuten typeof se puede usar para conocer el tipo del arreglo

122 Capiacutetulo 10 Arreglos

juliagt typeof(quesos)ArrayString1juliagt typeof(numeros)ArrayInt641juliagt typeof(vacio)ArrayAny1

El tipo del arreglo se especifica entre llaves y se compone de un tipo y unnuacutemero El nuacutemero indica las dimensiones El conjunto vaciacuteo contiene valores detipo Any es decir puede contener valores de todos los tipos

Los arreglos son mutablesLa sintaxis para acceder a los elementos de un arreglo es el mismo que paraacceder a los caracteres de una cadena el operador corchete La expresioacutendentro de los corchetes especifica el iacutendice Recuerde que los iacutendices comienzanen 1

juliagt quesos[1]Cheddar

A diferencia de las cadenas los arreglos son mutables lo que significa quepodemos cambiar sus elementos Se puede modificar uno de sus elementosusando el operador corchetes en el lado izquierdo de una asignacioacuten

juliagt numeros[2] = 55juliagt print(numeros)[42 5]

El segundo elemento de numeros que era 123 ahora es 5

Figura 11 muestra los diagramas de estado para quesos numeros y vacio

Figura 11 Diagrama de estado

Los arreglos son representados mediante cuadros con elementos del arreglo en

Los arreglos son mutables 123

su interior El arreglo quesos hace referencia a un arreglo con tres elementosindexados 1 2 y 3 El arreglo numeros contiene dos elementos El diagramamuestra que el valor del segundo elemento de numeros se ha reasignado de 123a 5 Finalmente vacio hace referencia a un arreglo sin elementos

Los iacutendices de un arreglo funcionan de la misma manera que los iacutendices de unacadena (pero sin los problemas generados por la codificacioacuten UTF-8)

bull Cualquier expresioacuten entera se puede usar como iacutendice

bull Si se intenta leer o escribir un elemento que no existe se obtiene unBoundsError

bull La palabra reservada end indica el uacuteltimo iacutendice del arreglo

El operador isin tambieacuten funciona en arreglos

juliagt Edam isin quesostruejuliagt Brie in quesosfalse

Recorriendo un ArregloLa forma maacutes comuacuten de recorrer los elementos de un arreglo es con un ciclo forLa sintaxis es la misma que para las cadenas

for queso in quesos println(queso)end

Esto funciona bien si solo se necesita leer los elementos del arreglo pero si sedesea escribir o actualizar los elementos es necesario utilizar iacutendices Una formacomuacuten de hacerlo es usando la funcioacuten integrada eachindex

for i in eachindex(numeros) numeros[i] = numeros[i] 2end

Este bucle recorre el arreglo y actualiza cada elemento En cada iteracioacuten delciclo i representa el iacutendice del elemento actual La sentencia de asignacioacuten usanumeros[i] para leer el valor original del elemento y asignar el nuevo valor

Por otra parte length devuelve el nuacutemero de elementos en el arreglo

Un ciclo for sobre un arreglo vaciacuteo nunca ejecuta el cuerpo del bucle

124 Capiacutetulo 10 Arreglos

for x in [] println(Esto nunca pasa)end

Aunque un arreglo puede contener otro arreglo este arreglo anidado cuentacomo un elemento uacutenico Por ejemplo la longitud de este arreglo es cuatro

[spam 1 [Brie Roquefort Camembert] [1 2 3]]

Porciones de arreglos

El operador porcioacuten tambieacuten funciona en arreglos

juliagt t = [a b c d e f]

juliagt print(t[13])[a b c]juliagt print(t[3end])[c d e f]

El operador porcioacuten [] hace una copia de todo el arreglo

juliagt print(t[])[a b c d e f]

Como los arreglos son mutables es uacutetil hacer una copia antes de realizaroperaciones que las modifiquen

Un operador porcioacuten en el lado izquierdo de una asignacioacuten puede actualizarvarios elementos

juliagt t[23] = [x y]

juliagt print(t)[a x y d e f]

Libreriacutea de ArreglosJulia tiene funciones integradas que operan en arreglos Por ejemplo pushagrega un nuevo elemento al final de un arreglo

Porciones de arreglos 125

juliagt t = [a b c]

juliagt push(t d)

juliagt print(t)[a b c d]

append agrega elementos de un arreglo al final de otro

juliagt t1 = [a b c]

juliagt t2 = [d e]

juliagt append(t1 t2)

juliagt print(t1)[a b c d e]

En este ejemplo t2 no es modificado

sort ordena los elementos de un arreglo de menor a mayor

juliagt t = [d c e b a]

juliagt sort(t)

juliagt print(t)[a b c d e]

sort devuelve una copia ordenada de los elementos de un arreglo

juliagt t1 = [d c e b a]

juliagt t2 = sort(t1)

juliagt print(t1)[d c e b a]juliagt print(t2)[a b c d e]

NOTA Como convencioacuten en Julia se agrega a los nombres de lasfunciones que modifican sus argumentos

126 Capiacutetulo 10 Arreglos

Mapear Filtrar y ReducirPara sumar todos los nuacutemeros en un arreglo se puede usar un ciclo como este

function sumartodo(t) total = 0 for x in t total += x end totalend

total se inicializa en 0 En cada iteracioacuten con += se antildeade un elemento delarreglo a la suma total El operador += es una forma simple de actualizar estavariable Esta sentencia de asignacioacuten aumentada

total += x

es equivalente a

total = total + x

A medida que se ejecuta el ciclo total acumula la suma de los elementos A vecesse denomina acumulador a una variable utilizada de esta manera

Sumar los elementos de un arreglo es una operacioacuten tan comuacuten que Julia tieneuna funcioacuten integrada para ello sum

juliagt t = [1 2 3 4]

juliagt sum(t)10

Una operacioacuten como esta que combina una secuencia de elementos en un solovalor a veces se denomina operacioacuten de reduccioacuten

Es comuacuten querer recorrer un arreglo mientras se construye otro Por ejemplo lasiguiente funcioacuten toma un arreglo de cadenas y devuelve un nuevo arreglo quecontiene las mismas cadenas pero en mayuacutesculas

Mapear Filtrar y Reducir 127

function todoenmayusculas(t) res = [] for s in t push(res uppercase(s)) end resend

res se inicializa con un arreglo vaciacuteo y en cada iteracioacuten se le agrega un nuevoelemento De esta manera res es otro tipo de acumulador

Una operacioacuten como todoenmayusculas a veces se denomina mapeo porqueasigna una funcioacuten (en este caso uppercase) a cada uno de los elementos deuna secuencia

Otra operacioacuten comuacuten es seleccionar solo algunos de los elementos de un arregloy devolver una sub-arreglo Por ejemplo la siguiente funcioacuten toma un arreglo decadenas y devuelve un arreglo que contiene solamente las cadenas enmayuacutesculas

function solomayusculas(t) res = [] for s in t if s == uppercase(s) push(res s) end end resend

Operaciones como solomayusculas se llaman filtro porque seleccionan soloalgunos elementos filtrando otros

Las operaciones de arreglos maacutes comunes son una combinacioacuten de mapeo filtroy reduccioacuten

Sintaxis de puntoPara cada operador binario como por ejemplo ^ existe un operador puntocorrespondiente ^ que automaacuteticamente define la operacioacuten ^ para cadaelemento de un arreglo Por ejemplo [1 2 3] ^ 3 no estaacute definido pero [12 3] ^ 3 se define como el resultado de realizar la operacioacuten ^ en cadaelemento [1^3 2^3 3^3]

128 Capiacutetulo 10 Arreglos

juliagt print([1 2 3] ^ 3)[1 8 27]

Cualquier funcioacuten f de Julia puede ser aplicada a cada elemento de cualquierarreglo con la sintaxis de punto Por ejemplo para poner en mayuacutesculas unarreglo de cadenas no es necesario un bucle expliacutecito

juliagt t = uppercase([abc def ghi])

juliagt print(t)[ABC DEF GHI]

Esta es una forma elegante de crear un mapeo Siguiendo esta loacutegica la funcioacutentodoenmayusculas puede implementarse con una liacutenea

function todoenmayusculas(t) uppercase(t)end

Borrando (Insertando) ElementosHay varias formas de eliminar elementos de un arreglo Si se conoce el iacutendice delelemento que se desea eliminar se puede usar splice

juliagt t = [a b c]

juliagt splice(t 2)b ASCIIUnicode U+0062 (category Ll Letter lowercase)juliagt print(t)[a c]

splice modifica el arreglo y devuelve el elemento que se eliminoacute

pop elimina y devuelve el uacuteltimo elemento

juliagt t = [a b c]

juliagt pop(t)c ASCIIUnicode U+0063 (category Ll Letter lowercase)juliagt print(t)[a b]

popfirst elimina y devuelve el primer elemento

Borrando (Insertando) Elementos 129

juliagt t = [a b c]

juliagt popfirst(t)a ASCIIUnicode U+0061 (category Ll Letter lowercase)juliagt print(t)[b c]

Las funciones pushfirst y push insertan un elemento al principio y al final delarreglo respectivamente

Si no se necesita el valor eliminado se puede usar la funcioacuten deleteat

juliagt t = [a b c]

juliagt print(deleteat(t 2))[a c]

La funcioacuten insert inserta un elemento en un iacutendice dado

juliagt t = [a b c]

juliagt print(insert(t 2 x))[a x b c]

Arreglos y CadenasUna cadena es una secuencia de caracteres y un arreglo es una secuencia devalores pero un arreglo de caracteres no es lo mismo que una cadena Paraconvertir una cadena a un arreglo de caracteres se puede usar la funcioacutencollect

juliagt t = collect(spam)

juliagt print(t)[s p a m]

La funcioacuten collect divide una cadena u otra secuencia en elementos individuales

Si desea dividir una cadena en palabras puede usar la funcioacuten split

juliagt t = split(En un lugar de la Mancha)

juliagt print(t)SubStringString[En un lugar de la Mancha]

130 Capiacutetulo 10 Arreglos

Un argumento opcional llamado delimitador especifica queacute caracteres usar comoliacutemites de palabra El siguiente ejemplo usa un guioacuten como delimitador

juliagt t = split(hola-hola-hola -)

juliagt print(t)SubStringString[hola hola hola]

join es el inverso de split Toma un arreglo de cadenas y concatena loselementos

juliagt t = [En un lugar de la Mancha]

juliagt s = join(t )En un lugar de la Mancha

En este caso el delimitador es un caraacutecter de espacio en blanco Para concatenarcadenas sin espacios no especifique un delimitador

Objeto y ValoresUn objeto es algo a lo que una variable puede referirse Hasta ahora podriacutea usarobjeto y valor indistintamente

Si ejecutamos estas sentencias de asignacioacuten

a = bananab = banana

Se sabe que a y b apuntan a una cadena pero no se sabe si estaacuten apuntando a lamisma cadena Hay dos estados posibles los cuales se muestran en la Figura 10-2

Figura 12 Diagramas de estado

En un caso a y b se refieren a dos objetos diferentes que tienen el mismo valorEn el segundo caso se refieren al mismo objeto

Para verificar si dos variables se refieren al mismo objeto se puede usar eloperador equiv (equiv TAB)) o ===

Objeto y Valores 131

juliagt a = bananabananajuliagt b = bananabananajuliagt a equiv btrue

En este ejemplo Julia solo creoacute un objeto de cadena y ambas variables a y bapuntan a ella Pero cuando se crean dos arreglos se obtienen dos objetos

juliagt a = [1 2 3]

juliagt b = [1 2 3]

juliagt a equiv bfalse

Entonces el diagrama de estado se ve asiacute Figura 13

Figura 13 Diagrama de estado

En este caso se podriacutea decir que los dos arreglos son equivalentes porquetienen los mismos elementos pero no ideacutenticos ya que no son el mismo objetoSi dos objetos son ideacutenticos tambieacuten son equivalentes pero si son equivalentesno son necesariamente ideacutenticos

Para ser precisos un objeto tiene un valor Si se evaluacutea [1 2 3] se obtendraacute unobjeto arreglo cuyo valor es una secuencia de enteros Si otro arreglo tiene losmismos elementos se dice que tiene el mismo valor pero no es el mismo objeto

Alias (poner sobrenombres)Si a apunta a un objeto y se asigna b = a entonces ambas variables se refierenal mismo objeto

juliagt a = [1 2 3]

juliagt b = a

juliagt b equiv atrue

El diagrama de estado seriacutea como este Figura 14

132 Capiacutetulo 10 Arreglos

Figura 14 Diagrama de estado

La asociacioacuten de una variable con un objeto se llama referencia En este ejemplohay dos referencias al mismo objeto

Un objeto con maacutes de una referencia tiene maacutes de un nombre por lo quedecimos que el objeto tiene un alias

Si el objeto con alias es mutable los cambios hechos a un alias afectan al otro

juliagt b[1] = 4242juliagt print(a)[42 2 3]

AVISOAunque este comportamiento puede ser uacutetil a veces puede inducira errores En general es maacutes seguro evitar los alias cuando setrabaje con objetos mutables

No hay problema con los alias al trabajar con objetos inmutables tales comocadenas de texto En este ejemplo

a = bananab = banana

Casi nunca es relevante que a y b se refieran a la misma cadena o no

Arreglos como argumentosCuando se pasa un arreglo como argumento de una funcioacuten en realidad se pasauna referencia a ella Si la funcioacuten modifica el arreglo el que hizo la llamadaveraacute el cambio Por ejemplo la funcioacuten borrarprimero elimina el primer elementode un arreglo

function borrarprimero(t) popfirst(t)end

Aquiacute se aprecia el uso de borrarprimero

Arreglos como argumentos 133

juliagt letras = [a b c]

juliagt borrarprimero(letras)

juliagt print(letras)[b c]

El paraacutemetro t y la variable letras son alias de un mismo objeto El diagrama deestado es asiacute Figura 15

Figura 15 Diagrama de estado

Como el arreglo estaacute compartido por dos marcos se dibuja entre ambos

Es importante distinguir entre operaciones que modifiquen arreglos yoperaciones que creen nuevas arreglos Por ejemplo push modifica un arreglopero vcat crea un nuevo arreglo

Aquiacute hay un ejemplo de push

juliagt t1 = [1 2]

juliagt t2 = push(t1 3)

juliagt print(t1)[1 2 3]

t2 es un alias de t1

Aquiacute hay un ejemplo de vcat

juliagt t3 = vcat(t1 [4])

juliagt print(t1)[1 2 3]juliagt print(t3)[1 2 3 4]

El resultado de vcat es un nuevo arreglo El arreglo original no ha sufridocambios

Esta diferencia es importante al momento de escribir funciones que modificanarreglos

134 Capiacutetulo 10 Arreglos

Por ejemplo esta funcioacuten no elimina el primer elemento de un arrreglo

function noborrarprimero(t) t = t[2end] MALOend

El operador porcioacuten crea un nuevo arreglo y la asignacioacuten hace que t se refiera aella pero eso no afecta al arreglo t fuera de la funcioacuten

juliagt t4 = noborrarprimero(t3)

juliagt print(t3)[1 2 3 4]juliagt print(t4)[2 3 4]

Al comienzo de noborrarprimero t y t3 se refieren al mismo arreglo Al final t serefiere a un nuevo arreglo pero t3 todaviacutea se refiere al arreglo original nomodificado

Una alternativa es escribir una funcioacuten que cree y devuelva un nuevo arregloPor ejemplo la funcioacuten cola devuelve todos menos el primer elemento de unarreglo

function cola(t) t[2end]end

Esta funcioacuten no modifica el arreglo original y se usa de la siguiente manera

juliagt letras = [a b c]

juliagt demas = cola(letras)

juliagt print(demas)[b c]

DepuracioacutenUn uso inadecuado de los arreglos (y otros objetos mutables) puede llevar alargas horas de depuracioacuten A continuacioacuten se muestran algunos errorescomunes y coacutemo evitarlos

bull La mayoriacutea de las funciones que operan en arreglos modifican el argumentoEsto es lo opuesto a lo que ocurre en las funciones que operan en cadenas

Depuracioacuten 135

de texto que devuelven una nueva cadena y dejan la original sinmodificaciones

Si estaacute acostumbrado a escribir coacutedigo con cadenas de texto como este

nueva_palabra = strip(palabra)

Puede parecer tentador escribir coacutedigo con arreglos como este

t2 = sort(t1)

Pero como sort devuelve el arreglo original t1 modificado t2 es un alias det1

OBSERVACIOacuteN

Antes de utilizar funciones y operadores dearreglos debe leer la documentacioacutendetenidamente y luego probarla en modointeractivo

bull Escoja una expresioacuten y queacutedese con ella

Parte del problema con los arreglos es que hay demasiadas formas de hacerlas cosas Por ejemplo para eliminar un elemento de un arreglo se puedeusar pop popfirst delete_at o incluso una asignacioacuten de porcioacuten Paraagregar un elemento se puede usar push pushfirst insert or vcatSuponiendo que t es un arreglo y x es un elemento estas formas soncorrectas

insert(t 4 x)push(t x)append(t [x])

Y estas incorrectas

insert(t 4 [x]) MALOpush(t [x]) MALOvcat(t [x]) MALO

bull Haga copias para evitar usar alias

Si se desea utilizar una funcioacuten como sort que modifica el argumento perotambieacuten se necesita mantener el arreglo original es posible hacer unacopia

136 Capiacutetulo 10 Arreglos

juliagt t = [3 1 2]

juliagt t2 = t[] t2 = copy(t)

juliagt sort(t2)

juliagt print(t)[3 1 2]juliagt print(t2)[1 2 3]

En este ejemplo tambieacuten podriacutea usar la funcioacuten incorporada sort quedevuelve un nuevo arreglo ordenado y no modifica el original

juliagt t2 = sort(t)

juliagt println(t)[3 1 2]juliagt println(t2)[1 2 3]

Glosarioarreglo

Una secuencia de valores

elementoUno de los valores de un arreglo (u otra secuencia) tambieacuten llamado iacutetem

lista anidadaUn arreglo que es elemento de otro arreglo

acumuladorUna variable utilizada en un ciclo para sumar o acumular un resultado

asignacioacuten aumentadaUna sentencia que actualiza el valor de una variable usando un operadorcomo +=

operador puntoOperador binario que se aplica a cada elemento de un arreglo

Glosario 137

sintaxis de puntoSintaxis utilizada para aplicar una funcioacuten a todos los elementos decualquier arreglo

operacioacuten de reduccioacutenUn patroacuten de procesamiento que recorre una secuencia y acumula loselementos en un solo resultado

mapeoUn patroacuten de procesamiento que recorre una secuencia y realiza unaoperacioacuten en cada elemento

filtroUn patroacuten de procesamiento que recorre una secuencia y selecciona loselementos que satisfacen alguacuten criterio

objetoUna cosa a la que se puede referir una variable Un objeto tiene tipo y valor

equivalenteTener el mismo valor

ideacutenticoSer el mismo objeto (lo que implica equivalencia)

referenciaLa asociacioacuten entre una variable y su valor

aliasMuacuteltiples variables que contienen referencias al mismo objeto

argumentos opcionalesArgumentos que no son necesarios

delimitadorUn caraacutecter o cadena utilizado para indicar donde debe cortarse unacadena

Ejercicios

estaordenada (generic function with 1 method)

138 Capiacutetulo 10 Arreglos

Ejercicio 10-1

Escriba una funcioacuten llamada sumaanidada que tome un arreglo de arreglos deenteros y sume los elementos de todos los arreglos anidados Por ejemplo

juliagt t = [[1 2] [3] [4 5 6]]

juliagt sumaanidada(t)21

Ejercicio 10-2

Escriba una funcioacuten llamada sumaacumulada que tome un arreglo de nuacutemeros ydevuelva la suma acumulativa es decir un nuevo arreglo donde el eacutesimoelemento es la suma de los primeros elementos del arreglo original Porejemplo

juliagt t = [1 2 3]

juliagt print(sumaacumulada(t))Any[1 3 6]

Ejercicio 10-3

Escriba una funcioacuten llamada interior que tome un arreglo y devuelva un nuevoarreglo que contenga todos los elementos excepto el primero y el uacuteltimo Porejemplo

juliagt t = [1 2 3 4]

juliagt print(interior(t))[2 3]

Ejercicio 10-4

Escriba una funcioacuten llamada interior que tome un arreglo lo modifiqueeliminando el primer y el uacuteltimo elemento y que no devuelva un valor Porejemplo

Ejercicios 139

juliagt t = [1 2 3 4]

juliagt interior(t)

juliagt print(t)[2 3]

Ejercicio 10-5

Escriba una funcioacuten llamada estaordenada que tome un arreglo como paraacutemetroy devuelva true si el arreglo se ordena en orden ascendente y false de locontrario Por ejemplo

juliagt estaordenada([1 2 2])truejuliagt estaordenada([b a])false

Ejercicio 10-6

Dos palabras son anagramas si se pueden ordenar las letras de una para escribirla otra Escriba una funcioacuten llamada esanagrama que tome dos cadenas ydevuelva true si son anagramas

Ejercicio 10-7

Escriba una funcioacuten llamada repetido que tome un arreglo y devuelva true si hayalguacuten elemento que aparece maacutes de una vez No debe modificar el arreglooriginal

Ejercicio 10-8

Este ejercicio se relaciona con la llamada paradoja del cumpleantildeos sobre la cualpuede leer en httpseswikipediaorgwikiParadoja_del_cumpleaC3B1os

Si hay 23 estudiantes en su clase iquestcuaacuteles son las posibilidades de que dos deustedes tengan el mismo cumpleantildeos Puede estimar esta probabilidadgenerando muestras aleatorias de 23 cumpleantildeos y buscando coincidencias

OBSERVACIOacuteN Puede generar cumpleantildeos aleatorios con rand(1365)

Ejercicio 10-9

Escriba una funcioacuten que lea el archivo palabrastxt y construya un arreglo con unelemento por palabra Escriba dos versiones de esta funcioacuten una con push y la

140 Capiacutetulo 10 Arreglos

otra con la expresioacuten t = [t x] iquestCuaacutel tarda maacutes en ejecutarse iquestPor queacute

Ejercicio 10-10

Para verificar si una palabra estaacute en el arreglo de palabras se puede usar eloperador isin Esto seriacutea lento pues este operador busca las palabras en orden

Debido a que las palabras estaacuten en orden alfabeacutetico se puede acelerar laverificacioacuten con una buacutesqueda de biseccioacuten (tambieacuten conocida como buacutesquedabinaria) que es similar a lo que se hace cuando se busca una palabra en eldiccionario Se comienza en el medio y se verifica si la palabra que se estaacutebuscando va antes que la palabra localizada en el medio Si es asiacute se busca en laprimera mitad de la matriz de la misma manera De lo contrario se busca en lasegunda mitad

En ambos casos se reduce el espacio de buacutesqueda restante a la mitad Si elarreglo de palabras tiene 113809 palabras se necesitaraacuten unos 17 pasos paraencontrar la palabra o concluir que no estaacute alliacute

Escriba una funcioacuten llamada enbiseccion que tome un arreglo ordenado y unvalor objetivo y devuelva true si la palabra estaacute en el arreglo y false si no lo estaacute

Ejercicio 10-11

Dos palabras son un par inverso si cada una es la inversa de la otra Escriba unprograma llamado parinverso que encuentre todos los pares inversos en elarreglo de palabras

Ejercicio 10-12

Dos palabras se entrelazan si al tomar letras alternando entre cada palabra seforma una nueva palabra Por ejemplo pi y as se entrelazan para formarpais

Creacutedito Este ejercicio estaacute inspirado en un ejemplo de httppuzzlersorg

1 Escriba un programa que encuentre todos los pares de palabras que seentrelazan

OBSERVACIOacuteN iexclNo enumere todos los pares

2 iquestPuede encontrar tres palabras que se entrelacen es decir cada terceraletra forma una palabra empezando de la primera segunda o tercera letrade la palabra

Ejercicios 141

Capiacutetulo 11 DiccionariosEste capiacutetulo presenta otro tipo integrado llamado diccionario

Un Diccionario es un MapeoUn diccionario es como una matriz pero maacutes general En una matriz los iacutendicestienen que ser enteros en un diccionario pueden ser (casi) de cualquier tipo

Un diccionario contiene una coleccioacuten de iacutendices llamados claves y unacoleccioacuten de valores Cada clave estaacute asociada a un solo valor La asociacioacutenentre una clave y un valor se denomina par clave-valor o a veces item

En lenguaje matemaacutetico un diccionario representa un mapeo de las claves a losvalores es decir cada clave apunta a un valor A modo de ejemplo se crea undiccionario que asocia palabras en espantildeol con palabras en ingleacutes En estediccionario las claves y los valores son cadenas

La funcioacuten Dict crea un nuevo diccionario sin elementos Como Dict es el nombrede una funcioacuten integrada de Julia debe evitar usarla como nombre de variable

juliagt ing_a_esp = Dict()DictAnyAny()

El tipo de este diccionario estaacute compuesto por el tipo de las claves y de losvalores entre llaves En este caso las claves y los valores son de tipo Any

El diccionario estaacute vaciacuteo Para agregar elementos a eacutel se pueden usar corchetes

juliagt ing_a_esp[one] = uno

Esta liacutenea de coacutedigo crea un elemento con la clave one que apunta al valoruno Si se imprime el diccionario nuevamente se ve un par clave-valor con unaflecha =gt entre la clave y el valor

juliagt ing_a_espDictAnyAny with 1 entry one =gt uno

Este formato de salida tambieacuten es un formato de entrada Por ejemplo se puedecrear un nuevo diccionario con tres iacutetems de la siguiente manera

142 Capiacutetulo 11 Diccionarios

juliagt ing_a_esp = Dict(one =gt uno two =gt dos three =gt tres)DictStringString with 3 entries two =gt dos one =gt uno three =gt tres

Todas las claves y valores iniciales son cadenas por lo que se crea unDictStringString

AVISO

El orden de los pares clave-valor podriacutea no ser el mismo Siescribe el mismo ejemplo en su computadora podriacutea obtener unresultado diferente En general el orden de los elementos en undiccionario es impredecible

Esto no significa un problema ya que los elementos de un diccionario nunca seindexan con iacutendices enteros En lugar de ello se utilizan las claves para buscarlos valores correspondientes

juliagt ing_a_esp[two]dos

La clave two da el valor dos asiacute que el orden de los iacutetems no importa

Si la clave no estaacute en el diccionario se da un mensaje de error

juliagt ing_a_esp[four]ERROR KeyError key four not found

La funcioacuten length tambieacuten funciona con diccionarios y devuelve el nuacutemero depares clave-valor

juliagt length(ing_a_esp)3

La funcioacuten keys devuelve una coleccioacuten con las claves del diccionario

juliagt ks = keys(ing_a_esp)

juliagt print(ks)[two one three]

Tambieacuten se puede usar el operador isin para ver si algo es una clave en undiccionario

Un Diccionario es un Mapeo 143

juliagt one isin kstruejuliagt uno isin ksfalse

Para ver si algo es un valor en un diccionario se puede usar la funcioacuten valuesque devuelve una coleccioacuten de valores y luego usar el operador isin

juliagt vs = values(ing_a_esp)

juliagt uno isin vstrue

El operador isin utiliza diferentes algoritmos para matrices y diccionarios Para lasmatrices busca los elementos de la matriz en orden como en Seccioacuten 88 Eltiempo de buacutesqueda es directamente proporcional al largo de la matriz

Para los diccionarios Julia usa un algoritmo llamado tabla hash que tiene unapropiedad importante el operador isin toma aproximadamente la misma cantidadde tiempo sin importar cuaacutentos elementos haya en el diccionario

Diccionario como una Coleccioacuten de FrecuenciasSuponga que tiene una cadena y desea contar cuaacutentas veces aparece cada letraHay varias formas de hacerlo

bull Podriacutea crear 27 variables una para cada letra del alfabeto Luego recorrerla cadena y para cada caraacutecter incrementar el contador correspondienteprobablemente utilizando condiciones encadenadas

bull Podriacutea crear una matriz con 27 elementos Luego podriacutea convertir cadacaraacutecter en un nuacutemero (usando la funcioacuten integrada Int) usar el nuacutemerocomo iacutendice en la matriz e incrementar el contador apropiado

bull Puede crear un diccionario con caracteres como claves y contadores comolos valores correspondientes La primera vez que vea un caraacutecter agregariacuteaun elemento al diccionario Despueacutes de eso incrementariacutea el valor de unelemento existente

Cada una de estas opciones realiza el mismo caacutelculo pero la implementacioacuten esdiferente

Una implementacioacuten es una forma de realizar un caacutelculo Algunasimplementaciones son mejores que otras por ejemplo una ventaja de laimplementacioacuten del diccionario es que no hace falta saber de antemano queacuteletras aparecen en la cadena y solo hay que agregar las letras que aparecen

144 Capiacutetulo 11 Diccionarios

Asiacute es como se veriacutea el coacutedigo

function histograma(s) d = Dict() for c in s if c notin keys(d) d[c] = 1 else d[c] += 1 end end dend

La funcioacuten se llama histograma que es un teacutermino en estadiacutestica para unacoleccioacuten de frecuencias (o conteos)

La primera liacutenea de la funcioacuten crea un diccionario vaciacuteo El ciclo for recorre lacadena s En cada iteracioacuten de este ciclo si el caraacutecter c no estaacute en eldiccionario se crea un nuevo elemento con la clave c y el valor inicial 1 (ya quehemos visto esta letra una vez) Si c ya estaacute en el diccionario se incrementa d[c]

Asiacute es como funciona

juliagt h = histograma(brontosaurus)DictAnyAny with 8 entries n =gt 1 s =gt 2 a =gt 1 r =gt 2 t =gt 1 o =gt 2 u =gt 2 b =gt 1

El histograma indica que las letras a y b aparecen una vez o aparece dosveces y asiacute sucesivamente

Los diccionarios tienen una funcioacuten llamada get que toma como argumentos undiccionario una clave y un valor predeterminado Si la clave aparece en eldiccionario get devuelve el valor correspondiente de lo contrario devuelve elvalor predeterminado Por ejemplo

Diccionario como una Coleccioacuten de Frecuencias 145

juliagt h = histograma(a)DictAnyAny with 1 entry a =gt 1juliagt get(h a 0)1juliagt get(h b 0)0

Ejercicio 11-1

Use get para escribir la funcioacuten histograma de manera maacutes concisa Deberiacuteapoder eliminar la declaracioacuten if

Iteracioacuten y DiccionariosEs posible recorrer las claves del diccionario con un ciclo for Por ejemploimprimirhist imprime cada clave y su valor correspondiente

function imprimirhist(h) for c in keys(h) println(c h[c]) endend

Asiacute es como se ve la salida

juliagt h = histograma(perros)

juliagt imprimirhist(h)s 1e 1p 1r 2o 1

Nuevamente las claves no estaacuten en un orden particular Para recorrer las clavesen orden puede usar sort y collect

146 Capiacutetulo 11 Diccionarios

juliagt for c in sort(collect(keys(h))) println(c h[c]) ende 1o 1p 1r 2s 1

Buacutesqueda inversaDado un diccionario d y una clave k es faacutecil encontrar el valor correspondiente v= d[k] Esta operacioacuten se llama buacutesqueda

Pero iquestqueacute pasa si se tiene v y se quiere encontrar k Existen dos problemasprimeramente puede haber maacutes de una clave que apunta al valor v Dependiendode lo que se quiera es posible que se pueda elegir una de estas claves o que setenga que hacer una matriz que las contenga a todas En segundo lugar no hayuna sintaxis simple para hacer una buacutesqueda inversa solo se debe buscar

A continuacioacuten se muestra una funcioacuten que toma un valor y que devuelve laprimera clave que apunta a ese valor

function busquedainversa(d v) for k in keys(d) if d[k] == v return k end end error(Error de Busqueda)end

Esta funcioacuten es otro ejemplo del patroacuten de buacutesqueda pero utiliza una funcioacutenque no hemos visto antes error La funcioacuten error se usa para producir unErrorException que interrumpe el flujo normal En este caso tiene el mensajeError de Busqueda que indica que no existe una clave

Si llega al final del ciclo eso significa que v no aparece en el diccionario como unvalor por lo que se produce una excepcioacuten

A continuacioacuten se muestra un ejemplo de una buacutesqueda inversa exitosa

juliagt h = histograma(perros)

juliagt key = busquedainversa(h 2)r ASCIIUnicode U+0072 (category Ll Letter lowercase)

Buacutesqueda inversa 147

y una no exitosa

juliagt key = busquedainversa(h 3)ERROR Error de Busqueda

El efecto cuando generamos una excepcioacuten es el mismo que cuando Julia generauna se imprime un trazado inverso y un mensaje de error

Julia proporciona una forma optimizada de hacer una buacutesqueda inversafindall(isequal(3)h)

AVISO

Una buacutesqueda inversa es mucho maacutes lenta que una buacutesquedadirecta Si tiene que hacer buacutesquedas inversas con frecuencia o siel diccionario es muy grande el rendimiento de su programa severaacute afectado

Diccionarios y MatricesLas matrices pueden aparecer como valores en un diccionario Por ejemplo si setiene un diccionario que asigna frecuencias a letras y se quiere invertir es decirtener un diccionario que asigne letras a frecuencias Dado que pueden habervarias letras con la misma frecuencia cada valor en el diccionario invertidodeberiacutea ser una matriz de letras

Aquiacute hay una funcioacuten que invierte un diccionario

function invertirdic(d) inverso = Dict() for clave in keys(d) val = d[clave] if val notin keys(inverso) inverso[val] = [clave] else push(inverso[val] clave) end end inversoend

Cada vez que se recorre el bucle se asigna a la variable clave una clave de d y aval el valor correspondiente Si val no estaacute en el diccionario inverso significa queno se ha visto este valor antes por lo que se crea un nuevo item y se inicializacon un singleton (una matriz que contiene un solo elemento) De lo contrario seha visto este valor antes por lo que se agrega la clave correspondiente a lamatriz

148 Capiacutetulo 11 Diccionarios

Aquiacute hay un ejemplo

juliagt hist = histograma(perros)

juliagt inverso = invertirdic(hist)DictAnyAny with 2 entries 2 =gt [r] 1 =gt [s e p o]

Figura 16 Diagrama de estado

Figura 16 es un diagrama de estado que muestra hist e inverso Un diccionariose representa como un cuadro con los pares clave-valor dentro En este libro silos valores son enteros nuacutemeros de punto flotante o cadenas de texto se dibujandentro del cuadro y las matrices (generalmente) se dibujan fuera del cuadrosolo para mantener el diagrama simple

NOTA

Anteriormente se mencionoacute que un diccionario se implementausando una tabla hash (tambieacuten llamada matriz asociativahashing mapa hash tabla de dispersioacuten o tabla fragmentada) locual significa que las claves deben ser hashable

Un hash es una funcioacuten que toma un valor (de cualquier tipo) ydevuelve un entero Los diccionarios usan estos enteros llamadosvalores hash para almacenar y buscar pares clave-valor

PistasSi estuvo jugando con la funcioacuten fibonacci de Seccioacuten 67 es posible que hayanotado que cuanto maacutes grande el argumento que le da maacutes tiempo tarda lafuncioacuten en ejecutarse Maacutes auacuten el tiempo de ejecucioacuten aumenta muyraacutepidamente

Para entender por queacute considere Figura 17 que muestra el graacutefico de llamadaspara la funcioacuten fibonacci con n = 4

Pistas 149

Figura 17 Graacutefico de llamadas

Un graacutefico de llamadas muestra un conjunto de cuadros de funciones con liacuteneasque conectan cada cuadro con los cuadros de las funciones a las que llama En laparte superior del graacutefico fibonacci con n = 4 llama a fibonacci con n = 3 y n =2 A su vez fibonacci con n = 3 llama a fibonacci con n = 2 y n = 1 Y asiacutesucesivamente

Cuente cuaacutentas veces se llama a fibonacci(0) y fibonacci(1) Esta es una solucioacutenineficiente al problema y empeora a medida que el argumento aumenta entamantildeo

Una solucioacuten es llevar un registro de los valores que ya se han calculadoalmacenaacutendolos en un diccionario Un valor que ya ha sido calculado yalmacenado para un uso posterior se le denomina pista Aquiacute hay unaimplementacioacuten de fibonacci con pistas

anteriores = Dict(0=gt0 1=gt1)

function fibonacci(n) if n isin keys(anteriores) return anteriores[n] end res = fibonacci(n-1) + fibonacci(n-2) anteriores[n] = res resend

El diccionario llamado anteriores mantiene un registro de los valores deFibonacci que ya conocemos El programa comienza con dos pares 0corresponde a 1 y 1 corresponde a 1

Siempre que se llama a fibonacci se comprueba si el diccionario contiene elresultado ya calculado Si estaacute ahiacute la funcioacuten puede devolver el valorinmediatamente Si no tiene que calcular el nuevo valor antildeadirlo al diccionario ydevolverlo

150 Capiacutetulo 11 Diccionarios

Si ejecuta esta versioacuten de fibonacci y la compara con la original se daraacute cuentaque es mucho maacutes raacutepida

Variables GlobalesEn el ejemplo anterior el diccionario anteriores se crea fuera de la funcioacuten porlo que pertenece al marco especial llamado Main Las variables en Main a vecesson llamadas globales porque se puede acceder a ellas desde cualquier funcioacutenA diferencia de las variables locales que desaparecen cuando finaliza su funcioacutenlas variables globales existen de una llamada de funcioacuten a la siguiente

Es comuacuten usar variables globales como flags o banderas es decir variablesbooleanas que indican si una condicioacuten es verdadera Por ejemplo algunosprogramas usan una bandera llamada verbosa para controlar el nivel de detalleen la salida

verbose = true

function ejemplo1() if verbosa println(Ejecutando ejemplo1) endend

Si intenta reasignar una variable global se sorprenderaacute El siguiente ejemplotrata de llevar registro sobre si se ha llamado o no a una funcioacuten

ha_sido_llamada = false

function ejemplo2() ha_sido_llamada = true MALOend

Pero si lo ejecuta veraacute que el valor de ha_sido_llamada no cambia El problemaes que ejemplo2 + crea una nueva variable local llamada +ha_sido_llamada Lavariable local desaparece cuando finaliza la funcioacuten y no tiene efecto en lavariable global

Para reasignar una variable global dentro de una funcioacuten debe declarar lavariable global antes de usarla (reasignacioacuten

Variables Globales 151

been_called = false

function ejemplo2() global ha_sido_llamada ha_sido_llamada = trueend

La sentencia global le dice al inteacuterprete algo como esto ldquoEn esta funcioacuten cuandodigo ha_sido_llamada me refiero a la variable global asiacute que no crees unavariable local

A continuacioacuten se muestra un ejemplo que intenta actualizar una variable global

conteo = 0

function ejemplo3() conteo = conteo + 1 MALOend

Si lo ejecuta obtiene

juliagt ejemplo3()ERROR UndefVarError conteo not defined

Julia asume que conteo es local y bajo esa suposicioacuten lo estaacute leyendo antes deescribirlo La solucioacuten nuevamente es declarar conteo como global

conteo = 0

function ejemplo3() global conteo conteo += 1end

Si una variable global se refiere a un valor mutable puede modificar el valor sindeclarar la variable global

anteriores = Dict(0=gt0 1=gt1)

function ejemplo4() anteriores[2] = 1end

Por lo tanto puede agregar eliminar y reemplazar elementos de una matriz

152 Capiacutetulo 11 Diccionarios

global o diccionario pero si desea reasignar la variable debe declararla global

anteriores = Dict(0=gt0 1=gt1)

function ejemplo5() global anteriores anteriores = Dict()end

Para mejorar el rendimiento puede declarar la variable global como constanteCon esto ya no se puede reasignar la variable pero si se refiere a un valormutable siacute se puede modificar el valor

const known = Dict(0=gt0 1=gt1)

function example4() known[2] = 1end

AVISOLas variables globales pueden ser uacutetiles pero si tiene muchas deellas y las modifica con frecuencia pueden dificultar ladepuracioacuten y empeorar el desempentildeo de los programas

DepuracioacutenA medida que trabaja con conjuntos de datos maacutes grandes la depuracioacutenmediante la impresioacuten y verificacioacuten de la salida de manera manual puedetornarse difiacutecil Aquiacute hay algunas sugerencias para depurar grandes conjuntos dedatos

bull Reduzca la entrada

Si es posible reduzca el tamantildeo del conjunto de datos Por ejemplo si elprograma lee un archivo de texto comience con solo las primeras 10 liacuteneaso con el ejemplo maacutes pequentildeo que pueda encontrar que produzca erroresNo debe editar los archivos sino modificar el programa para que solo lea lasprimeras liacuteneas

Si hay un error puede reducir al valor maacutes pequentildeo que manifieste elerror y luego aumentarlo gradualmente a medida que encuentre y corrijaerrores

bull Revisar resuacutemenes y tipos

En lugar de imprimir y verificar todo el conjunto de datos considereimprimir resuacutemenes de los datos Por ejemplo el nuacutemero de elementos en

Depuracioacuten 153

un diccionario o el total de una serie de nuacutemeros

Una causa comuacuten de los errores de tiempo de ejecucioacuten son los valores detipo incorrecto Para depurar este tipo de error generalmente es suficienteimprimir el tipo de un valor

bull Escribir autocomprobaciones

Puede escribir coacutedigo que verifique errores automaacuteticamente Por ejemplosi estaacute calculando el promedio de una matriz de nuacutemeros puede verificarque el resultado no sea mayor que el elemento maacutes grande de la matriz omenor que el maacutes pequentildeo Esto se llama prueba de cordura

Otro tipo de verificacioacuten compara los resultados de dos caacutelculos diferentespara ver si son consistentes Esta se llama prueba de consistencia

bull Formatear la salida

Formatear la salida de depuracioacuten puede hacer que sea maacutes faacutecil detectarun error Vimos un ejemplo en Seccioacuten 69

Nuevamente el tiempo que dedica a construir andamiaje puede reducir eltiempo que dedica a la depuracioacuten

Glosariomapeo

Una relacioacuten en la que cada elemento de un conjunto corresponde a unelemento de otro conjunto

diccionarioUna asignacioacuten de claves a sus valores correspondientes

par clave-valorLa representacioacuten de la asociacioacuten entre una clave y un valor

itemEn un diccionario otro nombre para un par clave-valor

claveUn objeto que aparece en un diccionario como la primera parte de un parclave-valor

valorUn objeto que aparece en un diccionario como la segunda parte de un parclave-valor Este teacutermino es maacutes especiacutefico que nuestro uso previo de lapalabra valor

154 Capiacutetulo 11 Diccionarios

implementacioacutenUna forma de realizar un caacutelculo

tabla hashEl algoritmo utilizado para implementar los diccionarios de Julia

funcioacuten hashUna funcioacuten utilizada por una tabla hash para calcular la ubicacioacuten de unaclave

hashableUn tipo que tiene una funcioacuten hash

buacutesquedaUna operacioacuten sobre un diccionario que toma una clave y encuentra el valorcorrespondiente

buacutesqueda inversaUna operacioacuten sobre un diccionario que toma un valor y encuentra una omaacutes claves que se asignan a eacutel

singletonUna matriz (u otra secuencia) con un solo elemento

graacutefico de llamadaUn diagrama que muestra cada cuadro creado durante la ejecucioacuten de unprograma con una flecha entre cada funcioacuten y sus respectivas funcionesllamadas

pistaValor precalculado y almacenado temporalmente para evitar caacutelculosredundantes

variable globalUna variable definida fuera de una funcioacuten Se puede acceder a las variablesglobales desde cualquier funcioacuten

sentencia globalUna sentencia que declara un nombre de variable global

banderaUna variable booleana utilizada para indicar si una condicioacuten es verdadera

Glosario 155

declaracioacutenUna sentencia como global que le dice al inteacuterprete algo sobre una variable

variable global constanteUna variable global que no se puede reasignar

Ejercicios

Ejercicio 11-2

Escriba una funcioacuten que lea las palabras en palabrastxt y las almacene comoclaves en un diccionario No importa cuaacuteles sean los valores Luego puede usar eloperador isin como una forma raacutepida de verificar si una cadena estaacute en eldiccionario

Si hizo Seccioacuten 101510 puede comparar la velocidad de esta implementacioacutencon el operador array isin y la buacutesqueda binaria

Ejercicio 11-3

Lea la documentacioacuten de la funcioacuten que opera sobre diccionarios get y uacuteselapara escribir una versioacuten maacutes concisa de invertirdic

Ejercicio 11-4

Use pistas en la funcioacuten de Ackermann de Seccioacuten 6112 y vea si esto permiteevaluar la funcioacuten con argumentos de mayor tamantildeo

Ejercicio 11-5

Si hizo Seccioacuten 10157 ya tiene una funcioacuten llamada repetido que toma unamatriz como paraacutemetro y devuelve true si hay alguacuten objeto que aparece maacutes deuna vez en la matriz

Use un diccionario para escribir una versioacuten maacutes raacutepida y simple de repetido

Ejercicio 11-6

Dos palabras son pares desplazados si puede desplazar una de ellas y obtenerla otra (vea desplazarpalabra en Seccioacuten 8155)

Escriba un programa que lea una matriz de palabras y encuentre todos los paresdesplazados

156 Capiacutetulo 11 Diccionarios

Ejercicio 11-7

Aquiacute hay otro Puzzle de Car Talk (httpswwwcartalkcompuzzlerbrowse)

This was sent in by a fellow named Dan OrsquoLeary He came upon a commonone-syllable five-letter word recently that has the following unique propertyWhen you remove the first letter the remaining letters form a homophone ofthe original word that is a word that sounds exactly the same Replace thefirst letter that is put it back and remove the second letter and the result isyet another homophone of the original word And the question is whatrsquos theword

Now Irsquom going to give you an example that doesnrsquot work Letrsquos look at thefive-letter word lsquowrackrsquo W-R-A-C-K you know like to lsquowrack with painrsquo If Iremove the first letter I am left with a four-letter word rsquoR-A-C-Krsquo As inlsquoHoly cow did you see the rack on that buck It must have been a nine-pointerrsquo Itrsquos a perfect homophone If you put the lsquowrsquo back and remove thelsquorrsquo instead yoursquore left with the word lsquowackrsquo which is a real word itrsquos justnot a homophone of the other two words

But there is however at least one word that Dan and we know of which willyield two homophones if you remove either of the first two letters to maketwo new four-letter words The question is whatrsquos the word

You can use the dictionary from Seccioacuten 11101 to check whether a string is inthe word array

OBSERVACIOacuteNTo check whether two words are homophones you canuse the CMU Pronouncing Dictionary You can downloadit from httpwwwspeechcscmueducgi-bincmudict

Write a program that lists all the words that solve the Puzzler

Ejercicios 157

Capiacutetulo 12 TuplasEste capiacutetulo presenta otro tipo integrado las tuplas Luego muestra coacutemo losarreglos los diccionarios y las tuplas funcionan en conjunto Tambieacuten se presentauna caracteriacutestica uacutetil para los arreglos de longitud variable como argumento losoperadores de recopilacioacuten y dispersioacuten

Las Tuplas son ImmutablesUna tupla es una secuencia de valores Estos valores pueden ser de cualquiertipo y estaacuten indexados por enteros por lo que las tuplas son muy parecidas a losarreglos La diferencia maacutes importante es que las tuplas son inmutables y quecada elemento puede tener su propio tipo

Una tupla es una lista de valores separados por comas

juliagt t = a b c d e(a b c d e)

Aunque no es necesario es comuacuten encerrar las tuplas entre pareacutentesis

juliagt t = (a b c d e)(a b c d e)

Para crear una tupla con un solo elemento se debe incluir una coma final

juliagt t1 = (a)(a)juliagt typeof(t1)TupleChar

AVISO

Un valor entre pareacutentesis sin coma no es una tupla

juliagt t2 = (a)a ASCIIUnicode U+0061 (category Ll Letter lowercase)juliagt typeof(t2)Char

Otra forma de crear una tupla es la funcioacuten de tupla integrada en Julia Sinargumento esta funcioacuten crea una tupla vaciacutea

juliagt tuple()()

158 Capiacutetulo 12 Tuplas

Si se tienen muacuteltiples argumentos el resultado es una tupla con los argumentosdados

juliagt t3 = tuple(1 a pi)(1 a π)

Ya que tuple es el nombre de una funcioacuten integrada debe evitar usarla comonombre de variable

La mayoriacutea de los operadores de arreglos tambieacuten sirven en las tuplas Eloperador corchete indexa un elemento

juliagt t = (a b c d e)

juliagt t[1]a ASCIIUnicode U+0061 (category Ll Letter lowercase)

Y el operador porcioacuten selecciona un rango de elementos

juliagt t[24](b c d)

Pero si se intenta modificar uno de los elementos de la tupla se obtendraacute unerror

juliagt t[1] = AERROR MethodError no method matching setindex(NTuple5Char CharInt64)

Como las tuplas son inmutables sus elementos no se pueden modificar

Los operadores relacionales funcionan con las tuplas y otras secuencias Juliacomienza comparando el primer elemento de cada secuencia Si son igualespasa a los siguientes elementos y asiacute sucesivamente hasta que encuentraelementos que difieren Los elementos posteriores no se consideran (incluso sison realmente grandes)

juliagt (0 1 2) lt (0 3 4)truejuliagt (0 1 2000000) lt (0 3 4)true

Las Tuplas son Immutables 159

Asignacioacuten de tuplaDe vez en cuando es uacutetil intercambiar los valores de dos variables Para hacerlocon sentencias de asignacioacuten convencionales se debe usar una variable temporalPor ejemplo para intercambiar a y b

temp = aa = bb = temp

Esta solucioacuten resulta aparatosa La asignacioacuten de tuplas soluciona este problemaelegantemente

a b = b a

El lado izquierdo es una tupla de variables y el lado derecho es una tupla deexpresiones Cada valor se asigna a su respectiva variable Todas las expresionesdel lado derecho se evaluacutean antes de las asignaciones

El nuacutemero de variables de la izquierda tiene que ser menor o igual que el nuacutemerode valores a la derecha

juliagt (a b) = (1 2 3)(1 2 3)juliagt a b c = 1 2ERROR BoundsError attempt to access (1 2) at index [3]

El lado derecho puede ser cualquier tipo de secuencia (cadena arreglo o tupla)Por ejemplo para dividir una direccioacuten de correo electroacutenico en nombre deusuario y dominio se puede escribir

juliagt addr = juliocesarromajuliocesarromajuliagt unombre dominio = split(addr )

El valor de retorno de split es un arreglo con dos elementos el primer elementose asigna a unombre y el segundo a dominio

juliagt unombrejuliocesarjuliagt dominioroma

160 Capiacutetulo 12 Tuplas

Tuplas como valor de retornoEstrictamente hablando una funcioacuten solo puede devolver un valor pero si elvalor es una tupla el efecto es el mismo que devolver muacuteltiples valores Porejemplo si desea dividir dos enteros y calcular el cociente y el resto esineficiente calcular x divide y y luego x y Es mejor calcular ambos al mismotiempo

La funcioacuten integrada divrem toma dos argumentos y devuelve una tupla de dosvalores el cociente y el resto El resultado puede ser almacenado como unatupla

juliagt t = divrem(7 3)(2 1)

Tambieacuten se puede utilizar asignacioacuten de tuplas para almacenar los elementos porseparado

juliagt q r = divrem(7 3)

juliagt show q rq = 2r = 1

Aquiacute hay un ejemplo de una funcioacuten que devuelve una tupla

function minmax(t) minimum(t) maximum(t)end

maximum y minimum son funciones integradas que encuentran los elementosmaacutes grandes y maacutes pequentildeos de una secuencia respectivamente La funcioacutenminmax calcula ambos y devuelve una tupla de dos valores Otra alternativa esutilizar la funcioacuten integrada extrema lo cual es maacutes eficiente

Tupla con Argumentos de Longitud VariableLas funciones pueden tomar un nuacutemero variable de argumentos Un nombre deparaacutemetro que termina con recopila argumentos en una tupla Por ejemploimprimirtodo toma cualquier nuacutemero de argumentos y los imprime

function imprimirtodo(args) println(args)end

Tuplas como valor de retorno 161

El paraacutemetro de recopilacioacuten puede tener cualquier nombre pero la convencioacutenes llamarlo args A continuacioacuten se muestra coacutemo funciona la funcioacuten

juliagt imprimirtodo(1 20 3)(1 20 3)

El opuesto de la recopilacioacuten es la dispersioacuten Si tiene una secuencia de valores ydesea pasarla a una funcioacuten como argumento muacuteltiple puede usar el operador Por ejemplo divrem toma exactamente dos argumentos y no funciona contuplas

juliagt t = (7 3)

juliagt divrem(t)ERROR MethodError no method matching divrem(TupleInt64Int64)

No obstante si dispersamos la tupla funciona

juliagt divrem(t)(2 1)

Muchas de las funciones integradas usan tuplas con argumentos de longitudvariable Por ejemplo max y min pueden tomar cualquier nuacutemero deargumentos

juliagt max(1 2 3)3

Pero sum no

juliagt sum(1 2 3)ERROR MethodError no method matching sum(Int64 Int64 Int64)

Ejercicio 12-1

Escriba una funcioacuten llamada sumartodo que tome cualquier nuacutemero deargumentos y devuelva su suma

En el mundo de Julia generalmente se le llama ldquoslurprdquo (sorber en espantildeol) areunir y splat (plaf en espantildeol como el ruido cuando cae algo) a dispersar

162 Capiacutetulo 12 Tuplas

Arreglos y tuplaszip es una funcioacuten integrada que toma dos o maacutes secuencias y devuelve unacoleccioacuten de tuplas donde cada tupla contiene un elemento de cada secuencia Elnombre de la funcioacuten se refiere a una cremallera que une e intercala dos filas dedientes

Este ejemplo une e intercala una cadena y un arreglo

juliagt s = abc

juliagt t = [1 2 3]

juliagt zip(s t)zip(abc [1 2 3])

El resultado es un objeto zip que permite iterar a traveacutes de los pares El uso maacutescomuacuten de zip es en un bucle for

juliagt for par in zip(s t) println(par) end(a 1)(b 2)(c 3)

Un objeto zip es un tipo de iterador que es cualquier objeto que itera a traveacutes deuna secuencia Los iteradores son en cierto modo similares a los arreglos peroa diferencia de estos uacuteltimos no se puede usar un iacutendice para seleccionar unelemento de un iterador

Si desea usar operadores y funciones de arreglos puede usar un objeto zip parahacer un arreglo

juliagt collect(zip(s t))3-element ArrayTupleCharInt641 (a 1) (b 2) (c 3)

El resultado es una serie de tuplas En este ejemplo cada tupla contiene uncaraacutecter de la cadena y el elemento correspondiente del arreglo

Si las secuencias no tienen la misma longitud el resultado tiene la longitud de lamaacutes corta

Arreglos y tuplas 163

juliagt collect(zip(Juan Gabriel))4-element ArrayTupleCharChar1 (J G) (u a) (a b) (n r)

Se puede usar asignacioacuten de tuplas en un bucle for para recorrer un arreglo detuplas

juliagt t = [(a 1) (b 2) (c 3)]

juliagt for (letra numero) in t println(numero letra) end1 a2 b3 c

En cada iteracioacuten del ciclo Julia selecciona la siguiente tupla en el arreglo yasigna estos elementos a letra y nuacutemero Los pareacutentesis de (letra nuacutemero) sonobligatorios

Combinando zip for y asignacioacuten de tuplas se obtiene una forma para recorrerdos (o maacutes) secuencias al mismo tiempo Por ejemplo la funcioacuten coinciden tomados secuencias t1 y t2 y devuelve true si hay un iacutendice i tal que t1[i] == t2[i]

function coinciden(t1 t2) for (x y) in zip(t1 t2) if x == y return true end end falseend

Si se necesita recorrer los elementos de una secuencia y sus iacutendices se puedeusar la funcioacuten integrada enumerate

juliagt for (indice elemento) in enumerate(abc) println(indice elemento) end1 a2 b3 c

164 Capiacutetulo 12 Tuplas

El resultado de enumerate es un objeto enumerate el cual hace una iteracioacutensobre una secuencia de pares doacutende cada par contiene un iacutendice (a partir de 1) yun elemento de la secuencia dada

Diccionarios y TuplasLos diccionarios se pueden usar como iteradores que iteran sobre los paresclave-valor Puede usarlos en un bucle for como este

juliagt d = Dict(a=gt1 b=gt2 c=gt3)

juliagt for (key value) in d println(key value) enda 1c 3b 2

Como es de esperar en un diccionario los elementos no estaacuten en un ordenparticular

Ahora si se quiere hacer lo contrario se puede usar una serie de tuplas parainicializar un nuevo diccionario

juliagt t = [(a 1) (c 3) (b 2)]

juliagt d = Dict(t)DictCharInt64 with 3 entries a =gt 1 c =gt 3 b =gt 2

Al combinar Dict con zip podemos crear un diccionario de una manera muysimple

juliagt d = Dict(zip(abc 13))DictCharInt64 with 3 entries a =gt 1 c =gt 3 b =gt 2

Es comuacuten usar tuplas como claves en los diccionarios Por ejemplo un directoriotelefoacutenico puede asignar nuacutemeros de teleacutefono a una tupla con apellido y nombreSuponiendo que se ha definido apellido nombre y numero podriacuteamos escribir

Diccionarios y Tuplas 165

directorio[apellido nombre] = numero

La expresioacuten entre pareacutentesis es una tupla Se podriacutea usar asignacioacuten de tuplaspara recorrer este diccionario

for ((apellido nombre) numero) in directorio println(nombre apellido numero)end

Este bucle recorre los pares clave-valor en directorio los cuales son tuplasAsigna los elementos de la clave de cada tupla a apellido y nombre y el valor anumero luego imprime el nombre y el nuacutemero de teleacutefono correspondiente

Hay dos formas de representar tuplas en un diagrama de estado La versioacuten maacutesdetallada muestra los iacutendices y elementos tal como aparecen en un arreglo Porejemplo la tupla (Cortaacutezar Julio) se veriacutea como en Figura 18

Figura 18 Diagrama de estado

Pero en un diagrama maacutes grande es posible que desee omitir algunos detallesPor ejemplo un diagrama del directorio telefoacutenico puede verse como en Figura19

Figura 19 Diagrama de estado

Aquiacute las tuplas se muestran usando la sintaxis de Julia para tener un esquemamaacutes simple El nuacutemero de teleacutefono del diagrama es el nuacutemero de reclamos de laBBC asiacute que no intentes llamar

Secuencias de SecuenciasHasta ahora el capiacutetulo se ha centrado en los arreglos de tuplas pero casi todoslos ejemplos que se han visto tambieacuten funcionan con arreglos de arreglos tuplasde tuplas y tuplas de arreglos Para evitar enumerar todas las posiblescombinaciones a veces es maacutes faacutecil hablar sobre secuencias de secuencias

En muchos contextos los diferentes tipos de secuencias (cadenas arreglos ytuplas) se pueden usar indistintamente Entonces iquestcoacutemo elegir uno u otro

166 Capiacutetulo 12 Tuplas

Para comenzar con lo mas obvio las cadenas son maacutes limitadas que las demaacutessecuencias porque los elementos deben ser caracteres Ademaacutes son inmutablesSi se necesita poder cambiar los caracteres en una cadena (en vez de crear unanueva) puede que lo mas adecuado sea elegir un arreglo de caracteres

Los arreglos se usan con mas frecuencia que las tuplas principalmente porqueson mutables No obstante hay algunos casos donde es posible que seapreferible usar tuplas

bull En algunos contextos como en una sentencia return resultasintaacutecticamente maacutes simple crear una tupla que un arreglo

bull Si se pasa una secuencia como argumento de una funcioacuten el uso de tuplasreduce los comportamientos potencialmente indeseados debido a lacreacioacuten de alias

bull Por rendimiento El compilador puede especializarse en este tipo

Dado que las tuplas son inmutables no tienen funciones como sort y reverseque modifiquen arreglos ya existentes Sin embargo Julia proporciona lasfunciones integradas sort que toma un arreglo y devuelve una secuencia nuevacon los mismos elementos ordenados y reverse que toma cualquier secuencia ydevuelve una secuencia nueva del mismo tipo con los mismos elementos en elorden contrario

DepuracioacutenLos arreglos diccionarios y tuplas son ejemplos de estructuras de datos En estecapiacutetulo se empiezan a ver estructuras de datos compuestas como arreglos otuplas y diccionarios que contienen tuplas como claves y arreglos como valoresLas estructuras de datos compuestas son uacutetiles aunque tambieacuten resultanpropensas a lo que se llaman errores de forma es decir errores causados cuandouna estructura de datos tiene el tipo tamantildeo o estructura incorrecta Porejemplo si estaacute esperando una lista con un entero y se le pasa simplemente unentero (no en una lista) no funcionaraacute

Julia permite antildeadir el tipo a elementos de una secuencia Esto se detalla enCapiacutetulo 17 Especificar el tipo elimina muchos errores de forma

Glosariotupla

Una secuencia inmutable de elementos donde cada elemento puede tener supropio tipo

asignacioacuten en tuplaUna asignacioacuten con una secuencia en el lado derecho y una tupla devariables en el izquierdo Primero se evaluacutea el lado derecho y luego sus

Depuracioacuten 167

elementos son asignados a las variables de la izquierda

reunirLa operacioacuten de armar una tupla con argumentos de longitud variable

dispersarLa operacioacuten de tratar una secuencia como una lista de argumentos

objeto zipEl resultado de llamar a la funcioacuten integrada zip un objeto que itera atraveacutes de una secuencia de tuplas

iteradorUn objeto que puede iterar a traveacutes de una secuencia pero que no tiene losoperadores y funciones de arreglos

estructura de datosUna coleccion de valores relacionados a menudo organizados en arreglosdiccionarios tuplas etc

error de formaUn error causado porque un valor tiene la forma incorrecta es decir el tipoo tamantildeo incorrecto

Ejercicios

Ejercicio 12-2

Escriba una funcioacuten llamada masfrecuente que tome una cadena e imprima lasletras en orden decreciente de frecuencia Encuentre muestras de texto de variosidiomas diferentes y vea coacutemo la frecuencia de las letras variacutea entre idiomasCompare sus resultados con las tablas en httpsenwikipediaorgwikiLetter_frequencies

Ejercicio 12-3

iexclMaacutes anagramas

1 Escriba un programa que lea una lista de palabras de un archivo (veaSeccioacuten 91) e imprima todos los conjuntos de palabras que son anagramas

Aquiacute hay un ejemplo de coacutemo se veriacutea la salida

168 Capiacutetulo 12 Tuplas

[brazo zobra broza zarbo][palabra parlaba][vida diva][gato toga gota]

OBSERVACIOacuteN

Es posible que desee crear un diccionario queasigne a una coleccioacuten de letras una serie depalabras que se puedan deletrear con esas letrasLa pregunta es iquestcoacutemo representar la coleccioacuten deletras de una manera que pueda usarse comoclave

2 Modifique el programa anterior para que imprima primero el arreglo maacuteslargo de anagramas seguido del segundo maacutes larga y asiacute sucesivamente

3 En Scrabble un bingo es cuando juegas las siete fichas de tu atril juntocon una letra del tablero para formar una palabra de ocho letras iquestQueacutecoleccioacuten de 8 letras forman parte del bingo maacutes probable

Ejercicio 12-4

Dos palabras metatizan si se puede transformar una en la otra intercambiandodos letras como es el caso de conversar y conservar Escriba un programaque encuentre todos los pares de metaacutetesis en el diccionario

OBSERVACIOacuteN No pruebe con todos los pares de palabras ni tampococon todos los intercambios posibles

Creacuteditos Este ejercicio estaacute inspirado en un ejemplo de httppuzzlersorg

Ejercicio 12-5

Aquiacute hay otro Puzzle de Car Talk (httpswwwcartalkcompuzzlerbrowse)

Ejercicios 169

iquestCuaacutel es la palabra en espantildeol maacutes larga que sigue siendo una palabra enespantildeol vaacutelida a medida que se eliminan sus letras una a una

Las letras se pueden eliminar de cualquier extremo o del medio pero no sepuede reordenar ninguna de ellas Cada vez que elimina una letra se quedacon otra palabra en espantildeol Eventualmente terminaraacute con una letra la cualtambieacuten seraacute una palabra en espantildeol que puede encontrar en el diccionarioSe desea saber cuaacutel es la palabra maacutes larga y cuaacutentas letras tiene

A modo de ejemplo piense en la palabra Palote iquestDe acuerdo Comienza conpalote elimina la letra p y queda alote luego se quita la t y queda aloe setoma la e y se tiene alo quitando la o se tiene al y finalmente eliminando lal queda a

Escriba un programa que encuentre todas las palabras que se pueden reducir deesta manera y luego encuentre la maacutes larga

OBSERVACIOacuteN

Este ejercicio es un poco maacutes desafiante que el resto asiacuteque aquiacute hay algunas sugerencias

1 Es posible que quiera escribir una funcioacuten que tomeuna palabra y calcule un arreglo de todas laspalabras que se pueden formar al eliminar unaletra Estos son los hijos de la palabra

2 De manera recursiva una palabra es reducible sialguno de sus hijos es reducible Como caso basepuede considerar la cadena vaciacutea reducible

3 La lista de palabras palabrastxt no tiene la cadenavaciacutea por lo que tendraacute que agregarla

4 Para mejorar el rendimiento de su programa esposible que desee guardar las palabras que se sabeque son reducibles

170 Capiacutetulo 12 Tuplas

Capiacutetulo 13 Estudio de Caso Seleccioacuten deEstructura de DatosHasta ahora hemos aprendido sobre las principales estructuras de datos de Juliay hemos visto algunos de los algoritmos que las utilizan

Este capiacutetulo presenta un estudio de caso con ejercicios que le permitenpracticar la eleccioacuten de estructuras de datos y su uso

Anaacutelisis de Frecuencia de PalabrasComo de costumbre se recomienda intentar resolver los ejercicios antes de leerlas soluciones

Ejercicio 13-1

Escriba un programa que lea un archivo divida cada liacutenea en palabras elimine elespacio en blanco y la puntuacioacuten de las palabras y luego las convierta enminuacutesculas

OBSERVACIOacuteN La funcioacuten isletter permite saber si un caraacutecterpertenece al alfabeto

Ejercicio 13-2

Vaya a la paacutegina de Proyecto Gutenberg (httpsgutenbergorg) y descargue sulibro favorito sin derechos de autor en formato de texto plano La mayoriacutea de loslibros estaacuten en ingleacutes pero existen algunos en espantildeol

Modifique su programa del ejercicio anterior para leer el libro que descargoacuteomita la informacioacuten del encabezado al comienzo del archivo y procese el restode las palabras tal como en el ejercicio previo

Luego modifique el programa para contar la cantidad total de palabras en ellibro y la cantidad de veces que se usa cada palabra

Imprima la cantidad de palabras diferentes que se usan en el libro Comparediferentes libros de diferentes autores escritos en diferentes eacutepocas iquestQueacute autorusa un vocabulario maacutes extenso

Ejercicio 13-3

Modifique el programa del ejercicio anterior para imprimir las 20 palabras maacutesutilizadas en el libro

Anaacutelisis de Frecuencia de Palabras 171

Ejercicio 13-4

Modifique el programa anterior para que lea una lista de palabras y luegoimprima todas las palabras del libro que no esteacuten en la lista de palabrasiquestCuaacutentos de ellos son errores tipograacuteficos iquestCuaacutentos de ellos son palabrascomunes que deberiacutean estar en la lista de palabras iquest Cuaacutentos de ellos sonteacuterminos realmente macabros

Nuacutemeros aleatoriosDadas las mismas entradas la mayor parte de los programas generan la mismasalida cada vez que los ejecutamos por lo que se dice que son deterministasNormalmente el determinismo es algo bueno ya que esperamos que un caacutelculonos entregue siempre el mismo resultado Para algunas aplicaciones sinembargo queremos que el computador sea impredecible Por ejemplo en losjuegos entre otros casos

Hacer que un programa sea realmente no determinista resulta difiacutecil pero hayformas de que hacer que al menos parezca no determinista Una de ellas es usaralgoritmos para generar nuacutemeros pseudoaleatorios Los nuacutemerospseudoaleatorios no son verdaderamente aleatorios porque se generan medianteun caacutelculo determinista pero al mirar estos nuacutemeros es casi imposibledistinguirlos de lo aleatorio

La funcioacuten rand devuelve un numero de punto flotante entre 00 y 10(incluyendo 00 pero no 10) Cada vez que usted llama a rand obtiene elsiguiente numero de una larga serie Para ver un ejemplo ejecute este bucle

for i in 110 x = rand() println(x)end

La funcioacuten rand puede tomar un iterador o arreglo como argumento y devuelveun elemento aleatorio de ellos

for i in 110 x = rand(16) print(x )end

Ejercicio 13-5

Escriba una funcioacuten llamada escogerdelhistograma que tome un histogramadefinido como en Seccioacuten 112 y devuelva un valor aleatorio del histogramaelegido con probabilidad proporcional a la frecuencia Por ejemplo para este

172 Capiacutetulo 13 Estudio de Caso Seleccioacuten de Estructura de Datos

histograma

juliagt t = [a a b]

juliagt histograma(t)DictAnyAny with 2 entries a =gt 2 b =gt 1

su funcioacuten debe devolver a con probabilidad y b con probabilidad

Histograma de PalabrasDebe hacer los ejercicios anteriores antes de continuar Tambieacuten necesitaraacutehttpsgithubcomJuliaIntroIntroAJuliajlblobmasterdataDonQuijotetxt

Aquiacute hay un programa que lee un archivo y construye un histograma de laspalabras en el archivo

function procesararchivo(nombrearchivo) hist = Dict() for linea in eachline(nombrearchivo) procesarlinea(linea hist) end histend

function procesarlinea(linea hist) linea = replace(linea - =gt ) for palabra in split(linea) palabra = string(filter(isletter [palabra])) palabra = lowercase(palabra) hist[palabra] = get(hist palabra 0) + 1 endend

Histograma de Palabras 173

DictAnyAny with 23607 entries enojoacute =gt 1 angosta =gt 1 hurto =gt 10 sirviesen =gt 2 solene =gt 1 coronan =gt 1 endereacutecese =gt 2 alteza =gt 15 rescatarlos =gt 1 enderezador =gt 1 libertad =gt 81 abundante =gt 5 bajeza =gt 4 embotoacute =gt 1 estime =gt 1 renovaban =gt 1 acreciente =gt 4 debieron =gt 8 garci =gt 1 ⋮ =gt ⋮

hist = procesararchivo(DonQuijotetxt)

Este programa lee DonQuijotetxt que contiene el texto de Don Quijote deMiguel de Cervantes

procesararchivo recorre las liacuteneas del archivo pasando una liacutenea a la vez aprocesarlinea El histograma hist se estaacute utilizando como acumulador

procesarlinea usa la funcioacuten replace para reemplazar los guiones por espaciosantes de usar split para dividir la liacutenea en un arreglo de cadenas Recorre elconjunto de palabras y usa filter isletter y lowercase para eliminar los signos depuntuacioacuten y convertir las palabras a minuacutesculas (Decir que las cadenas seconvierten es incorrecto recuerde que las cadenas son inmutables por lo queuna funcioacuten como lowercase devuelve cadenas nuevas)

Finalmente procesarlinea actualiza el histograma creando un nuevo elemento oincrementando uno existente

Para contar el nuacutemero total de palabras en el archivo podemos sumar lasfrecuencias en el histograma

function palabrastotales(hist) sum(values(hist))end

174 Capiacutetulo 13 Estudio de Caso Seleccioacuten de Estructura de Datos

El nuacutemero de palabras diferentes es el nuacutemero de elementos en el diccionario

function palabrasdiferentes(hist) length(hist)end

Para imprimir los resultados se puede usar el siguiente coacutedigo

juliagt println(Nuacutemero total de palabras palabrastotales(hist))Nuacutemero total de palabras 385925

juliagt println(Nuacutemero de palabras diferentes palabrasdiferentes(hist))Nuacutemero de palabras diferentes 23607

Observacioacuten No se considera el encabezado del archivo de texto soacutelo el libro

Palabras Maacutes ComunesPara encontrar las palabras maacutes comunes podemos hacer un arreglo de tuplasdonde cada tupla contiene una palabra y su frecuencia y ordenarlas Lasiguiente funcioacuten toma un histograma y devuelve un arreglo de tuplas defrecuencia de palabras

function mascomun(hist) t = [] for (clave valor) in hist push(t (valorclave)) end reverse(sort(t))end

En cada tupla la frecuencia aparece primero por lo que el arreglo resultante seordena por frecuencia A continuacioacuten se muestra un bucle que imprime las 10palabras maacutes comunes

t = mascomun(hist)println(Las palabras maacutes comunes son)for (frec palabra) in t[110] println(palabra t frec)end

En este ejemplo utilizamos un caraacutecter de tabulacioacuten (t) como separador envez de un espacio por lo que la segunda columna estaacute alineada A continuacioacutense muestran los resultados de Don Quijote

Palabras Maacutes Comunes 175

Las palabras maacutes comunes sonque 20626de 18217y 18188la 10363a 9881en 8241el 8210no 6345los 4748se 4690

OBSERVACIOacuteN

Este coacutedigo se puede simplificar usando comoargumento la palabra reservada rev de la funcioacuten sortPuede leer sobre esto en httpsdocsjulialangorgenv1basesortBasesort

Parametros OpcionalesSe han tratado funciones integradas de Julia que toman argumentos opcionalesTambieacuten es posible escribir funciones definidas por el programador conargumentos opcionales Por ejemplo aquiacute hay una funcioacuten que imprime laspalabras maacutes comunes en un histograma

function imprimirmascomun(hist num=10) t = mascomun(hist) println(Las palabras maacutes comunes son ) for (frec palabra) in t[1num] println(palabra t frec) endend

El primer paraacutemetro es obligatorio y el segundo es opcional El valorpredeterminado de num es 10

Si solo pasas un argumento

imprimirmascomun(hist)

num toma el valor predeterminado Si pasas dos argumentos

imprimirmascomun(hist 20)

num toma el valor del argumento En otras palabras el argumento opcional

176 Capiacutetulo 13 Estudio de Caso Seleccioacuten de Estructura de Datos

anula el valor predeterminado

Si una funcioacuten tiene paraacutemetros obligatorios y opcionales los paraacutemetrosobligatorios deben ir primero seguidos de los opcionales

Resta de DiccionarioEncontrar las palabras de un libro que no estaacuten en la lista de palabras depalabrastxt es un problema similar a una resta de conjuntos es decir se quiereencontrar todas las palabras de un conjunto (las palabras en el libro) que noestaacuten en el otro (las palabras en la lista)

resta toma los diccionarios d1 y d2 y devuelve un nuevo diccionario que contienetodas las claves de d1 que no estaacuten en d2 Como realmente no importan losvalores se fijan como nothing

function resta(d1 d2) res = Dict() for clave in keys(d1) if clave notin keys(d2) res[clave] = nothing end end resend

Para encontrar las palabras en el libro que no estaacuten en palabrastxt se ouedeusar procesararchivo para construir un histograma para palabrastxt y luego lafuncioacuten resta

palabras = procesararchivo(palabrastxt)dif = resta(hist palabras)

println(Palabras en el libro que no estaacuten en la lista de palabras)for palabra in keys(dif) print(palabra )end

Estos son algunos de los resultados de Don Quijote

Palabras en el libro que no estaacuten en la lista de palabrasenojoacute angosta coronan sirviesen solene endereacutecese rescatarlos embotoacuteestime renovaban

Algunas de estas palabras son conjugaciones de verbos Otros como solene yano son de uso comuacuten iexclPero algunas son palabras comunes que deberiacutean estar en

Resta de Diccionario 177

la lista

Ejercicio 13-6

Julia proporciona una estructura de datos llamada Set que permite muchasoperaciones comunes de conjuntos Puede leer sobre ellas en Seccioacuten 202 oconsultar la documentacioacuten en httpsdocsjulialangorgenv1basecollectionsSet-Like-Collections-1

Escriba un programa que use la resta de conjuntos para encontrar palabras en ellibro que no estaacuten en la lista de palabras

Palabras al AzarPara elegir una palabra aleatoria del histograma el algoritmo maacutes simple esconstruir un arreglo con muacuteltiples copias de cada palabra de acuerdo con lafrecuencia observada y luego elegir una palabra del arreglo

function palabraalazar(h) t = [] for (palabra frec) in h for i in 1frec push(t palabra) end end rand(t)end

Este algoritmo funciona pero no es muy eficiente ya que cada vez que elige unapalabra aleatoria reconstruye el arreglo que es tan grande como el librooriginal Una mejora es construir el arreglo una vez y luego hacer muacuteltiplesselecciones pero el arreglo sigue siendo grande

Una alternativa es

1 Use las claves para obtener un arreglo de palabras del libro

2 Cree un arreglo que contenga la suma acumulada de las frecuencias depalabras (vea Seccioacuten 10152) El uacuteltimo elemento en este arreglo es elnuacutemero total de palabras en el libro

3 Elija un nuacutemero aleatorio del 1 al Use buacutesqueda binaria (vea Seccioacuten101510) para encontrar el iacutendice donde se insertaraacute el nuacutemero aleatorio enla suma acumulada

4 Use el iacutendice para encontrar la palabra correspondiente en el arreglo depalabras

178 Capiacutetulo 13 Estudio de Caso Seleccioacuten de Estructura de Datos

Ejercicio 13-7

Escriba un programa que use este algoritmo para elegir una palabra aleatoriadel libro

Anaacutelisis de MarkovSi elige palabras del libro al azar puede tener una idea del vocabulario usadopero probablemente no se va a obtener una oracioacuten

rocinante plaacuteticas sazoacuten ojos Dulcinea Dios

Una serie de palabras aleatorias rara vez tiene sentido porque no hay relacioacutenentre palabras sucesivas Por ejemplo en una oracioacuten real se esperariacutea que unartiacuteculo como el fuese seguido por un sustantivo y probablemente no un verboo un adverbio

Una forma de medir este tipo de relaciones es con el anaacutelisis de Markov quedefine para una secuencia dada de palabras la probabilidad de las palabras quepodriacutean venir despueacutes Por ejemplo en la cancioacuten La vida es un carnaval (deCeliz Cruz)

Todo aquelQue piense que la vida siempre es cruelTiene que saber que no es asiacuteQue tan solo hay momentos malosY todo pasa

Todo aquelQue piense que esto nunca va cambiarTiene que saber que no es asiacuteQue al mal tiempo buena caraY todo cambia

Ay no hay que llorar (No hay que llorar)Que la vida es un carnavalQue es maacutes bello vivir cantando

En este texto la frase que piense siempre va seguida de la palabra que perola frase piense que puede ir seguida de la o esto

El resultado del anaacutelisis de Markov es un mapeo de cada prefijo (como quepiense y piense que) a todos los sufijos posibles (como la y esto)

Dada esta asignacioacuten se puede generar un texto aleatorio comenzando concualquier prefijo y eligiendo aleatoriamente entre los posibles sufijos A

Anaacutelisis de Markov 179

continuacioacuten puede combinar el final del prefijo y el nuevo sufijo para formar elsiguiente prefijo y repetir

Por ejemplo si comienza con el prefijo Que la la siguiente palabra seraacute vidaporque el prefijo solo aparece dos veces en el texto y siempre estaacute seguido deeste sufijo El siguiente prefijo es la vida por lo que el siguiente sufijo podriacuteaser siempre o es

En este ejemplo la longitud del prefijo siempre es dos pero puede hacer anaacutelisisde Markov con un prefijo de cualquier longitud

Ejercicio 13-8

Anaacutelisis de Markov

1 Escriba un programa que lea un texto desde un archivo y realice un anaacutelisisde Markov El resultado debe ser un diccionario que asocie prefijos y unacoleccioacuten de posibles sufijos La coleccioacuten puede ser un arreglo tupla odiccionario depende de usted hacer una eleccioacuten adecuada Puede probarsu programa con una longitud de prefijo de dos pero debe escribir elprograma de manera tal que sea faacutecil probar con otras longitudes

2 Agregue una funcioacuten al programa anterior para generar un texto aleatoriobasado en anaacutelisis de Markov Aquiacute hay un ejemplo de Don Quijote conlongitud de prefijo 2

Trifaldi habiacutea de Troya ni por la majestad real Y con mis quejasDesechaacutesteme iexcloh estremo su friacuteo del agravio a la espada tenieacutendolapor aca y maacutes que soacutelo se trueca y con el cual encendiacutea el ejemplo deaquellos cazadores

Para este ejemplo se dejoacute la puntuacioacuten anexa a las palabras El resultadoes casi sintaacutecticamente correcto Semaacutenticamente casi tiene sentido perono del todo

iquestQueacute sucede si aumenta la longitud del prefijo iquestEl texto aleatorio tiene maacutessentido

3 Una vez que su programa esteacute funcionando podriacutea probar combinandotexto de dos o maacutes libros El texto aleatorio que genere combinaraacute elvocabulario y las frases de las fuentes de maneras interesantes

Creacutedito Este estudio de caso se basa en un ejemplo de Kernighan y Pike ThePractice of Programming Addison-Wesley 1999

OBSERVACIOacuteN Debe hacer este ejercicio antes de continuar

180 Capiacutetulo 13 Estudio de Caso Seleccioacuten de Estructura de Datos

Estructuras de DatosUsar anaacutelisis de Markov para generar texto aleatorio es divertido pero ademaacuteseste ejercicio tiene un trasfondo la seleccioacuten de la estructura de datos En los losejercicios anteriores teniacutea que elegir

bull Coacutemo representar los prefijos

bull Coacutemo representar la coleccioacuten de los posibles sufijos

bull Coacutemo representar la asociacioacuten de cada prefijo con la coleccioacuten de posiblessufijos

El uacuteltimo es faacutecil un diccionario es la opcioacuten obvia para una asociacioacuten entreclaves y valores correspondientes

Para los prefijos las opciones maacutes obvias son cadena arreglo de cadenas o tuplade cadenas

Para los sufijos puede ser un arreglo o un histograma (diccionario)

iquestCoacutemo se elige El primer paso es pensar en las operaciones que deberaacuteimplementar para cada estructura de datos Para los prefijos se debe ser capazde eliminar palabras del principio y agregarlas al final Por ejemplo si el prefijoactual es que piense y la siguiente palabra es que debe poder formar elsiguiente prefijo piense que

Para los prefijos podriacutea elegir un arreglo ya que en eacutel es faacutecil agregar y eliminarelementos

Para la coleccioacuten de sufijos las operaciones que se deben realizar incluyenagregar un nuevo sufijo (o aumentar la frecuencia de uno existente) y elegir unsufijo aleatorio

Agregar un nuevo sufijo es igualmente faacutecil para la implementacioacuten del arreglo odel histograma Elegir un elemento aleatorio de un arreglo es faacutecil pero elegireficientemente de un histograma es maacutes difiacutecil (ver Seccioacuten 1371)

Hasta ahora se ha hablado principalmente sobre la facilidad de implementacioacutenpero hay otros factores a considerar al elegir las estructuras de datos Uno es eltiempo de ejecucioacuten A veces hay una razoacuten teoacuterica para esperar que unaestructura de datos sea maacutes raacutepida que otra Por ejemplo anteriormente semencionoacute que el operador in es maacutes raacutepido para los diccionarios que para losarreglos al menos cuando el nuacutemero de elementos es grande

Aunque generalmente no se sabe de antemano queacute implementacioacuten seraacute maacutesraacutepida una opcioacuten es implementar ambos y ver cuaacutel es mejor Este enfoque sellama benchmarking Una alternativa praacutectica es elegir la estructura de datosque sea maacutes faacutecil de implementar y luego ver si es lo suficientemente raacutepida parala aplicacioacuten prevista Si es asiacute no hay necesidad de continuar Si no hay

Estructuras de Datos 181

herramientas como el moacutedulo Profile que pueden identificar los lugares en unprograma que toman maacutes tiempo

El otro factor a considerar es el espacio de almacenamiento Por ejemplo usar unhistograma para la coleccioacuten de sufijos puede tomar menos espacio porque solotiene que almacenar cada palabra una vez sin importar cuaacutentas veces aparezcaen el texto En algunos casos ahorrar espacio tambieacuten puede hacer que suprograma se ejecute maacutes raacutepido En el peor de los casos su programa podriacutea noejecutarse si se queda sin memoria pero para muchas aplicaciones el espacio esuna consideracioacuten secundaria despueacutes del tiempo de ejecucioacuten

Una uacuteltima reflexioacuten en esta discusioacuten se ha dado a entender que se deberiacuteausar una estructura de datos para el anaacutelisis y la generacioacuten Pero dado queestas son fases separadas tambieacuten seriacutea posible usar una estructura para elanaacutelisis y luego convertirla en otra estructura para la generacioacuten Esto seriacuteaconveniente si el tiempo ahorrado durante la generacioacuten excede el tiempodedicado a la conversioacuten

OBSERVACIOacuteNEl paquete de Julia DataStructures (verhttpsgithubcomJuliaCollectionsDataStructuresjl)implementa una variedad de estructuras de datos

DepuracioacutenCuando estaacute depurando un programa y especialmente si estaacute tratando deresolver un error difiacutecil hay cinco cosas que puede probar

LeeExamine su coacutedigo leacutealo y verifique que dice lo que queriacutea decir

EjecutaExperimente haciendo cambios y ejecutando diferentes versiones Amenudo si muestra lo correcto en el lugar correcto del programa elproblema se vuelve obvio pero para ello a veces tiene que desarrollarandamiaje

ReflexionaiexclToacutemese un tiempo para pensar iquestQueacute tipo de error es de sintaxis tiempode ejecucioacuten o semaacutentica iquestQueacute informacioacuten puede obtener de los mensajesde error o de la salida del programa iquestQueacute tipo de error podriacutea causar elproblema que estaacutes viendo iquestQueacute cambioacute antes de que apareciera elproblema

HablaSi le explica el problema a otra persona a veces puede encontrar larespuesta incluso antes de terminar de hacer la pregunta Generalmente no

182 Capiacutetulo 13 Estudio de Caso Seleccioacuten de Estructura de Datos

es necesaria otra persona incluso se podriacutea hablar con un pato de gomaEste es el origen de la conocida estrategia llamada depuracioacuten del pato degoma Esto es real vea httpsenwikipediaorgwikiRubber_duck_debugging

Vuelve atraacutesEn ocasiones lo mejor que puede hacer es retroceder deshacer los cambiosrecientes hasta regresar a un programa que funcione y que comprenda Unavez logrado esto puede comenzar a reconstruir

Los programadores principiantes a veces se atascan en una de estas actividadesy olvidan las otras Cada actividad viene con su propia forma de fallar

Por ejemplo leer su coacutedigo podriacutea ayudar si el problema es un error tipograacuteficopero no si el problema es un malentendido conceptual Si no comprende lo quehace su programa puede leerlo 100 veces y nunca ver el error porque el errorestaacute en su cabeza

Ejecutar experimentos puede ayudar especialmente si ejecuta pruebas pequentildeasy simples pero si ejecuta experimentos sin pensar o leer su coacutedigo puede caeren un patroacuten llamado programacioacuten de caminata aleatoria que es el proceso dehacer cambios aleatorios hasta que el programa haga lo correcto No hace faltadecir que la programacioacuten de caminata aleatoria puede llevar mucho tiempo

La persona que programa tiene que tomarse su tiempo para pensar Ladepuracioacuten es como una ciencia experimental Debe tener al menos una hipoacutetesissobre la causa del problema Si hay dos o maacutes opciones trate de pensar en unaprueba que elimine una de ellas

Incluso las mejores teacutecnicas de depuracioacuten fallaraacuten si hay demasiados errores osi el coacutedigo que estaacute tratando de corregir es demasiado grande y complicado Aveces la mejor opcioacuten es volver atraacutes simplificando el programa hasta quellegue a algo que funcione y que comprenda

Los programadores principiantes a menudo son reacios a volver atraacutes porque nopueden soportar eliminar una liacutenea de coacutedigo (incluso si es incorrecto) Si le hacesentir mejor copie su programa en otro archivo antes de comenzar a eliminarloLuego puede copiar las piezas una por una

Encontrar un error difiacutecil requiere leer ejecutar reflexionar y a veces volveratraacutes Si se queda atascado en una de estas actividades pruebe las otras

Glosariodeterminiacutestico

Perteneciente a un programa que hace lo mismo cada vez que se ejecuta apartir de las mismas entradas

Glosario 183

pseudoaleatorioPerteneciente a una secuencia de nuacutemeros que parecen ser aleatorios peroque son generados por un programa determinista

valor por defecto (o valor por omisioacuten)El valor dado a un paraacutemetro opcional si no se proporciona un argumento

anularReemplazar un valor por defecto con un argumento

benchmarkingEl proceso de elegir entre estructuras de datos implementando alternativasy probaacutendolas con una muestra de las posibles entradas

depuracioacuten del pato de gomaDepuracioacuten en doacutende se explica el problema a un objeto inanimado talcomo un pato de goma Articular el problema puede ayudarle a resolverloincluso si el pato de goma no sabe de Julia

Ejercicios

Ejercicio 13-9

El rango de una palabra es su posicioacuten en un arreglo de palabras ordenadaspor frecuencia la palabra maacutes comuacuten tiene rango 1 la segunda maacutes comuacuten tienerango 2 etc

La ley de Zipf describe una relacioacuten entre los rangos y las frecuencias de laspalabras en idiomas naturales (httpsenwikipediaorgwikiZipfs_law)Especiacuteficamente predice que la frecuencia de la palabra con rango es

donde y son paraacutemetros que dependen del idioma y el texto Si aplicaslogaritmo a ambos lados de esta ecuacioacuten obtienes

Entonces si se grafica versus se deberiacutea obtener una liacutenea recta conpendiente e intercepto

Escriba un programa que lea un texto de un archivo cuente las frecuencias delas palabras e imprima una liacutenea para cada palabra en orden descendente defrecuencia con y

Instale una libreriacutea para graficar

184 Capiacutetulo 13 Estudio de Caso Seleccioacuten de Estructura de Datos

(v10) pkggt add Plots

Su uso es muy sencillo

using Plotsx = 110y = x^2plot(x y)

Use la libreriacutea Plots para graficar los resultados y verificar si forman una liacutenearecta

Ejercicios 185

Capiacutetulo 14 ArchivosEste capiacutetulo presenta el concepto de persistencia que alude a los programasque mantienen los datos en almacenamiento permanente y muestra coacutemo usardiferentes tipos de almacenamiento permanente tales como archivos y bases dedatos

PersistenciaLa mayoriacutea de los programas que hemos visto hasta ahora han sido transitorioses decir se ejecutan por un tiempo corto y generan una salida pero cuandofinalizan sus datos desaparecen Si ejecuta el programa nuevamente estecomienza de cero

Otros programas en cambio son persistentes se ejecutan durante un largoperiacuteodo de tiempo (o todo el tiempo) mantienen al menos parte de sus datos enalmacenamiento permanente (en un disco duro por ejemplo) y si se apagan yvuelven a comenzar retoman donde lo dejaron

Ejemplos de programas persistentes son los sistemas operativos que se ejecutansiempre que una computadora esteacute encendida y los servidores web que seejecutan todo el tiempo esperando a que lleguen solicitudes a la red

Una de las formas maacutes simples para que los programas mantengan sus datos esleyendo y escribiendo archivos de texto Ya se han visto programas que leenarchivos de texto y en este capiacutetulo se van a ver programas que los escriben

Otra alternativa es almacenar el estado del programa en una base de datos Eneste capiacutetulo tambieacuten se presentaraacute coacutemo usar una base de datos simple

Lectura y EscrituraUn archivo de texto es una secuencia de caracteres almacenados en un mediopermanente como un disco duro o una memoria flash Ya se vio coacutemo abrir y leerun archivo en Seccioacuten 91

Para escribir un archivo debe abrirlo usando el modo w (de write) comosegundo paraacutemetro

juliagt fout = open(salidatxt w)IOStream(ltfile salidatxtgt)

Si el archivo ya existe abrirlo en modo de escritura borra los datos antiguos ycomienza de nuevo iexclasiacute que tenga cuidado Si el archivo no existe se crea unonuevo open devuelve un objeto de archivo y la funcioacuten write escribe datos en elarchivo

186 Capiacutetulo 14 Archivos

juliagt linea1 = El Cid convoca a sus vasallosn

juliagt write(fout linea1)31

El valor de retorno es el nuacutemero de caracteres que se escribieron El objeto dearchivo fout lleva el registro de doacutende se quedoacute por uacuteltima vez por lo que sillama a write nuevamente esta agrega nuevos datos al final del archivo

juliagt linea2 = eacutestos se destierran con eacuteln

juliagt write(fout linea2)30

Cuando el usuario haya terminado de escribir debe cerrar el archivo

juliagt close(fout)

Si no cierra el archivo este se cierra cuando finaliza el programa

FormateoEl argumento de write tiene que ser una cadena por lo que si queremos ponerotros valores en un archivo tenemos que convertirlos a cadenas La forma maacutesfaacutecil de hacerlo es con la funcioacuten string o con interpolacioacuten de cadenas

juliagt fout = open(salidatxt w)IOStream(ltfile salidatxtgt)juliagt write(fout string(150))3

Otra alternativa es utilizar la familia de funciones de print(ln)

juliagt camellos = 4242juliagt println(fout He visto $camellos camellos)

OBSERVACIOacuteN

Una alternativa maacutes potente es la macro printf queimprime utilizando cadenas con especificacioacuten deformato al maacutes puro estilo C Puede leer maacutes sobre estoen httpsdocsjulialangorgenv1stdlibPrintf

Formateo 187

Nombre de Archivo y RutaLos archivos estaacuten organizados en directorios (tambieacuten llamados carpetas)Cada programa en ejecucioacuten tiene su propio directorio actual que es eldirectorio que usaraacute por defecto para para la mayoriacutea de las operaciones Porejemplo cuando abre un archivo para leer Julia lo busca en el directorio actual

La funcioacuten pwd (en ingleacutes print working directory) devuelve el nombre deldirectorio actual

juliagt cwd = pwd()homeben

cwd significa directorio del trabajo actual (en ingleacutes ldquocurrent workingdirectoryrdquo) El resultado en este ejemplo es homeben que es el directorio deinicio de un usuario llamado ben

Una cadena como homeben que identifica un archivo o directorio se llamaruta o path

Un nombre de archivo simple como memotxt tambieacuten se considera una rutaaunque es una ruta relativa porque comienza en el directorio actual Si eldirectorio actual es homeben el nombre de archivo memotxt se refiere ahomebenmemotxt

Una ruta que comienza con no depende del directorio actual Este tipo de rutase llama ruta absoluta Para encontrar la ruta absoluta de un archivo puede usarabspath

juliagt abspath(memotxt)homebenmemotxt

Julia tambieacuten tiene otras funciones para trabajar con nombres de archivo y rutasPor ejemplo ispath comprueba si existe un archivo o directorio

juliagt ispath(memotxt)true

Si existe isdir comprueba si es un directorio

juliagt isdir(memotxt)falsejuliagt isdir(homeben)true

188 Capiacutetulo 14 Archivos

Del mismo modo isfile comprueba que se trate de un archivo

readdir devuelve un arreglo de los archivos (y otros directorios) en el directoriodado

juliagt readdir(cwd)3-element ArrayString1 memotxt musica fotos

Para mostrar el comportamiento de estas funciones el siguiente ejemplorecorre un directorio imprime los nombres de todos los archivos y se llama a siacutemisma de manera recursiva en todos los directorios

function recorrer(nombredir) for nombre in readdir(nombredir) ruta = joinpath(nombredir nombre) if isfile(ruta) println(ruta) else recorrer(ruta) end endend

joinpath toma un directorio y un nombre de archivo y los une en una rutacompleta

OBSERVACIOacuteN

Julia tiene una funcioacuten integrada llamada walkdir (veahttpsdocsjulialangorgenv1basefileBaseFilesystemwalkdir) que es similar a esta pero maacutesversaacutetil Como ejercicio lea la documentacioacuten y uacuteselapara imprimir los nombres de los archivos en undirectorio dado y sus subdirectorios

Captura de ExcepcionesMuchas cosas pueden salir mal al intentar leer y escribir archivos Al intentarabrir un archivo que no existe se obtiene un SystemError

juliagt fin = open(archivo_malo)ERROR SystemError opening file archivo_malo No such file or directory

Si el usuario intenta abrir un archivo pero no tiene permiso para acceder a eacutel

Captura de Excepciones 189

obtiene el error de sistema Permission denied (Permiso denegado)

Para evitar estos errores se podriacutean usar funciones como ispath e isfile perotomariacutea mucho tiempo y liacuteneas de coacutedigo verificar todas las posibilidades

Es maacutes faacutecil intentar lidiar con los problemas a medida que ocurren que esexactamente lo que hace la sentencia try La sintaxis es similar a una sentenciaif

try fin = open(archivo_malotxt)catch exc println(Algo salioacute mal $exc)end

Julia comienza ejecutando el bloque try Si nada falla se saltaraacute el bloque catch yfinalizaraacute Si ocurre una excepcioacuten Julia saltaraacute fuera del bloque try y ejecutaraacuteel bloque catch

Gestionar una excepcioacuten con try recibe el nombre de capturar una excepcioacuten Eneste ejemplo el bloque catch muestra un mensaje de error que no es muy uacutetil Engeneral capturar una excepcioacuten da la oportunidad de corregir el problemavolverlo a intentar o al menos terminar el programa con elegancia

Cuando el coacutedigo realiza cambios de estado o usa recursos como archivosgeneralmente se deben hacer ciertas cosas al finalizar la programacioacuten delcoacutedigo como por ejemplo cerrar los archivos Las excepciones pueden complicaresta tarea ya que se podriacutea salir antes de lo esperado de un bloque de coacutedigo Lapalabra reservada finally permite ejecutar un coacutedigo al salir de un bloque decoacutedigo determinado independientemente de coacutemo salga

f = open(salidatxt)try linea = readline(f) println(linea)finally close(f)end

En este ejemplo la funcioacuten close siempre se ejecutaraacute

Bases de datosUna base de datos es un archivo que estaacute organizado para almacenar datos Lamayoriacutea de las bases de datos estaacuten organizadas como diccionarios en el sentidode que realizan asociaciones entre claves y valores La diferencia maacutes importanteentre un diccionario y una base de datos es que la base de datos se encuentra en

190 Capiacutetulo 14 Archivos

el disco (u otro almacenamiento permanente) de modo que su contenido seconserva despueacutes de que el programa haya finalizado

IntroAJulia proporciona una interfaz para GDBM (GNU dbm) que permite creary actualizar archivos de base de datos A modo de ejemplo se crea una base dedatos que contiene pies de foto para archivos de imagen

Abrir una base de datos es similar a abrir otros archivos

juliagt using IntroAJulia

juliagt bd = DBM(piedefoto c)DBM(ltpiedefotogt)

El modo c significa que la base de datos debe crearse si no existe El resultadoes un objeto de base de datos que se puede usar (para la mayoriacutea de lasoperaciones) como un diccionario

Cuando se crea un nuevo elemento GDBM actualiza el archivo de base de datos

juliagt bd[luismipng] = Foto de Luis MiguelFoto de Luis Miguel

Cuando accede a uno de los elementos GDBM lee el archivo

juliagt bd[luismipng]Foto de Luis Miguel

Si realiza otra asignacioacuten a una clave existente GDBM reemplaza el valoranterior

juliagt bd[luismipng] = Foto de Luis Miguel cantandoFoto de Luis Miguel cantandojuliagt bd[luismipng]Foto de Luis Miguel cantando

Algunas funciones que tienen un diccionario como argumento con claves yvalores no funcionan con objetos de base de datos No obstante la iteracioacuten conun bucle for siacute

for (clave valor) in bd println(clave valor)end

Al igual que con otros archivos debe cerrar la base de datos cuando haya

Bases de datos 191

terminado

juliagt close(bd)

SerializacioacutenUna limitacioacuten de GDBM es que las claves y los valores deben ser cadenas oconjuntos de bytes Si intenta utilizar cualquier otro tipo se produciraacute un error

Las funciones serialize y deserialize pueden ser uacutetiles Traducen casi cualquiertipo de objeto en un arreglo de bytes (un iobuffer) adecuado para elalmacenamiento en una base de datos y luego traducen los arreglos de bytesnuevamente en objetos

juliagt using Serialization

juliagt io = IOBuffer()

juliagt t = [1 2 3]

juliagt serialize(io t)24juliagt print(take(io))UInt8[0x37 0x4a 0x4c 0x0a 0x04 0x00 0x00 0x00 0x15 0x00 0x080xe2 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x02 0x00 0x000x00 0x00 0x00 0x00 0x00 0x03 0x00 0x00 0x00 0x00 0x00 0x000x00]

El formato no es intuitivo para nosotros pero es faacutecil de interpretar para Juliadeserialize reconstituye el objeto

juliagt io = IOBuffer()

juliagt t1 = [1 2 3]

juliagt serialize(io t1)24juliagt s = take(io)

juliagt t2 = deserialize(IOBuffer(s))

juliagt print(t2)[1 2 3]

serialize y deserialize escriben y leen desde un objeto iobuffer que representa unIO stream en memoria La funcioacuten take recupera el contenido del iobuffer como

192 Capiacutetulo 14 Archivos

un arreglo de bytes y reestablece el iobuffer a su estado inicial

Aunque el nuevo objeto tiene el mismo valor que el anterior no es (en general) elmismo objeto

juliagt t1 == t2truejuliagt t1 equiv t2false

En otras palabras la serializacioacuten y luego la deserializacioacuten tienen el mismoefecto que copiar el objeto

Esto se puede usar para almacenar valores que no sean cadenas en una base dedatos

OBSERVACIOacuteN

De hecho el almacenamiento de valores que no soncadenas en una base de datos es tan comuacuten que se haencapsulado en un paquete llamado JLD2 (consultehttpsgithubcomJuliaIOJLD2jl)

Objetos de ComandoLa mayoriacutea de los sistemas operativos proporcionan una interfaz de liacutenea decomandos tambieacuten conocida como shell Las shells generalmente proporcionancomandos para navegar por el sistema de archivos y ejecutar aplicaciones Porejemplo en Unix puede cambiar los directorios con cd mostrar el contenido deun directorio con ls e iniciar un navegador web escribiendo (por ejemplo) firefox

Cualquier programa que se pueda iniciar desde la shell tambieacuten puede iniciarsedesde Julia usando un objeto de comando

juliagt cmd = `echo hola``echo hola`

Las comillas invertidas se usan para delimitar el comando

La funcioacuten run ejecuta el comando

juliagt run(cmd)hola

hola es la salida del comando echo enviado a STDOUT La funcioacuten run devuelveun objeto de proceso y genera un ErrorException si el comando externo no se

Objetos de Comando 193

ejecuta correctamente

Si se desea leer la salida del comando externo se puede usar read en su lugar

juliagt a = read(cmd String)holan

Por ejemplo la mayoriacutea de los sistemas Unix tienen un comando llamadomd5sum o md5 que lee el contenido de un archivo y calcula una suma deverificacioacuten Puede leer sobre Md5 en httpsenwikipediaorgwikiMd5 Estecomando proporciona una manera eficiente de verificar si dos archivos tienen elmismo contenido La probabilidad de que diferentes contenidos produzcan lamisma suma de comprobacioacuten es muy pequentildea

Puede usar un objeto de comando para ejecutar md5 desde Julia y obtener elresultado

juliagt nombrearchivo = salidatxtsalidatxtjuliagt cmd = `md5 $nombrearchivo``md5 salidatxt`juliagt res = read(cmd String)ERROR IOError could not spawn `md5 salidatxt` no such file ordirectory (ENOENT)

Modulos

Supongamos que tenemos un archivo llamado wcjl con el siguiente coacutedigo

function contarlineas(nombrearchivo) conteo = 0 for linea in eachline(nombrearchivo) conteo += 1 end conteoend

print(contarlineas(wcjl))

Si ejecuta este programa se leen las liacuteneas de coacutedigo y se imprime el nuacutemero deliacuteneas en el archivo que es 9 Tambieacuten puede incluirlo en REPL de esta manera

juliagt include(wcjl)9

194 Capiacutetulo 14 Archivos

Los moacutedulos permiten crear espacios de trabajo separados es decir nuevosglobal scopes (aacutembitos de tipo global) Una sentencia tiene global scope si tieneefecto en todo el programa

Un moacutedulo comienza con la palabra reservada module y termina con end Al usarmoacutedulos se evitan los conflictos de nombres entre sus propias definiciones denivel superior y las que se encuentran en el coacutedigo de otra persona importpermite controlar queacute nombres de otros moacutedulos estaacuten visibles y exportespecifica cuaacuteles de sus nombres son puacuteblicos es decir aquellos que se puedenusar fuera del moacutedulo sin tener el prefijo del nombre del moacutedulo

module ContarLineas export contarlineas

function contarlineas(nombrearchivo) conteo = 0 for linea in eachline(nombrearchivo) conteo += 1 end conteo endend

El moacutedulo ContarLineas proporciona la funcioacuten contarlineas

juliagt using ContarLineas

juliagt contarlineas(wcjl)11

Ejercicio 14-1

Escriba este ejemplo en un archivo llamado wcjl incluacuteyalo en REPL (coninclude) y escriba using ContarLineas

AVISO

Si importa un moacutedulo que ya se ha importado Julia no hace nadaNo se vuelve a leer el archivo incluso si ha sido modificado

Si desea volver a cargar un moacutedulo debe reiniciar REPL Elpaquete Revise puede ayudarlo a no reiniciar tan seguido (veahttpsgithubcomtimholyRevisejl)

DepuracioacutenAl leer y escribir archivos el usuario puede tener problemas con los espacios enblanco Estos errores pueden ser difiacuteciles de depurar porque los espacios las

Depuracioacuten 195

tabulaciones y las nuevas liacuteneas son generalmente invisibles

juliagt s = 1 2t 3n 4

juliagt println(s)1 2 3 4

Las funciones integradas repr o dump pueden ser de ayuda Toman cualquierobjeto como argumento y devuelven una representacioacuten de tipo cadena delobjeto

1 2t 3n 4

juliagt repr(s)1 2t 3n 4juliagt dump(s)String 1 2t 3n 4

Esto puede ser uacutetil para la depuracioacuten

Otro problema con el que es faacutecil encontrarse es que en diferentes sistemasoperativos se usan diferentes caracteres para indicar el final de una liacuteneaAlgunos sistemas usan una nueva liacutenea representada por n Otros usan uncaraacutecter de retorno r Algunos usan ambos Si un archivo es usado en diferentessistemas estas inconsistencias podriacutean causar problemas

Para la mayoriacutea de los sistemas hay aplicaciones para convertir de un formato aotro Puede encontrarlas (y leer maacutes sobre este tema) enhttpsenwikipediaorgwikiNewline O por supuesto podriacutea escribir una ustedmismo

Glosariopersistente

Perteneciente a un programa que se ejecuta indefinidamente y mantiene almenos algunos de sus datos en almacenamiento permanente

archivo de textoUna secuencia de caracteres almacenados en almacenamiento permanentetal como en un disco duro

directorioUna coleccioacuten de archivos con nombre tambieacuten llamada carpeta

196 Capiacutetulo 14 Archivos

rutaUna cadena que identifica a un archivo

ruta relativaUna ruta que comienza en el directorio actual

ruta absolutaUna ruta que comienza en el directorio superior del sistema de archivos

capturar (catch)Evitar que una excepcioacuten haga terminar un programa utilizando lassentencias try catch finally

base de datosUn archivo cuyo contenido estaacute organizado como un diccionario con clavesque corresponden a valores

shellUn programa que permite a los usuarios escribir comandos y luegoejecutarlos iniciando otros programas

objeto de comandoUn objeto que representa un comando de shell Esto permite que unprograma de Julia ejecute comandos y lea los resultados

Ejercicios

Ejercicio 14-2

Escriba una funcioacuten llamada sed que tome como argumentos una cadena depatrones una cadena de reemplazo y dos nombres de archivo La funcioacuten debeleer el primer archivo y escribir el contenido en el segundo archivo (creaacutendolo sies necesario) Si la cadena de patrones aparece en alguacuten lugar del archivo debereemplazarse con la cadena de reemplazo

Si se produce un error al abrir leer escribir o cerrar los archivos su programadebe detectar la excepcioacuten imprimir un mensaje de error y terminar

Ejercicio 14-3

Si hizo Seccioacuten 12102 recordaraacute que debiacutea crear un diccionario que asociabauna cadena ordenada de letras al conjunto de palabras que se podiacutea deletrearcon esas letras Por ejemplo cuaderno estaba asociado al arreglo [cuadernoeducaron encuadro]

Escriba un moacutedulo que importe conjuntoanagramas y proporcione dos nuevas

Ejercicios 197

funciones almacenaranagramas que almacena el diccionario de anagramasusando JLD2 (vea httpsgithubcomJuliaIOJLD2jl) y leeranagramas que buscauna palabra y devuelve un arreglo de sus anagramas

Ejercicio 14-4

En una gran coleccioacuten de archivos MP3 puede haber maacutes de una copia de lamisma cancioacuten almacenada en diferentes directorios o con diferentes nombresde archivo El objetivo de este ejercicio es buscar duplicados

1 Escriba un programa que busque un directorio y todos sus subdirectoriosde forma recursiva y devuelva un arreglo de rutas completas para todos losarchivos con un sufijo dado (como mp3)

2 Para reconocer duplicados puede usar md5sum o md5 para calcular unasuma de verificacioacuten para cada archivo Si dos archivos tienen la mismasuma de verificacioacuten probablemente tengan el mismo contenido

3 Para verificarlo puede usar el comando de Unix diff

198 Capiacutetulo 14 Archivos

Capiacutetulo 15 Estructuras y ObjetosA esta altura ya debe saber coacutemo usar funciones para tener un coacutedigo maacutesorganizado y coacutemo usar los tipos integrados de Julia para organizar sus datos Elsiguiente paso es aprender a construir sus propios tipos para organizar tanto elcoacutedigo como los datos Este es un gran tema y por lo tanto tomaraacute un par decapiacutetulos abarcar todo

Tipos CompuestosSe han utilizado muchos tipos integrados en Julia y ahora se va a definir unnuevo tipo A modo de ejemplo se crea un tipo llamado Punto que representa unpunto en un espacio bidimensional

En notacioacuten matemaacutetica los puntos suelen escribirse entre pareacutentesis con unacoma que separa las coordenadas Por ejemplo representa el origen y representa el punto localizado unidades a la derecha y unidades hacia arribadel origen

Hay varias formas en que se podriacutean representar puntos del plano cartesiano enJulia

bull Almacenando las coordenadas por separado en dos variables x e y

bull Almacenando las coordenadas como elementos de un arreglo o tupla

bull Creando un nuevo tipo para representar puntos como objetos

Crear un nuevo tipo exige un poco maacutes de esfuerzo que las otras dos opcionespero tiene algunas ventajas como pronto se veraacute

Un tipo compuesto definido por el programador tambieacuten se denomina estructura(struct en ingleacutes) La definicioacuten de estructura de un punto se ve asiacute

struct Punto x yend

El encabezado indica que la nueva estructura se llama Punto El cuerpo definelos atributos o campos de la estructura La estructura de Punto tiene doscampos x e y

Una estructura es como una faacutebrica que crea objetos Para crear un punto sedebe llamar a Punto como si fuera una funcioacuten que tiene como argumentos losvalores de los campos Cuando Punto se usa como una funcioacuten se llamaconstructor

Tipos Compuestos 199

juliagt p = Punto(30 40)Punto(30 40)

El valor de retorno es una referencia a un objeto Punto el cual es asignado a p

La creacioacuten de un nuevo objeto se llama instanciacioacuten y el objeto creado es unainstancia del tipo

Cuando se imprime una instancia Julia dice a queacute tipo pertenece y cuaacuteles son losvalores de los atributos

Cada objeto es una instancia de alguacuten tipo por lo que objeto e instancia sonintercambiables No obstante en este capiacutetulo se utiliza instancia para indicarque se estaacute hablando de un tipo definido por el programador

Un diagrama de estado que muestra un objeto y sus atributos se denominadiagrama de objeto (ver Figura 20)

Figura 20 Diagrama de objeto

Las Estructuras son Inmutables

Puede obtener los valores de los campos utilizando la notacioacuten

juliagt x = px30juliagt py40

La expresioacuten px significa Vaya al objeto al que se apunta p y obtenga el valorde x En el ejemplo se asigna ese valor a una variable llamada x No hayconflicto entre la variable x y el atributo x

Puede usar esa notacioacuten de punto como parte de cualquier expresioacuten Porejemplo

juliagt distancia = sqrt(px^2 + py^2)50

Sin embargo las estructuras son inmutables por defecto y despueacutes de laconstruccioacuten los campos no pueden cambiar su valor

200 Capiacutetulo 15 Estructuras y Objetos

juliagt py = 10ERROR setfield immutable struct of type Punto cannot be changed

Esto puede parecer extrantildeo al principio pero tiene varias ventajas

bull Puede ser maacutes eficiente

bull No es posible violar las invariantes (requisitos que deberiacutean cumplirse entodos los objetos en todo momento) de los constructores de un tipocompuesto (ver Seccioacuten 174)

bull El coacutedigo que usa objetos inmutables puede ser maacutes faacutecil de entender

Estructuras MutablesDe ser necesario se pueden declarar tipos compuestos mutables con la palabrareservada mutable struct A continuacioacuten se muestra la definicioacuten de un puntomutable

mutable struct MPunto x yend

Puede asignar valores a una instancia de una estructura mutable utilizandonotacioacuten de punto ()

juliagt blanco = MPunto(00 00)MPunto(00 00)juliagt blancox = 3030juliagt blancoy = 4040

RectaacutengulosA veces decidir cuaacuteles deberiacutean ser los campos de un objeto es faacutecil pero enotros casos no Por ejemplo imagine que se quiere un tipo que represente unrectaacutengulo iquestQueacute campos usariacutea para especificar la ubicacioacuten y el tamantildeo de unrectaacutengulo Puede ignorar el aacutengulo Para simplificar las cosas suponga que elrectaacutengulo es vertical u horizontal

Hay al menos dos posibilidades

bull Puede especificar una esquina del rectaacutengulo (o el centro) el ancho y laaltura

Estructuras Mutables 201

bull Puede especificar dos esquinas opuestas

Es difiacutecil decir que una opcioacuten es mejor que la otra por lo que implementaremosla primera a modo de ejemplo

Representa un rectaacutengulo

atributos ancho alto esquinastruct Rectangulo ancho alto esquinaend

El texto escrito entre comillas triples es llamado cadena de documentacioacuten (odocstring) y permite documentar La documentacioacuten es el acto de comentarconvenientemente cada una de las partes que tiene el programa

En este ejemplo la cadena de documentacioacuten (o docstring) enumera losatributos Los atributos ancho y alto son nuacutemeros y esquina es un objeto Puntoque especifica la esquina inferior izquierda

Para representar un rectaacutengulo debe crear una instancia del tipo Rectangulo

juliagt origen = MPunto(00 00)MPunto(00 00)juliagt caja = Rectangulo(1000 2000 origen)Rectangulo(1000 2000 MPunto(00 00))

Figura 21 muestra el estado de este objeto Un objeto es embebido si es atributode otro objeto Debido a que el atributo esquina se refiere a un objeto mutablese dibuja fuera del objeto Rectangulo

Figura 21 Diagrama de objeto

Instancias como ArgumentosPodemos pasar una instancia como argumento de la manera habitual Porejemplo

202 Capiacutetulo 15 Estructuras y Objetos

function imprimirpunto(p) println(($(px) $(py)))end

imprimirpunto toma un Punto como argumento y lo muestra en notacioacutenmatemaacutetica Puede llamar a imprimirpunto con un argumento p

juliagt imprimirpunto(blanco)(30 40)

Ejercicio 15-1

Escriba una funcioacuten llamada distanciaentrepuntos que tome dos puntos comoargumentos y devuelva la distancia entre ellos

Si un objeto de estructura mutable se pasa a una funcioacuten como argumento lafuncioacuten puede modificar los campos del objeto Por ejemplo moverpunto tomaun objeto mutable Punto y dos nuacutemeros dx y dy los cuales suma a los atributos xe y de Punto respectivamente

function moverpunto(p dx dy) px += dx py += dy nothingend

Aquiacute hay un ejemplo que muestra como funciona

juliagt origen = MPunto(00 00)MPunto(00 00)juliagt moverpunto(origen 10 20)

juliagt origenMPunto(10 20)

Dentro de la funcioacuten p es un alias de origen por lo que cuando la funcioacutenmodifica p origen tambieacuten cambia

Al pasar un objeto inmutable Punto a moverpunto se produce un error

juliagt moverpunto(p 10 20)ERROR setfield immutable struct of type Punto cannot be changed

Sin embargo se puede modificar el valor de un atributo mutable de un objeto

Instancias como Argumentos 203

inmutable Por ejemplo moverrectangulo tiene como argumentos un objetoRectangulo y dos nuacutemeros dx y dy Esta funcioacuten usa moverpunto para mover laesquina del rectaacutengulo

function moverrectangulo(rect dx dy) moverpunto(rectesquina dx dy)end

Ahora p en moverpunto es un alias para rectesquina por lo que cuando p semodifica rectesquina tambieacuten cambia

juliagt cajaRectangulo(1000 2000 MPunto(00 00))juliagt moverrectangulo(caja 10 20)

juliagt cajaRectangulo(1000 2000 MPunto(10 20))

AVISO

No puede reasignar un atributo mutable de un objeto inmutable

juliagt cajaesquina = MPunto(10 20)ERROR setfield immutable struct of type Rectangulo cannotbe changed

Instancias como Valores de RetornoLas funciones pueden devolver instancias Por ejemplo encontrarcentro toma unRectangulo como argumento y devuelve un Punto que contiene las coordenadasdel centro del rectaacutengulo

function encontrarcentro(rect) Punto(rectesquinax + rectancho 2 rectesquinay + rectalto 2)end

La expresioacuten rectcornerx significa ldquoVaya al objeto al que rect apunta yseleccione el atributo llamado esquina Luego vaya a ese objeto y seleccione elatributo llamado x

A continucioacuten se observa un ejemplo que toma caja como argumento y asigna elPunto resultante a centro

juliagt centro = encontrarcentro(caja)Punto(510 1020)

204 Capiacutetulo 15 Estructuras y Objetos

CopiadoEl uso de alias puede hacer que un programa sea difiacutecil de leer ya que loscambios hechos en un lugar pueden tener efectos inesperados en otro lugar Esdifiacutecil estar al tanto de todas las variables a las que puede apuntar un objetodado

Copiar un objeto es muchas veces una alternativa a la creacioacuten de un alias Juliaprovee una funcioacuten llamada copy que puede duplicar cualquier objeto

juliagt p1 = MPunto(30 40)MPunto(30 40)juliagt p2 = deepcopy(p1)MPunto(30 40)juliagt p1 equiv p2falsejuliagt p1 == p2false

El operador equiv indica que p1 y p2 no son el mismo objeto lo cual es esperable Loque no es del todo esperable es que == no devuelva true aunque estos puntoscontengan los mismos datos Resulta que para los objetos mutables elcomportamiento predeterminado del operador == es el mismo que el operador=== es decir comprueba la identidad del objeto no la equivalencia del objetoEsto se debe a que Julia no sabe queacute deberiacutea considerarse equivalente para lostipos compuestos mutables Al menos no todaviacutea

Ejercicio 15-2

Cree una instancia de Punto haga una copia y verifique la equivalencia y laigualdad de ambas El resultado puede sorprenderlo pero explica por queacute elalias no es un problema para un objeto inmutable

DepuracioacutenAl comenzar a trabajar con objetos es probable que encuentre algunasexcepciones nuevas Si intenta acceder a un campo que no existe obtendraacute

juliagt p = Punto(30 40)Punto(30 40)juliagt pz = 10ERROR type Punto has no field z

Si no estaacute seguro del tipo de un objeto puede saberlo de la siguiente manera

Copiado 205

juliagt typeof(p)Punto

Tambieacuten puede usar isa para verificar si un objeto es una instancia de un tipoespeciacutefico

juliagt p isa Puntotrue

Si no estaacute seguro de si un objeto tiene un atributo particular puede usar lafuncioacuten fieldnames

juliagt fieldnames(Punto)(x y)

o la funcioacuten isdefined

juliagt isdefined(p x)truejuliagt isdefined(p z)false

El primer argumento puede ser cualquier objeto y el segundo argumento es elsiacutembolo seguido del nombre del atributo

Glosarioestructura

Un tipo compuesto

constructorUna funcioacuten con el mismo nombre que un tipo que crea instancias de estetipo

instanciaUn objeto que pertenece a un tipo

instanciarCrear un nuevo objeto

atributo o campoUn valor con nombre asociado un objeto

206 Capiacutetulo 15 Estructuras y Objetos

objeto embebidoUn objeto que se almacena como atributo de otro objeto

deep copy o copia profundaCopiar el contenido de un objeto y cualquier objeto embebido en eacutel y a suvez cualquier objeto embebido en ellos y asiacute sucesivamente Implementadopor la funcioacuten deepcopy

diagrama de objetoUn diagrama que muestra objetos sus atributos y valores de atributos

Ejercicios

Ejercicio 15-3

1 Escriba una definicioacuten de un tipo llamado Circulo que tenga atributos centroy radio y doacutende centro sea un objeto Punto y radio un nuacutemero

2 Cree una instancia de un objeto Circulo que represente a un ciacuterculo concentro en y radio 75

3 Escriba una funcioacuten llamada puntoencirculo que tome un objeto Circulo y unobjeto Punto y devuelva true si el punto se encuentra dentro o en el liacutemitedel ciacuterculo

4 Escriba una funcioacuten llamada rectencirculo que tome un objeto Circulo y unobjeto Rectangulo y devuelva true si el rectaacutengulo se encuentracompletamente dentro o en el liacutemite del ciacuterculo

5 Escriba una funcioacuten llamada sobreposicionrectcirc que tome un objetoCirculo y un objeto Rectangulo y devuelva true si alguna de las esquinas delrectaacutengulo cae dentro del ciacuterculo Una versioacuten maacutes desafiante es escribiruna funcioacuten que devuelva true si alguna parte del rectaacutengulo (nonecesariamente una esquina) cae dentro del ciacuterculo

Ejercicio 15-4

1 Escriba una funcioacuten llamada dibujarrect que tome como argumentos unobjeto turtle y un objeto Rectaacutengulo y use turtle para dibujar el rectaacutenguloConsulte el Capiacutetulo 4 para ver ejemplos que usen objetos Turtle

2 Escriba una funcioacuten llamada dibujarcirculo que tome como argumentos unobjeto Turtle y un objeto Circulo y dibuje el ciacuterculo

Ejercicios 207

Capiacutetulo 16 Estructuras y FuncionesAhora que se ha tratado coacutemo crear tipos compuestos el siguiente paso esescribir funciones que tomen objetos definidos por el programador comoparaacutemetros y que devuelvan otros como resultados En este capiacutetulo tambieacuten sepresenta el estilo de programacioacuten funcional y dos nuevas formas dedesarrollar programas

TiempoComo otro ejemplo de tipo compuesto se define una estructura llamada Horaque registra la hora del diacutea La definicioacuten de esta estructura se muestra acontinuacioacuten

Representa la hora del diacutea

atributos hora minuto segundostruct Hora hora minuto segundoend

Observacioacuten Time es una palabra reservada de Julia

juliagt tiempo = Hora(11 59 30)Hora(11 59 30)

El diagrama de objeto para el objeto Hora luce asiacute Figura 22

Figura 22 Diagrama de objeto

Ejercicio 16-1

Escriba una funcioacuten llamada imprimirhora que tome un objeto Hora y lo imprimacon el formato horaminutosegundo Printf de la macro printf del moacuteduloStdLib permite imprimir un nuacutemero entero con el formato 02d es decirutilizando al menos dos diacutegitos incluido un cero inicial si es necesario

208 Capiacutetulo 16 Estructuras y Funciones

Ejercicio 16-2

Escriba una funcioacuten booleana llamada estadespues que tome dos objetos Horat1 y t2 y devuelva true si la hora t1 estaacute despueacutes que t2 y false de lo contrarioDesafiacuteo no use sentencias if

Funciones PurasEn las siguientes secciones se escriben dos versiones de una funcioacuten que calculala suma de horas La primera versioacuten muestra un tipo de funcioacuten llamado funcioacutenpura y la segunda un tipo llamado modificador Ademaacutes estas versionespermitiraacuten mostrar un nuevo plan de desarrollo de programas llamado desarrollode prototipos una forma de abordar un problema complejo comenzando con unprototipo simple y lidiando gradualmente con las complicaciones

Este es un primer prototipo de la funcioacuten sumahora

function sumahora(t1 t2) Hora(t1hora + t2hora t1minuto + t2minuto t1segundo +t2segundo)end

La funcioacuten crea un nuevo objeto Hora inicializa sus atributos y devuelve unareferencia al nuevo objeto A esto se le llama funcioacuten pura porque no modificaninguno de los objetos que se le pasan como argumento y no tiene efectos (comomostrar un valor o tomar una entrada del usuario) maacutes que devolver un valor

Para probar esta funcioacuten se crean dos objetos Hora inicio que contiene la horade inicio de una peliacutecula como Roma y duracion que contiene la duracioacuten de lapeliacutecula que es dos horas y 15 minutos

sumahora calcula cuaacutendo se terminaraacute la peliacutecula

imprimirhora (generic function with 1 method)

juliagt inicio = Hora(9 50 0)

juliagt duracion = Hora(2 15 0)

juliagt finaliza = sumahora(inicio duracion)

juliagt imprimirhora(finaliza)116500

El resultado 116500 no es lo que se buscaba El problema es que esta funcioacuten

Funciones Puras 209

no considera los casos en los que el nuacutemero de segundos o minutos suma maacutesque sesenta Cuando esto ocurre debemos acarrear (como en una suma) lossegundos sobrantes a la columna de los minutos o los minutos extras a lacolumna de las horas He aquiacute una versioacuten corregida de la funcioacuten

function sumahora(t1 t2) segundo = t1segundo + t2segundo minuto = t1minuto + t2minuto hora = t1hora + t2hora if segundo gt= 60 segundo -= 60 minuto += 1 end if minuto gt= 60 minuto -= 60 hora += 1 end Hora(hora minuto segundo)end

Aunque esta funcioacuten es correcta es muy larga Maacutes adelante se exploraraacute unaalternativa maacutes corta

ModificadoresHay veces en las que es uacutetil que una funcioacuten modifique uno o maacutes de los objetosque recibe como paraacutemetros En ese caso los cambios son visibles en el nivel endonde se ubica la sentencia de llamada Estas funciones se llaman modificadores

La funcioacuten incrementar que agrega un nuacutemero dado de segundos a un objetoHora puede escribirse naturalmente como un modificador Aquiacute se muestra unprototipo de la funcioacuten

function incrementar(tiempo segundos) tiemposegundo += segundos if tiemposegundo gt= 60 tiemposegundo -= 60 tiempominute += 1 end if tiempominuto gt= 60 tiempominuto -= 60 tiempohora += 1 endend

La primera liacutenea realiza la suma de los segundos y las restantes se ocupan de los

210 Capiacutetulo 16 Estructuras y Funciones

casos especiales vistos anteriormente

iquestEs correcta esta funcioacuten iquestQueacute ocurre si el paraacutemetro segundos es muchomayor que sesenta

En tal caso no es suficiente con acarrear una vez debemos seguir hacieacutendolohasta que tiemposegundo sea menor que sesenta Una solucioacuten es sustituir lassentencias if por sentencias while Esta funcioacuten seriacutea correcta pero no es lasolucioacuten maacutes eficiente

Ejercicio 16-3

Escriba una versioacuten correcta de incrementar sin bucles

Todo lo que se pueda hacer con modificadores tambieacuten puede lograrse confunciones puras De hecho algunos lenguajes de programacioacuten solo permitenfunciones puras Hay ciertas evidencias de que los programas que usanfunciones puras son maacutes raacutepidos de desarrollar y menos propensos a errores quelos programas que usan modificadores Sin embargo a veces los modificadoresson uacutetiles y en algunos casos los programas funcionales (es decir con funcionespuras) tienden a ser menos eficientes

En general recomendamos que escriba funciones puras siempre que searazonable y recurra a los modificadores soacutelo si hay una ventaja convincente Esteenfoque podriacutea llamarse estilo de programacioacuten funcional

Ejercicio 16-4

Escriba una versioacuten pura de incrementar que cree y devuelva un nuevo objetoHora en vez de modificar el paraacutemetro

Desarrollo de prototipos frente a la planificacioacutenEl desarrollo de programas que veremos ahora se llama ldquodesarrollo deprototiposrdquo En cada una de las funciones anteriores escribimos un prototipoque realizaba el caacutelculo baacutesico y luego lo probamos sobre unos cuantos casoscorrigiendo los errores a medida que iban apareciendo

Este enfoque puede ser efectivo especialmente si auacuten no tiene un conocimientoprofundo del problema No obstante las correcciones incrementales puedengenerar coacutedigo innecesariamente complicado (que considere muchos casosespeciales) y poco confiable (es difiacutecil saber si ha encontrado todos los errores)

Una alternativa es el desarrollo planificado en el que la comprensioacuten delproblema en profundidad puede facilitar en gran medida la programacioacuten En elcaso de sumahora se puede ver un objeto Hora como iexclun nuacutemero de tres diacutegitosen base 60 (vea httpsenwikipediaorgwikiSexagesimal ) El atributo segundoes la ldquocolumna de unidadesrdquo el atributo minuto es la ldquocolumna de los sesentasrdquo y

Desarrollo de prototipos frente a la planificacioacuten 211

el atributo hora es la ldquocolumna de los tres mil seiscientosrdquo

Cuando se escribiacutea sumahora e incrementar efectivamente se estaba sumandoen base 60 por eso se tuvo que acarrear de una columna a la siguiente

Esta observacioacuten sugiere otro enfoque para el problema se pueden convertir losobjetos Hora en enteros y aprovechar el hecho de que la computadora saberealizar aritmeacutetica con enteros

La siguiente funcioacuten convierte un objeto Hora en un entero

function horaaentero(tiempo) minutos = tiempohora 60 + tiempominuto segundos = minutos 60 + tiemposegundoend

Ahora para convertir un entero en un objeto Hora (recuerde que divrem divideel primer argumento por el segundo y devuelve el cociente y el resto como unatupla)

function enteroahora(segundos) (minutos segundo) = divrem(segundos 60) hora minuto = divrem(minutos 60) Hora(hora minuto segundo)end

Puede que tenga que pensar un poco y realizar algunas pruebas paraconvencerse de que estas funciones son correctas Una forma de probarlas esverificar que horaaentero((enteroahora(x)) == x para muchos valores de x Estees un ejemplo de prueba de consistencia

Una vez que esteacute convencido puede usar estas funciones para reescribirsumahora

function sumahora(t1 t2) segundos = horaaentero(t1) + horaaentero(t2) enteroahora(segundos)end

Esta versioacuten es maacutes corta que la original y maacutes faacutecil de verificar

Ejercicio 16-5

Reescriba incrementar usando horaaentero y enteroahora

Convertir de base 60 a base 10 y viceversa es maacutes difiacutecil que solo trabajar con

212 Capiacutetulo 16 Estructuras y Funciones

los tiempos El cambio de base es maacutes abstracto pero la intuicioacuten humana paratratar con las horas es mejor

Si al usuario se le ocurre tratar los tiempos como nuacutemeros de base 60 e invierteun poco de tiempo en escribir las funciones de conversioacuten (horaaentero yenteroahora) obtiene un programa maacutes corto faacutecil de leer y depurar y confiable

El cambio de base tambieacuten hace que sea maacutes faacutecil antildeadir funcionalidadesposteriormente Por ejemplo imagine restar dos Horas para hallar el intervaloentre ellas El enfoque simple seriacutea implementar una resta con preacutestamo perousar funciones de conversioacuten seriacutea maacutes faacutecil y con mayor probabilidad correcto

Iroacutenicamente a veces hacer un poblema maacutes complejo (o maacutes general) lo hacemaacutes faacutecil porque hay menos casos especiales y por lo tanto el margen de errores menor

DepuracioacutenUn objeto Hora estaacute bien definido si los valores de minuto y segundo estaacuten entre0 y 60 (incluido 0 pero no 60) y si hora es positivo hora y minuto deben servalores enteros pero se podriacutea permitir que segundo sea fraccional

Los requisitos como estos se denominan invariantes porque siempre deben serverdaderos Dicho de otra manera si no son ciertos algo estaacute mal

Escribir coacutedigo para verificar invariantes puede ayudar a detectar errores yencontrar sus causas Por ejemplo podriacutea tener una funcioacuten como eshoravalidaque tome un objeto Hora y devuelva false si viola una invariante

function eshoravalida(tiempo) if tiempohora lt 0 || tiempominuto lt 0 || tiemposegundo lt 0 return false end if tiempominuto gt= 60 || tiemposegundo gt= 60 return false end trueend

Al comienzo de cada funcioacuten puede verificar los argumentos para asegurarse deque sean vaacutelidos

Depuracioacuten 213

function sumahora(t1 t2) if eshoravalida(t1) || eshoravalida(t2) error(objeto Hora en sumahora es invaacutelido) end segundos = horaaentero(t1) + horaaentero(t2) enteroahora(segundos)end

O podriacutea usar una macro assert que verifica un invariante dado y genera unaexcepcioacuten si falla

function sumahora(t1 t2) assert(eshoravalida(t1) ampamp eshoravalida(t2) objeto Hora en sumahoraes invaacutelido) segundos = horaaentero(t1) + horaaentero(t2) enteroahora(segundos)end

Las macros assert son uacutetiles porque permiten distinguir el coacutedigo que tratacondiciones normales del coacutedigo que verifica los errores

Glosariodesarrollo de prototipos

Una forma de desarrollar programas que involucra generar un prototipo delprograma hacer pruebas y corregir errores a medida que son encontrados

desarrollo planificadoUna forma de desarrollar programas que implica una profunda comprensioacutendel problema y maacutes planificacioacuten que desarrollo incremental o desarrollo deprototipos

funcioacuten puraUna funcioacuten que no modifica los objetos que recibe como paraacutemetros Lamayoriacutea de las funciones puras son productivas

modificadorUna funcioacuten que modifica uno o maacutes de los objetos que recibe comoparaacutemetros La mayoriacutea de los modificadores son nulos es decir entreganresultado nothing

estilo funcional de programacioacutenUn estilo de programacioacuten en el que la mayoriacutea de las funciones son puras

214 Capiacutetulo 16 Estructuras y Funciones

invarianteUna condicioacuten que nunca deberiacutea cambiar durante la ejecucioacuten de unprograma

Ejercicios

Ejercicio 16-6

Escriba una funcioacuten llamada multhora que tome un objeto Hora y un nuacutemero ydevuelva un nuevo objeto Hora que contenga el producto entre Hora original y elnuacutemero

Luego use multhora para escribir una funcioacuten que tome un objeto Hora querepresente el tiempo de duracioacuten de una carrera y un nuacutemero que represente ladistancia y devuelva un objeto Hora que represente el ritmo promedio (minutospor kiloacutemetro)

Ejercicio 16-7

Julia proporciona objetos de tiempo similares a los objetos Hora de este capiacutetulopero que tienen un amplio conjunto de funciones y operadores Lea ladocumentacioacuten en httpsdocsjulialangorgenv1stdlibDates

1 Escriba un programa que tome la fecha actual e imprima el diacutea de lasemana

2 Escriba un programa que tome como entrada una fecha de cumpleantildeos eimprima la edad del usuario y la cantidad de diacuteas horas minutos ysegundos hasta su proacuteximo cumpleantildeos

3 Para dos personas nacidas en diacuteas diferentes hay un diacutea en que una tiene eldoble de edad que la otra Ese es su Diacutea Doble Escriba un programa quetome dos cumpleantildeos y calcule su Diacutea doble

4 Desafiacuteo Escriba una versioacuten maacutes general que calcule el diacutea en que unapersona es veces mayor que la otra

Ejercicios 215

Capiacutetulo 17 Dispatch MuacuteltipleJulia permite escribir coacutedigo que puede funcionar con diferentes tipos Esto sellama programacioacuten geneacuterica

En este capiacutetulo se discutiraacute sobre las declaraciones de tipo en Julia Ademaacutes sepresentan los meacutetodos que son formas de implementar diferentescomportamientos en una funcioacuten dependiendo del tipo de sus argumentos Estoes conocido como dispatch muacuteltiple

Declaraciones de Tipo

El operador asocia anotaciones de tipo con expresiones y variables

juliagt (1 + 2) Float64ERROR TypeError in typeassert expected Float64 got a value of typeInt64juliagt (1 + 2) Int643

Esto ayuda a verificar que el programa funciona de la manera esperada

El operador tambieacuten se puede agregar al lado izquierdo de una asignacioacuten ocomo parte de una declaracioacuten

juliagt function devolverfloat() xFloat64 = 100 x enddevolverfloat (generic function with 1 method)juliagt x = devolverfloat()1000juliagt typeof(x)Float64

La variable x siempre es de tipo Float64 y su valor se convierte en un puntoflotante si es necesario

Tambieacuten se puede antildeadir una anotacioacuten de tipo al encabezado de una definicioacutende funcioacuten

216 Capiacutetulo 17 Dispatch Muacuteltiple

function sinc(x)Float64 if x == 0 return 1 end sin(x)(x)end

El valor de retorno de sinc siempre se convierte al tipo Float64

En Julia cuando se omiten los tipos los valores pueden ser de cualquier tipo(Any)

MeacutetodosEn Capiacutetulo 16 definimos una estructura llamada Hora y en Seccioacuten 161escribimos una funcioacuten llamada imprimirhora

using Printf

struct Hora hora Int64 minuto Int64 segundo Int64end

function imprimirhora(tiempo) printf(02d02d02d tiempohora tiempominuto tiemposegundo)end

Para mejorar el rendimiento se pueden (y deben) agregar las declaraciones detipo a los atributos en una definicioacuten de estructura

Para llamar a esta funcioacuten debe pasarle un objeto Hora como argumento

juliagt inicio = Hora(9 45 0)Hora(9 45 0)juliagt imprimirhora(inicio)094500

Para agregar un meacutetodo a la funcioacuten imprimirhora con el fin de que esta soloacepte como argumento un objeto Hora todo lo que hay que hacer es agregar seguido de Hora al argumento tiempo en la definicioacuten de funcioacuten

Meacutetodos 217

function imprimirhora(tiempoHora) printf(02d02d02d tiempohora tiempominuto tiemposegundo)end

Un meacutetodo es una definicioacuten de funcioacuten con una especificacioacuten imprimirhoratiene un argumento de tipo Hora

Llamar a la funcioacuten imprimirhora con un objeto Hora produce el mismo resultadoque antes

juliagt imprimirhora(inicio)094500

Se redefine el primer meacutetodo sin la anotacioacuten de tipo lo cual permite unargumento de cualquier tipo

function imprimirhora(tiempo) println(No seacute coacutemo imprimir el tiempo del argumento)end

Si se llama a la funcioacuten imprimirhora con un objeto diferente de Hora seobtendraacute

juliagt imprimirhora(150)No seacute coacutemo imprimir el tiempo del argumento

Ejercicio 17-1

Reescriba horaaentero y enteroahora (de Seccioacuten 164) especificando el tipo delos argumentos

enteroahora (generic function with 1 method)

Ejemplos AdicionalesAquiacute hay una versioacuten de la funcioacuten incrementar (Ejercicio 16-5 de Seccioacuten 163)reescrita especificando el tipo de los argumentos

function incrementar(tiempoHora segundosInt64) segundos += horaaentero(tiempo) enteroahora(segundos)end

218 Capiacutetulo 17 Dispatch Muacuteltiple

Tenga en cuenta que ahora incrementar es una funcioacuten pura no un modificador

Asiacute es como se llama a la funcioacuten incrementar

juliagt inicio = Hora(9 45 0)Hora(9 45 0)juliagt incrementar(inicio 1337)Hora(10 7 17)

Si se colocan los argumentos en el orden incorrecto se obtiene un error

juliagt incrementar(1337 inicio)ERROR MethodError no method matching incrementar(Int64 Hora)

La especificacioacuten del meacutetodo es incrementar(tiempoHora segundosInt64) noincrementar(segundosInt64 tiempoHora)

Al reescribir estadespues (Ejercicio 16-2 de Seccioacuten 163) para que solo acepteobjetos Hora se tiene

function estadespues(t1Hora t2Hora) (t1hora t1minuto t1segundo) gt (t2hora t2minuto t2segundo)end

Hace falta destacar que los argumentos opcionales permiten definir muacuteltiplesmeacutetodos Por ejemplo esta definicioacuten

function f(a=1 b=2) a + 2bend

se traduce en los siguientes tres meacutetodos

f(a b) = a + 2bf(a) = f(a 2)f() = f(1 2)

Estas expresiones son definiciones vaacutelidas de meacutetodos de Julia Esta es unanotacioacuten abreviada para definir funcionesmeacutetodos

ConstructoresUn constructor es una funcioacuten especial que se llama para crear un objeto Losmeacutetodos por defecto del constructor Hora tienen las siguientes especificaciones

Constructores 219

Hora(hora minuto segundo)Hora(horaInt64 minutoInt64 segundoInt64)

Tambieacuten se pueden agregar meacutetodos propios de constructores externos

function Hora(tiempoHora) Hora(tiempohora tiempominuto tiemposegundo)end

Este meacutetodo se llama constructor de copia porque el nuevo objeto Hora es unacopia de su argumento

Para imponer invariantes se necesitan meacutetodos de constructor interno

struct Hora hora Int64 minuto Int64 segundo Int64 function Hora(horaInt64=0 minutoInt64=0 segundoInt64=0) assert(0 le minuto lt 60 Minuto no estaacute entre 0 y 60) assert(0 le segundo lt 60 Segundo no estaacute entre 0 y 60) new(hora minuto segundo) endend

La estructura Hora tiene ahora 4 meacutetodos de constructor interno

Hora()Hora(horaInt64)Hora(horaInt64 minutoInt64)Hora(horaInt64 minutoInt64 segundoInt64)

Un meacutetodo de constructor interno siempre se define dentro del bloque de unadeclaracioacuten de tipo y tiene acceso a una funcioacuten especial llamada new que creaobjetos del tipo recieacuten declarado

AVISOSi se define alguacuten constructor interno el constructor por defectoya no estaacute disponible Se tienen que escribir expliacutecitamente todoslos constructores internos necesarios

Tambieacuten existe un meacutetodo sin argumentos de la funcioacuten local new

220 Capiacutetulo 17 Dispatch Muacuteltiple

mutable struct Hora hora Int64 minuto Int64 segundo Int64 function Hora(horaInt64=0 minutoInt64=0 segundoInt64=0) assert(0 le minuto lt 60 Minuto estaacute entre 0 y 60) assert(0 le segundo lt 60 Segundo estaacute entre 0 y 60) tiempo = new() tiempohora = hora tiempominuto = minuto tiemposegundo = segundo tiempo endend

Esto permite construir estructuras de datos recursivas es decir una estructuradonde uno de los atributos es la estructura misma En este caso la estructuradebe ser mutable ya que sus atributos se modifican despueacutes de la creacioacuten deinstancias

showshow es una funcioacuten especial que devuelve la representacioacuten de cadena de unobjeto A continuacioacuten se muestra el meacutetodo show para objetos Hora

using Printf

function Baseshow(ioIO tiempoHora) printf(io 02d02d02d tiempohora tiempominutotiemposegundo)end

Esta funcioacuten guarda como cadena de texto una hora dada en el archivo al que iohace referencia

El prefijo Base es necesario si se quiere agregar un nuevo meacutetodo a la funcioacutenBaseshow

Cuando se imprime un objeto Julia llama a la funcioacuten show (esto ocurre siemprey como agregamos un nuevo meacutetodo a la funcioacuten Baseshow entonces se muestraHora con el formato que queremos)

juliagt tiempo = Hora(9 45 0)094500

Al escribir un nuevo tipo compuesto casi siempre es preferible empezar

show 221

escribiendo un constructor externo puesto que facilita la creacioacuten de instanciasde objetos y show que es uacutetil para la depuracioacuten

Ejercicio 17-2

Escriba un meacutetodo de constructor externo para la clase Punto que tome x e ycomo paraacutemetros opcionales y los asigne a los atributos correspondientes

incrementar (generic function with 1 method)

Sobrecarga de OperadoresEs posible cambiar la definicioacuten de los operadores cuando se aplican a tiposdefinidos por el usuario Esto se hace definiendo meacutetodos del operador Porejemplo si se define un meacutetodo llamado + con dos argumentos Hora se puedeusar el operador + en los objetos Hora

Asiacute es como se veriacutea la definicioacuten

import Base+

function +(t1Hora t2Hora) segundos = horaaentero(t1) + horaaentero(t2) enteroahora(segundos)end

La sentencia import agrega el operador + al aacutembito local (local scope) para quese puedan agregar meacutetodos

A continuacioacuten se muestra coacutemo usar este operador para objetos Hora

juliagt inicio = Hora(9 45)094500juliagt duracion = Hora(1 35 0)013500juliagt inicio + duracion112000

Al aplicar el operador + a objetos Hora Julia invoca el meacutetodo recieacuten agregadoCuando REPL muestra el resultado Julia invoca a show iexclHay muchas cosasocurriendo pero que no se observan

Ampliar el comportamiento de los operadores de modo que funcionen con tiposdefinidos por el usuarioprogramador se denomina sobrecarga del operador

222 Capiacutetulo 17 Dispatch Muacuteltiple

Dispatch MuacuteltipleEn la seccioacuten anterior se sumaron dos objetos Hora Imagine que ahora se quieresumar un nuacutemero entero a un objeto Hora

function +(tiempoHora segundosInt64) incrementar(tiempo segundos)end

He aquiacute un ejemplo que usa el operador + con un objeto Hora y un entero

juliagt inicio = Hora(9 45)094500juliagt inicio + 1337100717

La suma es un operador conmutativo por lo que se debe agregar otro meacutetodo

function +(segundosInt64 tiempoHora) tiempo + segundosend

Y se obtiene el mismo resultado

juliagt 1337 + inicio100717

La eleccioacuten del meacutetodo a ejecutar cuando se aplica una funcioacuten se llamadispatch Julia permite que el proceso de dispatch elija a cuaacutel de los meacutetodos deuna funcioacuten llamar en funcioacuten del nuacutemero y tipo de los argumentos dados El usode todos los argumentos de una funcioacuten para elegir el meacutetodo que se debeinvocar se conoce como dispatch muacuteltiple

Ejercicio 17-3

Escriba los siguientes meacutetodos + para objetos Punto

bull Si ambos operandos son objetos Punto el meacutetodo deberiacutea devolver un nuevoobjeto Punto cuya coordenada x sea la suma de las coordenadas x de losoperandos De manera anaacuteloga haga lo mismo para la coordenada y

bull Si el primer o el segundo operando es una tupla el meacutetodo debe agregar elprimer elemento de la tupla a la coordenada x y el segundo elemento a lacoordenada y y devolver un nuevo objeto Punto con el resultado

Dispatch Muacuteltiple 223

Programacioacuten GeneacutericaEl dispatch muacuteltiple es uacutetil cuando es necesario pero (afortunadamente) nosiempre lo es A menudo puede evitarse escribiendo funciones que funcionencorrectamente para argumentos de diferentes tipos

Muchas de las funciones que se han visto para cadenas tambieacuten funcionan paraotros tipos de secuencia Por ejemplo en Seccioacuten 112 se usa histograma paracontar la cantidad de veces que cada letra aparece en una palabra

function histograma(s) d = Dict() for c in s if c notin keys(d) d[c] = 1 else d[c] += 1 end end dend

Esta funcioacuten tambieacuten funciona para listas tuplas e incluso diccionarios siemprey cuando los elementos de s sean hashables ya que asiacute pueden usarse comoclaves de d

juliagt t = (spam huevo spam spam tocino spam)(spam huevo spam spam tocino spam)juliagt histograma(t)DictAnyAny with 3 entries spam =gt 4 huevo =gt 1 tocino =gt 1

Las funciones que pueden tomar paraacutemetros de diferentes tipos se llamanpolimoacuterficas El polimorfismo puede facilitar la reutilizacioacuten del coacutedigo

Por ejemplo la funcioacuten integrada sum que suma los elementos de una secuenciafunciona siempre que los elementos de la secuencia permitan la suma

Como se antildeadioacute el meacutetodo + para los objetos Hora entonces se puede usar sumpara Hora

224 Capiacutetulo 17 Dispatch Muacuteltiple

juliagt t1 = Hora(1 7 2)010702juliagt t2 = Hora(1 5 8)010508juliagt t3 = Hora(1 5 0)010500juliagt sum((t1 t2 t3))031710

Si todas las operaciones realizadas dentro de la funcioacuten se pueden aplicar al tipola funcioacuten se puede aplicar al tipo

El mejor tipo de polimorfismo es el que no se busca cuando usted descubre queuna funcioacuten que habiacutea escrito se puede aplicar a un tipo para el que nunca lahabiacutea planeado

Interfaz e implementacioacutenUno de los objetivos del dispatch muacuteltiple es hacer que el software sea maacutes faacutecilde mantener lo que significa poder mantener el programa funcionando cuandootras partes del sistema cambian y modificar el programa para cumplir con losnuevos requisitos

Una teacutecnica de disentildeo que ayuda a lograr ese objetivo es mantener las interfacesseparadas de las implementaciones Esto significa que los meacutetodos que tienen unargumento con anotacioacuten de tipo no deberiacutean depender de coacutemo se representanlos atributos de ese tipo

Por ejemplo en este capiacutetulo se desarrolla una estructura que representa unahora del diacutea Los meacutetodos que tienen un argumento con anotacioacuten de este tipoincluyen horaaentero estadespues y +

Se pueden implementar esos meacutetodos de varias maneras Los detalles de laimplementacioacuten dependen de coacutemo se represente Hora En este capiacutetulo losatributos de un objeto Hora son hora minuto y segundo

Otra opcioacuten seriacutea reemplazar estos atributos con un solo entero que representeel nuacutemero de segundos desde la medianoche Esta implementacioacuten hariacutea quealgunas funciones como estadespues sean maacutes faacuteciles de escribir pero hace queotras sean maacutes difiacuteciles

Despueacutes de implementar un tipo puede descubrir una mejor implementacioacuten Siotras partes del programa estaacuten usando su tipo cambiar la interfaz puede llevarmucho tiempo y ser propenso a errores No obstante si hizo un buen disentildeoacute deinterfaz puede cambiar la implementacioacuten sin cambiar la interfaz lo quesignifica que otras partes del programa no tienen que cambiar

Interfaz e implementacioacuten 225

DepuracioacutenLlamar a una funcioacuten con los argumentos correctos puede ser difiacutecil cuando seespecifica maacutes de un meacutetodo para la funcioacuten Julia permite examinar lasespecificaciones de los meacutetodos de una funcioacuten

Para saber queacute meacutetodos estaacuten disponibles para una funcioacuten determinada puedeusar la funcioacuten methods

juliagt methods(imprimirhora) 2 methods for generic function imprimirhora[1] printtime(timeMyTime) in Main at REPL[3]2[2] printtime(time) in Main at REPL[4]2

En este ejemplo la funcioacuten imprimirhora tiene 2 meacutetodos uno con un argumentoHora y otro con un argumento Any

Glosarioanotacioacuten de tipo

El operador seguido de un tipo que indica que una expresioacuten o unavariable es de ese tipo

meacutetodoUna definicioacuten de un posible comportamiento de una funcioacuten

dispatchLa eleccioacuten de queacute meacutetodo ejecutar cuando se ejecuta una funcioacuten

especificacioacutenEl nuacutemero y tipo de argumentos de un meacutetodo que permite al dispatchseleccionar el meacutetodo maacutes especiacutefico de una funcioacuten durante la llamada afuncioacuten

constructor externoConstructor definido fuera de la definicioacuten de tipo para definir meacutetodosuacutetiles para crear un objeto

constructor internoConstructor definido dentro de la definicioacuten de tipo para imponerinvariantes o para construir objetos recursivos

constructor por defectoConstructor interno que estaacute disponible cuando el usuario no defineconstructores internos

226 Capiacutetulo 17 Dispatch Muacuteltiple

constructor de copiaMeacutetodo de constructor externo de un tipo que tiene como uacutenico argumentoun objeto del tipo Crea un nuevo objeto que es una copia del argumento

sobrecarga de operadoresAmpliar el comportamiento de los operadores como ++ de modo quetrabajen con tipos definidos por el usuario

dispatch muacuteltipleDispatch basado en todos los argumentos de una funcioacuten

programacioacuten geneacutericaEscribir coacutedigo que pueda funcionar con maacutes de un tipo

Ejercicios

Ejercicio 17-4

Cambie los atributos de Hora para que sea un solo nuacutemero entero querepresente los segundos desde la medianoche Luego modifique los meacutetodosdefinidos en este capiacutetulo para que funcionen con la nueva implementacioacuten

Ejercicio 17-5

Escriba una definicioacuten para un tipo llamado Canguro con un atributo llamadocontenidodemarsupio de tipo Arreglo y los siguientes meacutetodos

bull Un constructor que inicialice contenidodemarsupio a un arreglo vaciacuteo

bull Un meacutetodo llamado ponerenmarsupio que tome un objeto Canguro y unobjeto de cualquier tipo y lo agregue a contenidodemarsupio

bull Un meacutetodo show que devuelva una representacioacuten de cadena del objetoCanguro y el contenido del marsupio

Pruebe su coacutedigo creando dos objetos Canguro asignaacutendolos a variablesllamadas cangu y ro y luego agregando ro al contenido del marsupio de cangu

Ejercicios 227

Capiacutetulo 18 SubtiposEn el capiacutetulo anterior se presentoacute el dispatch muacuteltiple y los meacutetodospolimoacuterficos Al no especificar el tipo de los argumentos de un meacutetodo este sepuede invocar con argumentos de cualquier tipo Ahora se veraacute coacutemo especificarun subconjunto de tipos permitidos en las especificaciones de un meacutetodo

En este capiacutetulo se explica el concepto de subtipo usando tipos que representannaipes mazos de naipes y manos de poacuteker

Si usted nunca ha jugado poacuteker puede leer sobre eacutel en httpseswikipediaorgwikiPC3B3quer aunque no es necesario ya que se explicaraacute todo lonecesario para los ejercicios

NaipesHay cincuenta y dos naipes en una baraja inglesa cada uno de los cualespertenece a uno de los cuatro palos y tiene un valor Los palos son Picas (spades)Corazones (hearts) Diamantes (diams) y Treacuteboles (clubs) Los valores son As (A) 2 3 4 5 67 8 9 10 Jota (J) Reina (Q) y Rey (K) Dependiendo del tipo de juego el valordel As puede ser mayor que al Rey o inferior al 2

Si queremos definir un nuevo objeto para representar un naipe son obvios losatributos que deberiacutea tener valor y palo Lo que no es tan obvio es el tipo que sedebe dar a estos atributos Una opcioacuten es usar cadenas de caracteres quecontengan palabras como Picas para los palos y Reina para los valores Unproblema de esta implementacioacuten es que no seriacutea faacutecil comparar naipes para vercuaacutel tiene mayor valor o palo

Una alternativa es usar nuacutemeros enteros para codificar los valores y palos Eneste contexto codificar significa definir una asociacioacuten entre nuacutemeros y paloso entre nuacutemeros y valores Este tipo de codificacioacuten no estaacute relacionada concifrar o traducir a un coacutedigo secreto (eso seriacutea cifrado)

Por ejemplo esta tabla muestra una correspondencia entre palos y coacutedigos(nuacutemeros) enteros

bull spades 4

bull hearts 3

bull diams 2

bull clubs 1

Este coacutedigo facilita la comparacioacuten de naipes los palos maacutes altos se asignan a losnuacutemeros maacutes altos por lo tanto podemos comparar los palos al comparar suscoacutedigos

228 Capiacutetulo 18 Subtipos

Estamos usando el siacutembolo para dejar en claro que estas asignaciones no sonparte de Julia Forman parte del disentildeo del programa pero no aparecenexpliacutecitamente en el coacutedigo

La definicioacuten de estructura de Naipe se ve asiacute

struct Naipe palo Int64 valor Int64 function Naipe(paloInt64 valorInt64) assert(1 le palo le 4 el palo no estaacute entre 1 y 4) assert(1 le valor le 13 el valor no estaacute entre 1 y 13) new(palo valor) endend

Para crear un Naipe se debe llamar a Naipe con el palo y el valor del naipedeseado

juliagt reina_de_diamantes = Naipe(2 12)Naipe(2 12)

Variables GlobalesPara poder imprimir los objetos Naipe de una manera que sea faacutecil de leer senecesita establecer una correspondencia entre los coacutedigos enteros y suscorrespondientes palos y valores Una manera natural de hacer esto es conarreglos de cadenas

const nombres_palo = [clubs diams hearts spades]const nombres_valor = [A 2 3 4 5 6 7 8 9 10J Q K]

Las variables nombres_palo y nombres_valor son variables globales Ladeclaracioacuten const significa que la variable solo se puede asignar una vez Estoresuelve el problema de rendimiento de las variables globales

Ahora se puede implementar un meacutetodo show apropiado

function Baseshow(ioIO naipeNaipe) print(io nombres_valor[naipevalor] nombres_palo[naipepalo])end

La expresioacuten nombres_valor[naipevalor] significa use el atributo valor delobjeto naipe como iacutendice en el arreglo nombres_valor y seleccione la cadena

Variables Globales 229

correspondiente

Con los meacutetodos que se tienen hasta ahora se pueden crear e imprimir naipes

juliagt Naipe(3 11)Jhearts

Comparacioacuten de naipesPara los tipos integrados existen operadores relacionales (lt gt == etc) quecomparan valores y determinan cuaacutendo uno es mayor menor o igual a otro Paralos tipos definidos por el usuario se puede sustituir el comportamiento de estosoperadores si se proporciona un meacutetodo llamado lt

El orden correcto de los naipes no es obvio Por ejemplo iquestcuaacutel es mejor el 3 deTreacuteboles o el 2 de Diamantes Uno tiene un valor mayor pero el otro tiene unpalo mayor Para hacer que los naipes sean comparables se debe decidir queacute esmaacutes importante valor o palo

La respuesta puede depender del tipo de juego pero para simplificar las cosasse establece la eleccioacuten arbitraria de que el palo es maacutes importante por lo quetodas los treacuteboles superan a todos los diamantes y asiacute sucesivamente

Con esa decisioacuten tomada se puede escribir lt

import Baselt

function lt(c1Naipe c2Naipe) (c1palo c1valor) lt (c2palo c2valor)end

Ejercicio 18-1

Escriba un meacutetodo lt para objetos Hora Puede usar comparacioacuten de tuplas ocomparacioacuten de enteros

Prueba unitariaUna prueba unitaria permite verificar el correcto funcionamiento de su coacutedigocomparando los resultados obtenidos con los esperados Esto puede ser uacutetil paraverificar que su coacutedigo funciona correctamente despueacutes de haberlo modificado ytambieacuten es una forma de predefinir el comportamiento correcto de su coacutedigodurante el desarrollo

Se pueden realizar pruebas unitarias simples con las macros test

230 Capiacutetulo 18 Subtipos

juliagt using Test

juliagt test Naipe(1 4) lt Naipe(2 4)Test Passedjuliagt test Naipe(1 3) lt Naipe(1 4)Test Passed

test devuelve Test Passed (Prueba aprobada) si la expresioacuten que sigue estrue Test Failed (Prueba fallida) si es false y Error Result (Resultado deerror) si no se pudo evaluar

MazosAhora que ya tenemos Naipes el proacuteximo paso es definir Mazos Como un mazoestaacute compuesto de naipes naturalmente cada Mazo contendraacute un arreglo denaipes como atributo

A continuacioacuten se muestra una definicioacuten para Mazo El constructor crea elatributo naipes y genera la baraja estaacutendar de cincuenta y dos naipes

struct Mazo naipes ArrayNaipe 1end

function Mazo() mazo = Mazo(Naipe[]) for palo in 14 for valor in 113 push(mazonaipes Naipe(palo valor)) end end mazoend

La forma maacutes faacutecil de poblar el mazo es mediante un bucle anidado El bucleexterior enumera los palos desde 1 hasta 4 El bucle interior enumera los valoresdesde 1 hasta 13 Cada iteracioacuten crea un nuevo Naipe con el palo y valor actualy lo agrega a mazonaipes

Este es un meacutetodo show para Mazo

Mazos 231

function Baseshow(ioIO mazoMazo) for naipe in mazonaipes print(io naipe ) end println()end

Asiacute es como se ve el resultado

juliagt Mazo()Aclubs 2clubs 3clubs 4clubs 5clubs 6clubs 7clubs 8clubs 9clubs 10clubs Jclubs Qclubs Kclubs Adiams 2diams 3diams 4diams 5diams 6diams 7diams 8diams 9diams 10diams JdiamsQdiams Kdiams Ahearts 2hearts 3hearts 4hearts 5hearts 6hearts 7hearts 8hearts 9hearts 10hearts Jhearts Qhearts Khearts Aspades 2spades 3spades 4spades 5spades 6spades 7spades 8spades 9spades10spades Jspades Qspades Kspades

Antildeadir Eliminar Barajar y OrdenarPara repartir los naipes se debe tener una funcioacuten que elimine un naipe delmazo y lo devuelva La funcioacuten pop proporciona una forma conveniente derealizar esto

function Basepop(mazoMazo) pop(mazonaipes)end

Como pop elimina el uacuteltimo naipe en el arreglo se estaacute repartiendo desde elextremo inferior del mazo

Para antildeadir un naipe se puede usar la funcioacuten push

function Basepush(mazoMazo naipeNaipe) push(mazonaipes naipe) mazoend

Un meacutetodo como este que usa otro meacutetodo sin hacer mucho maacutes se llamaenchapado La metaacutefora proviene de la carpinteriacutea donde un enchapado es unacapa fina de madera de alta calidad que se pega a la superficie de una pieza demadera de baja calidad para mejorar su apariencia

En este caso push es un meacutetodo fino que expresa una operacioacuten de arreglosadecuada para los mazos Mejora la apariencia o interfaz de la implementacioacuten

Tambieacuten podemos escribir un meacutetodo llamado shuffle (barajar en ingleacutes) usandola funcioacuten Randomshuffle

232 Capiacutetulo 18 Subtipos

using Random

function Randomshuffle(mazoMazo) shuffle(mazonaipes) mazoend

Ejercicio 18-2

Escriba una funcioacuten llamada sort (ordenar en ingleacutes) que use la funcioacuten sortpara ordenar las cartas en un Mazo sort usa el meacutetodo isless que definimospara determinar el orden

Tipos Abstractos y SubtiposSe busca que un tipo represente una mano es decir los naipes que tiene unjugador Una mano es similar a un mazo ambos estaacuten compuestos de unconjunto de naipes y ambos requieren de operaciones tales como agregar yeliminar una carta

Una mano es diferente de un mazo en ciertos aspectos ya que existen ciertasoperaciones sobre una mano que no tendriacutean sentido sobre un mazo Porejemplo en el poker se debe comparar una mano con otra para ver quieacuten ganaEn bridge se necesita calcular el puntaje de la mano para asiacute poder hacer lasubasta

Por lo tanto hace falta una forma de agrupar los tipos concretos que estaacutenrelacionados En Julia esto se hace definiendo un abstract type (tipo abstracto eningleacutes) que sea padre de Mazo y Mano A esto se le llama crear subtipos

Se llama al tipo abstracto ConjuntoDeCartas

abstract type ConjuntoDeCartas end

Se puede crear un nuevo tipo abstracto con la palabra reservada abstract typeDe manera opcional se puede especificar un tipo padre de una estructuracolocando despueacutes del nombre de esta el siacutembolo lt seguido del nombre de untipo abstracto existente

Cuando no se proporciona un supertipo el supertipo por defecto es Any es decirun tipo abstracto predefinido del que todos los objetos son instancias y del quetodos los tipos son subtipos

Ahora se puede expresar que Mazo es un hijo de ConjuntoDeCartas

Tipos Abstractos y Subtipos 233

struct Mazo lt ConjuntoDeCartas naipes ArrayNaipe 1end

function Mazo() mazo = Mazo(Naipe[]) for palo in 14 for valor in 113 push(mazonaipes Naipe(palo valor)) end end mazoend

El operador isa comprueba si un objeto es de un tipo dado

juliagt mazo = Mazo()

juliagt mazo isa ConjuntoDeCartastrue

Una mano tambieacuten es un ConjuntoDeCartas

struct Mano lt ConjuntoDeCartas naipes ArrayNaipe 1 etiqueta Stringend

function Mano(etiquetaString=) Mano(Naipe[] etiqueta)end

En lugar de llenar la mano con 52 naipes nuevos el constructor de Manoinicializa naipes a un arreglo vaciacuteo Se puede etiquetar a la Mano pasando unargumento opcional al constructor

juliagt mano = Mano(nueva mano)Mano(Naipe[] nueva mano)

Tipos Abstractos y FuncionesAhora podemos expresar las operaciones que tienen en comuacuten Mazo y Mano alser funciones que tienen como argumento a ConjuntoDeCartas

234 Capiacutetulo 18 Subtipos

function Baseshow(ioIO cdcConjuntoDeCartas) for naipe in cdcnaipes print(io naipe ) endend

function Basepop(cdcConjuntoDeCartas) pop(cdcnaipes)end

function Basepush(cdcConjuntoDeCartas naipeNaipe) push(cdcnaipes naipe) nothingend

Se puede usar pop y push para repartir una carta

juliagt mazo = Mazo()Aclubs 2clubs 3clubs 4clubs 5clubs 6clubs 7clubs 8clubs 9clubs 10clubs Jclubs Qclubs Kclubs Adiams 2diams 3diams 4diams 5diams 6diams 7diams 8diams 9diams 10diams JdiamsQdiams Kdiams Ahearts 2hearts 3hearts 4hearts 5hearts 6hearts 7hearts 8hearts 9hearts 10hearts Jhearts Qhearts Khearts Aspades 2spades 3spades 4spades 5spades 6spades 7spades 8spades 9spades10spades Jspades Qspades Kspadesjuliagt shuffle(mazo)10clubs 9hearts 7spades 2spades Ahearts 4clubs Jhearts 2diams 6clubs Qclubs 8diams 8hearts 3hearts 7clubs 3diams 2clubs Jclubs 8clubs 9diams 6spades 3spades 5spades Adiams Aclubs10hearts 4spades Qhearts Jdiams Kspades 10diams Khearts Kclubs 5clubs 5hearts 5diams 10spades 7diams 3clubs 9spades Aspades 2hearts 7hearts 9clubs Qdiams 6hearts 8spades Jspades 4diamsQspades 6diams Kdiams 4heartsjuliagt naipe = pop(mazo)4heartsjuliagt push(mano naipe)

A continuacioacuten se encapsula este coacutedigo en una funcioacuten llamada mover

function mover(cdc1ConjuntoDeCartas cdc2ConjuntoDeCartas nInt) assert 1 le n le length(cs1naipes) for i in 1n naipe = pop(cdc1) push(cdc2 naipe) end nothingend

mover toma tres argumentos dos objetos ConjuntoDeCartas y el nuacutemero decartas a repartir Modifica ambos objetos ConjuntoDeCartas y devuelve nothing

En algunos juegos las cartas se mueven de una mano a otra o de una mano almazo Puede usar mover para cualquiera de estas operaciones cdc1 y cdc2pueden ser un Mazo o una Mano

Tipos Abstractos y Funciones 235

Diagramas de tiposHasta ahora se han visto diagramas de pila que muestran el estado de unprograma y diagramas de objetos que muestran los atributos de un objeto y susvalores Estos diagramas son como una foto sacada durante la ejecucioacuten de unprograma por lo que cambian a medida que se ejecuta el programa

Tambieacuten son muy detallados en algunos casos demasiado detallados Undiagrama de tipos es una representacioacuten maacutes abstracta de la estructura de unprograma En vez de mostrar objetos individuales muestra los tipos y lasrelaciones entre ellos

Hay varias formas de relacioacuten entre tipos

bull Los objetos de un tipo concreto pueden contener referencias a objetos deotro tipo Por ejemplo cada Rectaacutengulo contiene una referencia a un Puntoy cada Mazo contiene referencias a un conjunto de Naipes Este tipo derelacioacuten se llama TIENE-UN como por ejemplo un Rectaacutengulo tiene unPunto

bull Un tipo concreto puede tener un tipo abstracto como supertipo Estarelacioacuten se llama ES-UN como por ejemplo una Mano es unConjuntoDeCartas

bull Un tipo puede depender de otro si los objetos de un tipo toman objetos delsegundo tipo como paraacutemetros o usan objetos del segundo tipo como partede un caacutelculo Este tipo de relacioacuten se llama dependencia

Figura 23 Diagrama de tipo

Cada una de las flechas superiores representa una relacioacuten ES-UN En este casoindica que Mano tiene como supertipo a ConjuntoDeCartas

Cada una de las flechas inferiores representa una relacioacuten TIENE-UN en estecaso un Mazo tiene referencias a objetos Naipe

El asterisco () cerca de la flecha es una multiplicidad e indica cuaacutentos Naipestiene un Mazo Una multiplicidad puede ser un nuacutemero simple como 52 unrango como 57 o un asterisco lo cual indica que un Mazo puede tener cualquiernuacutemero de Naipes

236 Capiacutetulo 18 Subtipos

No hay dependencias en este diagrama Normalmente se mostrariacutean con unaflecha achurada Si hay muchas dependencias a veces se omiten

Un diagrama maacutes detallado podriacutea mostrar que un Mazo en realidad contiene unarreglo de Naipes pero los tipos integrados como arreglos y diccionariosgeneralmente no se incluyen en los diagramas de tipos

DepuracioacutenUtilizar subtipos puede dificultar la depuracioacuten ya que al llamar a una funcioacutencon un objeto como argumento puede ser complicado determinar queacute meacutetodo seinvocaraacute

Al escribir una funcioacuten que funciona con objetos Mano se busca que funcionecon todo tipo de Manos como ManoDePoker ManoDeBridge etc Si el usuarioinvoca un meacutetodo como sort podriacutea obtener el meacutetodo definido para un tipoabstracto Mano pero si existiera un meacutetodo sort que tuviera como argumentocualquiera de estos subtipos de Mano obtendriacutea esa versioacuten Estecomportamiento suele ser algo bueno pero puede ser confuso

function Basesort(manoMano) sort(manonaipes)end

Si usted no estaacute seguro del flujo de ejecucioacuten de un programa la solucioacuten maacutessimple es agregar sentencias de impresioacuten al inicio de sus meacutetodos maacutesrelevantes Si shuffle imprimiera un mensaje como Ejecutando shuffle en Mazodurante la ejecucioacuten del programa seriacutea posible rastrear el flujo de ejecucioacuten

Una mejor alternativa es la macro which

juliagt which sort(mano)sort(manoMano) in Main at REPL[5]1

Entonces el meacutetodo sort de mano es el que tiene como argumento un objeto detipo Mano

Una sugerencia para el disentildeo del programa cuando anula un meacutetodo lainterfaz del nuevo meacutetodo deberiacutea ser la misma que la anterior Deberiacutea tomarlos mismos paraacutemetros devolver el mismo tipo y obedecer las mismascondiciones previas y posteriores Si sigue esta regla cualquier funcioacuten disentildeadapara funcionar con una instancia de un supertipo como un ConjuntoDeCartastambieacuten funcionaraacute con instancias de sus subtipos Mazo y Mano

Si viola esta regla llamada principio de sustitucioacuten de Liskov su coacutedigocolapsaraacute como un castillo de naipes (jeje)

Depuracioacuten 237

La funcioacuten supertype permite encontrar el supertipo directo de un tipo

juliagt supertype(Mazo)ConjuntoDeCartas

Encapsulado de DatosLos capiacutetulos anteriores muestran un plan de desarrollo que podriacuteamos llamardisentildeo orientado a tipos Se identifican los objetos necesarios como PuntoRectaacutengulo y Hora y se definen estructuras para representarlos En cada casohay una correspondencia obvia entre el objeto y alguna entidad en el mundo real(o al menos en el mundo matemaacutetico)

A veces no es tan obvio saber queacute objetos se necesitan y coacutemo estos debeninteractuar En ese caso se necesita un plan de desarrollo diferente Lo mismoque ocurre con interfaces de funciones por encapsulado y generalizacioacuten ocurrecon interfaces de tipo por encapsulado de datos

El anaacutelisis de Markov de Seccioacuten 138 es un buen ejemplo Si descarga el coacutedigodesde httpsgithubcomBenLauwensThinkJuliajlblobmastersrcsolutionschap13jl veraacute que se usan dos variables globales sufijos y prefijo las cuales seleen y escriben desde varias funciones

sufijos = Dict()prefijos = []

Debido a que estas variables son globales solo se puede ejecutar un anaacutelisis a lavez Si se leen dos textos sus prefijos y sufijos se agregariacutean a las mismasestructuras de datos (lo que generariacutea un texto interesante)

Para ejecutar muacuteltiples anaacutelisis y mantenerlos separados se puede encapsular elestado de cada anaacutelisis en un objeto Asiacute es como se veriacutea

struct Markov orden Int64 sufijos DictTupleStringVarargString ArrayString 1 prefijo ArrayString 1end

function Markov(ordenInt64=2) new(orden DictTupleStringVarargString ArrayString 1()ArrayString 1())end

A continuacioacuten se transforman las funciones en meacutetodos Por ejemplo para

238 Capiacutetulo 18 Subtipos

procesarpalabra

function procesarpalabra(markovMarkov palabraString) if length(markovprefijo) lt markovorden push(markovprefijo palabra) return end get(markovsufijos (markovprefijo) ArrayString 1()) push(markovsufijos[(markovprefijo)] palabra) popfirst(markovprefijo) push(markovprefijo palabra)end

Transformar un programa asiacute (cambiando el disentildeo sin cambiar elcomportamiento) es otro ejemplo de refactorizacioacuten (vea Seccioacuten 47)

Este ejemplo sugiere el siguiente plan de desarrollo para disentildear tipos

bull Comience escribiendo funciones que lean y escriban variables globales(cuando sea necesario)

bull Una vez que el programa esteacute funcionando busque asociaciones entre lasvariables globales y las funciones que las usan

bull Encapsule variables relacionadas como atributos de una estructura

bull Transforme las funciones asociadas en meacutetodos que tengan comoargumentos objetos del nuevo tipo

Exercise 18-3

Descargue el coacutedigo de Markov de httpsgithubcomBenLauwensThinkJuliajlblobmastersrcsolutionschap13jl y siga los pasos descritos anteriormente paraencapsular las variables globales como atributos de una nueva estructurallamada Markov

Glosariocodificar

Representar un conjunto de valores utilizando otro conjunto de valoresgenerando una asociacioacuten entre ellos

prueba unitariaManera estandarizada de probar que el coacutedigo estaacute correcto

enchapadoUn meacutetodo o funcioacuten que mejora la interfaz de otra funcioacuten sin hacermuchos caacutelculos

Glosario 239

crear subtiposLa capacidad de definir una jerarquiacutea de tipos relacionados

tipo abstractoUn tipo que puede ser padre de otro tipo

tipo concretoUn tipo que se puede construir

subtipoUn tipo que tiene como padre un tipo abstracto

supertipoUn tipo abstracto que es el padre de otro tipo

relacioacuten ES-UNUna relacioacuten entre un subtipo y su supertipo

relacioacuten TIENE-UNUna relacioacuten entre dos tipos donde las instancias de un tipo contienenreferencias a instancias del otro

dependenciaUna relacioacuten entre dos tipos donde las instancias de un tipo usan instanciasdel otro tipo pero no las almacenan como atributos

diagrama de tiposUn diagrama que muestra los tipos en un programa y las relaciones entreellos

multiplicidadUna notacioacuten en un diagrama de tipo que muestra para una relacioacutenTIENE-UN cuaacutentas referencias hay a instancias de otra clase

encapsulado de datosUn plan de desarrollo de programas que implica hacer un prototipo que usevariables globales y una versioacuten final que convierta las variables globales enatributos de instancia

Ejercicios

Ejercicio 18-4

Para el siguiente programa dibuje un diagrama de tipos que muestre estos tiposy las relaciones entre ellos

240 Capiacutetulo 18 Subtipos

abstract type PadrePingPong end

struct Ping lt PadrePingPong pong PadrePingPongend

struct Pong lt PadrePingPong pings ArrayPing 1 function Pong(pings=ArrayPing 1()) new(pings) endend

function agregarping(pongPong pingPing) push(pongpings ping) nothingend

pong = Pong()ping = Ping(pong)agregarping(pong ping)

Ejercicio 18-5

Escriba un meacutetodo llamado repartir que tome tres paraacutemetros un Mazo elnuacutemero de manos y el nuacutemero de naipes por mano Deberiacutea crear el nuacutemeroapropiado de objetos Mano repartir el nuacutemero apropiado de naipes por mano ydevolver un arreglo de Manos

Ejercicio 18-6

Las siguientes son las posibles manos en el poacuteker en orden de valor creciente yprobabilidad decreciente

parejaDos cartas del mismo nuacutemero

doble parejaDos pares de cartas del mismo nuacutemero

triacuteoTres cartas del mismo nuacutemero

escaleraCinco cartas consecutivas (los ases pueden ser considerados altos o bajospor lo tanto As-2-3-4-5 es escalera 10-Jota-Reina-Rey-As tambieacuten pero

Ejercicios 241

Reina-Rey-As-2-3 no)

colorCinco cartas del mismo palo

fullTres cartas iguales en su valor maacutes otras dos iguales en su valor

poacutekerCuatro cartas iguales en su valor

escalera de colorCinco cartas consecutivas del mismo palo

El objetivo de este ejercicio es estimar la probabilidad de tener cada una de estasmanos

1 Agregue meacutetodos llamados tienepareja tienedoblepareja etc quedevuelvan true o false seguacuten si la mano cumple o no con los criteriosrelevantes Su coacutedigo deberiacutea funcionar correctamente para manos quecontengan cualquier nuacutemero de naipes (aunque 5 y 7 son los tamantildeos maacutescomunes)

2 Escriba un meacutetodo llamado clasificar que descubra la clasificacioacuten de mayorvalor para una mano y defina el atributo etiqueta con esta clasificacioacuten Porejemplo una mano de 7 cartas que contiene un color y una pareja debeetiquetarse como color

3 Cuando esteacute convencido de que sus meacutetodos de clasificacioacuten estaacutenfuncionando correctamente estime las probabilidades de las distintasmanos Escriba una funcioacuten que baraje un mazo de naipes la divida endiferentes manos clasifique las manos y cuente la cantidad de veces queaparecen varias clasificaciones

4 Imprima una tabla de las clasificaciones y sus probabilidades Ejecute suprograma con un nuacutemero cada vez mayor de manos hasta que los valores desalida converjan con un grado razonable de precisioacuten Compare susresultados con los valores en httpsenwikipediaorgwikiHand_rankings

242 Capiacutetulo 18 Subtipos

Capiacutetulo 19 Extra SintaxisUno de los objetivos de este libro es ensentildearle lo justo y necesario de Julia Seexplica una sola forma de hacer las cosas y en ocasiones se deja como ejercicioal lector una segunda manera

Ahora se veraacuten algunos temas que se han dejado de lado pero que son uacutetilesJulia proporciona una serie de caracteriacutesticas que no son realmente necesarias(se puede escribir un buen coacutedigo sin ellas) pero a veces permiten escribir uncoacutedigo maacutes conciso legible yo eficiente

En este capiacutetulo y el siguiente se discute aquello que se ha omitido en loscapiacutetulos anteriores

bull maacutes sintaxis

bull funciones tipos y macros disponibles directamente de Base

bull funciones tipos y macros de la Biblioteca Estaacutendar (Standard Library)

Tuplas con nombreEs posible colocarle nombre a los componentes de una tupla creando una tuplacon nombre

juliagt x = (a=1 b=1+1)(a = 1 b = 2)juliagt xa1

En las tuplas con nombre se puede acceder a los atributos con su nombreutilizando la sintaxis de punto (xa)

FuncionesLas funciones en Julia tambieacuten se pueden definir mediante una sintaxiscompacta de la siguiente forma

juliagt f(xy) = x + yf (generic function with 1 method)

Funciones Anonimas

Podemos definir una funcioacuten sin especificar su nombre

Tuplas con nombre 243

juliagt x -gt x^2 + 2x - 11 (generic function with 1 method)juliagt function (x) x^2 + 2x - 1 end3 (generic function with 1 method)

Estos son ejemplos de funciones anoacutenimas Las funciones anoacutenimasgeneralmente se usan como argumento de otra funcioacuten

juliagt using Plots

juliagt plot(x -gt x^2 + 2x - 1 0 10 xlabel=x ylabel=y)

Figura 24 muestra el resultado del comando plot (graficar en ingleacutes)

Figura 24 Plot

Argumentos con nombre

Tambieacuten se puede poner nombre a los argumentos de una funcioacuten

juliagt function migrafico(x y style=continua width=1 color=negro) endmigrafico (generic function with 1 method)juliagt migrafico(010 010 style=dotted color=blue)

Los argumentos con nombre en una funcioacuten se especifican despueacutes de un punto ycoma en la especificacioacuten pero al llamar a la funcioacuten se pueden utilizar solocomas

244 Capiacutetulo 19 Extra Sintaxis

Clausuras

Una clausura es una teacutecnica que permite que una funcioacuten capture una variabledefinida fuera del aacutembito de la funcioacuten

juliagt foo(x) = ()-gtxfoo (generic function with 1 method)

juliagt bar = foo(1)1 (generic function with 1 method)

juliagt bar()1

En este ejemplo la funcioacuten foo devuelve una funcioacuten anoacutenima que tiene acceso alargumento x de la funcioacuten foo bar apunta a la funcioacuten anoacutenima y devuelve elvalor del argumento de foo

BloquesUn bloque es una forma de agrupar varias sentencias Un bloque comienza con lapalabra reservada begin y termina con end

En Capiacutetulo 4 se presentoacute la macro svg

ὂ = Turtle()svg begin forward(ὂ 100) turn(ὂ -90) forward(ὂ 100)end

En este ejemplo la macro svg tiene un uacutenico argumento un bloque queagrupa 3 llamadas a funciones

Bloques let

Un bloque let es uacutetil para crear nuevas ligaduras (o bindings) es decir variableslocales que pueden apuntar a valores

Bloques 245

juliagt x y z = -1 -1 -1

juliagt let x = 1 z show x y z endx = 1y = -1ERROR UndefVarError z not definedjuliagt show x y zx = -1y = -1z = -1

En el ejemplo la primera macro show muestra la variable local x la variableglobal y y la variable local indefinida z Las variables globales se mantienenintactas

Bloques do

En Seccioacuten 142 se cierra el archivo despueacutes de terminar de escribir en eacutel Estose puede hacer automaacuteticamente usando un Bloque do

juliagt datos = El Cid convoca a sus vasallosneacutestos se destierran coneacutelnEl Cid convoca a sus vasallosneacutestos se destierran con eacutelnjuliagt open(salidatxt w) do fout write(fout datos) end61

En este ejemplo fout es el archivo stream utilizado para la salida

Esto es equivalente a

juliagt f = fout -gt begin write(fout datos) end3 (generic function with 1 method)juliagt open(f salidatxt w)61

La funcioacuten anoacutenima se utiliza como primer argumento de la funcioacuten open

246 Capiacutetulo 19 Extra Sintaxis

function open(fFunction args) io = open(args) try f(io) finally close(io) endend

Un bloque do puede capturar variables de su aacutembito envolvente (enclosedscope) Por ejemplo la variable datos en el ejemplo anterior de open do escapturada desde el aacutembito externo

Estructuras de control

Operador ternario

El operador ternario puede utilizarse en vez de una sentencia if-elseif Estasentencia se usa cuando se necesita elegir entre diferentes expresiones con valoruacutenico

juliagt a = 150150juliagt a 2 == 0 println(par) println(impar)par

La expresioacuten que va antes de es una expresioacuten de condicioacuten Si la condicioacuten estrue se evaluacutea la expresioacuten que va antes de De lo contrario se evaluacutea laexpresioacuten que va despueacutes de

Evaluacioacuten de cortocircuito

Los operadores ampamp y || realizan una evaluacioacuten de cortocircuito es decir seevaluacutea el siguiente argumento solo cuando es necesario para determinar el valorfinal

Por ejemplo una funcioacuten factorial recursiva podriacutea definirse asiacute

function fact(nInteger) n gt= 0 || error(n debe ser no negativo) n == 0 ampamp return 1 n fact(n-1)end

Estructuras de control 247

Tarea (o Corrutina)

Una tarea es una estructura de control que puede ceder el control de formacooperativa sin hacer return En Julia una tarea puede implementarse como unafuncioacuten con un objeto Channel como primer argumento Se usa un channel parapasar valores de la funcioacuten a la sentencia que la llama

El teacutermino cooperativo alude a que los programas deben cooperar para quetodo el esquema de programacioacuten funcione

La secuencia de Fibonnaci se puede generar mediante una tarea

function fib(cChannel) a = 0 b = 1 put(c a) while true put(c b) (a b) = (b a+b) endend

put almacena valores en un objeto channel y take lee valores desde eacutel

juliagt fib_gen = Channel(fib)

juliagt take(fib_gen)0juliagt take(fib_gen)1juliagt take(fib_gen)1juliagt take(fib_gen)2juliagt take(fib_gen)3

El constructor Channel crea la tarea La funcioacuten fib se suspende despueacutes de cadallamada a put y se reanuda al llamar a take Por razones de rendimiento sealmacenan varios valores de la secuencia en el objeto channel durante un ciclode reanudacioacutensuspensioacuten

Un objeto channel tambieacuten se puede usar como iterador

248 Capiacutetulo 19 Extra Sintaxis

juliagt for val in Channel(fib) print(val ) val gt 20 ampamp break end0 1 1 2 3 5 8 13 21

Tipos

Tipos Primitivos

Un tipo concreto compuesto por bits se llama tipo primitivo A diferencia de lamayoriacutea de los lenguajes en Julia se puede declarar nuestros propios tiposprimitivos Los tipos primitivos estaacutendar se definen de la misma manera

primitive type Float64 lt AbstractFloat 64 endprimitive type Bool lt Integer 8 endprimitive type Char lt AbstractChar 32 endprimitive type Int64 lt Signed 64 end

El nuacutemero en las sentencias especifica cuaacutentos bits son necesarios

El siguiente ejemplo crea un tipo primitivo Byte y un constructor

juliagt primitive type Byte 8 end

juliagt Byte(valUInt8) = reinterpret(Byte val)Bytejuliagt b = Byte(0x01)Byte(0x01)

La funcioacuten reinterpret se usa para almacenar los bits de un entero sin signo con8 bits (UInt8) en el byte

Tipos Parameacutetricos

El sistema de tipos de Julia es parameacutetrico lo que significa que los tipos puedentener paraacutemetros

Los paraacutemetros de un tipo se colocan despueacutes del nombre del tipo entre llaves

struct PuntoTltReal xT yTend

Tipos 249

Con esto se define un nuevo tipo parameacutetrico PuntoTltReal que contiene doscoordenadas de tipo T que puede ser cualquier tipo que tenga Real comosupertipo

juliagt Punto(00 00)PuntoFloat64(00 00)

Ademaacutes de los tipos compuestos los tipos abstractos y los tipos primitivostambieacuten pueden tener paraacutemetros

OBSERVACIOacuteN

Para mejorar el rendimiento es totalmenterecomendable tener tipos concretos como atributos deuna estructura por lo que esta es una buena manera dehacer que Punto sea raacutepido y flexible

Union de Tipo

Una union de tipo es un tipo parameacutetrico abstracto que puede actuar comocualquiera de los tipos de sus argumentos

juliagt EnteroOCadena = UnionInt64 StringUnionInt64 Stringjuliagt 150 EnteroOCadena150juliagt Julia EnteroOCadenaJulia

Una unioacuten de tipos es en la mayoriacutea de los lenguajes informaacuteticos unaconstruccioacuten interna para trabajar con tipos Sin embargo Julia pone adisposicioacuten esta caracteriacutestica para sus usuarios ya que permite generar uncoacutedigo eficiente (cuando la unioacuten es entre pocos tipos) Esta caracteriacutestica otorgauna gran flexibilidad para controlar el dispatch

Meacutetodos

Meacutetodos Parameacutetricos

Las definiciones de meacutetodos tambieacuten pueden tener paraacutemetros de tipo quelimiten su especificacioacuten

250 Capiacutetulo 19 Extra Sintaxis

juliagt espuntoentero(pPuntoT) where T = (T === Int64)espuntoentero (generic function with 1 method)juliagt p = Punto(1 2)PuntoInt64(1 2)juliagt espuntoentero(p)true

Objetos Similares a Funciones

Cualquier objeto arbitrario de Julia puede hacerse invocable Tales objetosinvocables a veces se denominan funtores

struct PolinomioR coefVectorRend

function (pPolinomio)(x) val = pcoef[end] for coef in pcoef[end-1-11] val = val x + coef end valend

Para evaluar el polinomio simplemente debemos llamarlo

juliagt p = Polinomio([110100])PolinomioInt64([1 10 100])juliagt p(3)931

ConstructoresLos tipos parameacutetricos se pueden construir expliacutecita o impliacutecitamente

juliagt Punto(12) T implicitoPuntoInt64(1 2)juliagt PuntoInt64(1 2) T explicitoPuntoInt64(1 2)juliagt Punto(125) T implicitoERROR MethodError no method matching Punto(Int64 Float64)

Se generan constructores internos y externos por defecto para cada T

Constructores 251

struct PuntoTltReal xT yT PuntoT(xy) where TltReal = new(xy)end

Punto(xT yT) where TltReal = PuntoT(xy)

y tanto x como y deben ser del mismo tipo

Cuando x e y son de tipos diferentes se puede definir el siguiente constructorexterno

Punto(xReal yReal) = Punto(promote(xy))

La funcioacuten promote se detalla en Seccioacuten 1982

Conversioacuten y PromocioacutenJulia tiene un sistema para convertir argumentos de diferentes tipos a un tipocomuacuten Esto es llamado promocioacuten y aunque no es automaacutetico se puede realizarfaacutecilmente

Conversioacuten

Un valor se puede convertir de un tipo a otro

juliagt x = 1212juliagt typeof(x)Int64juliagt convert(UInt8 x)0x0cjuliagt typeof(ans)UInt8

Se pueden agregar nuestros propios meacutetodos convert

juliagt Baseconvert(TypePuntoT xArrayT 1) where TltReal =Punto(x)

juliagt convert(PuntoInt64 [1 2])PuntoInt64(1 2)

252 Capiacutetulo 19 Extra Sintaxis

Promocioacuten

Promocioacuten es la conversioacuten de valores de diferentes tipos a un solo tipo comuacuten

juliagt promote(1 25 3)(10 25 30)

Generalmente los meacutetodos para la funcioacuten promote no se definen directamentesino que se usa la funcioacuten auxiliar promot_rule para especificar las reglas de lapromocioacuten

promote_rule(TypeFloat64 TypeInt32) = Float64

MetaprogramacioacutenUn coacutedigo de Julia se puede representar como una estructura de datos del mismolenguaje Esto permite que un programa escriba y manipule su propio coacutedigo

Expresiones

Cada programa de Julia comienza como una cadena

juliagt prog = 1 + 21 + 2

El siguiente paso es analizar cada cadena en un objeto llamado expresioacutenrepresentado por el tipo de Julia Expr

juliagt ex = Metaparse(prog)(1 + 2)juliagt typeof(ex)Exprjuliagt dump(ex)Expr head Symbol call args ArrayAny((3)) 1 Symbol + 2 Int64 1 3 Int64 2

La funcioacuten dump muestra objetos expr con anotaciones

Las expresiones se pueden construir directamente con el prefijo entrepareacutentesis o usando un bloque quote

Metaprogramacioacuten 253

juliagt ex = quote 1 + 2 end

eval

Julia puede evaluar un objeto de expresioacuten usando la funcioacuten eval

juliagt eval(ex)3

Cada moacutedulo tiene su propia funcioacuten eval que evaluacutea las expresiones de suaacutembito

AVISO Generalmente si un coacutedigo tiene muchas llamadas a eval significaque algo estaacute mal eval se considera malo

Macros

Las macros pueden incluir coacutedigo generado en un programa Una macro asociauna tupla de objetos Expr directamente con una expresioacuten compilada

Aquiacute hay una macro simple

macro contenedorvariable(contenedor elemento) return esc(($(Symbol(contenedorelemento)) = $contenedor[$elemento]))end

Las macros se llaman anteponiendo (arroba) a su nombre La llamada a lamacro contenedorvariable letras 1 se reemplaza por

(letras1 = letras[1])

macroexpand contenedorvariable letras 1 returns this expression which isextremely useful for debugging

Este ejemplo ilustra coacutemo una macro puede acceder al nombre de susargumentos algo que una funcioacuten no puede hacer Se debe escapar de laexpresioacuten de retorno con esc porque debe resolverse en el entorno de la macrollamada

254 Capiacutetulo 19 Extra Sintaxis

NOTA

iquestPor queacute usar Macros

Las macros generan e incluyen fragmentos de coacutedigopersonalizado durante el tiempo de anaacutelisis es decir antes deejecutar el programa completo

Funciones Generadas

La macro generated crea coacutedigo especializado para meacutetodos dependiendo deltipo de los argumentos

generated function cuadrado(x) println(x) (x x)end

El cuerpo devuelve una expresioacuten citada como una macro

Para la sentencia que llama la funcioacuten generada se comporta como una funcioacutennormal

juliagt x = cuadrado(2) nota la salida es de la instruccioacuten println ()que estaacute en el cuerpoInt64juliagt x ahora imprimimos x4juliagt y = cuadrado(spam)Stringjuliagt yspamspam

Datos FaltantesLos datos faltantes se pueden representar a traveacutes del objeto missing que es lainstancia uacutenica del tipo Missing

Los arreglos pueden contener datos que faltan missing values en ingleacutes

juliagt a = [1 missing]2-element ArrayUnionMissing Int641 1 missing

El tipo de dicho arreglo es UnionMissing T doacutende T es el tipo de los valoresque realmente tenemos en el arreglo

Datos Faltantes 255

Las funciones de reduccioacuten devuelven missing cuando se invocan con arreglosque contienen valores que faltan

juliagt sum(a)missing

En este caso se puede usar la funcioacuten skipmissing para omitir los valores quefaltan

juliagt sum(skipmissing([1 missing]))1

Llamar a Coacutedigo de C y FortranSe escribe mucho coacutedigo en C o Fortran Reutilizar un coacutedigo que ya ha sidoprobado generalmente es mejor que escribir su propia versioacuten en otro lenguajeJulia puede llamar directamente a las bibliotecas C o Fortran existentesutilizando la sintaxis ccall

En Seccioacuten 146 se presentoacute una interfaz de Julia de la biblioteca GDBM defunciones de base de datos La biblioteca estaacute escrita en C Para cerrar la base dedatos se debe hacer una llamada a la funcioacuten close(db)

Baseclose(dbmDBM) = gdbm_close(dbmhandle)

function gdbm_close(handlePtrCvoid) ccall((gdbm_close libgdbm) Cvoid (PtrCvoid) handle)end

Un objeto dbm tiene un atributo handle de tipo PtrCvoid Este atributocontiene un puntero de C que apunta a la base de datos Para cerrar la base dedatos debe llamarse a la funcioacuten de C gdbm_close teniendo como uacutenicoargumento el puntero C apuntando a la base de datos sin valor de retorno Juliahace esto directamente con la funcioacuten ccall que tiene como argumentos

bull una tupla que consiste en un siacutembolo que contiene el nombre de la funcioacutenque queremos llamar gdbm_close y la libreriacutea compartida especificadacomo una cadena +libgdm

bull el tipo de retorno Cvoid

bull una tupla de tipos de argumentos (PtrCvoid)

bull los valores del argumento handle

Una visioacuten completa de la libreriacutea GDBM se puede encontrar como ejemplo enlas fuentes de ThinkJulia

256 Capiacutetulo 19 Extra Sintaxis

Glossaryclausura

Funcioacuten que captura variables del aacutembito en doacutende estaacute definida

bloque letBloque de asignacioacuten de nuevas ligaduras variables

funcioacuten anoacutenimaFuncioacuten definida sin nombre

tupla con nombreTupla con componentes con nombre

argumentos con nombreArgumentos identificados por su nombre en vez de solo por la posicioacuten queocupan

bloque doConstruccioacuten usada para definir y llamar a una funcioacuten anoacutenima parecida aun bloque de coacutedigo normal

operador ternarioOperador de estructura de control que toma tres operandos una condicioacutenuna expresioacuten que se ejecutaraacute si la condicioacuten devuelve true y una expresioacutenque se ejecutaraacute si la condicioacuten devuelve false

evaluacioacuten de cortocircuitoEvaluacioacuten de un operador booleano para el que se ejecuta o evaluacutea elsegundo argumento solo si el primero no es suficiente para determinar elvalor de la expresioacuten

tareas (corrutina)Caracteriacutestica de las estructuras de control que permite suspender yreanudar caacutelculos de manera flexible

tipo primitivoTipo concreto cuyos datos estaacuten compuestos de bits

unioacuten de tiposTipo que incluye todas las instancias de cualquiera de sus tipos deparaacutemetros como objetos

Glossary 257

tipo parameacutetricoTipo que tiene paraacutemetros

funtorObjeto con un meacutetodo asociado para que sea invocable

conversioacutenPermite convertir un valor de un tipo a otro

promocioacutenConversioacuten de valores de diferentes tipos a un solo tipo comuacuten

expresioacutenTipo de Julia que contiene una construccioacuten de lenguaje

macroForma de incluir el coacutedigo generado en el cuerpo final de un programa

funciones generadasFunciones capaces de generar coacutedigo especializado seguacuten el tipo de losargumentos

datos faltantesInstancias que representan datos sin valor

258 Capiacutetulo 19 Extra Sintaxis

Capiacutetulo 20 Extra Base y Libreriacutea EstaacutendarJulia tiene todo lo necesario El moacutedulo Base contiene las funciones tipos ymacros maacutes uacutetiles los cuales estaacuten disponibles directamente en Julia

Julia tambieacuten posee una gran cantidad de moacutedulos especializados en suBiblioteca Estaacutendar (moacutedulos para fechas computacioacuten distribuida aacutelgebralineal perfiles nuacutemeros aleatorios entre otros) Las funciones los tipos y lasmacros definidos en la Biblioteca Estaacutendar deben importarse antes de poderusarse

bull import _Module_ importa el modulo y _Modulefn_(x) llama a la funcioacuten _fn_

bull using _Module_ importa todas las funciones tipos y macros exportadas de_Module_

Ademaacutes es posible agregar maacutes funciones a una gran cantidad de paquetes(httpsjuliaobservercom)

Este capiacutetulo no es un reemplazo de la documentacioacuten oficial de Julia Soacutelo sedan algunos ejemplos para ilustrar lo que es posible hacer sin ser exhaustivoLas funciones ya vistas no estaacuten incluidas Se puede encontrar una explicacioacutenmaacutes completa en httpsdocsjulialangorg

Midiendo el RendimientoHemos visto que algunos algoritmos funcionan mejor que otros fibonnaci enSeccioacuten 116 es mucho maacutes raacutepido que fib en Seccioacuten 67 La macro timepermite cuantificar la diferencia

juliagt fib(1)1juliagt fibonacci(1)1juliagt time fib(40) 0567546 seconds (5 allocations 176 bytes)102334155juliagt time fibonacci(40) 0000012 seconds (8 allocations 1547 KiB)102334155

time imprime el tiempo que tardoacute en ejecutarse la funcioacuten el nuacutemero deasignaciones (allocations) y la memoria asignada antes de devolver el resultadoLa funcioacuten fibonacci que guarda resultados previos es mucho maacutes raacutepida peronecesita maacutes memoria

Midiendo el Rendimiento 259

El teorema No free lunch dice que no existe un uacutenico modelo que funcionemejor en todos los casos

OBSERVACIOacuteN

Para comparar dos algoritmos estos debenimplementarse como funciones Una funcioacuten en Julia secompila la primera vez que se ejecuta por lo tanto sedebe excluir la primera vez que se llama a estasfunciones al medir el rendimiento De lo contrariotambieacuten se mediriacutea el tiempo de compilacioacuten

El paquete BenchmarkTools (httpsgithubcomJuliaCIBenchmarkToolsjl) proporciona la macro btime querealiza una evaluacioacuten comparativa de la maneracorrecta iexclAsiacute que uacutesela

Colecciones y Estructuras de DatosEn Seccioacuten 136 se usan diccionarios para encontrar las palabras que apareciacuteanen un documento y que no apareciacutean en un arreglo de palabras La funcioacuten quese escribioacute tomaba d1 que conteniacutea las palabras del documento como claves yd2 que conteniacutea el arreglo de palabras Y devolviacutea un diccionario que conteniacutealas claves de d1 que no estaban en d2

function resta(d1 d2) res = Dict() for clave in keys(d1) if clave notin keys(d2) res[clave] = nothing end end resend

En todos estos diccionarios los valores son nothing porque nunca son usadosCon esto se estaacute desperdiciando espacio de almacenamiento

Julia ofrece otro tipo integrado llamado conjunto que se comporta como unacoleccioacuten de claves de diccionario sin valores Agregar elementos a un conjuntoes raacutepido y tambieacuten lo es verificar si un elemento forma parte de eacutel Ademaacutes losconjuntos proporcionan funciones y operadores para calcular operaciones deconjuntos

Por ejemplo la resta de conjuntos estaacute disponible como una funcioacuten llamadasetdiff Entonces reescribiendo resta

260 Capiacutetulo 20 Extra Base y Libreriacutea Estaacutendar

function resta(d1 d2) setdiff(d1 d2)end

El resultado es un conjunto en vez de un diccionario

Algunos de los ejercicios en este libro se pueden hacer de manera eficiente yconcisa con conjuntos Por ejemplo a continuacioacuten se muestra una solucioacuten pararepetido de Seccioacuten 10157 que usa un diccionario

function repetido(t) d = Dict() for x in t if x isin d return true end d[x] = nothing end falseend

Cuando un elemento aparece por primera vez se agrega al diccionario Si elmismo elemento aparece nuevamente la funcioacuten devuelve true

Usando conjuntos podemos escribir la misma funcioacuten

function repetido(t) length(Set(t)) lt length(t)end

Un elemento solo puede aparecer en un conjunto una vez por lo que si unelemento en t aparece maacutes de una vez el conjunto seraacute maacutes pequentildeo que t Si nohay elementos repetidos el conjunto tendraacute el mismo tamantildeo que t

Tambieacuten podemos usar conjuntos para hacer algunos de los ejercicios deCapiacutetulo 9 Por ejemplo aquiacute hay una versioacuten de usasolo con un bucle

function usasolo(palabra disponibles) for letra in palabra if letra notin disponibles return false end end trueend

Colecciones y Estructuras de Datos 261

usasolo comprueba si todas las letras en palabra estaacuten en disponibles Podemosreescribir esta funcioacuten

function usasolo(palabra disponibles) Set(palabra) sube Set(disponibles)end

El operador sube (subseteq TAB) verifica si un conjunto es un subconjunto deotro incluida la posibilidad de que sean iguales lo cual es cierto si todas lasletras en palabra aparecen en disponibles

Exercise 20-1

Reescriba la funcioacuten evita de Capiacutetulo 9 usando conjuntos

MatemaacuteticasTambieacuten se pueden usar nuacutemeros complejos en Julia La constante global im estaacuteasociada al nuacutemero complejo que representa la raiacutez cuadrada principal de

Ahora se puede verificar la identidad de Euler

juliagt ℯ^(imπ)+100 + 12246467991473532e-16im

El siacutembolo ℯ (euler TAB) es la base de los logaritmos naturales

Se puede analizar la naturaleza compleja de las funciones trigonomeacutetricas

Se puede probar esta foacutermula para diferentes valores de

juliagt x = 0012π000162juliagt cos(x) == 05(ℯ^(imx)+ℯ^(-imx))true

Aquiacute se muestra otro ejemplo del operador punto Julia tambieacuten permite usarvalores numeacutericos con identificadores (siacutembolos leacutexicos que nombran entidadescomo π) como en 2π

262 Capiacutetulo 20 Extra Base y Libreriacutea Estaacutendar

CadenasEn Capiacutetulo 8 y Capiacutetulo 9 se realizan algunas buacutesquedas en cadenas AdemaacutesJulia puede usar expresiones regulares (o regexes) compatibles con Perl lo quefacilita la tarea de encontrar patrones complejos en cadenas

La funcioacuten usasolo se puede implementar como una expresioacuten regular

function usasolo(palabra disponibles) r = Regex([^$(disponibles)]) occursin(r palabra)end

La expresioacuten regular busca un caraacutecter que no estaacute en la cadena disponible yoccursin devuelve true si el patroacuten se encuentra en palabra

juliagt usasolo(banana abn)truejuliagt usasolo(bananas abn)false

Las expresiones regulares tambieacuten se pueden construir como literales de cadenano estaacutendar con el prefijo r

juliagt match(r[^abn] banana)

juliagt m = match(r[^abn] bananas)RegexMatch(s)

En este caso la interpolacioacuten de cadenas no estaacute permitida La funcioacuten matchdevuelve nothing si no se encuentra el patroacuten de lo contrario devuelve un objetoregexmatch

Podemos extraer la siguiente informacioacuten de un objeto regexmatch

bull La subcadena que coincide mmatch

bull Las subcadenas que coinciden en forma de arreglo de cadenas mcaptures

bull La primera posicioacuten en la que se encuentra el patroacuten moffset

bull Las posiciones de las subcadenas que coinciden en forma de arreglomoffsets

Cadenas 263

juliagt mmatchsjuliagt moffset7

Las expresiones regulares son extremadamente poderosas y el manual de PERLhttpperldocperlorgperlrehtml explica coacutemo realizar hasta las buacutesquedas maacutesextrantildeas

ArreglosEn el Capiacutetulo 10 se usa un objeto de arreglo unidimensional con un iacutendice paraacceder a sus elementos Sin embargo en Julia las matrices sonmultidimensionales

Se puede crear una matriz de ceros de 2 por 3

juliagt z = zeros(Float64 2 3)2times3 ArrayFloat642 00 00 00 00 00 00juliagt typeof(z)ArrayFloat642

El tipo de esta matriz es un arreglo que contiene nuacutemeros de punto flotante Estamatriz es de 2 dimensiones

La funcioacuten size devuelve una tupla con el nuacutemero de elementos en cadadimensioacuten

juliagt size(z)(2 3)

La funcioacuten ones construye una matriz con elementos de valor unitario

juliagt s = ones(String 1 3)1times3 ArrayString2

El elemento de valor unitario de una cadena es una cadena vaciacutea

264 Capiacutetulo 20 Extra Base y Libreriacutea Estaacutendar

AVISO

s no es un arreglo unidimensional

juliagt s == [ ]false

s es un vector fila y [ ] es un vector columna

Se puede crear una matriz usando espacios para separar elementos en una fila ypunto y coma para separar filas

juliagt a = [1 2 3 4 5 6]2times3 ArrayInt642 1 2 3 4 5 6

Se pueden usar corchetes para modificar elementos de una matriz

juliagt z[12] = 11juliagt z[23] = 11juliagt z2times3 ArrayFloat642 00 10 00 00 00 10

Se pueden usar porciones en cada dimensioacuten para seleccionar un subgrupo deelementos

juliagt u = z[2end]2times2 ArrayFloat642 10 00 00 10

El operador aplica una operacioacuten en todas las dimensiones

juliagt ℯ^(imu)2times2 ArrayComplexFloat642 0540302+0841471im 10+00im 10+00im 0540302+0841471im

Arreglos 265

InterfacesJulia especifica algunas interfaces informales para definir comportamientos esdecir meacutetodos con un objetivo especiacutefico Cuando se extienden estos meacutetodospara un tipo los objetos de ese tipo se pueden usar para construir estoscomportamientos

Si parece un pato nada como un pato y grazna como un pato entoncesprobablemente sea un pato

En Seccioacuten 67 implementamos la funcioacuten fib que devuelve el elemento -eacutesimode la secuencia de Fibonnaci

Recorrer los valores de una coleccioacuten lo cual recibe el nombre de iteracioacuten esuna interfaz de este tipo Se puede crear un iterador que devuelva la secuenciade Fibonacci

struct FibonacciTltReal endFibonacci(dDataType) = dltReal Fibonaccid() error(No Real type)

Baseiterate(FibonacciT) where TltReal = (zero(T) (one(T) one(T)))Baseiterate(FibonacciT stateTupleT T) where TltReal =(state[1] (state[2] state[1] + state[2]))

Se implementa un tipo parameacutetrico Fibonacci sin atributos un constructorexterno y dos meacutetodos iterate Se llama al primer meacutetodo iterate para inicializarel iterador y este devuelve una tupla que consta de un primer valor 0 y unestado El estado en este caso es una tupla que contiene el segundo y el tercervalor 1 y 1

Se llama al segundo meacutetodo iterate para obtener el siguiente valor de lasecuencia de Fibonacci y devuelve una tupla que tiene como primer elemento elsiguiente valor y como segundo elemento el estado que es una tupla con los dosvalores siguientes

Ahora se puede usar Fibonacci en un bucle for

juliagt for e in Fibonacci(Int64) e gt 100 ampamp break print(e ) end0 1 1 2 3 5 8 13 21 34 55 89

Parece sacado debajo de la manga pero la explicacioacuten es simple Un bucle for enJulia

266 Capiacutetulo 20 Extra Base y Libreriacutea Estaacutendar

for i in iter bodyend

se traduce en

next = iterate(iter)while next == nothing (i state) = next body next = iterate(iter state)end

Este es un ejemplo de coacutemo una interfaz bien definida permite que unaimplementacioacuten use todas las funciones disponibles en esta interfaz

Moacutedulo Interactive UtilitiesYa se ha visto el moacutedulo InteractiveUtils en Seccioacuten 1810 La macro which essolo una de las tantas opciones

La biblioteca LLVM transforma el coacutedigo de Julia en coacutedigo de maacutequina envarios pasos Podemos visualizar la salida de cada etapa

Aquiacute se muestra un ejemplo simple

function sumacuadrada(aFloat64 bFloat64) a^2 + b^2end

El primer paso es mirar el coacutedigo de bajo nivel (lowered code)

juliagt using InteractiveUtils

juliagt code_lowered sumacuadrada(30 40)CodeInfo(1 1 = Coreapply_type(BaseVal 2) 2 = (1)() 3 = Baseliteral_pow(^ a 2) 4 = Coreapply_type(BaseVal 2) 5 = (4)() 6 = Baseliteral_pow(^ b 5) 7 = 3 + 6 return 7)

Moacutedulo Interactive Utilities 267

La macro code_lowered devuelve un arreglo de una representacioacuten intermediadel coacutedigo que utiliza el compilador para generar coacutedigo optimizado

El siguiente paso antildeade informacioacuten del tipo

juliagt code_typed sumacuadrada(30 40)CodeInfo(1 1 = Basemul_float(a a)Float64 2 = Basemul_float(b b)Float64 3 = Baseadd_float(1 2)Float64 return 3) =gt Float64

El tipo de resultados intermedios y el valor de retorno se infiere correctamente

Esta representacioacuten del coacutedigo se transforma en coacutedigo LLVM

juliagt code_llvm sumacuadrada(30 40) none1 within `sumacuadradadefine double julia_sumacuadrada_6080(double double) top none2 within `sumacuadrada intfuncsjl296 within `literal_pow floatjl405 within ` 2 = fmul double 0 0 3 = fmul double 1 1 floatjl401 within `+ 4 = fadd double 2 3 ret double 4

Y finalmente se genera el coacutedigo de maacutequina

268 Capiacutetulo 20 Extra Base y Libreriacutea Estaacutendar

juliagt code_native sumacuadrada(30 40) text none2 within `sumacuadrada intfuncsjl296 within `literal_pow floatjl405 within ` vmulsd xmm0 xmm0 xmm0 vmulsd xmm1 xmm1 xmm1 floatjl401 within `+ vaddsd xmm1 xmm0 xmm0 retq nopl (rax)

DepuracioacutenLas macros Logging son una alternativa al andamiaje con sentencias deimpresioacuten

juliagt warn iexclOh vosotros los que entraacuteis abandonad la depuracioacuten conprintf Warning iexclOh vosotros los que entraacuteis abandonad la depuracioacuten conprintf Main REPL[1]1

Las sentencias de depuracioacuten (debug) no tienen que eliminarse del coacutedigo Porejemplo en contraste con el warn anterior

juliagt debug La suma de algunos valores $(sum(rand(100)))

debug por defecto no produce salida En este caso sum(rand(100)) nunca seevaluaraacute a menos que debug logging esteacute habilitado

El nivel de logging puede seleccionarse mediante la variable de entornoJULIA_DEBUG

$ JULIA_DEBUG=all julia -e debug La suma de algunos valores$(sum(rand(100))) Debug La suma de algunos valores 47116520814555024 Main none1

Aquiacute hemos utilizado all para obtener toda la informacioacuten de depuracioacuten perotambieacuten se puede optar por generar salida solo para un archivo o moacuteduloespeciacutefico

Depuracioacuten 269

Glosarioregex

Expresioacuten regular una secuencia de caracteres que definen un patroacuten debuacutesqueda

matrizArreglo bidimensional

representacioacuten intermediaEstructura de datos utilizada internamente por un compilador pararepresentar el coacutedigo fuente

coacutedigo de maacutequinaInstrucciones que pueden ser ejecutadas directamente por la unidad centralde procesamiento de una computadora

debug loggingAlmacenar mensajes de depuracioacuten en un registro (log)

270 Capiacutetulo 20 Extra Base y Libreriacutea Estaacutendar

Capiacutetulo 21 DepuracioacutenAl depurar es necesario distinguir entre los diferentes tipos de errores pararastrearlos maacutes raacutepidamente

bull Los errores de sintaxis se descubren cuando el inteacuterprete traduce el coacutedigofuente a coacutedigo de bytes Estos errores indican que hay una falla en laestructura del programa Por ejemplo omitir la palabra reservada end alfinal de un bloque de funciones genera el mensaje ERROR LoadErrorsyntax incomplete function requires end

bull Los errores en tiempo de ejecucioacuten se presentan si algo falla mientras seejecuta el programa La mayoriacutea de los mensajes de error en tiempo deejecucioacuten indican doacutende ocurrioacute el error y queacute funciones se estabanejecutando Ejemplo Una recursioacuten infinita eventualmente causa el error entiempo de ejecucioacuten ERROR StackOverflowError

bull Los errores semaacutenticos ocurren cuando un programa se ejecuta sin generarmensajes de error pero no hace lo que deberiacutea Por ejemplo una expresioacutenpuede no evaluarse en el orden esperado generando un resultadoincorrecto

El primer paso en la depuracioacuten es averiguar el tipo de error al que se enfrentaAunque las siguientes secciones estaacuten organizadas por tipo de error algunasteacutecnicas son aplicables en maacutes de una situacioacuten

Errores de SintaxisLos errores de sintaxis suelen ser faacuteciles de corregir una vez se descubre cuaacutelesson Desafortunadamente muchas veces los mensajes de error no son uacutetiles Losmensajes maacutes comunes son

ERROR LoadError syntax incomplete premature end of input

y

ERROR LoadError syntax unexpected =

los cuales no son muy informativos

Por otro lado el mensaje indica en queacute parte del programa se produjo elproblema En realidad indica doacutende Julia notoacute que habiacutea un problema que no esnecesariamente doacutende estaacute el error A veces el error es anterior a la ubicacioacutendel mensaje de error generalmente en la liacutenea anterior

Si estaacute programando incrementalmente el usuario deberiacutea tener casi localizadoel error ya que estaraacute en la uacuteltima liacutenea que agregoacute

Si estaacute copiando coacutedigo de un libro comience comparando su coacutedigo con el

Errores de Sintaxis 271

coacutedigo del libro y verifique cada letra Al mismo tiempo recuerde que el libropuede contener errores por lo que si ve algo que parece un error de sintaxis esposible que lo sea

Aquiacute hay algunas formas de evitar los errores de sintaxis maacutes comunes

1 Aseguacuterese de no estar usando una palabra reservada de Julia en un nombrede variable

2 Compruebe que tiene la palabra reservada end al final de cada sentenciacompuesta incluyendo los bloques for while if y function

3 Aseguacuterese de que las cadenas tengan su par de comillas de apertura ycierre Aseguacuterese de que todas las comillas sean comillas rectas y no otrotipo de comillas

4 Si tiene cadenas que ocupan varias liacuteneas con triples comillas aseguacuterese deque ha terminado la cadena correctamente Una cadena sin terminar puedeprovocar un error invalid token al final de su programa o puede hacer quela siguiente parte del programa sea tratada como una cadena hasta llegar ala siguiente cadena iexclEl segundo caso podriacutea no presentar mensaje de error

5 Un pareacutentesis sin cerrar mdash( or [mdash hace que Julia continuacutee con la liacuteneasiguiente como parte de la sentencia actual Generalmente se produce unerror casi inmediatamente en la siguiente liacutenea

6 Verifique el claacutesico error que se produce al ocupar = en lugar de == dentrode un condicional

7 Si tiene caracteres que no son ASCII en el coacutedigo (incluidas cadenas ycomentarios) esto podriacutea causar un problema aunque Julia generalmentemaneja caracteres no ASCII Tenga cuidado si pega texto de una paacutegina webu otra fuente

Si nada funciona pase a la siguiente seccioacuten hellip

Sigo haciendo cambios y no hay diferencia

Si el REPL dice que hay un error y usted no lo ve podriacutea deberse a que usted y elREPL no estaacuten viendo el mismo coacutedigo Verifique su entorno de programacioacutenpara asegurarse de que el programa que estaacute editando es el que Julia estaacutetratando de ejecutar

Si no estaacute seguro intente poner un error de sintaxis obvio y deliberado alcomienzo del programa Ahora ejecuacutetelo de nuevo Si REPL no encuentra elnuevo error no estaacute ejecutando el nuevo coacutedigo

Estas son algunas de las posibles razones

bull Editoacute el archivo y olvidoacute guardar los cambios antes de ejecutarlonuevamente Algunos entornos de programacioacuten hacen esto por usted pero

272 Capiacutetulo 21 Depuracioacuten

otros no

bull Cambioacute el nombre del archivo pero auacuten estaacute ejecutando el archivo con elnombre anterior

bull Algo en su entorno de desarrollo estaacute configurado incorrectamente

bull Si estaacute escribiendo un moacutedulo y estaacute usando using aseguacuterese de no darle asu moacutedulo el mismo nombre que uno de los moacutedulos estaacutendar de Julia

bull Si estaacute usando using para importar un moacutedulo recuerde que debe reiniciarREPL cuando modifique el coacutedigo en el moacutedulo Si vuelve a importar elmoacutedulo no ocurre nada

Si se queda atascado y no puede darse cuenta de lo que estaacute sucediendo unenfoque es comenzar de nuevo con un nuevo programa como iexclHola Mundo yasegurarse de que puede ejecutar este programa ya conocido Luego puedeagregar gradualmente las piezas del programa original al nuevo

Errores en Tiempo de EjecucioacutenUna vez que su programa es sintaacutecticamente correcto Julia puede leerlo y almenos comenzar a ejecutarlo iquestQueacute podriacutea salir mal

Mi programa no hace absolutamente nada

Este problema es comuacuten cuando su archivo consta de funciones y clases pero enrealidad no llama a ninguna funcioacuten para iniciar la ejecucioacuten Esto puede serintencional si soacutelo se busca importar este moacutedulo para suministrar clases yfunciones

Si no es intencional aseguacuterese de que haya una llamada a la funcioacuten en elprograma y aseguacuterese de que el flujo de ejecucioacuten pase por esta llamada (veaSeccioacuten 21223)

Mi programa se congela

Si un programa se detiene y parece no estar haciendo nada estaacute congeladoGeneralmente eso significa que estaacute atrapado en un bucle infinito o en unarecursioacuten infinita

bull Si hay un bucle en particular que le resulta sospechoso de poder provocar elproblema agregue una sentencia de impresioacuten justo antes del bucle quediga entrando al bucle y otra inmediatamente posterior que diga saliendodel bucle

Ejecute el programa Si recibe el primer mensaje y no el segundo tiene unbucle infinito Vea Seccioacuten 21221

bull La mayoriacutea de las veces una recursioacuten infinita haraacute que el programa se

Errores en Tiempo de Ejecucioacuten 273

ejecute por un rato y luego produzca un error ERROR LoadErrorStackOverflowError Si eso sucede vea Seccioacuten 21222

Si no obtiene este error pero sospecha que hay un problema con un meacutetodoo funcioacuten recursiva igual puede utilizar las teacutecnicas de Seccioacuten 21222

bull Si ninguno de esos pasos funciona comience a probar otros bucles y otrasfunciones y meacutetodos recursivos

bull Si esto no funciona quizaacutes es porque usted no entiende el flujo de ejecucioacutende su programa Vea Seccioacuten 21223

Bucle Infinito

Si cree tener un bucle infinito y cree saber cuaacutel es antildeada una sentencia deimpresioacuten que imprima los valores de las variables de la condicioacuten al final delbucle junto con el valor de la condicioacuten

Por ejemplo

while x gt 0 ampamp y lt 0 hacer algo con x hacer algo con y debug variables x y debug condicion x gt 0 ampamp y lt 0end

Ahora cuando ejecute el programa en modo de depuracioacuten veraacute el valor de lasvariables y la condicioacuten en cada iteracioacuten En la uacuteltima iteracioacuten la condicioacutendebe ser false Si el ciclo continuacutea podraacute ver los valores de x e y y podraacuteaveriguar por queacute no se actualizan correctamente

Recursioacuten Infinita

La mayoriacutea de las veces una recursioacuten infinita hace que el programa se ejecutedurante un tiempo y luego produzca un error

ERROR LoadError StackOverflowError

Si sospecha que una funcioacuten o un meacutetodo estaacute causando una recursioacuten infinitacomience por asegurarse de que hay un caso base En otras palabras deberiacuteahaber una condicioacuten que haga que la funcioacuten devuelva un valor sin hacer otrallamada recursiva Si no necesita revisar el algoritmo y encontrar ese caso base

Si hay un caso base pero el programa no parece llegar hasta eacutel antildeada unasentencia de impresioacuten al inicio de la funcioacuten que imprima los paraacutemetrosAhora cuando ejecute el programa veraacute el valor de los paraacutemetros cada vez quese llame la funcioacuten Si los paraacutemetros no se acercan al caso base eso le daraacute

274 Capiacutetulo 21 Depuracioacuten

alguna idea de por queacute no lo hace

Flujo de Ejecucioacuten

Si no estaacute seguro del flujo de ejecucioacuten en su programa antildeada sentencias deimpresioacuten al principio de cada funcioacuten con mensajes como ldquoentrando a la funcioacutenfunrdquo donde fun sea el nombre de la funcioacuten

Ahora cuando ejecute el programa se imprimiraacute una mensaje en cada funcioacuten amedida que estas sean llamadas

Cuando ejecuto el programa recibo una excepcioacuten

Si algo sale mal durante la ejecucioacuten Julia imprime un mensaje que incluye elnombre de la excepcioacuten la liacutenea del programa donde sucedioacute el problema y untrazado inverso

El trazado inverso identifica la funcioacuten que se estaacute ejecutando y la funcioacuten que lallamoacute y luego la funcioacuten que llamoacute a esa y asiacute sucesivamente En otras palabrastraza la ruta de las llamadas a las funciones que le llevaron a donde seencuentra Tambieacuten incluye los nuacutemeros de las liacuteneas de su archivo doacutendesuceden todas esas llamadas

El primer paso es examinar el lugar del programa donde ocurrioacute el error y ver sipuede adivinar lo que sucedioacute Estos son algunos de los errores en tiempo deejecucioacuten maacutes comunes

ArgumentErrorUno de los argumentos para llamar a una funcioacuten no tiene la formaesperada

BoundsErrorSe estaacute tratando de acceder a un elemento de un arreglo fuera de los liacutemitesde indexacioacuten

DomainErrorEl argumento de una funcioacuten o constructor no pertenece al dominio vaacutelido

DivideErrorSe intentoacute dividir un entero por 0

EOFErrorNo habiacutea maacutes datos disponibles para leer desde un archivo o stream

InexactErrorNo se puede convertir a un tipo

Errores en Tiempo de Ejecucioacuten 275

KeyErrorSe estaacute tratando de acceder o eliminar un elemento inexistente de un objetoAbstractDict (Dict) o Set

MethodErrorNo existe un meacutetodo con la especificacioacuten de tipo requerida en la funcioacutengeneacuterica dada Alternativamente no existe un meacutetodo uacutenico maacutes especiacutefico

OutOfMemoryErrorUna operacioacuten asignoacute demasiada memoria para que el sistema o elrecolector de basura opere correctamente

OverflowErrorEl resultado de una expresioacuten es demasiado grande para el tipo especificadoy se produce un desbordamiento

StackOverflowErrorUna llamada a funcioacuten trata de usar maacutes espacio que el que estaacute disponibleen la pila de llamadas Esto generalmente ocurre cuando una llamada serepite infinitamente

StringIndexErrorSe produjo un error al intentar acceder a un iacutendice invaacutelido de una cadena

SystemErrorFalloacute una llamada al sistema y se muestra un mensaje de error

TypeErrorError de asercioacuten de tipo o error producido al llamar a una funcioacutenintegrada con un tipo de argumento incorrecto

UndefVarErrorUn siacutembolo en el entorno (o aacutembito) actual no estaacute definido

Puse tantas sentencias de impresioacuten que me ahogo eninformacioacuten

Uno de los problemas de usar sentencias print en la depuracioacuten es que puedeterminar ahogado por tanta informacioacuten Hay dos formas de resolver estosimplificar la salida o simplificar el programa

Para simplificar la salida puede eliminar o comentar (convertir en comentariosno evaluados coacutemo oacuterdenes del programa) las sentencias print que no sean uacutetileso combinarlas Tambieacuten puede dar a la salida un formato que la haga maacutescomprensible

276 Capiacutetulo 21 Depuracioacuten

Para simplificar el programa puede hacer varias cosas Primero puede reducir laescala del problema en el que estaacute trabajando el programa Por ejemplo si estaacutebuscando algo en una lista buacutesquelo en una lista pequentildea Si el programa aceptaentradas del usuario ingrese la entrada maacutes simple que provoque el problema

Segundo puede limpiar el programa Elimine el coacutedigo muerto y reorganice elprograma para hacerlo tan legible como sea posible Por ejemplo si sospechaque el problema estaacute en una parte del programa con un anidamiento (nesting)muy profundo pruebe a reescribir esa parte con una estructura maacutes simple Sisospecha de una funcioacuten muy larga trate de dividirla en funciones maacutes pequentildeasy prueacutebelas separadamente

Generalmente el proceso de encontrar el caso de prueba miacutenimo lleva el usuarioa encontrar el error Si encuentra que un programa funciona en una situacioacutenpero no en otra eso le daraacute una pista sobre lo que estaacute sucediendo

De forma parecida reescribir una porcioacuten de coacutedigo puede ayudarle a encontrarerrores sutiles Si realiza un cambio que cree que no deberiacutea afectar elprograma pero lo hace entonces eso puede darle una pista

Errores SemaacutenticosEn cierto modo los errores semaacutenticos son los maacutes difiacuteciles de corregir ya que elinteacuterprete no entrega informacioacuten sobre lo que estaacute mal Soacutelo usted sabe lo quese supone que debe hacer el programa

El primer paso es hacer una conexioacuten entre el coacutedigo y el comportamiento queestaacute viendo Necesita una hipoacutetesis sobre lo que realmente estaacute haciendo elprograma Una de las dificultades que nos encontramos es la alta velocidad delos computadores

A menudo seriacutea deseable ralentizar el programa a una velocidad humana Eltiempo que lleva colocar unas sentencias print en los lugares adecuados sueleser menor que el que lleva configurar un depurador poner y quitar puntos deinterrupcioacuten y ldquohacer avanzarrdquo al programa hasta donde se produce el error

Mi programa no funciona

Deberiacutea hacerse estas preguntas

bull iquestHay algo que se supone que deberiacutea hacer el programa pero que nosucede Busque la seccioacuten del coacutedigo que realiza esa funcioacuten y aseguacuterese deque se ejecuta cuando deberiacutea

bull iquestOcurre algo que no deberiacutea Busque el coacutedigo en su programa que realizaesa funcioacuten y vea si se ejecuta cuando no debe

bull iquestHay alguna seccioacuten del coacutedigo que cause un efecto que no esperabaAseguacuterese de que entiende el coacutedigo en cuestioacuten especialmente si incluye

Errores Semaacutenticos 277

funciones o meacutetodos de otros moacutedulos de Julia Lea la documentacioacuten de lasfunciones a las que llama Prueacutebelas escribiendo casos de prueba simples ycomprobando sus resultados

Para programar necesitaraacute tener un modelo mental de coacutemo funcionan losprogramas Si escribe un programa que no hace lo que esperaba de eacutel muchasveces el problema no estaraacute en el programa sino en su modelo mental

La mejor manera de corregir su modelo mental es dividiendo el programa en suscomponentes (normalmente en funciones y meacutetodos) y probando cadacomponente de forma independiente Una vez que encuentre la discrepanciaentre su modelo y la realidad podraacute solucionar el problema

Por supuesto deberiacutea ir haciendo y probando componentes a medida quedesarrolla el programa Si encuentra un problema soacutelo habriacutea que revisar unapequentildea cantidad de coacutedigo nuevo

Tengo una expresioacuten grande y peliaguda y no hace lo queespero

Estaacute bien escribir expresiones complejas mientras sean legibles pero pueden serdifiacuteciles de depurar Suele ser una buena idea dividir una expresioacuten compleja enuna serie de asignaciones de variables temporales

Por ejamplo

agregarcarta(juegomanos[i] sacarcarta(juegomanos[encontrarvecino(juegoi)]))

Puede reescribirse como

vecino = encontrarvecino(juego i)cartaseleccionada = sacarcarta(juegomanos[vecino])agregarcarta(juegomanos[i] cartaseleccionada)

La versioacuten expliacutecita es maacutes faacutecil de leer porque los nombres de variables nosentregan documentacioacuten adicional y es maacutes faacutecil de depurar porque se puedencomprobar los tipos de las variables intermedias y mostrar sus valores

Otro problema que puede suceder con las expresiones grandes es que el ordende evaluacioacuten puede no ser el que usted esperaba Por ejemplo si estaacutetraduciendo la expresioacuten a Julia podriacutea escribir

y = x 2 π

Esto no es correcto ya que la multiplicacioacuten y la divisioacuten tienen la misma

278 Capiacutetulo 21 Depuracioacuten

precedencia y se evaluacutean de izquierda a derecha De este modo la anteriorexpresioacuten calcula

Una buena forma de depurar expresiones es antildeadir pareacutentesis para que seaexpliacutecito el orden de evaluacioacuten

y = x (2 π)

Siempre que no esteacute seguro del orden de evaluacioacuten utilice pareacutentesis Elprograma no soacutelo seraacute correcto (en el sentido de que hace lo que usted quiere)sino que ademaacutes seraacute maacutes legible para otras personas que no hayan memorizadolas reglas de precedencia y que lean el coacutedigo

Tengo una funcioacuten que no devuelve lo que esperaba

Si tiene una sentencia return con una expresioacuten compleja no tendraacute laoportunidad de imprimir el valor de retorno antes de retornar De nuevo puedeusar una variable temporal Por ejemplo en lugar de

return sacarpares(juegomanos[i])

podriacutea escribir

contar = sacarpares(juegomanos[i])return contar

Ahora ya tiene la oportunidad de mostrar el valor de count antes de retornar

Estoy atascado de verdad y necesito ayuda

Primero intente alejarse del computador durante unos minutos Trabajar con uncomputador puede provocar estos efectos

bull Frustracioacuten yo furia

bull Creencias supersticiosas (ldquoel computador me odiardquo) y pensamiento maacutegico(ldquoel programa soacutelo funciona cuando me pongo la gorra hacia atraacutesrdquo)

bull Programar dando palos de ciego (el empentildeo de programar escribiendo todoslos programas posibles y eligiendo el que hace lo correcto)

Si se encuentra afectado por alguno de estos siacutentomas levaacutentese y deacute un paseoCuando esteacute calmado piense en el programa iquestQueacute es lo que hace iquestCuaacutelespueden ser las causas de tal comportamiento iquestCuaacutendo fue la uacuteltima vez que suprograma funcionaba y queacute fue lo siguiente que hizo

A veces lleva tiempo encontrar un error Muchas veces encontramos errores

Errores Semaacutenticos 279

cuando estamos lejos del computador y divagamos Algunos de los mejoreslugares para encontrar errores son los trenes las duchas y la cama justo antesde quedarse dormido

No de verdad necesito ayuda

Sucede Incluso los mejores programadores se atascan de vez en cuando A vecestrabaja durante tanto tiempo en un programa que no puede ver el error Lo quenecesita es un par de ojos nuevos

Antes de llamar a alguien aseguacuterese de estar preparado Su programa deberiacuteaser tan simple como sea posible y usted deberiacutea estar trabajando con la entradamiacutenima que provoca el error Deberiacutea tener sentencias print en los lugaresadecuados (y lo que dicen deberiacutea ser comprensible) y deberiacutea tambieacuten entenderel problema lo bastante bien como para describirlo de manera concisa

Cuando llame a alguien para que le ayude aseguacuterese de darle la informacioacuten quenecesitan

bull Si hay un mensaje de error iquestcuaacutel es y queacute parte del programa sentildeala

bull iquestQueacute fue lo uacuteltimo que hizo antes de que apareciera el error iquestCuaacuteles sonlas uacuteltimas liacuteneas de coacutedigo que escribioacute o cuaacutel es el nuevo caso de pruebaque falla

bull iquestQueacute ha intentado hasta ahora y queacute ha averiguado

Cuando encuentre el error toacutemese un momento para pensar acerca de lo quepodriacutea haber hecho para encontrarlo maacutes raacutepido La siguiente vez que vea algoparecido seraacute capaz de encontrar el error antes

Recuerde el objetivo no es solo hacer que el programa funcione El objetivo esaprender coacutemo hacer funcionar el programa

280 Capiacutetulo 21 Depuracioacuten

Apeacutendice A Entrada de UnicodeLa siguiente tabla muestra algunos de los muchos caraacutecteres Unicode quepueden ingresarse mediante abreviaciones similares a aquellas utilizadas enLatex en el REPL de Julia (y en muchos otros entornos de edicioacuten)

Caraacutecter Tab completionsequence

representacioacuten ASCII

sup2 ^2₁ _1₂ _2ἴ appleἴ bananaὂ camelἵ pearὂ turtlecap capequiv equiv ===

ℯ eulerisin in in

ge ge gt=

le le lt=

ne ne =

notin notinπ pi pi

sube subseteqε varepsilon

Apeacutendice A Entrada de Unicode 281

Apeacutendice B JuliaBoxJuliaBox permite ejecutar Julia en su navegador Ingrese a la paacuteginahttpswwwjuliaboxcom inicie sesioacuten y comience a usar el entorno Jupyter

La pantalla inicial se muestra en Figura 25 El botoacuten new (nuevo) permite lacreacioacuten de un notebook de Julia un archivo de texto (text file) una carpeta(folder) o una sesioacuten de terminal (terminal session)

En una sesioacuten de terminal el comando julia inicia REPL como se muestra enFigura 26

La interfaz del notebook permite mezclar texto (en modo Markdown) y coacutedigocon su respectiva salida Figura 27 muestra un ejemplo

Puedes encontrar maacutes documentacioacuten en el sitio web de Jupyterhttpjupyterorgdocumentation

Figura 25 Pantalla inicial

282 Apeacutendice B JuliaBox

Figura 26 Sesioacuten de terminal

Apeacutendice B JuliaBox 283

Figura 27 Notebook

284 Apeacutendice B JuliaBox

Apeacutendice C Cambios de ThinkJuliaEste libro es una traduccioacuten de ThinkJulia que estaacute disponible bajo la LicenciaCreative Commons Atribucioacuten-NoComercial 30 No portada Esta licenciarequiere que los trabajos derivados (como este libro) enumeren los cambiosrealizados en relacioacuten a la fuente

Las diferencias de este libro respecto a ThinkJulia incluyen lo siguiente

bull Traduccioacuten del ingleacutes al espantildeol

bull Se cambiaron muchas frases idiomaacuteticas que no seriacutean familiares para loshispanohablantes (Se cayoacute el centavo)

bull En vez de usar el texto de la novela Emma en el Capiacutetulo 13 se usa eltexto de Don Quijote

bull Debido a que OrsquoReilly no financioacute la traduccioacuten algunas de las referencias aOrsquoReilly en el prefacio fueron eliminadas

Apeacutendice C Cambios de ThinkJulia 285

Index 126 57=

veacutease ne 57

veacutease cadena vaciacutea 101

veacutease comillas triples 51hellip (comillas)

veacutease comillas 11

veacutease comentario 22$

veacutease interpolacioacuten de cadenas102

161veacutease operador moacutedulo 56

ampamp 247 57 21 21 (asterisco)

operador de multiplicacioacutenveacutease asterisco 9

+ 21+ (operador de suma)

veacutease suma 9+= 127 (coma)

no usar en enterosveacutease coma 11

- 21- (operador de resta)

veacutease subtraction 9 200 201 265

veacutease operador punto 128 21 (operador de divisioacuten)

veacutease division 10 206 253 244 25 265 64lt 57lt=

veacutease le 57=

veacutease sentencia de asignacioacuten 17== 105 205 57 75===

veacutease equiv 131=gt 142gt 57gt=

veacutease ge 57

veacutease help 51 247 254assert 214code_llvm 268code_lowered 267code_native 268code_typed 268contenedorvariable 254debug 269generated 255macroexpand 254printf 187show 73svg 43test 230time 259warn 269which 237 267[]

veacutease slice operator 125[]

veacutease operador corchete 97n 196r 196t 175 196] 42^ 21 21^ (circunflejo)

operador de exponenciacioacutenveacutease circunflejo 10

_ (guioacuten bajo)en enteros

veacutease guioacuten bajo (_) 11``

286 Index

veacutease comillas invertidas 193

veacutease llaves 142|| 247 57divide 161

veacutease operador divisioacuten entera 56hellip 161isin

veacutease in 104notin 115cap 177ne 57equiv 131 205le 57ge 57sube 262

Aabreviaturas tipo LaTeX 18abs 71 92abspath 188abstract type 233 233 240ack 83actualizacioacuten 94acumulador 127 137 174algoritmo 93 95alias 133 138 167 203 205ambas 105analizar 32andamiaje 154 73 83anidado 122anotacioacuten de tipo 226anular 177 184Any 123 142 217anaacutelisis de Markov 179anaacutelisis de sintaxis 12 15append 126arc 49archivo de texto 196arco 49 53areacirculo 74ArgumentError 27 275 64argumento 27 30 32 33 38argumento opcional 131 176argumentos con nombre 244 257argumentos opcionales 138

Arreglo 123arreglo 122 137 166arreglo vaciacuteo 122 124asignacioacuten 160 191 24asignacioacuten aumentada 137asignacioacuten de tupla 160 164asignacioacuten en tupla 168asignacioacuten muacuteltiple 86 94asterisco ()

operador de multiplicacioacuten 9atributo 199 206

Bbandera 151 155Base 243 259base de datos 191 197begin 245benchmarking 182 184Biblioteca Estaacutendar 243bloque 245bloque do 257bloque let 257Bool 57borrarprimero 133BoundsError 107 160 275break 89bucle 44 52 88bucle infinito 273 88 95bugs

veacutease errores 15Byte 249buacutesqueda 102 103 109 109 115 155buacutesqueda de biseccioacuten 178buacutesqueda inversa 155

Ccadena 166 97 97

concatenacioacutenveacutease concatenar 21

repeticioacutenveacutease repeticioacuten 22

cadena vaciacutea 101 108cadenas 10 14calculadora 26campo

veacutease atributo 199

Index 287

Canguro 227capturar 197capturar una excepcion 190Car Talk 120 157 169carpeta

veacutease directorio actual 188caraacutecter guioacuten bajo 18Caraacutecter Unicode 17caraacutecter Unicode 30 72caso base 63 66caso especial 119 120catch 190ccall 256cd 193Channel 248Char 112 97cifrado Ceacutesar 112Circulo 207circunflejo (^)

operador de exponenciacioacuten 10clasificar 242clausura 257clave 142 154close 113 187 192codificacioacuten UTF-8 108 99codificar 228 239coinciden 164cola 135collect 130 146 163coma ()

no usar en enteros 11coma final 158comentario 22 25comillas 30comillas (hellip)

entre 11comillas invertidas 193comillas triples 51comparacioacuten de cadenas 105componentes leacutexicos 11 15composicioacuten 29 33 39 74concatenacioacuten de cadenas 25concatenar 21 34concatenar_dos 34condicional alternativa 71condicional anidada 59 66

condicional encadenada 59 66condicioacuten 58 66conjetura de Collatz 89conjuntoanagramas 198ConjuntoDeCartas 233const 153 229constructor 199 206 219 251

copiaveacutease constructor de copia

220externo

veacutease constructor externo220

internoveacutease constructor interno

220constructor de copia 220 227constructor externo 220 226constructor interno 220 226constructor por defecto 226contador 104 109ContarLineas 195contarlineas 194conteo 109continue 90conversioacuten 252 258conversioacuten de tipo 27convert 252copia 125copiar 193 205copodenieve 69corchetes 142 265cos 33cuadrado 46cuatroveces 40cuenta regresiva 61cuentaregresiva 88cuerpo 30 38curva de Koch 69ciacuterculo 47 50coacutedigo ASCII 108 97coacutedigo de maacutequina 268coacutedigo muerto 277 71 82

Ddatos faltantes 255 258

288 Index

DBM 191de Cervantes

Miguel 174debug logging 269 270declaracioacuten 151 156decremento 88 94deepcopy 205 206 207definicioacuten circular 76definicioacuten de funcioacuten 29 38definicioacuten recursiva 76deleteat 130delimitador 131 138dependencia 236 240depuracioacuten 106 119 135 153 154

167 182 196 205 213 22623 269 37 52 65 72 81 93

emociones de la manejando las13

veacutease errores (bugs) probando15

depuracioacuten del pato de goma 183 184depuracioacuten experimental 37depuracioacuten por biseccioacuten 93desarrollo de prototipos 209 211 214desarrollo incremental 72 82desarrollo planificado 212 214deserialize 192desplazarpalabra 112 156determiniacutestico 172 183devolverfloat 216diaframa de estado 123diagrama

estadoveacutease diagrama de estado 17

graacutefico de llamadasveacutease graacutefico de llamadas

149objeto

veacutease diagrama de objeto200

pilaveacutease diagrama de pila 34

tiposveacutease diagrama de tipos 236

diagrama de estado 131 132 149166 166 17 24 86

diagrama de objeto 200 202 207diagrama de pila 134 34 39 62 68

78diagrama de tipos 236 240dibujarcirculo 207dibujarrect 207diccionario 142 154Dict 142Dijkstra

Edsger W 119dimensioacuten 264directorio 188 196disentildeo orientado a tipos 238dispatch 223 226dispatch muacuteltiple 223 227dispersar 168dispersioacuten 162distancia 72distanciaentrepuntos 203DivideError 275divisioacuten

operador de divisioacuten () 10divisioacuten entera 65divrem 161do 246docstring 202 51 53DomainError 275dosveces 40Doyle

Arthur Conan 37dump 196 253

Eeachindex 124eachline 114 194ejecucioacuten alternativa 58ejecutar 19 24elemento 122 137else 58elseif 59embebido 202emoji 97 99enbiseccion 141encabezado 30 38encapsulacioacuten 47encapsulado 53

Index 289

encapsulado de dato 238encapsulado de datos 240enchapado 232 239encontrarcentro 204end 101 124 190 195 199 245 30

44 58 98enteroahora 212 218entrelazan 141enumerate 164EOFError 275equivalente 132 138error 147 213

BaseEOFError 275KeyError 143StringIndexError 99SystemError 189

CoreArgumentError 27BoundsError 107DivideError 275DomainError 275InexactError 275MethodError 98OutOfMemoryError 276OverflowError 276StackOverflowError 63TypeError 216UndefVarError 34

semaacutenticoveacutease error semaacutentico 23

sintaxisveacutease error de sintaxis 18

tiempo de ejecucioacutenveacutease error de tiempo de

ejecucioacuten 23error de forma 168error de sintaxis 18 23 25 271 29error de tiempo de ejecucioacuten 23 25error en tiempo de ejecucioacuten 271 34error semaacutentico 23 25 271errores (bugs) 13

veacutease depuracioacuten 15errores de forma 167ES-UN 236esabecedaria 115 117

esanagrama 140esc 254escogerdelhistograma 173esdivisible 75eshoravalida 213espalindromo 110 118 84especificacioacuten 218 226 250espotencia 84esreverso 106 119estadespues 209 219estaordenada 140estilo de programacioacuten funcional 211estilo funcional de programacioacuten 214estimarpi 96estriangulo 68estructura 11 15estructura de dato 168estructuras de datos 167estructuras de datos recursivas 221eval 254 95evalbucle 96evaluacioacuten de cortocircuito 247 257evaluar 19 24evita 115 262evitar 114excepcioacuten

veacutease error de tiempo deejecucioacuten 23

exp 29export 195Expr 253expresioacuten 18 24 253 258expresioacuten booleana 57 66extension

jl 19extrema 161

Ffact 247 77 80 81factorial 78false 57faltantes 255fib 79Fibonacci 266fibonnaci 149 79file stream 113 119

290 Index

filter 174filtro 128 138finally 190findall 148findfirst 104findnext 104firstindex 99float 27flujo de ejecucioacuten 273 32 39 71 77

81 88for 44formateando 187formatting 154forward 42fractal 69funccioacuten

definida por el programadorconjuntoanagramas 198

funciondefinida por el programador

aacuterea 70funciones generadas 255 258funcioacuten 27 29 38

Baseabs 71abspath 188append 126buacutesqueda 109ccall 256coinciden 164collect 130conteo 109convert 252cos 33deepcopy 205 206deleteat 130divrem 161dump 196eachindex 124eachline 114enumerate 164error 147esc 254exp 29extrema 161factorial 78

filter 174findall 148firstindex 99float 27get 145get 156include 194insert 130isdefined 206isdir 188isequal 148isfile 189isletter 171ispath 188iterate 266join 131joinpath 189keys 143length 40log 28log10 28lpad 121match 263max 162maximum 161min 162minimum 161new 220nextind 99occursin 263ones 264open 113parse 27pop 129popfirst 129print 41promote 252promote_rule 253push 125pushfirst 130put 248pwd 188rand 140readdir 189readline 113 64reinterpret 249

Index 291

repr 196reverse 167reverse 167run 193setdiff 260show 36sin 28size 264sizeof 99skipmissing 256sort 126sort 126splice 129split 130sqrt 28string 28sum 127supertype 238take 192 248time 67trunc 27tupla 158uppercase 104values 144vcat 134walkdir 189write 186zeros 264zip 163

ContarLineascontarlineas 195

Coreeval 254 95

definida por el programadorack 83ambas 105areacirculo 74borrarprimero 133buacutesqueda 102clasificar 242cola 135concatenar_dos 34contarlineas 194copodenieve 69cuadrado 46cuatroveces 40

cuenta regresiva 61ciacuterculo 47desplazarpalabra 112devolverfloat 216dibujarcirculo 207dibujarrect 207distancia 72distanciaentrepuntos 203dosveces 40enbiseccion 141encontrarcentro 204enteroahora 212esabecedaria 115esanagrama 140escogerdelhistograma 173esdivisible 75eshoravalida 213espalindromo 84espotencia 84esreverso 106estadespues 209estaordenada 140estimarpi 96estriangulo 68evalbucle 96evita 114fact 77fib 79findfirst 104findnext 104histograma 145horaaentero 212imprimircuadricula 41imprimirdosveces 32imprimirhist 146imprimirhora 208imprimirmascomun 176imprimirpalabra 40imprimirpunto 202imprimirtodo 161incrementar 210interior 139interior 139invertirdic 148justificar_a_la_derecha 39koch 69

292 Index

leeranagramas 198mascomun 175masfrecuente 168mcd 85medio 84minmax 161miraiz 95mover 235moverpunto 203multhora 215noborrarprimero 135notiene_e 114palabraalazar 178palabrasdiferentes 175palabrastotales 174par inverso 141polyline 49poliacutegono 47ponerenmarsupio 227primera 84printn 62probarraiz 95procesararchivo 173procesarlinea 173procesarpalabra 239puntoencirculo 207recorrer 189rectencirculo 207recursioacuten 63repartir 241repetido 140repetirletras 30resta 177sed 197seq 89sinc 216sobreposicionrectcirc 207solomayusculas 128sumaacumulada 139sumaanidada 139sumacuadrada 267sumahora 209sumartodo 162tienedoblepareja 242tienepareja 242todoenmayusculas 127

ultima 84usasolo 115usatodo 115valorabsoluto 70verificarfermat 67

definido por el programadorimprimirletras 29

IntroAJuliaforward 42pendown 43penup 43turn 43

Metaparse 253 95

Plotsgraficar 185 244

programmer-definedarco 49

Randomshuffle 232

Serializacioacutendeserialize 192serialize 192

funcioacuten Ackermann 83funcioacuten anoacutenima 244 257funcioacuten booleana 75funcioacuten de Ackermann 156funcioacuten definida por el programador

29 33funcioacuten exponencial

veacutease exp 29funcioacuten factorial 77funcioacuten gamma 80funcioacuten hash 155funcioacuten logaritmo

veacutease log 28funcioacuten matemaacutetica 28funcioacuten nula 35 39funcioacuten productiva 35 39 70funcioacuten pura 209 214funcioacuten raiacutez

veacutease sqrt 28funcioacuten recursiva 61funcioacuten trigonomeacutetrica 28funcioacuten typeof 10function 29

Index 293

funtor 251 258

GGDBM 191generalizacioacuten 47 53get 145get 156 174global 151 99graficar 185graacutefico de llamada 155graacutefico de llamadas 149guardian 81guardiaacuten 83guioacuten bajo (_)

en enteros 11

Hhash 149hash table 144hashable 149 155help 51histograma 145 224Holmes

Sherlock 37Hora 208 217horaaentero 212 218

Iidentidad de Euler 262ideacutentico 132 138if 58im 262immutable 102 108 158 167 200implementacioacuten 144 155 225import 195 259imprimircuadricula 41imprimirdosveces 32imprimirhist 146imprimirhora 208 217imprimirletras 29imprimirmascomun 176imprimirpalabra 40imprimirpunto 202imprimirtodo 161in 100 124 143 156 44include 194

incrementar 218incrementar 210incremento 88 94indentacioacuten 46indicador 64

en REPL 14 9indice 98InexactError 275informaacuteticos habilidades de

veacutease programacioacuten 7inicializacioacuten 94initializacioacuten 87input 113insert 130 136instancia 200 206instanciacioacuten 200instanciar 206instrucciones

veacutease sentencias 7Int 112InteractiveUtils 237 267interfaz 225 266 48 53interior 139interior 139intermediate representation 270interpolacioacuten de cadenas 102 109

187 263IntroAJulia 42invariante 213 215invertirdic 148IOBuffer 192isa 206 234 80isdefined 206isdir 188isequal 148isfile 189isletter 171 174ispath 188item 122 142 154iteracioacuten 191 86 88 94iterador 163 168 266iterate 266

Jjoin 131joinpath 189

294 Index

Juliaejecutando 8

JuliaBox 19 8notebook graacutefico 42

justificar_a_la_derecha 39

KKeyError 143 276keys 143keyword

elseveacutease else 58

importveacutease import 259

koch 69

LLaTeX-like abbreviations 281leeranagramas 198lemario 113length 143 40 84 98lenguaje de programacioacuten 11 15lenguaje de programacioacuten completo 76lenguaje formal 11 15lenguaje natural 11 14ley de Zipf 184Linux 38lista anidada 137Llamada a funcioacuten 27 38llaves 142 249LLVM code 268log 28log10 28lookup 147lowercase 174lpad 121

Mmachine code 270macro 254 258 43

Baseassert 214debug 269generated 255macroexpand 254show 73

time 259warn 269

definida por el programadorcontenedorvariable 254

InteractiveUtilscode_llvm 268code_lowered 267code_native 268code_typed 268which 237

Luxorsvg 43

Printfprintf 187

Testtest 230

Mano 234map 128mapeo 138 142 154marco 34 39 62Markov 238mascomun 175masfrecuente 168match 263matemaacuteticas

operadores aritmeacuteticos 9matrix 264 270max 162maximum 161mayuacutescula 127Mazo 231mcd 85md5 194md5sum 194medio 84mensaje de error 23MethodError 101 159 162 219 276

98min 162minimum 161minmax 161miraiz 95Missing 255modelo mental 278modificador 210 214modo interactivo 19 24 36

Index 295

modo script 19 24 36module 195

ContarLineasveacutease ContarLineas 195

InteractiveUtilsveacutease InteractiveUtils 237

Randomveacutease Random 232

Testveacutease Test 230

modulo 42 52veacutease IntroAJulia 42

mover 235moverpunto 203MPunto 201multhora 215multiplicidad 236 240mutable 123 133 167mutable struct 201meacutetodo 217 226meacutetodo de Newton 91meacutetodos 226moacutedulo

Plotsveacutease Plots 184 244

Serializacioacutenveacutease Serializacioacuten 192

Nnada 39Naipe 229new 220nextind 99noborrarprimero 135norma Unicode 108 97notacioacuten de punto

veacutease 200nothing 177 36 36 70notiene_e 114 115nuacutemeros complejos 262

Oobjeto 131 138objeto de comando 193 197objeto de funcioacuten 38 40objeto embebido 207

objeto zip 163 168occursin 263ones 264open 113 186 246operacioacuten con cadenas 21operacioacuten de reduccioacuten 127 138operador

Base= 57 56+= 127 128lt 57lt= 57== 57gt 57gt= 57 247[] 125[] 97in 104isa 206 234divide 56isin 104notin 115cap 177ne 57equiv 131le 57ge 57sube 262

cadenas 21operador corchete 101 101 122 123

159 191 97operador de divisioacuten entera 56operador de exponenciacioacuten (^) 10operador de multiplicacioacuten () 9operador de resta (-) 9operador de suma (+) 9operador loacutegico 57 66operador moacutedulo 56 65operador porcioacuten 125 135 159operador punto 128 137operador relacional 159 57 66operador ternario 257

veacutease 247

296 Index

operadores 14 9aritmeacuteticos 9

operadores aritmeacuteticos 9operando 24orden alfabeacutetico 105orden de operaciones 21OutOfMemoryError 276output

sentencia de impresioacuten 14 9OverflowError 276

Ppalabra clave 18 24palabra reservada

abstract type 233begin 245break 89catch 190const 153 229continue 90do 246elseif 59export 195final 30finally 190for 44function 30global 151if 58import 195in 44module 195mutable struct 201quote 253return 62struct 199tipo primitivo 249try 190using 42while 88

palabraalazar 178palabrasdiferentes 175palabrastotales 174paliacutendromo 84PAPOMUDAS 21paquete 42 52

par clave-valor 142 154 165par inverso 141Paradoja del cumpleantildeos 140pares de metaacutetesis 169parse 253 64 95paraacutemetro 32 34 38pareacutentesis 158 164 21 27

vaciacuteos 30pendown 43penup 43persistente 186 196pi 17 28pista 150 155 156 170plan de desarrollo de programa 117

211 239 50 53 82plot 244Plots 184 244polimorfismo 225polimoacuterfica 224polygon 49polyline 49poliacutegono 47Poncela

Enrique Jardiel 114ponerenmarsupio 227pop 129 232 234popfirst 129 133porcioacuten 108 109 265postcondicioacuten 52 53 81precedencia del operador 25precondicioacuten 52 53 81prefijo 179primera 84Principal 35principio de sustitucioacuten de Liskov 237print 187 41println 187 41printn 62probarraiz 95procesararchivo 173procesarlinea 173procesarpalabra 239programacioacuten de caminata aleatoria

183programacioacuten geneacuterica 227programas 14 7

Index 297

promocioacuten 253 258promote 252 253promote_rule 253Proyecto Gutenberg 171prueba de consistencia 154prueba de cordura 154prueba unitaria 230 239pseudoaleatorio 172 184Ptr 256Punto 199 222puntoencirculo 207push 125 130 134 136 141 232

234pushfirst 130 136put 248pwd 188

Qquote 253

Rrama 59 66rand 140 172Random 232read 194readdir 189readline 113 64 90reasignacioacuten 151 204recopila 161recorrer 189recorrido 106 108 124 99Rectangulo 202rectencirculo 207recursividad 61recursioacuten 117 63 66 68 76 86 88recursioacuten infinita 274 63 67 80recursos en liacutenea

JuliaBox 8reduccioacuten a un problema previamente

resuelto 120reduccioacuten a un problema resuelto

previamente 117reducible 170reducir el tamantildeo 153refactorizacioacuten 239 50 53referencia 133 138 200

Regex 263regex 263 270RegexMatch 263reinterpret 249relacioacuten ES-UN 240relacioacuten TIENE-UN 240repartir 241repeticioacuten 22 34

veacutease iteracioacuten 8repetido 140 156 261repetirletras 30repetition 43REPL 281REPL (Read-Eval-Print Loop) 14 8replace 174repr 196representacioacuten intermedia 268resolucioacuten de problemas 14 7resta 177 260return 62reunir 168reverse 167 175reverse lookup 147reverse 167run 193ruta 188 197ruta absoluta 188 197ruta relativa 188 197

Ssangriacutea 30 60script 19 24secuencia 108 97 97secuencias de secuencias 166sed 197semaacutentica 25sentencia 19 24sentencia break 89 94sentencia compuesta 58 66sentencia condicional 58 66 76sentencia continue 90 95sentencia de asignacioacuten 123 17 86sentencia de asignacioacuten aumentada

127sentencia de depuracioacuten 269sentencia de impresioacuten 14

298 Index

funcioacuten println 9sentencia for 100 114 117 124 163

165 191 266 44 86 88sentencia global 152 155sentencia if 58sentencia print 81 94sentencia return 62 66 70sentencia try 190sentencia using 42 52sentencia while 117 88 94 99separador 175seq 89Serializacioacuten 192serialize 192Set 260setdiff 260shell 193 197show 221 227 229 234 36shuffle 232sin 28 32sinc 216singleton 148 155sintaxis 11 15sintaxis de punto 129 138 243size 264sizeof 99skipmissing 256slice 101sobrecarga de operadores 227sobrecarga del operador 222sobreposicionrectcirc 207solomayusculas 128sort 126 137 146 167 175sort 126 136 136 167 233splice 129split 130 160 174sqrt 28 73square 47StackOverflowError 274 276 63 80stacktrace 63String 97string 187 263 28StringIndexError 276 99strip 136struct 199 206subtipo 233 233 240 240

sufijo 179sum 127 162 224suma de verificacioacuten 194sumaacumulada 139sumaanidada 139sumacuadrada 267sumahora 209 213sumartodo 162supertipo 233 240supertype 238SVG picture 43Symbol 206SystemError 189 276

Ttabla hash 155take 192 248tarea 248 257teorema de Pitaacutegoras 72tesis de Turing 76Test 230TIENE-UN 236tienedoblepareja 242tienepareja 242Time 208time 67tipo 199 233

BaseAny 123 142Array 123Bool 57Channel 248Char 97Dict 142Expr 253IOBuffer 192Missing 255nothing 36Ptr 256Regex 263RegexMatch 263Set 260Symbol 206Tuple 158UInt8 249Union 250

Index 299

DatesTime 208

definida por el programadorByte 249Canguro 227Circulo 207ConjuntoDeCartas 233Fibonacci 266Hora 208Mano 234Markov 238Mazo 231MPunto 201Naipe 229Punto 199Rectangulo 202

IntroAJuliaDBM 191

LuxorTurtle 42

tipo compuesto 199tipo compuesto mutable 201tipo concreto 233 240tipo de punto flotante (Float64) 10 14tipo entero (Int64) 10 14tipo parameacutetrico 258tipo primitivo 249 257tipos 10 14

Float64veacutease tipo de punto flotante

10Int64

veacutease tipo entero 10String

veacutease cadenas 10tipos de datos

veacutease tipos 10todoenmayusculas 127 129Torvalds

Linus 38transitorio 186trazado inverso 35 39true 57trunc 27try 190tupla 158 158 166 167

tupla con nombre 243 257Tuple 158Turing

Alan 76turn 43Turtle 42TypeError 216 276typeof 122 158 205

UUInt8 249ultima 84UndefVarError 152 276 34 35 87Unicode character 281Union 250union de tipo 250unioacuten de tipos 257update 87uppercase 104usasolo 115 116 261 263usatodo 115 116using 259 42

Vvalor 131 142 154 17valor de retorno 27 39valor por defecto 184valor predeterminado 176valorabsoluto 70valores 10 14values 144variable 131 17 24

local 34variable de entorno 269variable global 151 155 229variable global constante 153 156variable local 34 38variable temporal 279 70 75 82vcat 134 136verificar 154verificar automaacuteticamente 154verificarfermat 67voto de confianza 78

Wwalkdir 189

300 Index

while 88write 186

Zzeros 264zip 163 165 167 167

Aacuteaacutembito 195aacuterea 70

Iacuteiacutendice 108 123

Uacuteuacuteltimo teorema de Fermat 67

Ππ

veacutease pi 17

ℯ 262

Index 301

  • Introduccioacuten a la Programacioacuten en Julia
  • Tabla de Contenido
  • Licencia
  • Dedicatoria
  • Prefacio
  • Capiacutetulo 1 El camino de la programacioacuten
  • Capiacutetulo 2 Variables expresiones y sentencias
  • Capiacutetulo 3 Funciones
  • Capiacutetulo 4 Estudio de Caso Disentildeo de Interfaz
  • Capiacutetulo 5 Condicionales y recursividad
  • Capiacutetulo 6 Funciones productivas
  • Capiacutetulo 7 Iteracioacuten
  • Capiacutetulo 8 Cadenas
  • Capiacutetulo 9 Estudio de Caso Juego de Palabras
  • Capiacutetulo 10 Arreglos
  • Capiacutetulo 11 Diccionarios
  • Capiacutetulo 12 Tuplas
  • Capiacutetulo 13 Estudio de Caso Seleccioacuten de Estructura de Datos
  • Capiacutetulo 14 Archivos
  • Capiacutetulo 15 Estructuras y Objetos
  • Capiacutetulo 16 Estructuras y Funciones
  • Capiacutetulo 17 Dispatch Muacuteltiple
  • Capiacutetulo 18 Subtipos
  • Capiacutetulo 19 Extra Sintaxis
  • Capiacutetulo 20 Extra Base y Libreriacutea Estaacutendar
  • Capiacutetulo 21 Depuracioacuten
  • Apeacutendice A Entrada de Unicode
  • Apeacutendice B JuliaBox
  • Apeacutendice C Cambios de ThinkJulia
  • Index
Page 5: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar

PrefacioEn enero de 2018 comenceacute a preparar un curso de programacioacuten pensado paraestudiantes que no tuvieran experiencia previa en programacioacuten Queriacutea usarJulia como lenguaje de programacioacuten y descubriacute que no existiacutea ninguacuten libro paraaprender a programar que usara Julia como primer lenguaje de programacioacutenHay tutoriales maravillosos que explican los conceptos clave de Julia peroninguno de ellos se dedicaba lo suficiente a ensentildear a pensar como programador

Conociacutea el libro Think Python de Allen Downey el cual contiene todos loselementos clave para aprender a programar correctamente Sin embargo estelibro se basa en el lenguaje de programacioacuten Python Mi primer borrador delcurso fue una mezcla de muchas referencias pero a medida que trabajaba eneste el contenido comenzoacute a parecerse cada vez maacutes a los capiacutetulos de ThinkPython Pronto la idea de desarrollar mi curso como base para trasladar eselibro a Julia se hizo realidad

Todo el material estaba disponible en un repositorio de GitHub en forma denotebooks de Jupyter Despueacutes de publicar un mensaje en el sitio Discourse deJulia sobre el progreso de mi curso los comentarios fueron abrumadoresAparentemente un libro sobre conceptos baacutesicos de programacioacuten con Juliacomo primer lenguaje de programacioacuten era algo que faltaba en el universo deJulia Contacteacute a Allen para ver si podiacutea iniciar oficialmente la versioacuten de ThinkPython para Julia y su respuesta fue inmediata ldquoiexcladelanterdquo me puso encontacto con su editor de OrsquoReilly Media y ahora un antildeo despueacutes estoy haciendolos retoques finales a este libro

Fue un camino difiacutecil En Agosto de 2018 se lanzoacute Julia v10 y como todos miscolegas programadores de Julia tuve que hacer una migracioacuten del coacutedigo Todoslos ejemplos en el libro se prueban durante la conversioacuten de los archivos fuente aarchivos ASCIIDoc compatibles con OrsquoReilly Tanto la cadena de herramientascomo el coacutedigo de los ejemplos teniacutean que ser compatibles con Julia v10Afortunadamente no hay cursos en Agostohellip

Espero que disfrutes al trabajar con este libro y que te ayude a aprender aprogramar y pensar como informaacutetico al menos un poco

Ben Lauwens

iquestPor queacute JuliaJulia fue lanzado originalmente en 2012 por Alan Edelman Stefan Karpinski JeffBezanson y Viral Shah Es un lenguaje de programacioacuten gratuito y de coacutedigoabierto

La eleccioacuten de un lenguaje de programacioacuten es siempre subjetiva Para miacute lassiguientes caracteriacutesticas de Julia son decisivas

iquestPor queacute Julia 3

bull Julia estaacute desarrollado como un lenguaje de programacioacuten de altorendimiento

bull Julia usa enviacuteo muacuteltiple (ldquomultiple dispatchrdquo en ingleacutes) que le permite alprogramador elegir entre diferentes patrones de programacioacuten de acuerdoa la aplicacioacuten

bull Julia es un lenguaje de tipo dinaacutemico que se puede usar faacutecilmente de formainteractiva

bull Julia tiene una sintaxis de alto nivel que es faacutecil de aprender

bull Julia es un lenguaje de programacioacuten con tipos opcionales cuyos tipos dedatos (definidos por el usuario) hacen que el coacutedigo sea claro y robusto

bull Julia tiene una biblioteca estaacutendar extendida ademaacutes estaacuten disponiblesnumerosos paquetes de terceros

Julia es un lenguaje de programacioacuten uacutenico ya que resuelve el problema de losdos idiomas No se necesita de ninguacuten otro lenguaje de programacioacuten paraescribir coacutedigo de alto rendimiento Esto no significa que ocurraautomaacuteticamente Es responsabilidad del programador optimizar el coacutedigo quegenere cuellos de botella aunque esto puede hacerse directamente en Julia

iquestA quieacuten estaacute dirigido este libroEste libro es para cualquier persona que quiera aprender a programar No serequieren conocimientos formales previos

Los nuevos conceptos se introducen gradualmente y los temas maacutes avanzados sedescriben en capiacutetulos posteriores

Introduccioacuten a Julia puede ser usado como un curso de un semestre de nivelsecundario o universitario

Convenciones utilizadas en este libroEn este libro se siguen las siguientes convenciones tipograacuteficas

CursivaIndica nuevos teacuterminos URL direcciones de correo electroacutenico nombres dearchivo y extensiones de archivo

Ancho constanteSe utiliza para mostrar coacutedigo de programas asiacute como dentro de lospaacuterrafos para referirse a elementos del programa como nombres devariables o funciones bases de datos tipos de datos variables de entornosentencias y palabras reservadas

4 Prefacio

Ancho constante en negrita

Muestra comandos u otro texto que el usuario debe escribir

Ancho constante en cursivaMuestra el texto que debe reemplazarse con valores proporcionados por elusuario o por valores determinados por el contexto

OBSERVACIOacuteN Esto indica consejo o sugerencia

NOTA Esto es una nota general

AVISO Esto indica una advertencia o precaucioacuten

Usando los coacutedigos de ejemploTodo el coacutedigo utilizado en este libro estaacute disponible en un repositorio de Git enGitHub httpsgithubcomJuliaIntroIntroAJuliajl Si no estaacute familiarizado conGit es un sistema de control de versiones que le permite realizar seguimiento alos archivos que componen un proyecto Una coleccioacuten de archivos controladospor Git se denomina ldquorepositoriordquo GitHub es un servicio de hosting queproporciona almacenamiento para repositorios de Git y una interfaz webconveniente

El siguiente paquete puede ser de utilidad y se puede agregar directamente aJulia Simplemente escriba add httpsgithubcomJuliaIntroIntroAJuliajlen el REPL en modo Pkg

La forma maacutes faacutecil de ejecutar un coacutedigo de Julia es yendo a httpsjuliaboxcome iniciar una sesioacuten de prueba gratuita Es posible utilizar tanto las interfacesREPL como de notebooks Si desea tener Julia instalada localmente en sucomputadora puede descargar JuliaPro de Julia Computing gratuitamenteConsiste en una versioacuten reciente de Julia el IDE de Juno basado en Atom y variospaquetes de Julia preinstalados Si es maacutes aventurero puede descargar Juliadesde httpsjulialangorg instale el editor que prefiera por ejemplo Atom oVisual Studio Code activando los complementos para su integracioacuten de Julia Enel caso de una instalacioacuten local tambieacuten puede agregar el paquete IJulia que lepermite ejecutar un notebook de Jupyter en su computadora

AgradecimientosRealmente quiero agradecer a Allen por escribir Think Python y permitirmetrasladar este libro a Julia iexclTu entusiasmo es contagioso

Tambieacuten me gustariacutea agradecer a los revisores teacutecnicos de este libro quehicieron muchas sugerencias uacutetiles Tim Besard Bart Janssens y David P

Usando los coacutedigos de ejemplo 5

Sanders

Gracias a Melissa Potter de OrsquoReilly Media por hacer de este un mejor libro Meobligaste a hacer las cosas bien y hacer que este libro sea lo maacutes originalposible

Gracias a Matt Hacker de OrsquoReilly Media que me ayudoacute con la cadena deherramientas Atlas y algunos problemas al destacar la sintaxis

Gracias a todos los estudiantes que trabajaron con una versioacuten temprana de estelibro y a todos los colaboradores (enumerados a continuacioacuten) que enviaroncorrecciones y sugerencias

Lista de ColaboradoresSi tiene una sugerencia o correccioacuten abra un issue en GitHub Si se realiza uncambio basado en sus comentarios seraacute agregado a la lista de contribuyentes (amenos que solicite ser omitido)

Aviacutesenos con queacute versioacuten del libro estaacute trabajando y en queacute formato Si incluyeal menos parte de la oracioacuten en la que aparece el error eso facilita la buacutesquedaLos nuacutemeros de paacutegina y seccioacuten tambieacuten son uacutetiles pero no es tan faacutecil trabajarcon ellos iexclGracias

bull Scott Jones sentildealoacute el cambio de nombre de Void a Nothing y con esto secomenzoacute la migracioacuten a Julia v10

bull Robin Deits encontroacute algunos errores tipograacuteficos en el Capiacutetulo 2

bull Mark Schmitz sugirioacute destacar la sintaxis

bull Zigu Zhao encontroacute algunos errores en el Capiacutetulo 8

bull Oleg Soloviev detectoacute un error en la url al agregar el paquete ThinkJulia

bull Aaron Ang encontroacute algunos problemas de representacioacuten y nomenclatura

bull Sergey Volkov encontroacute un enlace caiacutedo en el Capiacutetulo 7

bull Sean McAllister sugirioacute mencionar el excelente paquete BenchmarkTools

bull Carlos Bolech envioacute una larga lista de correcciones y sugerencias

bull Krishna Kumar corrigioacute el ejemplo de Markov en el Capiacutetulo 18

6 Prefacio

Capiacutetulo 1 El camino de la programacioacutenEl objetivo de este libro es ensentildearle a pensar como un informaacutetico Esta manerade pensar combina las mejores caracteriacutesticas de las matemaacuteticas la ingenieriacutea ylas ciencias naturales Los informaacuteticos al igual que los matemaacuteticos usanlenguajes formales para expresar ideas (especiacuteficamente caacutelculos) De manerasimilar a los ingenieros disentildean estructuras ensamblan componentes paraformar sistemas evaluando los costos y beneficios entre las alternativasAdemaacutes observan el comportamiento de sistemas complejos elaboran hipoacutetesisy prueban predicciones como los cientiacuteficos

La habilidad maacutes importante para un informaacutetico es la resolucioacuten de problemasEsto implica ser capaz de formular problemas encontrar soluciones creativasexpresando una solucioacuten de forma clara y precisa Como resultado el proceso deaprender a programar es una excelente oportunidad para practicar habilidadesde resolucioacuten de problemas Es por ello que este capiacutetulo se llama El camino dela programacioacuten

Por una parte aprenderaacute a programar que es una habilidad muy uacutetil por siacutemisma Pero ademaacutes la programacioacuten se constituiraacute como un medio para un finA medida que avancemos este fin seraacute maacutes claro

iquestQueacute es un programa

Un programa es una secuencia de instrucciones que especifica coacutemo hacer uncaacutelculo El caacutelculo puede ser de naturaleza matemaacutetica tal como resolver unsistema de ecuaciones o encontrar las raiacuteces de un polinomio pero tambieacutenpuede ser un caacutelculo simboacutelico como buscar y reemplazar texto en undocumento o bien algo graacutefico tal como procesar una imagen o reproducir unvideo

Los detalles difieren para cada lenguaje pero algunas instrucciones baacutesicasaparecen en casi todos los lenguajes

EntradaInputSe obtienen datos a traveacutes del teclado un archivo una red u otrodispositivo

SalidaOutputLos datos se muestran por pantalla se guardan en un archivo se enviacutean atraveacutes de la red etc

MatemaacuteticasSe realizan operaciones matemaacuteticas baacutesicas como la suma y lamultiplicacioacuten

iquestQueacute es un programa 7

Ejecucioacuten condicionalSe verifican ciertas condiciones y se ejecuta el coacutedigo apropiado

RepeticioacutenSe realiza alguna accioacuten repetidamente generalmente con alguna variacioacuten

Aunque no lo crea eso es todo lo que se debe hacer Cada programa que hausado sin importar su complejidad estaacute construido basaacutendose en instruccionesque se asemejan a estas De esta manera la programacioacuten puede entendersecomo el proceso de dividir una tarea compleja y larga en pequentildeas subtareas losuficientemente simples como para realizarse con una de estas instruccionesbaacutesicas

Ejecutando Julia

Uno de los desafiacuteos al comenzar a utilizar Julia es su instalacioacuten ademaacutes delsoftware relacionado Si estaacute familiarizado con su sistema operativo y se sientecoacutemodo con la interfaz de liacutenea de comandos no tendraacute problemas No obstantepara los principiantes puede ser difiacutecil aprender sobre administracioacuten de sistemay programacioacuten al mismo tiempo

Para evitar ese problema se recomienda que comience ejecutando Julia en unnavegador Maacutes tarde cuando se sienta coacutemodo con Julia se haraacuten sugerenciaspara instalar Julia en su ordenador

En el navegador puede ejecutar Julia en JuliaBox No se requiere instalacioacutensimplemente abra su navegador y entre a la paacutegina de JuliaBox inicie sesioacuten ycomience a programar (consulte Apeacutendice B)

Julia REPL (de ReadndashEvalndashPrint Loop que se traduce en Bucle de Leer-Evaluar-Imprimir) es un programa que lee y ejecuta coacutedigo de Julia Puede iniciar REPLabriendo un terminal en JuliaBox y escribiendo julia en la liacutenea de comandoCuando comienza deberiacutea ver una salida como esta

_ _ _ _(_)_ | Documentation httpsdocsjulialangorg (_) | (_) (_) | _ _ _| |_ __ _ | Type for help ] for Pkg help | | | | | | | _` | | | | |_| | | | (_| | | Version 152 (2020-09-23) _ |___|_|_|___| | Official httpsjulialangorg release|__ |

juliagt

Las primeras liacuteneas contienen informacioacuten sobre el REPL por lo que esto puede

8 Capiacutetulo 1 El camino de la programacioacuten

mostrarse diferente en su computadora Debe verificar que la versioacuten sea almenos 100

El uacuteltima liacutenea es un indicador sentildealando que el REPL estaacute listo para que seingrese una instruccioacuten Si escribe una liacutenea de coacutedigo y presiona Enter la REPLmuestra el resultado

juliagt 1 + 12

Los fragmentos de coacutedigo se pueden copiar y pegar textualmente incluido elindicador juliagt y cualquier salida

Ahora ya estaacute listo para comenzar De aquiacute en adelante ya sabraacute coacutemo iniciar laREPL de Julia y ejecutar su coacutedigo

El primer programaTradicionalmente el primer programa que se escribe en un nuevo lenguaje sellama ldquoiexclHola mundordquo porque todo lo que hace es mostrar las palabras ldquoiexclHolamundordquo En Julia se ve asiacute

juliagt println(iexclHola mundo)iexclHola mundo

Este es un ejemplo de una sentencia de impresioacuten aunque en realidad noimprime nada en papel Muestra un resultado en la pantalla

Las comillas en el programa marcan el principio y el final del texto que semostraraacute y no apareceraacuten en el resultado

Los pareacutentesis indican que println es una funcioacuten Se estudiaraacuten funciones enCapiacutetulo 3

Operadores aritmeacuteticos

Despueacutes de nuestro programa ldquoiexclHola mundordquo el siguiente paso es laaritmeacutetica Julia tiene operadores los cuales son siacutembolos que representancaacutelculos como la suma y la multiplicacioacuten

Los operadores + - y realizan las operaciones de suma resta y multiplicacioacutenrespectivamente como se muestra en los siguientes ejemplos

El primer programa 9

juliagt 40 + 242juliagt 43 - 142juliagt 6 742

El operador realiza la divisioacuten

juliagt 842420

Quizaacutes se pregunte por queacute el resultado es 420 en vez de 42 Esto seraacuteexplicado en la siguiente seccioacuten

Finalmente el operador ^ realiza la potencicioacuten es decir eleva un nuacutemero a unapotencia

juliagt 6^2 + 642

Valores y tipos

Un valor es uno de los elementos baacutesicos con los que trabaja un programa talcomo una letra o un nuacutemero Algunos de los valores que hemos visto hasta ahorason 2 420 y Hola Mundo

Estos valores pertenecen a diferentes tipos 2 es un entero (integer en ingleacutes)420 es un nuacutemero de punto flotante (floating-point number en ingleacutes) y HolaMundo es una cadena de caracteres (string en ingleacutes) llamada asiacute porque lasletras que contiene estaacuten unidas

Si no estaacute seguro del tipo de un valor el REPL puede ayudarle

juliagt typeof(2)Int64juliagt typeof(420)Float64juliagt typeof(iexclHola mundo)String

Los enteros pertenecen al tipo Int64 las cadenas pertenecen a String y losnuacutemeros de punto flotante pertenecen a Float64

10 Capiacutetulo 1 El camino de la programacioacuten

iquestQueacute pasa con los valores 2 y 420 Parecen nuacutemeros pero estaacuten entrecomillas como si fueran cadenas Estos valores tambieacuten son cadenas

juliagt typeof(2)Stringjuliagt typeof(420)String

Si se quiere escribir un nuacutemero de grandes dimensiones se podriacutea caer en lacostumbre de usar comas para separar sus cifras como por ejemplo 1000000Este no es un entero vaacutelido en Julia aunque siacute es vaacutelido

juliagt 1000000(1 0 0)

iexclEsto no es lo que se podriacutea esperar Julia entiende 1000000 como unasecuencia de enteros separados por comas Maacutes adelante aprenderemos maacutessobre este tipo de secuencias

Sin embargo puede obtener el resultado esperado usando 1_000_000

Lenguajes formales y naturales

Los lenguajes naturales son los lenguajes hablados como el espantildeol el ingleacutes oel franceacutes no fueron disentildeados por personas (aunque las personas intentanimponerles un orden) sino que evolucionaron naturalmente

Los lenguajes formales son lenguajes disentildeados por personas para propoacutesitosespeciacuteficos Por ejemplo la notacioacuten que usan los matemaacuteticos es un lenguajeformal particularmente uacutetil para denotar relaciones entre nuacutemeros y siacutembolosLos quiacutemicos usan un lenguaje formal para representar la estructura quiacutemica delas moleacuteculas Los lenguajes de programacioacuten tambieacuten son lenguajes formales yhan sido disentildeados para expresar caacutelculos

Los lenguajes formales tienden a dictar reglas estrictas de sintaxis quegobiernan la estructura de las sentencias Por ejemplo en matemaacuteticas lasentencia tiene la sintaxis correcta pero no En quiacutemica esuna foacutermula sintaacutecticamente correcta pero no lo es

Las reglas de sintaxis pueden ser de dos tipos correspondientes a componentesleacutexicos y a estructura Los componentes leacutexicos son los elementos baacutesicos dellenguaje como palabras nuacutemeros y elementos quiacutemicos Uno de los problemascon es que no es un componente leacutexico vaacutelido en matemaacuteticas (al menos

Lenguajes formales y naturales 11

hasta donde conocemos) Del mismo modo no es vaacutelido porque no existeninguacuten elemento con la abreviatura

El segundo tipo de reglas de sintaxis se refiere a la forma en que se combinan loscomponentes leacutexicos La ecuacioacuten no es vaacutelida porque aunque y soncomponentes leacutexicos vaacutelidos no se puede tener uno justo despueacutes el otro Delmismo modo en una foacutermula quiacutemica el subiacutendice se coloca despueacutes del nombredel elemento no antes

Esta es un oracioacuten en espa$ol bien estructurada con cmponentes leacutexicos novaacutelidos Esta oracioacuten leacutexicos todos componentes los tiene pero estructura una novaacutelida con

Cuando se lee una oracioacuten en espantildeol o en un lenguaje formal se tiene quedescubrir la estructura (aunque en un lenguaje natural se haceinconscientemente) Este proceso se llama parsing o anaacutelisis de sintaxis

Aunque los lenguajes formales y naturales tienen muchas caracteriacutesticas encomuacutenmdashcomponentes leacutexicos estructura y sintaxismdashexisten algunas diferencias

AmbiguumledadLos lenguajes naturales estaacuten llenos de ambiguumledades este problema esabordado mediante el uso del contexto y otra informacioacuten Los lenguajesformales estaacuten disentildeados para ser casi completamente precisos lo quesignifica que cualquier declaracioacuten tiene exactamente un significadoindependientemente del contexto

RedundanciaPara compensar la ambiguumledad y reducir los malentendidos los lenguajesnaturales emplean mucha redundancia Como resultado a menudo sonverbosos Los lenguajes formales son menos redundantes y maacutes concisos

MetaacuteforaLos lenguajes naturales estaacuten llenos de modismos y metaacuteforas Si se diceldquoCaiacute en la cuentardquo probablemente no haya una cuenta y nada que se caiga(este modismo significa que alguien entendioacute algo despueacutes de un periacuteodo deconfusioacuten) Por otro lado los lenguajes formales significan exactamente loque expresan

Debido a que todo el mundo crece hablando lenguajes naturales a veces esdifiacutecil adaptarse a los lenguajes formales La diferencia entre lenguaje formal ynatural es como la diferencia entre la poesiacutea y la prosa

PoesiacuteaLas palabras se usan por sus sonidos y significados El poema en conjuntocrea un efecto o una respuesta emocional La ambiguumledad no soacutelo es comuacutensino a menudo deliberada

12 Capiacutetulo 1 El camino de la programacioacuten

ProsaEl significado literal de las palabras es maacutes importante y la estructuraaporta significado La prosa es maacutes faacutecil de analizar que la poesiacutea pero amenudo sigue siendo ambigua

ProgramasEl significado de un programa computacional es inequiacutevoco y literal ypuede entenderse por completo mediante el anaacutelisis de los componentesleacutexicos y de estructura

Los lenguajes formales son maacutes densos que los naturales por lo que lleva maacutestiempo leerlos Ademaacutes la estructura es importante por lo que no siempre esmejor leer de arriba a abajo y de izquierda a derecha En cambio aprenderaacute aanalizar el programa mentalmente identificando los componentes leacutexicos einterpretando la estructura Finalmente los detalles son importantes Pequentildeoserrores de ortografiacutea y puntuacioacuten que pueden pasar desapercibidos en loslenguajes naturales pueden hacer una gran diferencia en un lenguaje formal

Depuracioacuten

Los programadores cometen errores Los errores de programacioacuten se denominanbugs y el proceso para rastrearlos se denomina debugging o depuracioacuten

La programacioacuten y especialmente la depuracioacuten pueden provocar emocionesnegativas Frente a un error difiacutecil de solucionar puede sentir enojo verguumlenzaoacute cansancio

Existe evidencia de que las personas responden naturalmente a lascomputadoras como si fueran personas Cuando trabajan bien se los consideracompantildeeros de equipo y cuando son obstinados o groseros se los trata de lamisma manera que a personas groseras y obstinadas [1]

Prepararse para estas reacciones puede ayudarlo a lidiar con ellas Un enfoquees pensar en la computadora como un empleado con ciertas fortalezas como lavelocidad y la precisioacuten y debilidades particulares como la falta de empatiacutea y laincapacidad para comprender el panorama general

Su trabajo es ser un buen gerente debe encontrar formas de aprovechar lasfortalezas y mitigar las debilidades Ademaacutes debe encontrar formas de usar susemociones para involucrarse con el problema sin dejar que sus reaccionesinterfieran con su capacidad para trabajar de manera efectiva

Aprender a depurar puede ser frustrante pero es una habilidad valiosa que esuacutetil para muchas actividades maacutes allaacute de la programacioacuten Al final de cadacapiacutetulo hay una seccioacuten como esta con algunas sugerencias para ladepuracioacuten iexclEspero que le sean de ayuda

Depuracioacuten 13

Glosarioresolucioacuten de problemas

El proceso de formular un problema encontrar una solucioacuten y expresarla

programaUna secuencia de instrucciones que especifica un caacutelculo

REPLUn programa que de manera reiterada lee una entrada la ejecuta y generaresultados

indicadorCaracteres mostrados por el REPL para indicar que estaacute listo para recibirinformacioacuten de entrada de parte del usuario

sentencia de impresioacuten (print)Una instruccioacuten que hace que el REPL de Julia muestre un valor en lapantalla

operadorUn siacutembolo que representa un caacutelculo simple como la suma lamultiplicacioacuten o la concatenacioacuten de cadenas

valorUna de las unidades baacutesicas de datos como un nuacutemero o cadena quemanipula un programa

tipoUna categoriacutea de valores Los tipos que se han visto hasta ahora sonenteros (Int64) nuacutemeros de punto flotante (Float64) y cadenas (String)

enteroUn tipo que representa nuacutemeros enteros

punto flotanteUn tipo que representa nuacutemeros con un punto decimal

cadenaUn tipo que representa secuencias de caracteres

lenguaje naturalCualquier lenguaje hablado que evoluciona naturalmente

14 Capiacutetulo 1 El camino de la programacioacuten

lenguaje formalCualquier lenguaje disentildeado para fines especiacuteficos como la representacioacutende ideas matemaacuteticas o programas de computadora Todos los lenguajes deprogramacioacuten son lenguajes formales

sintaxisLas reglas que gobiernan la estructura de un programa

componente leacutexicoUno de los elementos baacutesicos de la estructura de un programa anaacutelogo auna palabra en un lenguaje natural

estructuraLa manera en que los componentes leacutexicos se combinan

anaacutelisis de sintaxisExaminar un programa y analizar la estructura sintaacutectica

bugUn error en un programa

depuracioacutendebuggingEl proceso de buacutesqueda y correccioacuten de errores

Ejercicios

OBSERVACIOacuteNEs una buena idea leer este libro frente a unacomputadora para hacer los ejemplos y ejerciciosconforme avance

Ejercicio 1-1

Siempre que esteacute experimentando con algo nuevo debe intentar cometererrores Por ejemplo en el programa ldquoiexclHola mundordquo iquestQueacute sucede si omite unade las comillas iquestQueacute pasa si omite ambas iquestQueacute ocurre si escribe mal println

Este tipo de ejercicios le ayuda a recordar lo que leyoacute tambieacuten le ayuda aprogramar porque puede saber queacute significan los mensajes de error Es mejorcometer errores ahora y a propoacutesito en lugar de despueacutes y accidentalmente

1 En un comando print iquestQueacute sucede si omite uno de los pareacutentesis o ambos

2 Si estaacute intentando imprimir un string iquestQueacute sucede si omite una de lascomillas o ambas

3 Se puede usar un signo menos para escribir un nuacutemero negativo como -2

Ejercicios 15

iquestQueacute sucede si pone un signo + antes de un nuacutemero iquestQueacute pasa con 2++2

4 En notacioacuten matemaacutetica los ceros a la izquierda son correctos como en 02iquestQueacute pasa si intenta esto en Julia

5 iquestQueacute sucede si tiene dos valores sin operador entre ellos

Ejercicio 1-2

Inicie el REPL de Julia y uacuteselo como una calculadora

1 iquestCuaacutentos segundos hay en 42 minutos y 42 segundos

2 iquestCuaacutentas millas hay en 10 kiloacutemetros

OBSERVACIOacuteN Hay 161 kiloacutemetros en una milla

3 Si corre una carrera de 10 kiloacutemetros en 37 minutos y 48 segundos iquestCuaacuteles su ritmo promedio (tiempo por milla en minutos y segundos) iquestCuaacutel es suvelocidad promedio en millas por hora

[1] Reeves Byron and Clifford Ivar Nass 1996 ldquoThe Media Equation How People Treat ComputersTelevision and New Media Like Real People and Placesrdquo Chicago IL Center for the Study of Language andInformation New York Cambridge University Press

16 Capiacutetulo 1 El camino de la programacioacuten

Capiacutetulo 2 Variables expresiones y sentenciasUna de las caracteriacutesticas maacutes poderosas de un lenguaje de programacioacuten es lacapacidad de manipular variables Una variable es un nombre que hacereferencia a un valor

Sentencias de asignacioacuten

Una sentencia de asignacioacuten crea una nueva variable y le asigna un valor

juliagt mensaje = Y ahora algo completamente diferenteY ahora algo completamente diferentejuliagt n = 1717juliagt π_val = 31415926535897933141592653589793

Este ejemplo realiza tres asignaciones La primera asigna una cadena a unanueva variable llamada mensaje la segunda le asigna el entero 17 a la variable nla tercera asigna el valor (aproximado) de π (pi TAB) a la variable π_val

Una forma comuacuten de representar variables en papel es escribir el nombre de lavariable con una flecha apuntando a su valor Este tipo de figura se llamaldquodiagrama de estadordquo porque muestra en queacute estado se encuentra cada una delas variables La Figura 1 Figura 1 muestra el resultado del ejemplo anterior

Figura 1 Diagrama de estado

Nombres de variablesLos programadores generalmente eligen nombres representativos para susvariables es decir nombres que explican para queacute se usa o queacute contiene lavariable

Los nombres de las variables pueden ser tan largos como se desee Puedencontener casi todos los caracteres Unicode (consulte Seccioacuten 81) pero nopueden comenzar con un nuacutemero Es vaacutelido usar letras mayuacutesculas pero locomuacuten es usar solo minuacutesculas para nombres de variables

Los caracteres Unicode se pueden ingresar mediante autocompletado portabulacioacuten de las abreviaturas tipo LaTeX en el REPL de Julia

El caraacutecter guioacuten bajo _ puede formar parte del nombre de una variable

Sentencias de asignacioacuten 17

Generalmente se usa como separador en nombres con varias palabras como porejemplo en tu_nombre ovelocidad_aerodinamica_de_una_golondrina_sin_cargamento

Si se le da un nombre invaacutelido a una variable aparece un error de sintaxis

juliagt 76trombones = un gran desfileERROR syntax 76 is not a valid function argument name (ERRORsintaxis 76 no es un nombre de argumento de funcioacuten vaacutelido)juliagt mas = 1000000ERROR syntax extra token after end of expression (ERROR sintaxiscomponente leacutexico adicional despueacutes del final de la expresioacuten)juliagt struct = Quiacutemica avanzadaERROR syntax unexpected = (ERROR sintaxis = inesperado)

76trombones es un nombre de variable invaacutelido porque comienza con un nuacutemeroTambieacuten es invaacutelido mas porque contiene el caraacutecter invaacutelido Pero iquestCuaacutel esel error en struct

Resulta que struct es una de las palabras reservadas de Julia Julia usa laspalabras reservadas para reconocer la estructura del programa por ello nopueden usarse como nombres de variables

Julia tiene las siguientes palabras reservadas

abstract type baremodule begin break catchconst continue do else elseifend export finally for functionglobal if import importall inlet local macro module mutable structprimitive type quote return try usingstruct where while

No es necesario memorizar esta lista En la mayoriacutea de los entornos dedesarrollo las palabras reservadas se muestran en un color diferente por lotanto si intenta usar una como nombre de variable lo sabraacute

Expresiones y sentenciasUna expresioacuten es una combinacioacuten de valores variables y operadores Un valor ouna variable por siacute solos se consideran una expresioacuten por lo que las siguientesexpresiones son vaacutelidas

18 Capiacutetulo 2 Variables expresiones y sentencias

juliagt 4242juliagt n17juliagt n + 2542

Cuando escribe una expresioacuten en el indicador el REPL la evaluacutea lo que significaque encuentra el valor de la expresioacuten En este ejemplo n tiene el valor 17previamente asignado y n+25 retorna el valor 42

Una sentencia es una unidad de coacutedigo que tiene un efecto tal como crear unavariable o mostrar un valor

juliagt n = 1717juliagt println(n)17

La primera liacutenea es una sentencia de asignacioacuten ya que asigna un valor a n Lasegunda liacutenea es una sentencia de impresioacuten que muestra el valor de n

Cuando escribe una sentencia REPL la ejecuta es decir hace lo que dice lasentencia

Modo scriptHasta ahora se ha ejecutado Julia en modo interactivo lo que significa que se hainteractuado directamente con el REPL Este modo es una buena manera decomenzar pero si estaacute trabajando con varias liacuteneas de coacutedigo puede resultarincoacutemodo

Una alternativa es guardar el coacutedigo en un archivo de oacuterdenes o script y luegoutilizar Julia en modo script para ejecutarlo Por convencioacuten los scripts de Juliatienen nombres que terminan con la extensioacuten jl

Si sabe coacutemo crear y ejecutar un script en su computadora estaacute listo paracomenzar De lo contrario es recomendable usar JuliaBox nuevamente Abra unarchivo de texto escriba el script y guaacuterdelo con la extensioacuten jl El script sepuede ejecutar en una terminal con el comando julia nombre_del_scriptjl

Debido a que Julia proporciona ambos modos puede probar liacuteneas de coacutedigo enmodo interactivo antes de colocarlos en un script Auacuten asiacute tenga enconsideracioacuten que existen diferencias entre el modo interactivo y el modo scriptque pueden generar confusioacuten

Por ejemplo si estaacute utilizando Julia como una calculadora puede escribir

Modo script 19

juliagt millas = 262262juliagt millas 16142182

La primera liacutenea asigna un valor a millas y muestra el valor La segunda liacutenea esuna expresioacuten por lo que el REPL la evaluacutea y muestra el resultado Gracias alcoacutedigo anterior sabemos que una maratoacuten tiene unos 42 kiloacutemetros

Pero si escribe el mismo coacutedigo en un script y lo ejecuta no obtendraacute ninguacutenresultado En el modo script una expresioacuten por siacute sola no tiene ninguacuten efectovisible Julia evaluacutea la expresioacuten pero no muestra el valor a menos que se loindique

millas = 262println(millas 161)

Al principio este comportamiento puede ser confuso

Un script generalmente contiene una secuencia de sentencias Si hay maacutes de unasentencia los resultados aparecen de uno a la vez a medida que se ejecutan lassentencias

Por ejemplo el script

println(1)x = 2println(x)

produce la salida

12

Notar que la sentencia de asignacioacuten x = 2 no tiene salida

Ejercicio 2-1

Para comprobar que ha comprendido lo recientemente explicado escriba lassiguientes sentencias en el REPL de Julia y vea lo que hace cada una

5x = 5x + 1

20 Capiacutetulo 2 Variables expresiones y sentencias

Ahora coloque las mismas sentencias en un script y ejecuacutetelo iquestCuaacutel es elresultado Modifique el script transformando cada expresioacuten en una sentencia deimpresioacuten y luego ejecuacutetelo de nuevo

Orden de operacionesCuando una expresioacuten contiene maacutes de un operador el orden de evaluacioacutendepende de las reglas de precedencia Julia sigue la convencioacuten matemaacutetica parael orden de evaluacioacuten de los operadores matemaacuteticos El acroacutenimo PAPOMUDASes una forma uacutetil de recordar estas reglas

bull PAreacutentesis tienen la mayor precedencia y se pueden utilizar para forzar laevaluacioacuten de una expresioacuten en el orden que se desee Dado que lasexpresiones entre pareacutentesis se evaluacutean primero 2(3-1) es 4 y (1+1)^(5-2) es 8 Tambieacuten puede usar pareacutentesis para hacer una expresioacuten maacutes faacutecilde leer como en (minuto100)60 incluso si no cambia el resultado

bull POtenciacioacuten tiene la siguiente precedencia maacutes alta por lo que 1+2^3 es9 no 27 y 23^2 es 18 no 36

bull MUltiplicacioacuten y Divisioacuten tienen mayor precedencia que la Adicioacuten ySustraccioacuten Entonces 23-1 es 5 no 4 y 6+42 es 8 no 5

bull Los operadores con la misma precedencia se evaluacutean de izquierda a derecha(excepto potencias) Entonces en la expresioacuten grados2π la divisioacuten ocurreprimero y el resultado se multiplica por π Para dividir entre puede usarpareacutentesis escribir grados2π o grados2π

OBSERVACIOacuteNNo se esfuerce demasiado en recordar el orden de lasoperaciones Si el orden no es evidente mirando laexpresioacuten use pareacutentesis para que siacute lo sea

Operaciones con cadenasEn general no se pueden realizar operaciones matemaacuteticas con cadenas aunquelas cadenas puedan parecer nuacutemeros por lo que lo siguiente es invaacutelido

2 - 1huevos faacuteciltercero + talismaacuten

No obstante hay dos excepciones y ^

El operador realiza concatenacioacuten de cadenas lo que significa que une lascadenas de extremo a extremo Por ejemplo

Orden de operaciones 21

juliagt primer_str = autoautojuliagt segundo_str = moacutevilmoacuteviljuliagt primer_str segundo_strautomoacutevil

El operador ^ tambieacuten funciona con cadenas generando repeticiones Porejemplo Spam^3 es SpamSpamSpam Si uno de los valores es una cadena elotro tiene que ser un nuacutemero entero

De manera anaacuteloga este uso de y ^ tambieacuten tiene sentido en la multiplicacioacuten ypotencia Asiacute como 4^3 es equivalente a 444 esperamos que el Spam^3 sea lomismo que el SpamSpamSpam y lo es

ComentariosA medida que los programas se hacen maacutes largos y complejos se vuelven maacutesdifiacuteciles de leer Los lenguajes formales son densos y a menudo es difiacutecil leer elcoacutedigo y entender queacute estaacute haciendo o por queacute

Por esta razoacuten es una buena idea agregar notas a sus programas para explicaren lenguaje natural lo que estaacute haciendo el programa Estas notas se llamancomentarios y comienzan con el siacutembolo

calcula el porcentaje de hora que ha transcurridoporcentaje = (minuto 100) 60

En este caso el comentario aparece soacutelo en una liacutenea Tambieacuten puede ponercomentarios al final de una liacutenea

porcentaje = (minuto 100) 60 porcentaje de una hora

Todo desde el hasta el final de la liacutenea se ignora y no tiene ninguacuten efecto en laejecucioacuten del programa

Los comentarios son maacutes uacutetiles cuando documentan caracteriacutesticas no obvias delcoacutedigo Es razonable suponer que el lector puede averiguar queacute hace el coacutedigopor lo tanto es maacutes uacutetil explicar por queacute

Este comentario es inuacutetil porque es redundante con el coacutedigo

v = 5 asigna 5 a v

Este comentario contiene informacioacuten uacutetil que no estaacute presente en el coacutedigo

22 Capiacutetulo 2 Variables expresiones y sentencias

v = 5 velocidad en metrossegundo

OBSERVACIOacuteNLos nombres de las variables tienen que ser descriptivospara asiacute reducir la necesidad de comentarios pero notan largos como para dificultar la lectura del coacutedigo

DepuracioacutenSe pueden producir tres tipos de errores en un programa errores de sintaxiserrores en tiempo de ejecucioacuten y errores semaacutenticos Es uacutetil distinguirlos pararastrearlos maacutes raacutepidamente

Error de sintaxisldquoSintaxisrdquo se refiere a la estructura de un programa y las reglas sobre esaestructura Por ejemplo los pareacutentesis deben presentarse de a pares por loque (1+2) es vaacutelido pero 8) es un error de sintaxis

Si hay un error de sintaxis en cualquier parte de su programa Julia muestraun mensaje de error y se cierra no pudiendo ejecutar el programa Durantesus primeras semanas como programador puede pasar mucho tiemporastreando errores de sintaxis A medida que gane experiencia cometeraacutemenos errores y los encontraraacute maacutes raacutepido

Error en tiempo de ejecucioacutenEl segundo tipo de error es el error en tiempo de ejecucioacuten llamado asiacuteporque aparece durante la ejecucioacuten del programa Estos errores tambieacutense denominan excepciones porque generalmente indican que ha sucedidoalgo excepcional (y malo)

Los errores en tiempo de ejecucioacuten son raros en los programas simples queveraacute en los primeros capiacutetulos por lo que puede pasar un tiempo antes deque encuentre uno

Error semaacutenticoEl tercer tipo de error es ldquosemaacutenticordquo es decir relacionado con elsignificado Si hay un error semaacutentico en su programa este se ejecutaraacute singenerar mensajes de error pero no haraacute lo que se desea sino que haraacute otracosa Especiacuteficamente haraacute lo que usted le dijo que hiciera (y no lo queusted desea que realice)

Identificar errores semaacutenticos puede ser complicado porque requiere que setrabaje a la inversa analizando la salida del programa para intentar descubrirqueacute estaacute haciendo

Depuracioacuten 23

Glosariovariable

Un nombre que hace referencia a un valor

asignacioacutenUna sentencia que asigna un valor a una variable

diagrama de estadoUna representacioacuten graacutefica de un conjunto de variables y los valores a losque hace referencia

palabra claveUna palabra reservada que se utiliza para definir la sintaxis y estructura deun programa no puede usar palabras reservadas como if function ywhile como nombres de variables

operandoUno de los valores sobre los que opera un operador

expresioacutenUna combinacioacuten de variables operadores y valores que representa un solovalor como resultado

evaluarSimplificar una expresioacuten realizando operaciones para obtener un solo valor

sentenciaUna seccioacuten de coacutedigo que representa un comando o accioacuten Hasta ahoralas sentencias que hemos visto son asignaciones e impresiones

ejecutarEjecutar una sentencia y hacer lo que eacutesta dice

modo interactivoUna forma de utilizar el REPL de Julia escribiendo coacutedigo en el indicador

modo scriptUna forma de usar Julia para leer coacutedigo desde un script y ejecutarlo

scriptUn programa almacenado en un archivo

24 Capiacutetulo 2 Variables expresiones y sentencias

precedencia del operadorReglas que rigen el orden en que se evaluacutean las expresiones que involucranmuacuteltiples operadores matemaacuteticos y operandos

concatenarUnir dos cadenas de extremo a extremo

comentarioInformacioacuten en un programa que estaacute destinada a otros programadores (ocualquier persona que lea el coacutedigo fuente) y que no tiene efecto en laejecucioacuten del programa

error de sintaxisUn error en un programa que hace que sea imposible de analizar (y por lotanto imposible de ejecutar)

error en tiempo de ejecucioacuten o excepcioacutenUn error que se detecta mientras se ejecuta el programa

semaacutenticaEl significado de un programa

error semaacutenticoEs un error en un programa que provoca que se haga algo diferente a loque el programador pretendiacutea

Ejercicios

Ejercicio 2-2

Repitiendo el consejo del capiacutetulo anterior cada vez que aprenda algo nuevodebe probarlo en el modo interactivo y cometer errores a propoacutesito para ver elresultado

1 Hemos visto que n=42 es vaacutelido iquestQueacute pasa con 42=n

2 iquestY con x=y=1

3 En algunos lenguajes cada sentencia termina con un punto y coma iquestQueacutesucede si pone un punto y coma al final de una sentencia en Julia

4 iquestQueacute pasa si pone un punto al final de una sentencia

5 En notacioacuten matemaacutetica puede multiplicar x e y de esta manera x y iquestQueacutepasa si intenta eso en Julia iquestY queacute sucede con 5x

Ejercicios 25

Ejercicio 2-3

Practique usando el REPL de Julia como una calculadora

1 El volumen de una esfera con radio es iquestCuaacutel es el volumen de unaesfera con radio 5

2 Supongamos que el precio de venta de un libro es de $2495 pero laslibreriacuteas obtienen un descuento del 40 El enviacuteo cuesta $3 por la primeracopia y 75 centavos por cada copia adicional iquestCuaacutel es el costo total al pormayor de 60 copias

3 Si una persona sale de casa a las 652 am y corre 1 milla a un ritmorelajado (815 minutos por milla) luego 3 millas maacutes raacutepido (712 minutospor milla) y 1 milla a ritmo relajado nuevamente iquestA queacute hora llega a casapara desayunar

26 Capiacutetulo 2 Variables expresiones y sentencias

Capiacutetulo 3 FuncionesEn el contexto de la programacioacuten una funcioacuten es una secuencia de sentenciasque ejecuta una operacioacuten deseada y tiene un nombre Cuando se define unafuncioacuten se especifica su nombre y secuencia de sentencias Una vez hecho estose puede llamar a la funcioacuten por su nombre

Llamada a funcioacuten

Ya se ha visto un ejemplo de una llamada a funcioacuten

juliagt println(iexclHola Mundo)iexclHola Mundo

El nombre de esta funcioacuten es println La expresioacuten entre pareacutentesis se llamaargumento de la funcioacuten

Es comuacuten decir que una funcioacuten toma un argumento y devuelve un resultadoEl resultado tambieacuten se llama valor de retorno

Julia tiene funciones integradas que convierten valores de un tipo a otro Lafuncioacuten parse toma una cadena y si es posible la convierte en cualquier tipo denuacutemero en caso contrario arroja error

juliagt parse(Int64 32)32juliagt parse(Float64 314159)314159juliagt parse(Int64 Hola)ERROR ArgumentError invalid base 10 digit H in Hola

(ERROR ArgumentError base invaacutelida de 10 diacutegitos H en Hola)

trunc puede convertir valores de punto flotante a enteros pero no redondea sinoque trunca

juliagt trunc(Int64 399999)3juliagt trunc(Int64 -23)-2

float convierte nuacutemeros enteros en nuacutemeros de punto flotante

Llamada a funcioacuten 27

juliagt float(32)320

Finalmente string convierte el argumento en una cadena

juliagt string(32)32juliagt string(314159)314159

Funciones matemaacuteticasEn Julia la mayoriacutea de las funciones matemaacuteticas conocidas estaacuten disponiblesdirectamente

proporcioacuten = potencia_de_sentildealpotencia_de_ruidodecibelios = 10log10(proporcioacuten)

Este primer ejemplo utiliza la funcioacuten log10 para calcular la proporcioacuten entresentildeal y ruido en decibelios (suponiendo que potencia_de_sentildeal ypotencia_de_ruido estaacuten definidos) Tambieacuten existe la funcioacuten log que calcula ellogaritmo natural

radianes = 07altura = sin(radianes)

Este segundo ejemplo encuentra la razoacuten seno (en ingleacutes sine) de la variableradianes El nombre de esta variable es una pista de que la funcioacuten sin y las otrasfunciones trigonomeacutetricas (cos tan etc) toman argumentos en radianes Paraconvertir grados a radianes se debe dividir por 180 y multiplicar por

juliagt grados=4545juliagt radianes=grados180π07853981633974483juliagt sin(radianes)07071067811865475

El valor de la variable π es una aproximacioacuten de punto flotante de con unaprecisioacuten de aproximadamente 16 diacutegitos

Si sabe de trigonometriacutea puede verificar el resultado anterior comparaacutendolo conla raiacutez cuadrada de dos dividido por dos

28 Capiacutetulo 3 Funciones

juliagt sqrt(2) 207071067811865476

ComposicioacutenHasta ahora hemos analizado los elementos de un programa (variablesexpresiones y sentencias) de forma aislada sin mencionar coacutemo se combinan

Una de las caracteriacutesticas maacutes uacutetiles de los lenguajes de programacioacuten es sucapacidad para combinar pequentildeos bloques de coacutedigo Por ejemplo elargumento de una funcioacuten puede ser cualquier tipo de expresioacuten incluidosoperadores aritmeacuteticos

x = sin(grados3602π)

E incluso llamadas a funciones

x = exp(log(x + 1))

Casi en cualquier lugar donde se pueda colocar un valor se puede colocar unaexpresioacuten arbitraria con una excepcioacuten el lado izquierdo de una sentencia deasignacioacuten debe ser un nombre de variable Cualquier otra expresioacuten en el ladoizquierdo genera un error de sintaxis (se veraacuten excepciones a esta regla maacutesadelante)

2

juliagt minutos = horas 60 bien120juliagt horas 60 = minutos malERROR syntax 60 is not a valid function argument name

(ERROR sintaxis 60 no es un nombre de argumento de funcioacuten vaacutelido)

Agregar nuevas funcionesHasta ahora solo hemos usado las funciones integradas en Julia pero tambieacuten esposible agregar nuevas funciones Una definicioacuten de funcioacuten especifica el nombrede una nueva funcioacuten y la secuencia de sentencias que se ejecutan cuando sellama a la funcioacuten A continuacioacuten se muestra un ejemplo

Composicioacuten 29

function imprimirletras() println(Juguemos en el bosque) println(mientras el lobo no estaacute)end

function es una palabra reservada que indica que esta es una definicioacuten defuncioacuten El nombre de la funcioacuten es imprimirletras Las reglas para losnombres de funciones son las mismas que para los nombres de variables puedencontener casi todos los caracteres Unicode (consulte Seccioacuten 81) pero el primercaraacutecter no puede ser un nuacutemero No puede usar una palabra reservada comonombre de una funcioacuten y debe evitar tener una variable y una funcioacuten con elmismo nombre

Los pareacutentesis vaciacuteos despueacutes del nombre indican que esta funcioacuten no tieneargumentos

La primera liacutenea de una definicioacuten de funcioacuten se llama encabezado el resto sellama cuerpo El cuerpo termina con la palabra reservada end y puede contenertodas las sentencias que desee Para facilitar la lectura el cuerpo de la funcioacutendeberiacutea tener sangriacutea

Las comillas deben ser comillas rectas () generalmente ubicadas junto a latecla Enter en el teclado Las comillas inglesas (ldquordquo)no son vaacutelidas en Julia

Si escribe una definicioacuten de funcioacuten en modo interactivo Julia REPL inserta unasangriacutea para informarle que la definicioacuten no estaacute completa

juliagt function imprimirletras() println(Juguemos en el bosque)

Para finalizar la funcioacuten debe escribir end

La sintaxis para llamar a la nueva funcioacuten es la misma que para las funcionesintegradas en Julia

juliagt imprimirletras()Juguemos en el bosquemientras el lobo no estaacute

Una vez definida una funcioacuten puede usarla dentro de otra funcioacuten Por ejemplopara repetir el estribillo anterior se podriacutea escribir una funcioacuten llamadarepetirletras

30 Capiacutetulo 3 Funciones

function repetirletras() imprimirletras() imprimirletras()end

Y luego llamar a repetirletras

juliagt repetirletras()Juguemos en el bosquemientras el lobo no estaacuteJuguemos en el bosquemientras el lobo no estaacute

Definiciones y usosAl unir los fragmentos de coacutedigo de la seccioacuten anterior todo el programa se veasiacute

function imprimirletras() println(Jueguemos en el bosque) println(mientras el lobo no estaacute)end

funcioacuten repetirletras() imprimirletras() imprimirletras()end

repetirletras()

Este programa contiene dos definiciones de funcioacuten imprimirletras yrepetirletras Las definiciones de funcioacuten se ejecutan al igual que otrassentencias pero su ejecucioacuten crea nuevas funciones Las sentencias dentro de lafuncioacuten no se ejecutan hasta que se llama a la funcioacuten y la definicioacuten de lafuncioacuten no genera salida

Como es de esperar debe crear una funcioacuten antes de poder ejecutarla En otraspalabras la definicioacuten de la funcioacuten tiene que ejecutarse antes de que se llame ala funcioacuten

Ejercicio 3-1

Mueva la uacuteltima liacutenea de este programa a la parte superior de modo que lallamada a funcioacuten aparezca antes de las definiciones Ejecute el programa y veaqueacute mensaje de error obtiene

Definiciones y usos 31

Ahora mueva la llamada a funcioacuten hacia abajo y coloque la definicioacuten deimprimirletras despueacutes de la definicioacuten de repetirletras iquestQueacute sucede cuandoejecuta este programa

Flujo de ejecucioacutenPara asegurarse de que una funcioacuten sea definida antes de su primer uso debeconocer el orden en que se ejecutan las instrucciones lo que se denomina flujode ejecucioacuten

La ejecucioacuten siempre comienza con la primera sentencia del programa Lassentencias se ejecutan una a la vez en orden descendente

Las definiciones de funcioacuten no alteran el flujo de ejecucioacuten del programa pero sedebe recordar que las sentencias dentro de la funcioacuten no se ejecutan hasta quese llama a la funcioacuten

Una llamada a funcioacuten es como un desviacuteo en el flujo de ejecucioacuten En lugar depasar a la siguiente sentencia el flujo salta al cuerpo de la funcioacuten ejecuta lassentencias que estaacuten alliacute y luego regresa para continuar el coacutedigo donde lo dejoacute

Esto suena bastante simple hasta que se tiene en cuenta que una funcioacuten puedellamar a otra Mientras se estaacute ejecutando una funcioacuten el programa podriacutea tenerque ejecutar las sentencias de otra funcioacuten Luego mientras ejecuta esa nuevafuncioacuten iexclel programa podriacutea tener que ejecutar otra funcioacuten maacutes

Afortunadamente Julia es capaz de hacer el seguimiento de sus movimientos asiacuteque cada vez que una funcioacuten termina el programa retoma la funcioacuten que lallamoacute justo donde la dejoacute Cuando llega al final del programa la ejecucioacutentermina

En resumen cuando lee un programa no siempre debe leer de arriba haciaabajo A veces tiene maacutes sentido seguir el flujo de ejecucioacuten

Paraacutemetros y argumentosAlgunas de las funciones que se han visto requieren argumentos Por ejemplo lafuncioacuten cos necesita un nuacutemero como argumento Algunas funciones toman maacutesde un argumento por ejemplo parse toma dos un nuacutemero y una cadena

Dentro de la funcioacuten los argumentos se asignan a variables llamadasparaacutemetros A continuacioacuten se muestra un ejemplo de definicioacuten de funcioacuten quetoma un argumento

32 Capiacutetulo 3 Funciones

function imprimirdosveces(juan) println(juan) println(juan)end

Esta funcioacuten asigna el argumento a un paraacutemetro llamado juan Cuando se llamaa la funcioacuten esta imprime el valor del paraacutemetro (cualquiera que sea) dos veces

Esta funcioacuten funciona con cualquier valor que se pueda imprimir

juliagt imprimirdosveces(Correo no deseado)Correo no deseadoCorreo no deseadojuliagt imprimirdosveces(42)4242juliagt imprimirdosveces(π)π = 31415926535897 π = 31415926535897

Las mismas reglas de composicioacuten que se aplican a las funciones integradastambieacuten se aplican a las funciones definidas por el programador por lo quepodemos usar cualquier tipo de expresioacuten como argumento paraimprimirdosveces

juliagt imprimirdosveces(Correo no deseado ^4)Correo no deseado Correo no deseado Correo no deseado Correo no deseadoCorreo no deseado Correo no deseado Correo no deseado Correo no deseadojuliagt imprimirdosveces(cos(π))-10-10

El argumento se evaluacutea antes de llamar a la funcioacuten por lo que en los ejemploslas expresiones Correo no deseado ^4 y cos(π) solo se evaluacutean una vez

Tambieacuten puede usar una variable como argumento

juliagt michael = La vida es bellaLa vida es bellajuliagt imprimirdosveces(michael)La vida es bellaLa vida es bella

El nombre de la variable que pasamos como argumento (michael) no tiene nadaque ver con el nombre del paraacutemetro (juan) Para la funcioacuten imprimirdosveces

Paraacutemetros y argumentos 33

todos los paraacutemetros se llaman juan sin importar el nombre de la variable quepasemos como argumento (en este caso michael)

Las variables y los paraacutemetros son localesCuando se crea una variable dentro de una funcioacuten esta es local es decir soloexiste dentro de la funcioacuten Por ejemplo

function concatenar_dos(parte1 parte2) concat = parte1 parte2 imprimirdosveces(concat)end

Esta funcioacuten toma dos argumentos los concatena e imprime el resultado dosveces Aquiacute hay un ejemplo

juliagt linea1 = Hola holaHola holajuliagt linea2 = adioacutes adioacutesadioacutes adioacutesjuliagt concatenar_dos(liacutenea1 liacutenea2)Hola hola adioacutes adioacutesHola hola adioacutes adioacutes

Cuando concatenar_dos termina la variable concat es destruida Si intentamosimprimirla obtendremos un error

juliagt println(concat)ERROR UndefVarError concat not defined

Los paraacutemetros tambieacuten son locales Por ejemplo fuera de la funcioacutenimprimirdosveces no existe juan

Diagramas de pilaPara seguir la pista de queacute variables se usan en queacute lugares es uacutetil dibujar undiagrama de pila Al igual que los diagramas de estado los diagramas de pilamuestran el valor de cada variable pero tambieacuten muestran la funcioacuten a la quepertenece cada una

Cada funcioacuten se representa por un marco Un marco es un recuadro con elnombre de una funcioacuten a un costado y los paraacutemetros y variables de la funcioacutendentro El diagrama de pila para el ejemplo anterior se muestra en Figura 2

34 Capiacutetulo 3 Funciones

Figura 2 Diagrama de pila

Los marcos se ordenan de tal manera que cada funcioacuten llama a la funcioacuteninmediatamente inferior En este ejemplo imprimirdosveces fue llamado porconcatenar_dos y concatenar_dos fue llamado por Main que es un nombreespecial para la funcioacuten de maacutes alto nivel Cuando se crea una variable afuera decualquier funcioacuten pertenece a Main

Cada paraacutemetro se refiere al mismo valor que su argumento correspondienteEntonces parte1 tiene el mismo valor que linea1 parte2 tiene el mismo valorque linea2 y juan tiene el mismo valor que concat

Si se produce un error durante una llamada a funcioacuten Julia imprime el nombrede la funcioacuten el nombre de la funcioacuten que la llamoacute el nombre de la funcioacuten que asu vez llamoacute a esta otra y asiacute sucesivamente hasta llegar a la funcioacuten de maacutes altonivel Main

Por ejemplo si intenta acceder a concat desde imprimirdosveces obtendraacute unUndefVarError

ERROR UndefVarError concat not definedStacktrace [1] imprimirdosveces at REPL[1]gt2 [inlined] [2] concatenar_dos(String String) at REPL[2]gt3

Esta lista de funciones se llama trazado inverso Indica en queacute archivo deprograma se produjo el error en queacute liacutenea y queacute funciones se estaban ejecutandoen ese momento Tambieacuten muestra la liacutenea de coacutedigo que causoacute el error

El orden de las funciones en el trazado inverso es el opuesto del orden de losrecuadros en el diagrama de pila La funcioacuten que se estaacute ejecutando actualmenteestaacute en la parte superior

Funciones productivas y funciones nulasAlgunas de las funciones que hemos utilizado como las funciones matemaacuteticasdevuelven resultados A este tipo de funciones se les llamaraacute funcionesproductivas a falta de un nombre mejor Otras funciones comoimprimirdosveces realizan una accioacuten pero no devuelven un valor Estas sellaman funciones nulas

Funciones productivas y funciones nulas 35

Cuando se llama a una funcioacuten productiva casi siempre se quiere hacer algo conel resultado por ejemplo asignarlo a una variable o usarlo como parte de unaexpresioacuten

x = cos(radianes)aurea = (sqrt(5)+1)2

Cuando se llama a una funcioacuten en modo interactivo Julia muestra el resultado

juliagt sqrt(5)223606797749979

Pero en un script si se llama a una funcioacuten productiva iexclel valor de retorno sepierde para siempre

sqrt(5)

Output

223606797749979

Este script calcula la raiacutez cuadrada de 5 pero como no almacena ni muestra elresultado no es muy uacutetil

Las funciones nulas pueden mostrar algo en la pantalla o tener alguacuten otro efectopero no tienen un valor de retorno Si asigna el resultado a una variableobtendraacute un valor especial llamado nothing (nada en ingleacutes)

juliagt resultado = imprimirdosveces(Bing)BingBingjuliagt show(resultado)nothing

Para imprimir el valor nothing debe usar la funcioacuten show que es como la funcioacutenprint pero permite el valor nothing

El valor nothing no es lo mismo que la cadena nothing Es un valor especial quetiene su propio tipo

juliagt typeof (nothing)Nothing

Las funciones que hemos escrito hasta ahora son nulas Comenzaremos a escribir

36 Capiacutetulo 3 Funciones

funciones productivas en unos pocos capiacutetulos

iquestPor queacute se necesitan funcionesPuede que no esteacute claro por queacute vale la pena dividir un programa en funcionesHay varias razones

bull Crear una nueva funcioacuten le brinda la oportunidad de darle nombre a ungrupo de sentencias lo que hace que su programa sea maacutes faacutecil de leer ydepurar

bull Las funciones pueden hacer que un programa sea maacutes corto al eliminarcoacutedigo repetitivo Ademaacutes si realiza un cambio solo tiene que hacerlo en unsolo lugar

bull Dividir un programa largo en funciones le permite depurar las partes de unaen una y luego unirlas

bull Las funciones bien disentildeadas pueden ser uacutetiles para muchos programasUna vez que escribe y depura una puede reutilizarla

bull En Julia las funciones pueden mejorar mucho el rendimiento

DepuracioacutenUna de las habilidades maacutes importantes que adquiriraacute es la depuracioacuten Aunquepuede ser frustrante la depuracioacuten es una de las partes maacutes intelectualmentegratificantes desafiantes e interesantes de la programacioacuten

La depuracioacuten puede ser vista como un trabajo de detective El programador seenfrenta a pistas y tiene que inferir los procesos y eventos que generaron losresultados que ve

La depuracioacuten tambieacuten es como una ciencia experimental Una vez que se tieneuna idea de lo que estaacute mal se modifica el programa y se intenta nuevamente Sila hipoacutetesis era correcta se puede predecir el resultado de la modificacioacuten y asiacuteestar un paso maacutes cerca de un programa totalmente funcional Si la hipoacutetesis eraincorrecta se tiene que encontrar una nueva Como Sherlock Holmes sentildealoacute

Cuando todo aquello que es imposible ha sido eliminado lo que quede pormuy improbable que parezca es la verdad

mdash A Conan Doyle El signo de los cuatro

Para algunas personas la programacioacuten y la depuracioacuten son lo mismo Es decirla programacioacuten es el proceso de depurar gradualmente un programa hasta quehaga lo que desea Lo ideal es comenzar con un programa que funcione y hacer

iquestPor queacute se necesitan funciones 37

pequentildeas modificaciones depuraacutendolas a medida que avanza

Por ejemplo Linux es un sistema operativo que contiene millones de liacuteneas decoacutedigo pero comenzoacute como un programa simple que Linus Torvalds usoacute paraexplorar el chip Intel 80386 Seguacuten Larry Greenfield Uno de los proyectosanteriores de Linus fue un programa que cambiariacutea entre imprimir AAAA yBBBB Esto luego evolucionoacute a Linux (The Linux Usersrsquo Guide Beta Version1)

Glosariofuncioacuten

secuencia de sentencias que ejecuta una operacioacuten deseada y tiene unnombre Las funciones pueden tomar o no argumentos y pueden producir ono un resultado

definicioacuten de funcioacutenUna sentencia que crea una nueva funcioacuten especificando su nombreparaacutemetros y las sentencias que contiene

objeto de funcioacutenUn valor creado por una definicioacuten de funcioacuten El nombre de la funcioacuten esuna variable que se refiere a un objeto de funcioacuten

encabezadoLa primera liacutenea de una definicioacuten de funcioacuten

cuerpoSecuencia de sentencias dentro de una definicioacuten de funcioacuten

paraacutemetroUn nombre usado dentro de una funcioacuten para referirse al valor pasado comoargumento

Llamada a funcioacutenUna sentencia que ejecuta una funcioacuten Compuesta por el nombre de lafuncioacuten seguido por la lista de argumentos que usa entre pareacutentesis

argumentoValor que se le pasa a una funcioacuten cuando se la llama Este valor se asignaal paraacutemetro correspondiente en la funcioacuten

variable localUna variable definida dentro de una funcioacuten Una variable local solo puedeusarse dentro de su funcioacuten

38 Capiacutetulo 3 Funciones

valor de retornoEl resultado de una funcioacuten Si se utiliza una llamada a funcioacuten como unaexpresioacuten el valor de retorno es el valor de la expresioacuten

funcioacuten productivaUna funcioacuten que devuelve un valor

funcioacuten vaciacuteaUna funcioacuten que siempre devuelve nothing

nothingUn valor especial devuelto por las funciones nulas

composicioacutenUsar una expresioacuten como parte de una expresioacuten maacutes grande o unasentencia como parte de una sentencia maacutes grande

flujo de ejecucioacutenEl orden en que las sentencias se ejecutan

diagrama de pilaUna representacioacuten graacutefica de una pila de funciones sus variables y losvalores a los que se refieren

marcoUn recuadro que en un diagrama de pila representa una llamada de funcioacutenContiene las variables locales y los paraacutemetros de la funcioacuten

trazado inversoUna lista de las funciones que se estaacuten ejecutando las cuales son impresascuando ocurre una excepcioacuten

Ejercicios

OBSERVACIOacuteN Estos ejercicios deben realizarse utilizando soacutelo lo quese ha tratado hasta ahora

Ejercicio 3-2

Escriba una funcioacuten llamada justificar_a_la_derecha que tome una cadena s comoparaacutemetro y que imprima la cadena con suficientes espacios en blanco para quela uacuteltima letra de la cadena se encuentre en la columna 70 de la pantalla

using IntroAJulia

Ejercicios 39

justificar_a_la_derecha(Celia)

OBSERVACIOacuteN

Use concatenacioacuten de cadenas y repeticioacuten AdemaacutesJulia tiene integrada una funcioacuten llamada length quedevuelve la longitud de una cadena por lo que el valorde length(Celia) es 5

Ejercicio 3-3

Un objeto de funcioacuten es un valor que se puede asignar a una variable o serpasado como argumento Por ejemplo dosveces es una funcioacuten que toma unobjeto de funcioacuten como argumento y lo llama dos veces

function dosveces(f) f() f()end

A continuacioacuten se muestra un ejemplo que usa dosveces para llamar a unafuncioacuten llamada imprimirgato dos veces

function imprimirpalabra() println(palabra)end

dosveces(imprimirpalabra)

1 Escriba este ejemplo en un script y prueacutebelo

2 Modifique dosveces para que tome dos argumentos un objeto de funcioacuten yun valor y que llame a la funcioacuten dos veces pasando el valor comoargumento

3 Copie la definicioacuten de imprimirdosveces mencionada antes en este capiacutetuloa su secuencia de comandos

4 Use la versioacuten modificada de dosveces para llamar a imprimirdosveces dosveces pasando palabra como argumento

5 Defina una nueva funcioacuten llamada cuatroveces que tome un objeto defuncioacuten y un valor y que llame a la funcioacuten cuatro veces pasando el valorcomo paraacutemetro Debe haber solo dos sentencias en el cuerpo de estafuncioacuten no cuatro

40 Capiacutetulo 3 Funciones

Ejercicio 3-4

1 Escriba la funcioacuten imprimircuadricula que dibuje una cuadriacutecula como lasiguiente

juliagt imprimircuadricula()+ - - - - + - - - - +| | || | || | || | |+ - - - - + - - - - +| | || | || | || | |+ - - - - + - - - - +

1 Escriba una funcioacuten que dibuje una cuadriacutecula similar con cuatro filas ycuatro columnas

Creacuteditos Este ejercicio se basa en un ejercicio en Oualline Practical CProgramming Third Edition OrsquoReilly Media 1997

OBSERVACIOacuteN

Para imprimir maacutes de un valor por liacutenea se puedeimprimir una secuencia de valores separados por comas

println (+ -)

La funcioacuten print no avanza a la siguiente liacutenea

print(+)println(-)

El resultado de estas sentencias es + - en la mismaliacutenea El resultado de una siguiente sentencia deimpresioacuten comenzariacutea en la siguiente liacutenea

Ejercicios 41

Capiacutetulo 4 Estudio de Caso Disentildeo de InterfazEste capiacutetulo presenta un segundo estudio de caso que muestra el proceso dedisentildear funciones que trabajen en conjunto

Se presentan graacuteficos turtle que es una forma de crear dibujos a traveacutes de laprogramacioacuten Los graacuteficos turtle no estaacuten incluidos en la Biblioteca Estaacutendarpor lo que se debe agregar el moacutedulo IntroAJulia a su configuracioacuten de Julia

Los ejemplos de este capiacutetulo se pueden ejecutar en un notebook graacutefico enJuliaBox el cual combina coacutedigo texto formateado matemaacuteticas y multimedia enun solo documento (vea Apeacutendice B)

TurtlesUn modulo es un archivo que contiene una coleccioacuten de funciones relacionadasJulia proporciona algunos moacutedulos en su Biblioteca Estaacutendar Ademaacutes es posibleagregar maacutes funciones a una gran cantidad de paquetes(httpsjuliaobservercom)

Los paquetes se pueden instalar en REPL ingresando al modo Pkg REPL con latecla ]

(v12) pkggt add httpsgithubcomJuliaIntroIntroAJuliajl

Esto puede demorar un poco

Antes de que podamos usar las funciones de un moacutedulo tenemos que importarlocon una sentencia using

juliagt using IntroAJulia

juliagt ὂ = Turtle()LuxorTurtle(00 00 true 00 (00 00 00))

El moacutedulo IntroAJulia proporciona una funcioacuten llamada Turtle (tortuga enespantildeol) que crea un objeto LuxorTurtle el cual es asignado a una variablellamada ὂ (turtle TAB)

Una vez que crea una tortuga puede llamar a una funcioacuten para moverla y asiacutehacer un dibujo con ella Por ejemplo para mover la tortuga hacia adelante(forward en ingleacutes)

42 Capiacutetulo 4 Estudio de Caso Disentildeo de Interfaz

svg begin forward(ὂ 100)end

Figura 3 Haciendo avanzar a la tortuga

La palabra reservada svg ejecuta una macro que dibuja una imagen SVG Lasmacros son una caracteriacutestica importante pero avanzada de Julia

Los argumentos de forward son la tortuga y una distancia en piacutexeles por lo queel tamantildeo real depende de su pantalla

Tambieacuten es posible hacer girar a la tortuga con la funcioacuten turn Los argumentosde esta funcioacuten son la tortuga y un aacutengulo en grados

Ademaacutes cada tortuga estaacute sosteniendo un laacutepiz que puede estar hacia arriba ohacia abajo si el laacutepiz estaacute hacia abajo la tortuga deja un rastro cuando semueve Figura 3 muestra el rastro dejado por la tortuga Las funciones penup ypendown significan laacutepiz hacia arriba y laacutepiz hacia abajo

Para dibujar un aacutengulo recto modifique la llamada a la macro

ὂ = Turtle()svg begin forward(ὂ 100) turn(ὂ -90) forward(ὂ 100)end

Ejercicio 4-1

Ahora modifique la macro para que dibuje un cuadrado iexclNo sigas hasta haberloterminado

Repeticioacuten Simple

Es probable que haya escrito algo como esto

Repeticioacuten Simple 43

ὂ = Turtle()svg begin forward(ὂ 100) turn(ὂ -90) forward(ὂ 100) turn(ὂ -90) forward(ὂ 100) turn(ὂ -90) forward(ὂ 100)end

Se puede hacer lo mismo de manera maacutes concisa con una sentencia for

juliagt for i in 14 println(iexclHola) endiexclHolaiexclHolaiexclHolaiexclHola

Este es el uso maacutes simple de la sentencia for aunque se veraacuten maacutes usos despueacutesEacutesto deberiacutea ser suficiente para reescribir su programa que dibuja un cuadradoNo continuacutee hasta que lo haga

Aquiacute hay una sentencia for que dibuja un cuadrado

ὂ = Turtle()svg begin for i in 14 forward(ὂ 100) turn(ὂ -90) endend

La sintaxis de una sentencia for es similar a la definicioacuten de una funcioacuten Tieneun encabezado y un cuerpo que termina con la palabra reservada end El cuerpopuede contener el nuacutemero de sentencias que desee

Una sentencia for tambieacuten es llamada bucle porque el flujo de ejecucioacuten recorreel cuerpo y luego vuelve a la parte superior En este caso ejecuta el cuerpocuatro veces

Esta versioacuten es en realidad un poco diferente del coacutedigo anterior que dibujaba uncuadrado porque hace otro giro despueacutes de dibujar el uacuteltimo lado del cuadradoEl giro adicional lleva maacutes tiempo pero simplifica el coacutedigo si se hace lo mismo

44 Capiacutetulo 4 Estudio de Caso Disentildeo de Interfaz

en cada iteracioacuten del ciclo Esta versioacuten tambieacuten tiene el efecto de dejar a latortuga nuevamente en la posicioacuten inicial mirando hacia la direccioacuten inicial

EjerciciosLos siguientes ejercicios usan tortugas Son divertidos pero tambieacuten tienen untrasfondo Mientras trabaja en ellos piense cuaacutel es ese trasfondo

OBSERVACIOacuteNLas siguientes secciones muestran las soluciones paraestos ejercicios asiacute que no mire hasta que hayaterminado (o al menos lo haya intentado)

Ejercicio 4-2

Escriba una funcioacuten llamada cuadrado que tome como paraacutemetro a un turtle tDeberiacutea usar este turtle para dibujar un cuadrado

Ejercicio 4-3

Escriba una llamada a funcioacuten que pase t como argumento a cuadrado y luegovuelva a ejecutar la macro

Ejercicio 4-4

Agregue otro paraacutemetro llamado lon a cuadrado Modifique el cuerpo para quela longitud de los lados sea lon y luego modifique la llamada a funcioacutenagregando este segundo argumento Ejecute la macro nuevamente Pruebe conun rango de valores para lon

Ejercicio 4-5

Haga una copia de cuadrado y cambie su nombre a poliacutegono Agregue otroparaacutemetro llamado n y modifique el cuerpo para que dibuje un poliacutegono regularde -lados

OBSERVACIOacuteN Los aacutengulos exteriores de un poliacutegono regular de -ladosson grados

Ejercicio 4-6

Escriba una funcioacuten llamada ciacuterculo que tome un turtle t y un radio r comoparaacutemetros y que dibuje un ciacuterculo aproximado llamando a poliacutegono con unalongitud y nuacutemero de lados apropiados Pruebe su funcioacuten con un rango devalores de r

Ejercicios 45

OBSERVACIOacuteN Calcule la circunferencia del ciacuterculo y aseguacuterese de quelen n == circunferencia

Ejercicio 4-7

Haga una versioacuten maacutes general de circulo llamada arco que tome un paraacutemetroadicional angulo y que determine queacute fraccioacuten de un ciacuterculo dibujar angulo estaacuteen grados entonces cuando angulo= 360 arco deberiacutea dibujar un ciacuterculocompleto

EncapsulacioacutenEl primer ejercicio le pide que coloque el coacutedigo que permite dibujar uncuadrado en una definicioacuten de funcioacuten y que luego llame a la funcioacuten pasando aturtle como paraacutemetro Aquiacute hay una solucioacuten

function cuadrado(t) for i in 14 forward(t 100) turn(t -90) endendὂ = Turtle()svg begin cuadrado(ὂ)end

Las sentencias maacutes internas forward y turn tienen doble sangriacutea para mostrarque estaacuten dentro del bucle for que a su vez estaacute dentro de la definicioacuten defuncioacuten

Dentro de la funcioacuten t se refiere a la misma tortuga ὂ entonces turn(t -90)tiene el mismo efecto que turn(ὂ -90) En ese caso iquestpor queacute no llamar alparaacutemetro ὂ La razoacuten es que t puede ser cualquier tortuga no solo ὂ por loque podriacuteamos crear una segunda tortuga y pasarla como argumento a cuadrado

ὂ = Turtle()svg begin cuadrado(ὂ)end

Colocar una porcioacuten de coacutedigo en una funcioacuten se denomina encapsulacioacuten Unode los beneficios de la encapsulacioacuten es que al ponerle un nombre al coacutedigo estosirve como una especie de documentacioacuten Otra ventaja es que si reutiliza elcoacutedigo iexcles maacutes conciso llamar a una funcioacuten dos veces que copiar y pegar el

46 Capiacutetulo 4 Estudio de Caso Disentildeo de Interfaz

cuerpo

GeneralizacioacutenEl siguiente paso es agregar un paraacutemetro lon a cuadrado Aquiacute hay unasolucioacuten

function cuadrado(t lon) for i in 14 forward(t lon) turn(t -90) endendὂ = Turtle()svg begin cuadrado(ὂ 100)end

Agregar un paraacutemetro a una funcioacuten se llama generalizacioacuten porque hace que lafuncioacuten sea maacutes general en la versioacuten anterior el cuadrado siempre teniacutea elmismo tamantildeo en esta versioacuten puede ser de cualquier tamantildeo

El siguiente paso tambieacuten es una generalizacioacuten En vez de dibujar cuadradospoligono dibuja poliacutegonos regulares con cualquier nuacutemero de lados Aquiacute hay unasolucioacuten

function poligono(t n lon) angulo = 360 n for i in 1n forward(t lon) turn(t -angulo) endendὂ = Turtle()svg begin poligono(ὂ 7 70)end

Este ejemplo dibuja un poliacutegono de 7 lados con una longitud de 70 por lado

Disentildeo de InterfazEl siguiente paso es escribir circulo que toma un radio r como paraacutemetro Aquiacutehay una solucioacuten simple que usa poligono para dibujar un poliacutegono de 50 lados

Generalizacioacuten 47

function circulo(t r) circunferencia = 2 π r n = 50 lon = circunferencia n poligono(t n lon)end

La primera liacutenea calcula la circunferencia de un ciacuterculo con radio usando lafoacutermula n es el nuacutemero de segmentos de liacutenea de nuestra aproximacioacuten a unciacuterculo y lon es la longitud de cada segmento Por lo tanto poliacutegono dibuja unpoliacutegono de 50 lados que se aproxima a un ciacuterculo de radio r

Una limitante de esta solucioacuten es que n es constante lo que significa que paraciacuterculos muy grandes los segmentos de liacutenea son demasiado largos y paraciacuterculos pequentildeos perdemos tiempo dibujando segmentos muy pequentildeos Unasolucioacuten seriacutea generalizar la funcioacuten tomando n como paraacutemetro Esto le dariacutea alusuario (quien llama a ciacuterculo) maacutes control pero la interfaz seriacutea menos pulcra

La interfaz de una funcioacuten es un resumen de coacutemo se usa iquestcuaacuteles son losparaacutemetros iquestQueacute hace la funcioacuten iquestY cuaacutel es el valor de retorno Una interfazes pulcra si le permite al usuario que la llama hacer lo que quiera sin tener quelidiar con detalles innecesarios

En este ejemplo r pertenece a la interfaz porque especifica el ciacuterculo a dibujar nes menos apropiado porque se refiere a los detalles de coacutemo se debe representarel ciacuterculo

En lugar de saturar la interfaz es mejor elegir un valor apropiado de ndependiendo de la circunferencia

function circulo(t r) circunferencia = 2 π r n = trunc(circunferencia 3) + 3 lon = circunferencia n poligono(t n lon)end

Ahora el nuacutemero de segmentos es un nuacutemero entero cercano a circunferencia3por lo que la longitud de cada segmento es aproximadamente 3 que es losuficientemente pequentildeo como para que los ciacuterculos se vean bien pero losuficientemente grandes como para ser eficientes y aceptables para cualquierciacuterculo

Agregar 3 a n garantiza que el poliacutegono tenga al menos 3 lados

48 Capiacutetulo 4 Estudio de Caso Disentildeo de Interfaz

RefactorizacioacutenCuando se escribioacute circulo se pudo reutilizar poligono ya que un poliacutegono demuchos lados es una buena aproximacioacuten de un ciacuterculo Pero arco no es tanversaacutetil no se puede usar poligono o circulo para dibujar un arco

Una alternativa es comenzar con una copia de poligono y transformarla en arcoEl resultado podriacutea verse asiacute

function arco(t r angulo) arco_lon = 2 π r angulo 360 n = trunc(arco_lon 3) + 1 paso_lon = arco_lon n paso_angulo = angulo n for i in 1n forward(t paso_lon) turn(t -paso_angulo) endend

La segunda mitad de esta funcioacuten se parece a poligono pero no se puedereutilizar poligono sin cambiar la interfaz Se podriacutea generalizar poligono paratomar un angulo como tercer argumento iexclpero entonces poligono ya no seriacutea unnombre apropiado En su lugar se puede llamar a esta funcioacuten maacutes generalpolilinea

function polilinea(t n lon angulo) for i in 1n forward(t lon) turn(t -angulo) endend

Ahora se puede reescribir poligono y arco usando polilinea

Refactorizacioacuten 49

function poligono(t n lon) angulo = 360 n polilinea(t n lon angulo)end

function arco(t r angulo) arco_lon = 2 π r angulo 360 n = trunc(arco_lon 3) + 1 paso_lon = arco_lon n paso_angulo = angulo n polilinea(t n paso_lon paso_angulo)end

Finalmente se puede reescribir circulo usando arco

function circulo(t r) arco(t r 360)end

Este proceso que reorganiza un programa para mejorar las interfaces y facilitarla reutilizacioacuten del coacutedigo se denomina refactorizacioacuten En este caso se observaque habiacutea un coacutedigo similar en arco y poligono por lo que lo factorizamos enpolilinea

Si se hubiese planeado con anticipacioacuten se podriacutea haber escrito polilineaprimero y haber evitado la refactorizacioacuten pero a menudo no se sabe losuficiente al comienzo de un proyecto para disentildear todas las interfaces Una vezque se comienza a programar se comprende mejor el problema A vecesrefactorizar es una sentildeal de que se ha aprendido algo

Un Plan de DesarrolloUn plan de desarrollo de programa es un proceso para escribir programas Elproceso que se utiliza en este estudio de caso es encapsulacioacuten ygeneralizacioacuten Los pasos de este proceso son

1 Comience escribiendo un pequentildeo programa sin definiciones de funciones

2 Una vez que el programa funcione identifique una porcioacuten de coacutedigo quetenga un objetivo especiacutefico encapsule esta porcioacuten en una funcioacuten yasiacutegnele un nombre

3 Generalice la funcioacuten agregando los paraacutemetros apropiados

4 Repita los pasos 1ndash3 hasta que tenga un conjunto de funciones De serposible copie y pegue coacutedigo para evitar volver a escribir (y volver adepurar)

50 Capiacutetulo 4 Estudio de Caso Disentildeo de Interfaz

5 Busque oportunidades para mejorar el programa refactorizando Porejemplo si tiene un coacutedigo similar en varios lugares considere factorizarloen una funcioacuten general apropiada

Este proceso tiene algunos inconvenientes se exploraraacuten alternativas maacutesadelante pero puede ser uacutetil si no sabe de antemano coacutemo dividir el programaen funciones Este enfoque permite disentildear conforme se avanza

DocstringUn docstring es una cadena que va antes de una funcioacuten y que explica la interfaz(doc es la abreviatura de documentacioacuten) Aquiacute hay un ejemplo

polilinea(t n lon angulo)

Dibuja n segmentos de liacutenea de la longitud dada y conaacutengulo entre ellos (en grados) dado t es una tortugafunction polilinea(t n lon angulo) for i in 1n forward(t lon) turn(t -angulo) endend

Se puede acceder a la documentacioacuten en REPL o en un notebook escribiendo seguido del nombre de una funcioacuten o macro y presionando ENTER

helpgt polilineasearch

polilinea(t n lon angulo)

Dibuja n segmentos de liacutenea de la longitud dada y con aacutengulo entre ellos(en grados) dado t es una tortuga

Los docstring generalmente son cadenas de comillas triples tambieacuten conocidascomo cadenas de liacuteneas muacuteltiples ya que las comillas triples permiten que lacadena abarque maacutes de una liacutenea

Un docstring contiene la informacioacuten esencial que alguien necesitariacutea para usaresta funcioacuten Explica de manera concisa lo que hace la funcioacuten (sin entrar endetalles sobre coacutemo lo hace) Explica queacute efecto tiene cada paraacutemetro en elcomportamiento de la funcioacuten y de queacute tipo debe ser cada paraacutemetro (si no esobvio)

Docstring 51

OBSERVACIOacuteN

Escribir este tipo de documentacioacuten es una parteimportante del disentildeo de la interfaz Una interfaz biendisentildeada debe ser simple de explicar si tienedificultades para explicar una de sus funciones tal vez lainterfaz podriacutea mejorarse

DepuracioacutenUna interfaz es como un contrato entre una funcioacuten y el usuario El usuarioacepta proporcionar ciertos paraacutemetros y la funcioacuten acepta hacer cierto trabajo

Por ejemplo polilinea requiere cuatro argumentos t tiene que ser una tortuga ntiene que ser un nuacutemero entero lon deberiacutea ser un nuacutemero positivo y angulotiene que ser un nuacutemero en grados

Estos requisitos se llaman precondiciones porque se supone que son verdaderosantes de que la funcioacuten comience a ejecutarse Por el contrario las condicionesal final de la funcioacuten son postcondiciones Las postcondiciones incluyen el efectodeseado de la funcioacuten (como dibujar segmentos de liacutenea) y cualquier efectosecundario (como mover la tortuga o hacer otros cambios)

Las condiciones previas son responsabilidad del usuario Si el usuario viola unaprecondicioacuten (iexcldebidamente documentada) y la funcioacuten no funcionacorrectamente el error estaacute en el usuario no en la funcioacuten

Si se cumplen las precondiciones pero no las postcondiciones el error estaacute en lafuncioacuten Si sus pre y postcondiciones son claras pueden ayudar con ladepuracioacuten

Glosariomodulo

Un archivo que contiene una coleccioacuten de funciones relacionadas y otrasdefiniciones

paqueteUna biblioteca externa con maacutes funcionalidades

sentencia usingUna sentencia que lee un archivo de moacutedulo y crea un objeto de moacutedulo

bucleUna parte de un programa que puede ejecutarse repetidamente

52 Capiacutetulo 4 Estudio de Caso Disentildeo de Interfaz

encapsulacioacutenEl proceso de transformar una secuencia de sentencias en una definicioacuten defuncioacuten

generalizacioacutenEl proceso de reemplazar algo innecesariamente especiacutefico (como unnuacutemero) con algo maacutes general (como una variable o paraacutemetro)

interfazUna descripcioacuten de coacutemo usar una funcioacuten incluido el nombre y lasdescripciones de los argumentos y el valor de retorno

refactorizacioacutenEl proceso de modificar un programa para mejorar las interfaces de lasfunciones y otras cualidades del coacutedigo

plan de desarrollo de programaUn proceso para escribir programas

docstringUna cadena que aparece en la parte superior de una definicioacuten de funcioacutenpara documentar la interfaz de la funcioacuten

precondicioacutenUn requisito que debe cumplir el usuario antes de que comience unafuncioacuten

postcondicioacutenUn requisito que debe cumplir la funcioacuten antes de que finalice

Ejercicios

Ejercicio 4-8

Copie y pegue el coacutedigo de este capiacutetulo en un notebook

1 Dibuje un diagrama de pila que muestre el estado del programa mientrasejecuta circulo(ὂ radio) Puede hacer la aritmeacutetica a mano o agregarsentencias de impresioacuten al coacutedigo

2 La versioacuten de arco en Seccioacuten 47 no es muy precisa ya que la aproximacioacutenlineal del ciacuterculo siempre queda por afuera del ciacuterculo verdadero Comoresultado la tortuga termina a unos pocos piacutexeles del destino correcto Lasiguiente solucioacuten muestra una forma de reducir el efecto de este error Leael coacutedigo y vea si tiene sentido Si dibuja un diagrama es posible queentienda mejor coacutemo funciona

Ejercicios 53

arco(t r angulo)

Dibuja un arco con el radio y el aacutengulo dados

t tortuga r radio angulo aacutengulo subtendido por el arco en gradosfunction arco(t r angulo) arco_lon = 2 π r abs(angulo) 360 n = trunc(arco_lon 4) + 3 paso_lon = arco_lon n paso_angulo = angulo n

haciendo un ligero giro a la izquierda antes de comenzar se reduce el error causado por la aproximacioacuten lineal del arco turn(t -paso_angulo2) polilinea(t n paso_lon paso_angulo) turn(t paso_angulo2)end

Ejercicio 4-9

Escriba un conjunto de funciones generales que permitan dibujar flores como enFigura 4

Figura 4 Flores con Turtle

Ejercicio 4-10

Escriba un conjunto de funciones generales que puedan dibujar formas como enFigura 5

Figura 5 Poliacutegonos con Turtle

54 Capiacutetulo 4 Estudio de Caso Disentildeo de Interfaz

Ejercicio 4-11

Las letras del alfabeto se pueden construir a partir de un nuacutemero pequentildeo deelementos baacutesicos como liacuteneas verticales y horizontales y algunas curvasDisentildee un alfabeto que se pueda dibujar con un nuacutemero miacutenimo de elementosbaacutesicos y luego escriba funciones que dibujen las letras

Deberiacutea escribir una funcioacuten para cada letra con nombres dibujar_a dibujar_betc y colocar sus funciones en un archivo llamado letrasjl

Ejercicio 4-12

Lea sobre espirales en httpseswikipediaorgwikiEspiral luego escriba unprograma que dibuje una espiral de Arquiacutemedes como en Figura 6

Figura 6 Espiral de Arquiacutemedes

Ejercicios 55

Capiacutetulo 5 Condicionales y recursividadEl tema principal de este capiacutetulo es la sentencia if la cual permite ejecutardiferentes acciones dependiendo del estado del programa Inicialmente sepresentan dos nuevos operadores divisioacuten entera y moacutedulo

Divisioacuten entera y MoacuteduloEl operador divisioacuten entera divide (div TAB) divide dos nuacutemeros y redondea haciaabajo el resultado Por ejemplo suponga que la duracioacuten de una peliacutecula es de105 minutos Es posible que desee saber la duracioacuten en horas La divisioacutenconvencional devuelve un nuacutemero de punto flotante

juliagt minutos = 105105juliagt minutos 60175

No obstante las horas no se suelen escribir con decimales La divisioacuten enteradevuelve el nuacutemero entero de horas redondeado hacia abajo

juliagt horas = minutos divide 601

Para obtener el resto de la divisioacuten se puede restar una hora (en minutos) a laduracioacuten total de la peliacutecula

juliagt resto = minutos - horas 6045

Otra alternativa es usar el operador moacutedulo que divide dos nuacutemeros ydevuelve el resto

juliagt resto = minutos 6045

OBSERVACIOacuteN

El operador moacutedulo es maacutes uacutetil de lo que parecePermite verificar por ejemplo si un nuacutemero es divisiblepor otro si xy es cero entonces x es divisible por y

Ademaacutes puede extraer el (o los) diacutegito(s) maacutes a laderecha de un nuacutemero Por ejemplo x10 devuelve eldiacutegito maacutes a la derecha de un entero x (en base 10) Delmismo modo x100 devuelve los dos uacuteltimos diacutegitos

56 Capiacutetulo 5 Condicionales y recursividad

Expresiones booleanasUna expresioacuten booleana es una expresioacuten que es verdadera o falsa Lossiguientes ejemplos usan el operador == que compara dos operandos ydevuelve el valor true (verdadero en espantildeol) si son iguales y el valor false(falso) de lo contrario

juliagt 5 == 5truejuliagt 5 == 6false

true y false son valores especiales que pertenecen al tipo Bool no son cadenas

juliagt typeof(true)Booljuliagt typeof(false)Bool

El operador == es un operador relacional El resto de operadores relacionalesson

x = y x no es igual a y x ne y (ne TAB) x gt y x es mayor que y x lt y x es menor que y x gt= y x es mayor o igual que y x ge y (ge TAB) x lt= y x es menor o igual que y x le y (le TAB)

AVISO

Aunque estas operaciones probablemente le sean familiares lossiacutembolos de Julia son diferentes de los siacutembolos matemaacuteticos Unerror comuacuten es usar un solo signo igual (=) en vez de un doblesigno igual (== Recuerde que = es un operador de asignacioacuten y== es un operador relacional No existe =lt o =gt

Operadores LoacutegicosHay tres operadores loacutegicos ampamp (y) || (o) y (no) La semaacutentica (significado) deestos operadores es similar a su significado en espantildeol Por ejemplo xgt0 ampampxlt10 es verdadero solo si x es mayor que 0 y menor que 10

n2==0 || n3 == 0 es verdadero si una o ambas condiciones son verdaderases decir si el nuacutemero es divisible por 2 o por 3

Expresiones booleanas 57

Tanto ampamp como || se asocian en primer lugar con el objeto a su derecha pero ampamptiene preferencia por sobre ||

Finalmente el operador niega una expresioacuten booleana entonces (xgty) esverdadero si xgty es falso es decir si x es menor o igual que y

Ejecucioacuten CondicionalPara escribir programas uacutetiles generalmente se necesita verificar condiciones ycambiar el comportamiento del programa acorde a ellas Las sentenciascondicionales permiten llevar esto a cabo La forma maacutes simple es la sentencia if(si en ingleacutes)

if x gt 0 println(x es positivo)end

La expresioacuten booleana despueacutes de if se llama condicioacuten Si es verdadera seejecuta la instruccioacuten con sangriacutea Si no nada ocurre

Las sentencias if tienen la misma estructura que las definiciones de funcioacuten unencabezado seguido del cuerpo terminado con la palabra reservada end (enespantildeol fin) Las sentencias como esta se denominan sentencias compuestas

No hay liacutemite en el nuacutemero de sentencias que pueden aparecer en el cuerpo Aveces es uacutetil tener un cuerpo sin sentencias (por lo general como un marcadorde posicioacuten para el coacutedigo que auacuten no se ha escrito)

if x lt 0 TODO se necesita realizar alguna accioacuten con los valores negativosend

Ejecucioacuten alternativaUna segunda forma de la sentencia if es la ejecucioacuten alternativa en la que haydos posibilidades y la condicioacuten determina cuaacutel se ejecuta La sintaxis se ve asiacute

if x 2 == 0 println(x es par)else println(x es impar)end

Si el resto de x dividido por 2 es 0 entonces x es par y el programa muestra unmensaje acorde Si la condicioacuten es falsa se ejecuta el segundo conjunto de

58 Capiacutetulo 5 Condicionales y recursividad

sentencias Como la condicioacuten debe ser verdadera o falsa se ejecutaraacuteexactamente una de las alternativas Las alternativas se llaman ramas porqueson ramas en el flujo de ejecucioacuten

Condicionales encadenadasA veces hay maacutes de dos posibilidades y se necesitan maacutes de dos ramas Unamanera de expresar este coacutemputo es a traveacutes de una condicional encadenada

if x lt y println(x es menor que y)elseif x gt y println(x es mayor que y)else println(x e y son iguales)end

De nuevo soacutelo se ejecutaraacute una rama No hay liacutemite al nuacutemero de sentenciaselseif Si hay una sentencia else debe estar al final (aunque no es necesario queesteacute)

if alternativa == a dibujar_a()elseif alternativa == b dibujar_b()elseif alternativa == c dibujar_c()end

Cada condicioacuten se comprueba en orden Si la primera es falsa se comprueba lasiguiente y asiacute se sigue con las demaacutes Si una de ellas es verdadera se ejecuta larama correspondiente y la sentencia se termina Si es verdadera maacutes de unacondicioacuten soacutelo se ejecuta la primera rama verdadera

Condicionales anidadasUna condicional puede estar anidada (nested en ingleacutes) dentro de otraPodriacuteamos haber escrito el ejemplo de la seccioacuten anterior de la siguiente manera

Condicionales encadenadas 59

if x == y println(x e y son iguales)else if x lt y println(x es menor a y) else println(x es mayor a y) endend

La condicional externa contiene dos ramas La primera rama contiene unasentencia simple La segunda rama contiene otra sentencia if que tiene dosramas propias Estas dos ramas son ambas sentencias simples aunque podriacuteanser sentencias condicionales

Aunque la sangriacutea no obligatoria de las sentencias hace evidente su estructuralas condicionales anidadas muy pronto se vuelven difiacuteciles de leer Se recomiendaevitarlas cuando pueda

Los operadores loacutegicos a menudo proporcionan una forma de simplificar lassentencias condicionales anidadas Por ejemplo es posible reescribir el siguientecoacutedigo usando un solo condicional

if 0 lt x if x lt 10 println(x es un nuacutemero positivo de un solo diacutegito) endend

La sentencia print soacutelo se ejecuta si conseguimos superar ambas condicionalesde modo que se puede obtener el mismo efecto con el operador ampamp

if 0 lt x ampamp x lt 10 println(x es un nuacutemero positivo de un solo diacutegito)end

Para este tipo de condicioacuten Julia proporciona una sintaxis maacutes concisa

if 0 lt x lt 10 println(x es un nuacutemero positivo de un solo diacutegito)end

60 Capiacutetulo 5 Condicionales y recursividad

RecursividadEstaacute permitido que una funcioacuten llame a otra y tambieacuten que una funcioacuten se llamea siacute misma Puede no parecer uacutetil pero siacute lo es como puede verse en la siguientefuncioacuten

function cuentaregresiva(n) if n le 0 println(Despegue) else print(n ) cuentaregresiva(n-1) endend

Si n es 0 o negativo muestra la palabra Despegue En otro caso muestra elvalor n y luego llama a la funcioacuten cuentaregresiva pasaacutendole n-1 comoargumento

iquestQueacute sucede si llamamos a una funcioacuten como esta

juliagt cuentaregresiva(3)3 2 1 Despegue

La ejecucioacuten de cuentaregresiva empieza con n = 3 y como n es mayor que 0muestra el valor 3 y luego se llama a siacute mismahellip

 La ejecucioacuten de cuentaregresiva empieza con n = 2 y como n es mayor que 0   muestra el valor 2 y luego se llama a siacute mismahellip

  La ejecucioacuten de cuentaregresiva empieza con n = 1 y como n es mayor que0    muestra el valor 1 y luego se llama a siacute mismahellip

   La ejecucioacuten de cuentaregresiva empieza con n = 0 y como n no es mayorque 0     muestra la palabra Despegue y luego termina

  La cuentaregresiva cuyo argumento es n = 1 termina

 La cuentaregresiva cuyo argumento es n = 2 termina

La cuentaregresiva cuyo argumento es n = 3 termina

Y volvemos a Main

Una funcioacuten que se llama a siacute misma es una funcioacuten recursiva y el proceso deejecucioacuten se llama recursividad

Recursividad 61

Como otro ejemplo se puede escribir una funcioacuten que imprima una cadena veces

function printn(s n) if n le 0 return end println(s) printn(s n-1)end

Si n lt= 0 se usa la sentencia return para salir de la funcioacuten El flujo de laejecucioacuten vuelve inmediatamente a la sentencia de llamada a funcioacuten y no seejecutan las liacuteneas restantes de la funcioacuten

El resto de la funcioacuten es similar a cuenta regresiva muestra s y luego se llama asiacute misma para mostrar s veces maacutes de modo que el nuacutemero de lineasmostradas es es decir

Para ejemplos simples como este es maacutes faacutecil usar un ciclo for Se mostraraacutenejemplos que son difiacuteciles de escribir con un ciclo for y faacuteciles de escribir conrecursividad

Diagramas de pila para funciones recursivasEn Seccioacuten 39 se usoacute un diagrama de pila para representar el estado de unprograma durante una llamada de funcioacuten El mismo tipo de diagrama puede serde utilidad para interpretar una funcioacuten recursiva

Cada vez que se llama a una funcioacuten Julia crea un marco que contiene lasvariables locales de la funcioacuten y los paraacutemetros En una funcioacuten recursiva puedehaber maacutes de un marco en el diagrama de pila al mismo tiempo

Figura 7 Diagrama de pila

Figura 7 muestra un diagrama de pila para cuentaregresiva utilizando n=3

Como siempre la parte superior de la pila es el marco para Main Estaacute vaciacuteopues no se crearon variables en Main ni tampoco se pasaron argumentos

62 Capiacutetulo 5 Condicionales y recursividad

Los cuatro marcos de cuentaregresiva tienen diferentes valores del paraacutemetro nLa parte inferior del diagrama de pila donde n = 0 es llamado caso base Nohace una llamada recursiva asiacute que no hay maacutes marcos

Ejercicio 5-1

Como ejercicio dibuje un diagrama de pila para printn llamada con s = Hola yn = 2 Luego escriba una funcioacuten llamada hacer_n que tome como argumentosuna funcioacuten y un nuacutemero n y que luego llame a la funcioacuten dada veces

Recursioacuten infinitaSi una recursioacuten nunca alcanza un caso base continuacutea haciendo llamadasrecursivas para siempre y el programa nunca termina Esto se conoce comorecursioacuten infinita y generalmente no es una buena idea Aquiacute hay un coacutedigo conuna recursioacuten infinita

function recursion() recursion()end

En la mayoriacutea de los entornos de programacioacuten un programa con recursioacuteninfinita realmente no se ejecuta para siempre Julia entrega un mensaje de errorcuando se alcanza la profundidad de recursioacuten maacutexima

juliagt recursion()ERROR StackOverflowErrorStacktrace [1] recursion() at REPL[1]2 (repeats 80000 times)

Este stacktrace es un poco maacutes grande que el que vimos en el capiacutetulo anteriorCuando se produce el error iexclhay 80000 marcos de recursion en el diagrama depila

Si por accidente encuentra una recursioacuten infinita en su coacutedigo revise su funcioacutenpara confirmar que hay un caso base que no realiza una llamada recursiva Sihay un caso base verifique si realmente puede ocurrir

Entrada por tecladoLos programas que se han escrito hasta ahora no aceptan entradas del usuarioSimplemente hacen lo mismo cada vez

Julia tiene una funcioacuten incorporada llamada readline que detiene el programa yespera a que el usuario escriba algo Cuando el usuario presiona RETURN oENTER el programa se reanuda y readline devuelve lo que el usuario escribioacute

Recursioacuten infinita 63

como una cadena

juliagt text = readline()iquestQueacute estaacute esperandoiquestQueacute estaacute esperando

Antes de recibir una entrada por teclado del usuario es una buena idea imprimirun mensaje que le diga al usuario queacute escribir

juliagt print(iquestCuaacutel es su nombre ) readline()iquestCuaacutel es su nombre iexclArturo Rey de los BretonesiexclArturo Rey de los Bretones

Un punto y coma permite colocar varias sentencias en la misma liacutenea En elREPL solo la uacuteltima sentencia devuelve su valor

Si espera que el usuario escriba un nuacutemero entero puede intentar convertir elvalor de retorno a Int64

juliagt println(iquestCuaacutentos dejaron su casa su tierra o su posesioacuten)numero = readline()iquestCuaacutentos dejaron su casa su tierra o su posesioacuten115115juliagt parse(Int64 numero)115

Pero si el usuario no escribe una cadena de diacutegitos obtendraacute un error

juliagt println(iquestCuaacutentos dejaron su casa su tierra o su posesioacuten)numero = readline()iquestCuaacutentos dejaron su casa su tierra o su posesioacutenMaacutes de ciento quince sonMaacutes de ciento quince sonjuliagt parse(Int64 speed)ERROR ArgumentError invalid base 10 digit M in Maacutes de ciento quinceson[]

Veremos queacute hacer con este tipo de error maacutes adelante

DepuracioacutenCuando se produce un error de sintaxis o de tiempo de ejecucioacuten el mensaje deerror contiene mucha informacioacuten lo cual puede ser abrumador Las partes maacutes

64 Capiacutetulo 5 Condicionales y recursividad

uacutetiles suelen ser

bull Queacute tipo de error fue

bull Doacutende ocurrioacute tal error

Los errores de sintaxis suelen ser faacuteciles de encontrar y hay algunos trucos Engeneral los mensajes de error indican doacutende se descubrioacute el problema pero elerror real podriacutea estar antes en el coacutedigo a veces en una liacutenea anterior

Lo mismo aplica para los errores de tiempo de ejecucioacuten Suponga que estaacutetratando de calcular una relacioacuten sentildealruido en decibelios La foacutermula es

En Julia se podriacutea escribir algo como esto

intensidad_sentildeal = 9intensidad_ruido = 10relacion = intensidad_sentildeal divide intensidad_ruidodecibeles = 10 log10(relacion)print(decibeles)

Obteniendo

-Inf

Este no es el resultado que esperaacutebamos

Para encontrar el error puede ser uacutetil imprimir el valor de la variable relacionque resulta ser 0 El problema estaacute en la liacutenea 3 que usa la divisioacuten entera enlugar de la divisioacuten de punto flotante

AVISOEl usuario debe tomarse el tiempo de leer los mensajes de errorcuidadosamente pero no se debe asumir que todo lo que dicen escorrecto

GlosarioDivisioacuten entera

Un operador denotado por divide que divide dos nuacutemeros y redondea haciaabajo (hacia el infinito negativo) a un entero

operador moacuteduloUn operador denotado con el signo de porcentaje () que se utiliza conenteros y devuelve el resto cuando un nuacutemero se divide por otro

Glosario 65

expresioacuten booleanaUna expresioacuten cuyo valor es verdadero o falso

operador relacionalUno de los operadores que compara sus operandos == ne (=) gt lt ge(gt=) and le (lt=)

operador loacutegicoUno de los operadores que combina expresiones booleanas ampamp (and) ||(or) and (not)

sentencia condicionalUna sentencia que controla el flujo de ejecucioacuten dependiendo de algunacondicioacuten

condicioacutenLa expresioacuten booleana en una sentencia condicional que determina queacuterama se ejecuta

sentencia compuestaUna sentencia que consta de un encabezado y un cuerpo El cuerpo terminacon la palabra reservada end

ramaUna de las secuencias alternativas de sentencias en una sentenciacondicional

condicional encadenadaUna sentencia condicional con una serie de ramas alternativas

condicional anidadaUna sentencia condicional que aparece en una de las ramas de otrasentencia condicional

sentencia returnUna sentencia que hace que una funcioacuten finalice de inmediato y que vuelvaa la sentencia de llamada a funcioacuten

recursividad o recursioacutenEl proceso de llamar a la funcioacuten que se estaacute ejecutando actualmente

caso baseUna rama condicional en una funcioacuten recursiva que no realiza una llamadarecursiva

66 Capiacutetulo 5 Condicionales y recursividad

recursioacuten infinitaUna recursioacuten que no tiene un caso base o que nunca llega a eacutelEventualmente una recursioacuten infinita provoca un error de tiempo deejecucioacuten

Ejercicios

Ejercicio 5-2

La funcioacuten time devuelve el tiempo medio de Greenwich actual en segundosdesde la eacutepoca que es un tiempo arbitrario utilizado como punto de referenciaEn sistemas UNIX la eacutepoca es el 1 de enero de 1970

juliagt time()1603600382165353e9

Escriba un script que lea la hora actual y la convierta a una hora del diacutea enhoras minutos y segundos maacutes el nuacutemero de diacuteas transcurridos desde la eacutepoca

Ejercicio 5-3

El uacuteltimo teorema de Fermat dice que no hay enteros positivos and tal que

para cualquier valor de mayor que 2

1 Escriba una funcioacuten llamada verificarfermat que tome cuatroparaacutemetrosmdasha b c y nmdash y que verifique si el teorema de Fermat es vaacutelidoSi n es mayor que 2 y a^n + b^n == c^n el programa deberiacutea imprimiriexclSanto cielo Fermat estaba equivocado De lo contrario el programadeberiacutea imprimir No eso no funciona

2 Escriba una funcioacuten que solicite al usuario ingresar valores para a b c y nque los convierta en enteros y que use verificarfermat para verificar siviolan el teorema de Fermat

Ejercicio 5-4

Si tiene tres barras estas podriacutean o no formar un triaacutengulo Por ejemplo si unade las barras tiene 12 centiacutemetros de largo y las otras dos tienen un centiacutemetrode largo no es posible que las barras pequentildeas puedan juntarse al medio Paracualquier triacuteo de longitudes hay una prueba simple para ver si es posible formarun triaacutengulo

Ejercicios 67

OBSERVACIOacuteN

Si cualquiera de las tres longitudes es mayor que lasuma de las otras dos entonces no se puede formar untriaacutengulo De lo contrario se puede (Si la suma de doslongitudes es igual a la tercera forman lo que se llamaun triaacutengulo degenerado)

1 Escriba una funcioacuten llamada estriangulo que tome tres enteros comoargumentos y que imprima ldquoSiacuterdquo o ldquoNordquo dependiendo de si se puede o noformar un triaacutengulo a partir de barras de las longitudes dadas

2 Escriba una funcioacuten que solicite al usuario ingresar tres longitudes debarras las convierta en enteros y use estriangulo para verificar si las barrascon las longitudes dadas pueden formar un triaacutengulo

Ejercicio 5-5

iquestCuaacutel es el resultado del siguiente programa Dibuje un diagrama de pila quemuestre el estado del programa cuando imprima el resultado

function recursion(n s) if n == 0 println(s) else recursion(n-1 n+s) endend

recursion(3 0)

1 iquestQueacute pasariacutea si se llamara a esta funcioacuten asiacute recursion(-1 0)

2 Escriba un documento que explique todo lo que alguien necesitariacutea saberpara usar esta funcioacuten (y nada maacutes)

Los siguientes ejercicios utilizan el moacutedulo IntroAJulia descrito en Capiacutetulo 4

Ejercicio 5-6

Lea la siguiente funcioacuten y vea si puede averiguar queacute hace (vea los ejemplos enCapiacutetulo 4) Luego ejecuacutetelo y vea si lo hizo bien

68 Capiacutetulo 5 Condicionales y recursividad

function dibujar(t distancia n) if n == 0 return end angulo = 50 adelante(t distancian) girar(t -angulo) dibujar(t distancia n-1) girar(t 2angulo) dibujar(t distancia n-1) girar(t -angulo) adelante(t -distancian)end

Ejercicio 5-7

Figura 8 Una curva de Koch

La curva de Koch es un fractal que luce como Figura 8 Para dibujar una curva deKoch con longitud todo lo que tiene que hacer es

1 Dibuje una curva de Koch con longitud

2 Gire a la izquierda 60 grados

3 Dibuje una curva de Koch con longitud

4 Gire a la derecha 120 grados

5 Dibuje una curva de Koch con longitud

6 Gire a la izquierda 60 grados

7 Dibuje una curva de Koch con longitud

La excepcioacuten es cuando es menor que 3 en ese caso puede dibujar una liacutenearecta con una longitud

1 Escribe una funcioacuten llamada koch que tome una tortuga y una longitudcomo paraacutemetros y que use la tortuga para dibujar una curva de Koch con lalongitud dada

2 Escriba una funcioacuten llamada copodenieve que dibuje tres curvas de Kochpara hacer el contorno de un copo de nieve

3 La curva de Koch se puede generalizar de varias maneras ConsultehttpsenwikipediaorgwikiKoch_snowflake para ver ejemplos eimplementar su favorito

Ejercicios 69

Capiacutetulo 6 Funciones productivasMuchas de las funciones de Julia que se han utilizado como las funcionesmatemaacuteticas producen valores de retorno Todas las funciones que se hanescrito hasta ahora son nulas es decir tienen un efecto (como imprimir un valor)pero devuelven el valor nothing En este capiacutetulo se ensentildea a escribir funcionesproductivas

Valores de retornoLlamar a una funcioacuten genera un valor de retorno que generalmente se asigna auna variable o se usa como parte de una expresioacuten

e = exp(10)altura = radio sin(radio)

Las funciones que se han escrito hasta ahora son nulas Coloquialmentehablando no tienen valor de retorno de manera formal su valor de retorno esnothing En este capiacutetulo (finalmente) se van a escribir funciones productivas Elprimer ejemplo es area que devuelve el aacuterea de un ciacuterculo dado un radio

function area(radio) a = π radio^2 return aend

Se ha visto la sentencia return antes pero en una funcioacuten productiva la sentenciareturn incluye una expresioacuten Esta sentencia significa Retorne inmediatamentede esta funcioacuten y use la siguiente expresioacuten como valor de retorno La expresioacutendada puede ser arbitrariamente complicada Asiacute pues se podriacutea haber escritoesta funcioacuten maacutes concisamente

function area(radio) π radio^2end

El valor devuelto por una funcioacuten es el valor de la uacuteltima expresioacuten evaluadaque por defecto es la uacuteltima expresioacuten en el cuerpo de la definicioacuten de lafuncioacuten

Por otro lado las variables temporales como a y las sentencias return expliacutecitaspueden facilitar la depuracioacuten

A veces es uacutetil tener muacuteltiples sentencias return una en cada rama de unasentencia condicional

70 Capiacutetulo 6 Funciones productivas

function valorabsoluto(x) if x lt 0 return -x else return x endend

Dado que estas sentencias return estaacuten en una condicional alternativa solo seejecuta una

En cuanto se ejecuta una sentencia return la funcioacuten termina sin ejecutarninguna de las sentencias siguientes El coacutedigo que aparece despueacutes de lasentencia return o en cualquier otro lugar al que el flujo de ejecucioacuten nuncallegaraacute se llama coacutedigo muerto

En una funcioacuten productiva es una buena idea asegurarse que cualquier posiblerecorrido del programa llegue a una sentencia return Por ejemplo

function valorabsoluto(x) if x lt 0 return -x end if x gt 0 return x endend

Esta versioacuten no es correcta porque si x es igual a 0 ninguna de las condicioneses verdadera y la funcioacuten termina sin alcanzar una sentencia return Si el flujo deejecucioacuten llega al final de la funcioacuten el valor de retorno es nothing queclaramente no es el valor absoluto de 0

juliagt show(valorabsoluto(0))nothing

OBSERVACIOacuteN Julia tiene una funcioacuten incorporada llamada abs quecalcula los valores absolutos

Ejercicio 6-1

Escriba la funcioacuten comparar que tome dos valores x y y y que devuelva 1 si x gty 0 si x == y y -1 si x lt y

Valores de retorno 71

Desarrollo incrementalConforme vaya escribiendo funciones maacutes extensas puede empezar a dedicarmaacutes tiempo a la depuracioacuten

Para lidiar con programas de complejidad creciente se sugiere una teacutecnicallamada desarrollo incremental El objetivo del desarrollo incremental es evitarlargas sesiones de depuracioacuten antildeadiendo y probando solamente pequentildeasporciones de coacutedigo cada vez

Por ejemplo suponga que desea encontrar la distancia entre dos puntos dadospor las coordenadas y Por el teorema de Pitaacutegoras la distancia es

El primer paso es considerar queacute aspecto tendriacutea la funcioacuten distancia en Julia Enotras palabras iquestcuaacuteles son las entradas (paraacutemetros) y cuaacutel es la salida (valor deretorno)

En este caso las entradas son los dos puntos que se pueden representar usandocuatro nuacutemeros El valor devuelto es la distancia que es un nuacutemero de puntoflotante

He aquiacute una primera versioacuten de la funcioacuten

function distancia(x₁ y₁ x₂ y₂) 00end

Obviamente esta versioacuten de la funcioacuten no calcula distancias sino que siempredevuelve cero Aun asiacute es correcta sintaacutecticamente hablando y se ejecutaraacute loque implica que se puede probar antes de hacerla maacutes compleja Los nuacutemeros desubiacutendice estaacuten disponibles en la codificacioacuten de caracteres Unicode (_1 TAB_2 TAB etc)

Para probar la nueva funcioacuten se llama con una muestra de valores

distance(1 2 4 6)

Se eligen estos valores de tal forma que la distancia horizontal sea igual a 3 y ladistancia vertical sea igual a 4 y de esa manera el resultado es 5 (la hipotenusadel triaacutengulo 3-4-5) Cuando se comprueba una funcioacuten es uacutetil conocer larespuesta correcta

Hasta el momento se ha podido confirmar que la funcioacuten es sintaacutecticamentecorrecta por lo que se puede empezar a agregar liacuteneas de coacutedigo El paso loacutegico

72 Capiacutetulo 6 Funciones productivas

siguiente es encontrar las diferencias y En la siguiente versioacuten de lafuncioacuten se almacenaraacuten estos valores en variables temporales y se mostraraacuten conel macro show

function distancia(x₁ y₁ x₂ y₂) dx = x₂ - x₁ dy = y₂ - y₁ show dx dy 00end

Si la funcioacuten trabaja bien las salidas deben ser dx = 3 y dy = 4 Si es asiacute se sabeque la funcioacuten estaacute obteniendo los paraacutemetros correctos y realizando el primercaacutelculo correctamente Si no entonces soacutelo hay unas pocas liacuteneas que revisar

A continuacioacuten se calcula la suma de los cuadrados de dx y dy

function distancia(x₁ y₁ x₂ y₂) dx = x₂ - x₁ dy = y₂ - y₁ dsup2 = dx^2 + dy^2 show dsup2 00end

De nuevo se quiere ejecutar el programa en esta etapa y comprobar la salida(que deberiacutea ser 25) Los nuacutemeros en superiacutendice tambieacuten estaacuten disponibles (^2TAB) Finalmente se puede usar sqrt para calcular y devolver el resultado

function distancia(x₁ y₁ x₂ y₂) dx = x₂ - x₁ dy = y₂ - y₁ dsup2 = dx^2 + dy^2 sqrt(dsup2)end

Si esto funciona correctamente ya se habriacutea terminado Si no se podriacutea mostrarel valor de la variable resultado antes de la sentencia de retorno

La versioacuten final de la funcioacuten no muestra nada cuando se ejecuta soacutelo retorna unvalor Las sentencias print son uacutetiles para la depuracioacuten pero una vez que elprograma esteacute funcionando correctamente se deben eliminar El coacutedigoeliminado se llama andamiaje porque es uacutetil para construir el programa pero noes parte del producto final

Al principio deberiacutea antildeadir solamente una o dos liacuteneas de coacutedigo cada vez

Desarrollo incremental 73

Conforme vaya ganando experiencia puede que se encuentre escribiendo ydepurando fragmentos mayores de coacutedigo Sin embargo el proceso de desarrolloincremental puede ahorrarle mucho tiempo de depuracioacuten

Los aspectos clave del proceso son

1 Iniciar con un programa que funcione y hacerle pequentildeos cambiosincrementales En cualquier momento si hay un error sabraacute exactamentedoacutende estaacute

2 Usar variables temporales para guardar valores intermedios para que puedamostrarlos y verificarlos

3 Una vez que el programa esteacute funcionando tal vez prefiera eliminar partedel andamiaje o consolidar muacuteltiples sentencias en expresiones compuestaspero soacutelo si eso no hace que el programa sea difiacutecil de leer

Ejercicio 6-2

Use la teacutecnica de desarrollo incremental para escribir una funcioacuten llamadahipotenusa que retorne el largo de la hipotenusa de un triaacutengulo rectaacutengulo dadoel largo de las otras dos aristas Registre cada etapa del proceso de desarrollo

ComposicioacutenAhora como usted esperariacutea se puede llamar a una funcioacuten desde otra Comoejemplo se escribe una funcioacuten que tome dos puntos el centro del ciacuterculo y unpunto del periacutemetro y calcule el aacuterea del ciacuterculo

Suponga que el punto central estaacute almacenado en las variables xc y yc y que elpunto del periacutemetro lo estaacute en xp y yp El primer paso es hallar el radio delciacuterculo que es la distancia entre los dos puntos La funcioacuten distancia que realizaesta tarea seriacutea

radio = distancia(xc yc xp yp)

El siguiente paso es encontrar el aacuterea del ciacuterculo usando este radio De nuevo seusa una de las funciones definidas previamente

resultado = area(radio)

Envolviendo todo en una funcioacuten se obtiene

74 Capiacutetulo 6 Funciones productivas

function areacirculo(xc yc xp yp) radio = distancia(xc yc xp yp) resultado = area(radio) return resultadoend

Las variables temporales radio y resultado son uacutetiles para el desarrollo y ladepuracioacuten pero una vez que el programa estaacute funcionando se puede hacer maacutesconciso componiendo las llamadas a funcioacuten

function areacirculo(xc yc xp yp) area(distancia(xc yc xp yp))end

Funciones BooleanasLas funciones pueden devolver valores booleanos lo que a menudo esconveniente para ocultar complicadas comprobaciones dentro de funciones Porejemplo

function esdivisible(x y) if x y == 0 return true else return false endend

Es comuacuten dar a las funciones booleanas nombres que suenan como preguntasque tienen como respuesta un si oacute un no esdivisible devuelve true o false paraindicar si x es o no divisible por y

Por ejemplo

juliagt esdivisible(6 4)falsejuliagt esdivisible(6 3)true

El resultado del operador == es booleano por lo tanto se puede escribir lafuncioacuten de una manera maacutes concisa devolviendo el resultado directamente

Funciones Booleanas 75

function esdivisible(x y) x y == 0end

Las funciones booleanas se usan a menudo en las sentencias condicionales

if esdivisible(x y) println(x es divisible por y)end

Puede parecer tentador escribir algo como

if esdivisible(x y) == true println(x es divisible por y)end

pero la comparacioacuten extra con true es innecesaria

Ejercicio 6-3

Escriba la funcioacuten entremedio(xyz) que devuelva true si x le y le z o false enotro caso

Maacutes recursividadSolo se ha cubierto una pequentildea parte de Julia pero le puede interesar saber queesta parte ya es un lenguaje de programacioacuten completo lo que significa quecualquier coacutemputo puede expresarse en este lenguaje Cualquier programa quese haya escrito podriacutea reescribirse usando solo lo que ha aprendido hasta ahora(en realidad necesitariacutea algunos comandos para controlar dispositivos como elmouse discos etc pero eso es todo)

Probar esta afirmacioacuten es un ejercicio no trivial realizado por primera vez porAlan Turing uno de los primeros cientiacuteficos de la computacioacuten (algunosargumentariacutean que era matemaacutetico pero muchos de los primeros cientiacuteficosinformaacuteticos comenzaron como matemaacuteticos) En consecuencia esto se conocecomo la Tesis de Turing Para una discusioacuten maacutes completa (y precisa) de la Tesisde Turing se recomienda el libro de Michael Sipser Introduccioacuten a la Teoriacutea de laComputacioacuten

Para darle una idea de lo que puede hacer con las herramientas que haaprendido hasta ahora se evaluacutean algunas funciones matemaacuteticas definidasrecursivamente Una definicioacuten recursiva es similar a una definicioacuten circular enel sentido de que la definicioacuten contiene una referencia a lo que estaacute siendodefinido Una definicioacuten verdaderamente circular no es muy uacutetil

76 Capiacutetulo 6 Funciones productivas

vorpalUn adjetivo usado para describir algo que es vorpal

Si esta definicioacuten apareciese en el diccionario la persona que la leyera podriacuteamolestarse Por otro lado si se busca la definicioacuten de la funcioacuten factorialdenotada con el siacutembolo se encuentra encontrar algo como esto

Esta definicioacuten dice que el factorial de 0 es 1 y el factorial de cualquier otrovalor es multiplicado por el factorial de

Entonces es 3 veces que es 2 veces que es 1 vez Es decir es igual a3 por 2 por 1 por 1 que es 6

Si se puede escribir una definicioacuten recursiva se puede escribir un programa deJulia para evaluarlo El primer paso es decidir cuaacuteles deberiacutean ser losparaacutemetros En este caso debe quedar claro que factorial toma valores enteros

function fact(n) end

Si el argumento es 0 la funcioacuten debe devolver 1

function fact(n) if n == 0 return 1 endend

De lo contrario y esto es lo interesante se tiene que hacer una llamada recursivapara encontrar el factorial de n-1 y luego multiplicarlo por n

function fact(n) if n == 0 return 1 else recursion = fact(n-1) resultado = n recursion return resultado endend

El flujo de ejecucioacuten de este programa es similar al flujo de cuentaregresiva enSeccioacuten 58 Si llamamos a fact con el valor 3

Maacutes recursividad 77

Como 3 no es 0 se toma la segunda rama y se calcula el factorial de n-1 hellip

 Como 2 no es 0 se toma la segunda rama y se calcula el factorial de n-1 hellip

  Como 1 no es 0 se toma la segunda rama y se calcula el factorial de + n-1 +hellip

   Como 0 es igual a 0 se toma la primera rama y devuelve 1 sin realizar      maacutes llamadas recursivas

  El valor de retorno 1 se multiplica por n que es 1 y se devuelve elresultado

 El valor de retorno 1 se multiplica por n que es 2 y se devuelve el resultado

El valor de retorno 2 se multiplica por n que es 3 y el resultado 6 se convierteen el valor de retorno de la llamada a funcioacuten que inicioacute todo el proceso

Figura 9 Diagrama de pila

Figura 9 muestra coacutemo se ve el diagrama de pila para esta secuencia dellamadas a funciones

Los valores de retorno se pasan de nuevo a la pila En cada marco el valor deretorno es el valor de resultado que es el producto de n y recursion

En el uacuteltimo marco las variables locales recursion y resultado no existen porquela rama que las crea no se ejecuta

OBSERVACIOacuteN Julia tiene la funcioacuten factorial para calcular el factorialde un nuacutemero entero

Voto de confianzaSeguir el flujo de ejecucioacuten es una forma de leer programas pero puede llegar aser abrumador Una alternativa es lo que se conoce como el voto deconfianza(en ingleacutes leap of faith) Cuando llega a una llamada de funcioacuten enlugar de seguir el flujo de ejecucioacuten asume que la funcioacuten funcionacorrectamente y devuelve el resultado correcto

De hecho ya se estaacute dando este voto de confianza cuando se usan funciones

78 Capiacutetulo 6 Funciones productivas

integradas de Julia Cuando se llaman a cos o exp no se examinan los cuerpos deesas funciones Simplemente se asume que funcionan porque las personas quelas escribieron eran buenos programadores

Lo mismo ocurre cuando el usuario llama a una de sus propias funciones Porejemplo en Seccioacuten 64 se escribe una funcioacuten llamada esdivisible quedetermina si un nuacutemero es divisible por otro Una vez que se confirme que estafuncioacuten es correcta mdashal examinar y probar el coacutedigomdash se puede usar la funcioacutensin mirar nuevamente el cuerpo

Lo mismo aplica a los programas recursivos Cuando llegue a la llamadarecursiva en lugar de seguir el flujo de ejecucioacuten debe suponer que la llamadarecursiva funciona (devuelve el resultado correcto) y luego preguntarseSuponiendo que pueda encontrar el factorial de iquestse puede calcular elfactorial de Estaacute claro que es posible multiplicando por

Por supuesto es un poco extrantildeo suponer que la funcioacuten funciona correctamentecuando no ha terminado de escribirla iexclpero por eso se llama voto de confianza

Un Ejemplo MaacutesDespueacutes de los factoriales el ejemplo maacutes comuacuten de una funcioacuten matemaacuteticadefinida de manera recursiva es fibonacci que tiene la siguiente definicioacuten (verhttpsenwikipediaorgwikiFibonacci_number)

Traducido a Julia se ve asiacute

function fib(n) if n == 0 return 0 elseif n == 1 return 1 else return fib(n-1) + fib(n-2) endend

Si intenta seguir el flujo de ejecucioacuten en esta funcioacuten incluso para valoresbastante pequentildeos de n su cabeza podriacutea estallar Dando un voto de confianzaes decir asumiendo que las dos llamadas recursivas funcionan correctamenteentonces estaacute claro que se obtiene el resultado correcto al sumarlas

Un Ejemplo Maacutes 79

Tipos de Comprobacioacuten

iquestQueacute pasa si se llama a fact con 15 como argumento

juliagt fact(15)ERROR StackOverflowErrorStacktrace [1] fact(Float64) at REPL[3]2

Parece una recursioacuten infinita iquestComo es esto posible La funcioacuten tiene un casobase (cuando n == 0) Pero si n no es un nuacutemero entero es posible perderse elcaso base y hacer recursioacuten para siempre

En la primera llamada recursiva el valor de n es 05 En la siguiente es -05 Apartir de ahiacute se vuelve maacutes pequentildeo (maacutes negativo) pero nunca seraacute 0

Existen dos opciones Se puede intentar generalizar la funcioacuten factorial paratrabajar con nuacutemeros de punto flotante o se puede hacer que fact verifique eltipo del argumento La primera opcioacuten se llama funcioacuten gamma y estaacute un pocomaacutes allaacute del alcance de este libro En este libro se proseguiraacute con la segunda

Se puede usar el operador integrado isa para verificar el tipo de argumentoTambieacuten podemos asegurarnos de que el argumento sea positivo

function fact(n) if (n isa Int64) error(El factorial uacutenicamente estaacute definido para nuacutemerosenteros) elseif n lt 0 error(El factorial no estaacute definido para enteros negativos) elseif n == 0 return 1 else return n fact(n-1) endend

El primer caso base se hace cargo de nuacutemeros no enteros y el segundo deenteros negativos En ambos casos el programa imprime un mensaje de error ydevuelve nothing para indicar que algo salioacute mal

juliagt fact(fred)ERROR El factorial uacutenicamente estaacute definido para nuacutemeros enterosjuliagt fact(-2)ERROR El factorial no estaacute definido para enteros negativos

80 Capiacutetulo 6 Funciones productivas

Si se superan ambas verificaciones se sabe que n es positivo o cero por lo quees posible probar que la recursioacuten termina

Este programa muestra un patroacuten a veces llamado guardian Los dos primeroscondicionales actuacutean como guardianes protegiendo el coacutedigo que sigue de losvalores que pueden causar un error Los guardianes hacen posible demostrar queel coacutedigo es correcto

En Seccioacuten 145 se exploraraacute una alternativa maacutes flexible para imprimir unmensaje de error generar una excepcioacuten

DepuracioacutenDividir un coacutedigo extenso en pequentildeas funciones crea naturalmente puntos decontrol para la depuracioacuten Si un programa no estaacute funcionando existen tresposibilidades a considerar

bull Hay algo incorrecto en los argumentos de la funcioacuten se viola una condicioacutenprevia

bull Hay algo incorrecto en la funcioacuten se viola una condicioacuten posterior

bull Hay algo incorrecto en el valor de retorno o la forma en que se estaacuteutilizando

Para descartar la primera posibilidad puede agregar una sentencia de impresioacutenal comienzo de la funcioacuten para mostrar los valores de los paraacutemetros (y tal vezsus tipos) o bien escribir liacuteneas de coacutedigo que verifiquen las condiciones previasde manera expliacutecita

Si los paraacutemetros estaacuten bien agregue una sentencia de impresioacuten antes de cadasentencia return y muestre el valor de retorno Si es posible verifique elresultado a mano Considere tambieacuten llamar a la funcioacuten con valores quefaciliten la verificacioacuten del resultado (como en Seccioacuten 62)

Si la funcioacuten parece estar funcionando revise la llamada a la funcioacuten paraasegurarse de que el valor de retorno se estaacute utilizando correctamente (iexcloincluso si se estaacute utilizando)

Agregar sentencias de impresioacuten al principio y al final de una funcioacuten puedeayudar a que el flujo de ejecucioacuten sea maacutes transparente Por ejemplo aquiacute hayuna versioacuten de fact con sentencias de impresioacuten

Depuracioacuten 81

function fact(n) espacio = ^ (4 n) println(espacio factorial n) if n == 0 println(espacio devolviendo 1) return 1 else recursion = fact(n-1) resultado = n recursion println(espacio devolviendo resultado) return resultado endend

espacio es una cadena de caracteres de espacios que permite generar sangriacutea enla salida

juliagt fact(4) factorial 4 factorial 3 factorial 2 factorial 1factorial 0devolviendo 1 devolviendo 1 devolviendo 2 devolviendo 6 devolviendo 2424

Si estaacute confundido con el flujo de ejecucioacuten este tipo de salida puede ser uacutetilDesarrollar un buen andamiaje toma tiempo pero un poco de andamiaje puedeahorrar al usuario mucha depuracioacuten

Glosariovariable temporal

Variable usada para almacenar un valor intermedio en un caacutelculo complejo

coacutedigo muertoParte de un programa que nunca puede ser ejecutado a menudo porqueaparece despueacutes de una sentencia return

desarrollo incrementalPlan de desarrollo de un programa que intenta evitar la depuracioacutenagregando y probando solamente una pequentildea porcioacuten de coacutedigo a la vez

82 Capiacutetulo 6 Funciones productivas

andamiajeCoacutedigo que se usa durante el desarrollo de un programa pero que no esparte de la versioacuten final del mismo

guardiaacutenUn patroacuten de programacioacuten que usa una sentencia condicional paraverificar y manejar circunstancias que pueden causar un error

Ejercicios

Ejercicio 6-4

Dibuje un diagrama de pila para el siguiente programa iquestQueacute imprime elprograma

function b(z) prod = a(z z) println(z prod) prodend

function a(x y) x = x + 1 x yend

function c(x y z) total = x + y + z cuadrado = b(total)^2 cuadradoend

x = 1y = x + 1println(c(x y+3 x+y))

Ejercicio 6-5

La funcioacuten de Ackermann se define

Vea httpsenwikipediaorgwikiAckermann_function Escriba una funcioacutenllamada ack que evaluacutee la funcioacuten de Ackermann Use su funcioacuten para evaluarack(3 4) que deberiacutea ser 125 iquestQueacute sucede para valores mayores de m y n

Ejercicios 83

Ejercicio 6-6

Un paliacutendromo es una palabra que se escribe igual en un sentido que en otrocomo ana y radar De manera recursiva una palabra es un paliacutendromo si laprimera y la uacuteltima letra son iguales y lo que estaacute entre ellas es un paliacutendromo

Las siguientes funciones toman un argumento de tipo cadena y devuelven laprimera letra la uacuteltima y las intermedias

function primera(palabra) primera = firstindex(palabra) palabra[primera]end

function ultima(palabra) ultima = lastindex(palabra) palabra[ultima]end

function medio(palabra) primera = firstindex(palabra) ultima = lastindex(palabra) palabra[nextind(palabra primera) prevind(palabra ultima)]end

Se veraacute coacutemo funcionan en Capiacutetulo 8

1 Pruebe estas funciones iquestQueacute sucede si llama a la funcioacuten medio con unacadena de dos letras iquestY con una cadena de una letra iquestQueacute pasa con lacadena vaciacutea que no contiene letras

2 Escriba una funcioacuten llamada espalindromo que tome un argumento de tipocadena y devuelva true si es un paliacutendromo y false de lo contrario Recuerdeque puede usar la funcioacuten integrada length para verificar la longitud de unacadena

Ejercicio 6-7

Un nuacutemero es una potencia de si es divisible por y es una potencia de Escriba una funcioacuten llamada espotencia que tome los paraacutemetros a y b ydevuelva true si a es una potencia de b

OBSERVACIOacuteN Tendraacute que pensar en el caso base

Ejercicio 6-8

El maacuteximo comuacuten divisor (MCD) de y es el nuacutemero maacutes grande que los divide

84 Capiacutetulo 6 Funciones productivas

a ambos con resto 0

Una forma de encontrar el MCD de dos nuacutemeros se basa en la observacioacuten deque si es el resto cuando se divide por entonces mcd(a b) = mcd(b r)Como caso base podemos usar mcd(a 0) = a

Escriba una funcioacuten llamada mcd que tome los paraacutemetros a y b y devuelva sumaacuteximo divisor comuacuten

Creacuteditos Este ejercicio se basa en un ejemplo del libro Estructura einterpretacioacuten de programas informaacuteticos de Abelson y Sussman

Ejercicios 85

Capiacutetulo 7 IteracioacutenEste capiacutetulo se centra en la iteracioacuten que es la capacidad de ejecutarrepetidamente un bloque de sentencias Se han visto dos tipos de iteracioacutenusando recursioacuten en Seccioacuten 58 y usando ciclos for en Seccioacuten 42 En estecapiacutetulo veremos otro tipo maacutes usando sentencias while Primeramente seintroduciraacuten algunos teacuterminos sobre asignacioacuten de variables

Asignacioacuten muacuteltiplePuede que ya haya descubierto que estaacute permitido realizar maacutes de unaasignacioacuten a la misma variable Una nueva asignacioacuten hace que la variableexistente se refiera a un nuevo valor (y deje de referirse al viejo valor)

juliagt x = 55juliagt x = 77

La primera vez que se muestra x su valor es 5 y la segunda vez su valor es 7

Figura 10 Diagrama de estado

Figura 10 muestra el aspecto de una asignacioacuten muacuteltiple en un diagrama deestado

Es necesario aclarar algo que puede causar confusioacuten Puesto que Julia usa elsigno igual (=) para la asignacioacuten es tentador interpretar una sentencia a = bcomo una sentencia de igualdad Pero esta interpretacioacuten es incorrecta

Para empezar la igualdad es simeacutetrica y la asignacioacuten no lo es Por ejemplo enmatemaacuteticas si entonces Pero en Julia la sentencia a = 7 es vaacutelida y 7= a no lo es

Ademaacutes en matemaacuteticas una sentencia de igualdad es verdadera o falsasiempre Si ahora entonces siempre seraacute igual a En Julia una sentenciade asignacioacuten puede hacer que dos variables sean iguales pero no tienen porqueacute quedarse asiacute

86 Capiacutetulo 7 Iteracioacuten

juliagt a = 55juliagt b = a a y b son iguales5juliagt a = 3 a y b ya no son iguales3juliagt b5

La tercera liacutenea cambia el valor de a pero no cambia el valor de b por lo tanto yadejan de ser iguales

AVISO

Reasignar variables puede ser uacutetil pero se debe tener precaucioacutenSi los valores cambian frecuentemente la reasignacioacuten puedehacer que el coacutedigo sea difiacutecil de leer y depurar

Estaacute permitido definir una funcioacuten con el mismo nombre de unavariable definida anteriormente

Actualizacioacuten de variablesUna de las formas maacutes comunes de asignacioacuten muacuteltiple es la actualizacioacutendoacutende el nuevo valor de la variable depende del anterior

juliagt x = x + 18

Esto significa ldquotome el valor actual de x suacutemele uno y despueacutes actualice x con elnuevo valorrdquo

Si intenta actualizar una variable que no existe obtendraacute un error puesto queJulia evaluacutea la expresioacuten del lado derecho antes de asignar un valor a x

juliagt y = y + 1ERROR UndefVarError y not defined

Antes de actualizar una variable tiene que inicializarla usualmente con unaasignacioacuten simple

juliagt y = 00juliagt y = y + 11

Actualizar una variable sumaacutendole 1 se denomina un incremento y restaacutendole 1

Actualizacioacuten de variables 87

se llama un decremento

La Sentencia whileLas computadoras se usan a menudo para automatizar tareas repetitivasRealizar repetidamente tareas ideacutenticas o similares sin cometer errores es algoque las computadoras hacen bien y que los seres humanos hacen limitadamenteLa ejecucioacuten repetida de un conjunto de sentencias se llama iteracioacuten

Ya se han visto dos funciones cuentaregresiva y printn que iteran usandorecursividad Por ser la iteracioacuten tan comuacuten Julia proporciona variascaracteriacutesticas que la hacen maacutes faacutecil Una es la sentencia for que se vio enSeccioacuten 42 a la cual se volveraacute maacutes adelante

Otra caracteriacutestica es la sentencia while Aquiacute hay una versioacuten decuentaregresiva que muestra el uso de la sentencia while

function cuentaregresiva(n) while n gt 0 print(n ) n = n - 1 end println(iexclDespegue)end

Casi podriacutea leer la sentencia while como si fuera Espantildeol La funcioacuten anteriorsignifica ldquoMientras n sea mayor que 0 continuacutee mostrando el valor de n y luegoreduciendo el valor de n en 1 Cuando llegue a 0 muestre la palabra iexclDespegueldquo

Maacutes formalmente el flujo de ejecucioacuten de una sentencia while es el siguiente

1 Se determina si la condicioacuten es verdadera o falsa

2 Si es falsa se sale de la sentencia while y continuacutea la ejecucioacuten con lasiguiente sentencia

3 Si es verdadera ejecuta cada una de las sentencias en el cuerpo y regresa alpaso 1

Este tipo de flujo se llama bucle porque el tercer paso vuelve a la parte superior

El cuerpo del bucle deberiacutea cambiar el valor de una o maacutes variables de maneraque en alguacuten momento la condicioacuten sea falsa y el bucle termine En casocontrario el bucle se repetiraacute indefinidamente lo cual se llama bucle infinitoUna interminable fuente de diversioacuten para los informaacuteticos es la observacioacuten deque las instrucciones del champuacute ldquoEnjabone enjuague repitardquo son un bucleinfinito

88 Capiacutetulo 7 Iteracioacuten

En el caso de cuentaregresiva podemos probar que el bucle termina si n es ceroo negativo el ciclo termina En otro caso el valor de n se hace maacutes pequentildeocada vez que pasa por el bucle asiacute en cierto momento se llega a 0

En otros casos no es tan faacutecil decirlo Por ejemplo

function seq(n) while n = 1 println(n) if n 2 == 0 n is par n = n 2 else n is impar n = n3 + 1 end endend

La condicioacuten de este bucle es n = 1 de manera que el bucle continuaraacute hastaque n sea 1 que haraacute que la condicioacuten sea falsa

Cada vez que pasa por el bucle el programa muestra como salida el valor de n yluego comprueba si es par o impar Si es par el valor de n se divide por dos Si esimpar el valor de n se sustituye por n3 + 1 Por ejemplo si el argumento pasadoa la funcioacuten seq es 3 los valores resultantes n son 3 10 5 16 8 4 2 1

Puesto que n a veces aumenta y a veces disminuye no hay una prueba obvia deque n alcance alguna vez el valor 1 o de que el programa vaya a terminar Paraalgunos valores particulares de n se puede probar que siacute termina Por ejemplosi el valor de inicio es una potencia de dos entonces el valor de n seraacute par cadavez que se pasa por el bucle hasta que llegue a 1 El ejemplo anterior producedicha secuencia si se inicia con 16

Lo diacuteficil es preguntarse si se puede probar que este programa termina paratodos los valores positivos de n Hasta ahora nadie ha sido capaz de probar quelo hace o iexclque no lo hace (Vea httpseswikipediaorgwikiConjetura_de_Collatz)

Ejercicio 7-1

Reescribe la funcioacuten printn de Seccioacuten 58 utilizando iteracioacuten en vez derecursioacuten

breakA veces no se sabe que un ciclo debe terminar hasta que se llega al cuerpo Enese caso se puede usar la sentencia break para salir del bucle

break 89

Por ejemplo suponga que se desea recibir entradas del usuario hasta que esteescriba listo Podriacuteamos escribir

while true print(gt ) linea = readline() if line == listo break end println(linea)endprintln(iexclListo)

La condicioacuten del bucle es true que siempre es verdadero por lo que el bucle seejecuta hasta que llega a la sentencia break

En cada iteracioacuten se le pide al usuario (con el siacutembolo gt ) una entrada Si elusuario escribe listo la sentencia break sale del bucle De lo contrario elprograma repite lo que escriba el usuario y vuelve a la parte superior del bucleA continuacioacuten se muestra coacutemo funciona este programa

gt no listono listogt listoiexclListo

Esta forma de escribir bucles while es comuacuten porque permite verificar lacondicioacuten en cualquier parte del bucle (no solo en la parte superior) y puedeexpresar la condicioacuten de teacutermino de manera afirmativa (detenerse cuando estosuceda) en vez de negativamente (continuar hasta que esto suceda)

continueLa sentencia break permite terminar el bucle Cuando aparece una sentenciacontinue dentro de un bucle se regresa al comienzo del bucle ignorando todoslas sentencias que quedan en la iteracioacuten actual del bucle e inicia la siguienteiteracioacuten Por ejemplo

for i in 110 if i 3 == 0 continue end print(i )end

Output

90 Capiacutetulo 7 Iteracioacuten

1 2 4 5 7 8 10

Si i es divisible por 3 la sentencia continue detiene la iteracioacuten actual ycomienza la siguiente iteracioacuten Solo se imprimen los nuacutemeros en el rango de 1 a10 no divisibles por 3

Raiacuteces CuadradasLos bucles son comuacutenmente utilizados en programas que calculan resultadosnumeacutericos y que comienzan con una respuesta aproximada que es iterativamentemejorada

Por ejemplo una forma de calcular raiacuteces cuadradas es el meacutetodo de NewtonSuponga que desea conocer la raiacutez cuadrada de Si comienza con casi cualquierestimacioacuten puede calcular una mejor aproximacioacuten con la siguiente foacutermula

Por ejemplo si es 4 y es 3

juliagt a = 44juliagt x = 33juliagt y = (x + ax) 221666666666666665

El resultado estaacute maacutes cerca de la respuesta correcta ( ) Si se repite elproceso con la nueva estimacioacuten se acerca auacuten maacutes

juliagt x = y21666666666666665juliagt y = (x + ax) 220064102564102564

Despueacutes de algunas actualizaciones la estimacioacuten es casi exacta

Raiacuteces Cuadradas 91

juliagt x = y20064102564102564juliagt y = (x + ax) 220000102400262145juliagt x = y20000102400262145juliagt y = (x + ax) 220000000000262146

En general no se sabe de antemano cuaacutentos pasos se necesitan para llegar a larespuesta correcta pero se sabe que se ha llegado a ella cuando la estimacioacutendeja de cambiar

juliagt x = y20000000000262146juliagt y = (x + ax) 220juliagt x = y20juliagt y = (x + ax) 220

Cuando y == x ya se pueden detener los coacutemputos A continuacioacuten se muestraun ciclo que comienza con una estimacioacuten inicial x la cual mejora hasta que dejade cambiar

while true println(x) y = (x + ax) 2 if y == x break end x = yend

Para la mayoriacutea de los valores de a esto funciona bien aunque en general no serecomienda probar igualdad entre nuacutemeros de punto flotante Los nuacutemeros depunto flotante son aproximadamente correctos la mayoriacutea de los nuacutemerosracionales como e irracionales como no pueden ser representadosexactamente con un Float64

En lugar de verificar si x e y son exactamente iguales es maacutes seguro usar lafuncioacuten integrada abs para calcular el valor absoluto o la magnitud de ladiferencia entre ellos

92 Capiacutetulo 7 Iteracioacuten

if abs(y-x) lt ε breakend

Donde ε (varepsilon TAB) toma un valor como 00000001 que determina coacutemode cerca es suficientemente cerca

AlgoritmosEl meacutetodo de Newton es un ejemplo de un algoritmo un proceso mecaacutenico quepermite resolver una categoriacutea de problemas (en este caso el caacutelculo de raiacutecescuadradas)

Para comprender queacute es un algoritmo podriacutea ayudar empezar con algo que no esun algoritmo Cuando aprendioacute a multiplicar nuacutemeros de un solo diacutegitoprobablemente memorizoacute la tabla de multiplicar En efecto memorizoacute 100soluciones especiacuteficas Ese tipo de conocimiento no es un algoritmo

Pero si fuera perezoso podriacutea haber aprendido algunos trucos Por ejemplopara encontrar el producto de y 9 puede escribir como el primer diacutegito y

como el segundo diacutegito Este truco es una solucioacuten general para multiplicarcualquier nuacutemero de un solo diacutegito por 9 iexclEsto siacute es un algoritmo

Del mismo modo las teacutecnicas que aprendioacute para la suma con ldquollevamos tantordquo laresta con ldquopedimos prestado tantordquo y la divisioacuten ldquolarga o con galera o de casitardquoson todas ellas algoritmos Una de las caracteriacutesticas de los algoritmos es que norequieren inteligencia para realizarlos Son procesos mecaacutenicos donde cada pasose sigue de acuerdo con un conjunto simple de reglas

Ejecutar algoritmos es aburrido pero disentildearlos es interesante intelectualmentedesafiante y constituyen una parte central de la informaacutetica

Algunas de las cosas que las personas hacen naturalmente sin dificultad oconscientemente son las maacutes difiacuteciles de expresar en algoritmos Comprender ellenguaje natural es un buen ejemplo Todo el mundo lo hace pero hasta ahoranadie ha podido explicar coacutemo se hace al menos no en forma de algoritmo

DepuracioacutenA medida que comience a escribir programas maacutes extensos es posible que pasemaacutes tiempo depurando Maacutes coacutedigo significa maacutes posibilidades de cometer unerror y maacutes lugares doacutende se pueden esconder los errores

Una forma de reducir el tiempo de depuracioacuten es depurar por biseccioacuten Porejemplo si hay 100 liacuteneas en su programa y las revisa una a la vez seriacutean 100revisiones

Algoritmos 93

Es mejor tratar de dividir el problema en dos Busque en la mitad del programa oun valor intermedio que pueda verificar Agregue una sentencia de impresioacuten (oalgo que permita verificar) y ejecute el programa

Si esta verificacioacuten es incorrecta debe haber un problema en la primera mitaddel programa Si es correcta el problema estaacute en la segunda mitad

Cada vez que realiza una verificacioacuten como esta reduce a la mitad el nuacutemero deliacuteneas que debe revisar Despueacutes de seis pasos (que es mucho menos que 100) sereduciriacutea a una o dos liacuteneas de coacutedigo al menos en teoriacutea

En la praacutectica no siempre se conoce doacutende estaacute la mitad del programa y nosiempre es posible verificarlo No tiene sentido contar liacuteneas y encontrar el puntomedio exacto En su lugar piense en los lugares del programa donde puedehaber errores y en los lugares donde es faacutecil verificar Luego elija un lugar endonde usted crea que las posibilidades de encontrar un error antes o despueacutes deesta verificacioacuten son maacutes o menos las mismas

Glosarioasignacioacuten muacuteltiple

Asignar un nuevo valor a una variable que ya existe

actualizacioacutenAsignacioacuten donde el nuevo valor de la variable depende del antiguo

inicializacioacutenAsignacioacuten que le da un valor inicial a una variable que seraacute actualizada

incrementoActualizacioacuten que incrementa el valor de la variable (usualmente en 1)

decrementoActualizacioacuten que disminuye el valor de la variable (usualmente en 1)

iteracioacutenEjecucioacuten repetida de un conjunto de sentencias usando una funcioacutenrecursiva o un bucle

sentencia whileSentencia que permite iteraciones controladas por una condicioacuten

sentencia breakSentencia que permite salir de un bucle

94 Capiacutetulo 7 Iteracioacuten

sentencia continueSentencia localizada dentro de un bucle que obliga a iniciar una nuevaiteracioacuten desde el inicio del bucle

bucle infinitoUn bucle cuya condicioacuten de teacutermino no es satisfecha

algoritmoProceso general para resolver una categoriacutea de problemas

Ejercicios

Ejercicio 7-2

Copie el bucle de Seccioacuten 76 e inseacutertelo en una funcioacuten llamada miraiz que tomea como paraacutemetro elija un valor razonable de x y devuelva una estimacioacuten de laraiacutez cuadrada de a

Para probarla escriba una funcioacuten llamada probarraiz que imprima una tablacomo esta

a mysqrt sqrt diff- ------ ---- ----10 10 10 0020 1414213562373095 14142135623730951 2220446049250313e-1630 17320508075688772 17320508075688772 0040 20 20 0050 223606797749979 223606797749979 0060 2449489742783178 2449489742783178 0070 26457513110645907 26457513110645907 0080 282842712474619 28284271247461903 4440892098500626e-1690 30 30 00

La primera columna es un nuacutemero a la segunda columna es la raiacutez cuadrada dea calculada con miraiz la tercera columna es la raiacutez cuadrada calculada con lafuncioacuten integrada sqrt y la cuarta columna es el valor absoluto de la diferenciaentre las dos estimaciones

Exercise 7-3

La funcioacuten integrada Metaparse toma una cadena y la transforma en unaexpresioacuten Esta expresioacuten se puede evaluar en Julia con la funcioacuten Coreeval Porejemplo

Ejercicios 95

juliagt expr = Metaparse(1+23)(1 + 2 3)juliagt eval(expr)7juliagt expr = Metaparse(sqrt(π))(sqrt(π))juliagt eval(expr)17724538509055159

Escriba una funcioacuten llamada evalbucle que iterativamente solicite una entrada alusuario tome la entrada resultante la evaluacutee usando eval y pase posteriormentea imprimir el resultado Debe continuar hasta que el usuario ingrese listo y luegodevolver el valor de la uacuteltima expresioacuten que evaluoacute

Exercise 7-4

El matemaacutetico Srinivasa Ramanujan encontroacute una serie infinita que puede usarsepara generar una aproximacioacuten numeacuterica de

Escriba una funcioacuten llamada estimarpi que utilice esta foacutermula para calcular ydevolver una estimacioacuten de π Debe usar un ciclo while para calcular losteacuterminos de la suma hasta que el uacuteltimo teacutermino sea menor que 1e-15 (que es lanotacioacuten de Julia para ) Puede verificar el resultado comparaacutendolo con π

96 Capiacutetulo 7 Iteracioacuten

Capiacutetulo 8 CadenasLas cadenas son diferentes de los nuacutemeros enteros flotantes y booleanos Unacadena es una secuencia es decir una coleccioacuten ordenada de valores En estecapiacutetulo se veraacute coacutemo acceder a los caracteres que forman una cadena y seconoceraacuten algunas funciones integradas en Julia relacionadas con cadenas

CaracteresLos hispanohablantes estaacuten familiarizados con algunos caracteres tales como lasletras del alfabeto (A B C hellip) los nuacutemeros y los signos de puntuacioacuten comunesEstos caracteres estaacuten estandarizados en el coacutedigo ASCII (Coacutedigo EstaacutendarEstadounidense para el Intercambio de Informacioacuten)

Por supuesto hay muchos otros caracteres utilizados en idiomas distintos delespantildeol que no estaacuten en el coacutedigo ASCII tales como aquellos usados en losidiomas griego aacuterabe chino hebreo hindi japoneacutes y coreano

Definir queacute es un caraacutecter es altamente complejo La norma Unicode permiteabordar este problema y se considera como el estaacutendar definitivo para ello Estanorma funciona asignando un nuacutemero uacutenico para cada caraacutecter a nivel global

Un valor Char representa un uacutenico caraacutecter y estaacute entre comillas simples

juliagt xx ASCIIUnicode U+0078 (category Ll Letter lowercase)juliagt ἴἴ Unicode U+1F34C (category So Symbol other)juliagt typeof(x)Char

Incluso los emojis son parte del estaacutendar Unicode (banana TAB)

Una Cadena es una SecuenciaUna cadena es una secuencia de caracteres Se puede acceder a un caraacutecter conel operador corchete

juliagt fruta = bananabananajuliagt letra = fruta[1]b ASCIIUnicode U+0062 (category Ll Letter lowercase)

La segunda sentencia selecciona el caraacutecter nuacutemero 1 de fruta y la asigna a lavariable letra

Caracteres 97

La expresioacuten entre corchetes se llama indice El iacutendice indica el caraacutecter de lasecuencia a obtener (de ahiacute el nombre)

La indexacioacuten en Julia es base 1 es decir el primer elemento de cualquier objetoindexado con enteros estaacute en el iacutendice 1 y el uacuteltimo en el iacutendice end

juliagt fruta[end]a ASCIIUnicode U+0061 (category Ll Letter lowercase)

Como iacutendice se pueden usar expresiones que contengan variables y operadores

juliagt i = 11juliagt fruta[i+1]a ASCIIUnicode U+0061 (category Ll Letter lowercase)juliagt fruta[end-1]n ASCIIUnicode U+006E (category Ll Letter lowercase)

No obstante el valor del iacutendice tiene que ser un nuacutemero entero De lo contrariose obtiene

juliagt letra = fruta[15]ERROR MethodError no method matching getindex(String Float64)

lengthlength es una funcioacuten integrada que devuelve el nuacutemero de caracteres de unacadena

juliagt frutas = ἴ ἴ ἵἴ ἴ ἵjuliagt len = length(frutas)5

Para obtener la uacuteltima letra de una cadena puede sentirse tentado a probar algocomo esto

juliagt last = frutas[len] ASCIIUnicode U+0020 (category Zs Separator space)

Pero con esto no se obtiene el resultado esperado

Las cadenas se codifican usando codificacioacuten UTF-8 UTF-8 es una codificacioacutende longitud variable lo que significa que no todos los caracteres estaacuten

98 Capiacutetulo 8 Cadenas

codificados con el mismo nuacutemero de bytes

La funcioacuten sizeof devuelve el nuacutemero de bytes de una cadena

juliagt sizeof(ἴ)4

Dado que un emoji estaacute codificado en 4 bytes y la indexacioacuten de cadenas estaacutebasada en bytes el quinto elemento de frutas es un ESPACIO

Esto significa que no todos los iacutendices de byte de una cadena UTF-8 sonnecesariamente iacutendices vaacutelidos para un caraacutecter Si en una cadena se indexa conun iacutendice de bytes no vaacutelido se genera un error

juliagt frutas[2]ERROR StringIndexError(ἴ ἴ ἵ 2)

En el caso de frutas el caraacutecter ἴ es un caraacutecter de cuatro bytes por lo que losiacutendices 2 3 y 4 no son vaacutelidos y el iacutendice del siguiente caraacutecter es 5 el siguienteiacutendice vaacutelido se puede calcular con nextind(frutas 1) el subsiguiente connextind(frutas5) y asiacute sucesivamente

RecorridoMuchos caacutelculos implican procesar una cadena caraacutecter por caraacutecter A menudoempiezan por el principio seleccionan cada caraacutecter por turno hacen algo con eacutely continuacutean hasta el final Este patroacuten de proceso se llama recorrido Una formade escribir un recorrido es con una sentencia while

indice = firstindex(frutas)while indice lt= sizeof(frutas) letra = frutas[indice] println(letra) global indice = nextind(frutas indice)end

Este bucle recorre la cadena y muestra cada letra en una liacutenea distinta Lacondicioacuten del bucle es index lt= sizeof(fruta) de modo que cuando el iacutendice esmayor al nuacutemero de bytes en la cadena la condicioacuten es falsa y no se ejecuta elcuerpo del bucle

La funcioacuten firstindex devuelve el primer iacutendice de bytes vaacutelido La palabrareservada global antes de indice indica que queremos reasignar la variableindice definida en Main (ver Seccioacuten 117)

Recorrido 99

Ejercicio 8-1

Escriba una funcioacuten que tome una cadena como argumento y que muestre lasletras desde la uacuteltima a la primera una por liacutenea

Otra forma de escribir un recorrido es con un bucle for

for letra in frutas println(letra)end

Cada vez que se recorre el bucle se asigna a la variable letra el siguientecaraacutecter de la cadena El bucle continuacutea hasta que no quedan maacutes caracteres

El ejemplo siguiente muestra coacutemo usar la concatenacioacuten (multiplicacioacuten decadenas) y un bucle for para generar una serie abecedaria (es decir una seriecon elementos en orden alfabeacutetico) Por ejemplo en el libro de Robert McCloskeyMake Way for Ducklings los nombres de los patitos son Jack Kack Lack MackNack Ouack Pack y Quack Este bucle muestra esos nombres en orden

prefijos = JKLMNOPQsufijo = ack

for letra in prefijos println(letra sufijo)end

Output

JackKackLackMackNackOackPackQack

Por supuesto esto no es del todo correcto porque ldquoOuackrdquo y ldquoQuackrdquo no estaacutencorrectamente escritos

Ejercicio 8-2

Modifique este programa para solucionar este error

100 Capiacutetulo 8 Cadenas

Porciones de CadenasA la subcadena de una cadena se le llama porcioacuten La seleccioacuten de una porcioacuten essimilar a la seleccioacuten de un caraacutecter

juliagt str = Julio Cesar

juliagt str[15]Julio

El operador [nm] devuelve la parte de la cadena desde el n-eacutesimo byte hasta elm-eacutesimo Por lo tanto se siguen las mismas reglas que para la indexacioacuten simple

La palabra reservada end se puede usar para indicar al uacuteltimo byte de la cadena

juliagt str[7end]Cesar

Si el primer iacutendice es mayor que el segundo el resultado es una cadena vaciacutearepresentada por dos comillas

juliagt str[87]

Una cadena vaciacutea no contiene caracteres y tiene una longitud de 0 pero apartede eso es igual a cualquier otra cadena

Ejercicio 8-3

Continuando este ejemplo iquestqueacute cree que significa str[] Pruebe y veraacute

Las Cadenas son InmutablesEs tentador usar el operador [] en el lado izquierdo de una asignacioacuten con laintencioacuten de cambiar un caraacutecter en una cadena Por ejemplo

juliagt saludo = iexclHola mundoiexclHola mundojuliagt saludo[3] = JERROR MethodError no method matching setindex(String CharInt64)

Nota del traductor De acuerdo con la codificacioacuten de caracteres en utf-8 o latin-

Porciones de Cadenas 101

1 el caraacutecter de exclamacioacuten lsquoiexclrsquo en la variable saludo ocupa dos posiciones deahiacute que la letra lsquoHrsquo esteacute localizada en el iacutendice 3

La razoacuten del error es que las cadenas son inmutables lo que significa que no sepuede cambiar una cadena existente Lo maacuteximo que se puede hacer es crearuna nueva cadena que sea una variacioacuten de la original

juliagt saludo = iexclJ saludo[4end]iexclJola mundo

Este ejemplo concatena la apertura del signo de exclamacioacuten y una nuevaprimera letra a una porcioacuten de saludo Esta operacioacuten no tiene efecto sobre lacadena original

Interpolacioacuten de CadenasConstruir cadenas usando concatenacioacuten puede ser un poco engorroso Paradisminuir la necesidad de las llamadas a string o multiplicaciones repetidas Juliapermite la interpolacioacuten de cadenas usando $

juliagt saludo = iexclHolaiexclHolajuliagt paraquien = mundomundojuliagt $saludo $(paraquien)iexclHola mundo

Esto es maacutes entendible y conveniente que la concatenacioacuten de cadenas saludo paraquien

La expresioacuten inmediatamente siguiente a $ se toma como la expresioacuten cuyo valorse va a interpolar en la cadena Por lo tanto puede interpolar cualquierexpresioacuten en una cadena usando pareacutentesis

juliagt 1 + 2 = $(1 + 2)1 + 2 = 3

Buacutesqueda

iquestQueacute hace la siguiente funcioacuten

102 Capiacutetulo 8 Cadenas

function busqueda(palabra letra) indice = primerindice(palabra) while indice lt= sizeof(palabra) if palabra[indice] == letra return indice end indice = nextind(palabra indice) end -1end

En cierto sentido la funcioacuten buacutesqueda es lo contrario del operador [] En lugarde tomar un iacutendice y extraer el caraacutecter correspondiente toma un caraacutecter yencuentra el iacutendice donde aparece el caraacutecter Si el caraacutecter no se encuentra lafuncioacuten devuelve -1

Este es el primer ejemplo de una sentencia return dentro de un bucle Sipalabra[indice] == letra la funcioacuten devuelve inmediatamente el iacutendiceescapando del bucle prematuramente

Si el caraacutecter no aparece en la cadena entonces el programa sale del buclenormalmente y devuelve -1

Este patroacuten de computacioacuten se llama a veces un recorrido eureka porque tanpronto como encontramos lo que buscamos podemos gritar ldquoiexclEureka rdquo y dejarde buscar

Ejercicio 8-4

Modifique la funcioacuten busqueda para que tenga un tercer paraacutemetro el iacutendice depalabra donde deberiacutea comenzar a buscar

Iterando y contandoEl siguiente programa cuenta el nuacutemero de veces que aparece la letra a en unacadena

palabra = bananacontador = 0for letra in palabra if letra == a global contador = contador + 1 endendprintln(contador)

Iterando y contando 103

Este programa es otro ejemplo del patroacuten de computacioacuten llamado conteo Lavariable contador se inicializa en 0 y se incrementa cada vez que encuentra laletra a Cuando termina el bucle contador contiene el resultado (el nuacutemero totalde letras a)

Ejercicio 8-5

Coloque este coacutedigo en una funcioacuten llamada conteo y generaliacutecelo de tal maneraque tome como argumentos una cadena y una letra

Luego vuelva a escribir la funcioacuten para que en vez de revisar toda la cadenautilice la funcioacuten busqueda de tres paraacutemetros de la seccioacuten anterior

Libreriacutea con cadenasJulia tiene funciones integradas que realizan una variedad de operaciones uacutetilesen cadenas Por ejemplo la funcioacuten uppercase toma una cadena y devuelve unanueva cadena con todas las letras mayuacutesculas

juliagt uppercase(iexclHola mundo)iexclHOLA MUNDO

Existe una funcioacuten llamada findfirst que es notablemente similar a la funcioacutenbusqueda que escribimos

juliagt findfirst(a banana)22

La funcioacuten findfirst es maacutes general que la funcioacuten creada puede encontrarsubcadenas no solo caracteres

juliagt findfirst(na banana)34

Por defecto findfirst empieza la buacutesqueda al comienzo de la cadena pero lafuncioacuten findnext toma un tercer argumento el indice donde deberiacutea comenzar

juliagt findnext(na banana 4)56

El operador isinEl operador isin (in TAB) es un operador booleano que toma un caraacutecter y unacadena y devuelve true si el primero aparece en el segundo

104 Capiacutetulo 8 Cadenas

juliagt a isin banana a en bananatrue

Por ejemplo la siguiente funcioacuten imprime todas las letras de palabra1 quetambieacuten aparecen en palabra2

function ambas(palabra1 palabra2) for letra in palabra1 if letra isin palabra2 print(letra ) end endend

Una buena eleccioacuten de nombres de variables permite que Julia se pueda leercomo el espantildeol Este bucle puede leerse como para (cada) letra en (la primera)palabra si (la) letra es un elemento de (la segunda) palabra imprima (la) letra

Esto es lo que se obtiene si se compara manzanas y naranjas

juliagt ambas(manzanas naranjas)a n a n a s

Comparacioacuten de CadenasLos operadores de comparacioacuten trabajan sobre cadenas Para ver si dos cadenasson iguales

palabra = Pintildeaif palabra == banana println(iexclTenemos bananas)end

Otras operaciones de comparacioacuten son uacutetiles para ordenar alfabeacuteticamentepalabras

if palabra lt banana println(Su palabra $palabra va antes de banana)elseif word gt banana println(Su palabra $palabra va antes de banana)else println(iexclTenemos bananas)end

Comparacioacuten de Cadenas 105

Julia no maneja las letras mayuacutesculas y minuacutesculas del mismo modo que sonmanejadas en cualquier lengua hablada Todas las letras mayuacutesculas van antesde las letras minuacutesculas seguacuten el estaacutendar de codificacioacuten Por lo tanto

Su palabra Pintildea va antes de banana

OBSERVACIOacuteNUna forma comuacuten de abordar este problema es convertirlas cadenas a un formato estaacutendar como por ejemplo aminuacutesculas antes de realizar la comparacioacuten

DepuracioacutenCuando se usan iacutendices para recorrer los valores en una secuencia es difiacutecilacceder al principio y al final del recorrido Aquiacute hay una funcioacuten que comparados palabras y devuelve true si una de las palabras es el reverso de la otra perocontiene dos errores

function espalindroma(palabra1 palabra2) if length(palabra1) = length(palabra2) return false end i = firstindex(palabra1) j = lastindex(palabra2) while j gt= 0 j = prevind(palabra2 j) if palabra1[i] = palabra2[j] return false end i = nextind(palabra1 i) end trueend

La primera sentencia if verifica si las palabras tienen la misma longitud Si no sedevuelve false inmediatamente De lo contrario para el resto de la funcioacuten sepuede suponer que las palabras tienen la misma longitud Este es un ejemplo delpatroacuten guardiaacuten

i y j son iacutendices i recorre palabra1 de derecha a izquierda mientras que j recorrepalabra2 de izquierda a derecha Si dos letras no coinciden se devuelve falseinmediatamente Si el ciclo termina y todas las letras coinciden se devuelve true

La funcioacuten lastindex devuelve el uacuteltimo iacutendice de bytes vaacutelido de una cadena yprevind el iacutendice vaacutelido anterior a un caraacutecter

Si se prueba esta funcioacuten con las palabras amor y roma se espera el valor de

106 Capiacutetulo 8 Cadenas

retorno true pero se obtiene false

juliagt espalindroma(amor roma)false

Para depurar este tipo de error primeramente se imprimen los valores de losiacutendices

espalindroma (generic function with 1 method)

Ahora al ejecutar el programa se obtiene maacutes informacioacuten

juliagt espalindroma(amor roma)i = 1j = 3false

En la primera iteracioacuten del bucle el valor de j es 3 pero tendriacutea que ser 4 Estose puede solucionar trasladando la liacutenea j = prevind (palabra2 j) al final del ciclowhile

Si se soluciona ese error y se ejecuta el programa nuevamente se obtiene

espalindroma (generic function with 1 method)

juliagt espalindroma(amor roma)i = 1j = 4i = 2j = 3i = 3j = 2i = 4j = 1i = 5j = 0ERROR BoundsError attempt to access String at index [5]

Esta vez se ha producido un BoundsError El valor de i es 5 que estaacute fuera delrango de la cadena amor

Depuracioacuten 107

Ejercicio 8-6

Ejecute el programa en papel cambiando los valores de i y j durante cadaiteracioacuten Encuentre y arregle el segundo error en esta funcioacuten

Glosariosecuencia

Una coleccioacuten ordenada de valores donde cada valor se identifica medianteun iacutendice entero

coacutedigo ASCIICoacutedigo de caracteres estaacutendar para el intercambio de informacioacuten

norma UnicodeUn estaacutendar en la industria informaacutetica para la codificacioacuten representacioacuteny manejo consistentes de texto en la mayoriacutea de los sistemas de escrituradel mundo

iacutendiceUn valor entero usado para seleccionar un miembro de un conjuntoordenado como puede ser un caraacutecter de una cadena En Julia los iacutendicescomienzan en 1

codificacioacuten UTF-8Una codificacioacuten de caracteres de longitud variable capaz de codificar todoslos 1112064 puntos de coacutedigo vaacutelidos en Unicode utilizando de uno a cuatrobytes de 8 bits

recorrerIterar sobre los elementos de un conjunto realizando una operacioacuten similaren cada uno de ellos

porcioacutenUna parte de una cadena especificada mediante un rango de iacutendices

cadena vaciacuteaUna cadena sin caracteres y longitud 0 representada por dos comillas

immutableLa propiedad de una secuencia que hace que a sus elementos no se lespueda asignar nuevos valores

interpolacioacuten de cadenasEl proceso de evaluar una cadena que contiene uno o maacutes marcadores de

108 Capiacutetulo 8 Cadenas

posicioacuten produciendo un resultado en el que los marcadores de posicioacuten sereemplazan con sus valores correspondientes

buacutesquedaUn patroacuten de recorrido que se detiene cuando encuentra lo que estaacutebuscando

contadorUna variable utilizada para contar algo generalmente inicializada en cero yluego incrementada

Ejercicios

Ejercicio 8-7

Lea la documentacioacuten de las funciones relacionadas con cadenas enhttpsdocsjulialangorgenv1manualstrings Es posible que desee probaralgunas de ellas para asegurarse de comprender coacutemo funcionan strip y replaceson particularmente uacutetiles

La documentacioacuten utiliza una sintaxis que puede ser confusa Por ejemplo ensearch(cadenaAbstractString caracterChars [comienzoInteger]) loscorchetes indican argumentos opcionales Por lo tanto cadena y caracter sonobligatorios pero comienzo es opcional

Ejercicio 8-8

Hay una funcioacuten integrada llamada count que es similar a la funcioacuten en Seccioacuten89 Lea la documentacioacuten de esta funcioacuten y uacutesela para contar el nuacutemero deletras a en banana

Ejercicio 8-9

Una porcioacuten de cadena puede tomar un tercer iacutendice El primero especifica elinicio el tercero el final y el segundo el tamantildeo del paso es decir el nuacutemero deespacios entre caracteres sucesivos Un tamantildeo de paso de 2 significa cada uncaracter 3 significa cada dos etc

juliagt fruta = bananabananajuliagt fruta[126]bnn

Un tamantildeo de paso de -1 recorre la palabra hacia la izquierda por lo que laporcioacuten [end-11] genera una cadena invertida

Ejercicios 109

Use esto para escribir una versioacuten de una liacutenea de coacutedigo de espalindroma deSeccioacuten 6113

Exercise 8-10

Las siguientes funciones estaacuten destinadas a verificar si una cadena contieneletras minuacutesculas pero algunas de ellas son incorrectas Para cada funcioacutendescriba queacute hace realmente la funcioacuten (suponiendo que el paraacutemetro es unacadena)

110 Capiacutetulo 8 Cadenas

function cualquierminuscula1(s) for c in s if islowercase(c) return true else return false end endend

function cualquierminuscula2(s) for c in s if islowercase(c) return true else return false end endend

function cualquierminuscula3(s) for c in s bandera = islowercase(c) end flagend

function cualquierminuscula4(s) bandera = false for c in s bandera = bandera || islowercase(c) end flagend

function cualquierminuscula5(s) for c in s if islowercase(c) return false end end trueend

Exercise 8-11

Un cifrado Ceacutesar es una forma simple de cifrado que implica desplazar cada letraun nuacutemero fijo de lugares Desplazar una letra significa reemplazarla por otra

Ejercicios 111

letra que se encuentra un nuacutemero fijo de posiciones maacutes adelante en el alfabetoEs posible desplazarse hasta el principio del abecedario si fuera necesario Deesta manera con un desplazamiento de 3 A es D y con un desplazamiento de1 Z es A

Para desplazar una palabra desplace cada letra en la misma cantidad Porejemplo con un desplazamiento de 6 ABCDEF es GHIJKL y con undesplazamiento de -6 BCDE es VWXY En la peliacutecula 2001 Una odisea delespacio la computadora de la nave se llama HAL que es IBM desplazada por -1

Escriba una funcioacuten llamada desplazarpalabra que tome una cadena y un nuacutemeroentero como paraacutemetros y devuelva una nueva cadena que contenga las letrasde la cadena original desplazadas por la cantidad dada

OBSERVACIOacuteN

Es posible que desee utilizar la funcioacuten integrada Intque convierte un caraacutecter en un coacutedigo numeacuterico yChar que convierte los coacutedigos numeacutericos encaracteres Las letras del alfabeto estaacuten codificadas enorden alfabeacutetico por ejemplo

juliagt Int(c) - Int(a)2

Porque c es la tercera letra del alfabeto Pero cuidadolos coacutedigos numeacutericos para las letras mayuacutesculas sondiferentes

juliagt Char(Int(A) + 32)a ASCIIUnicode U+0061 (category Ll Letterlowercase)

Algunos chistes ofensivos en Internet estaacuten codificados en ROT13 que es uncifrado Ceacutesar con desplazamiento 13 Si no se ofende faacutecilmente encuentre ydecodifice algunos de ellos

112 Capiacutetulo 8 Cadenas

Capiacutetulo 9 Estudio de Caso Juego de PalabrasEste capiacutetulo presenta un segundo estudio de caso que consiste en resolverpuzzles buscando palabras que tengan ciertas propiedades Por ejemplo sebuscaraacuten palabras cuyas letras aparezcan en orden alfabeacutetico Ademaacutes sepresentaraacute otra forma de desarrollar programas la reduccioacuten a un problemapreviamente resuelto

Leer listas de palabrasPara los ejercicios de este capiacutetulo se necesita una lista de palabras en espantildeolHay muchas listas de palabras disponibles en la Web pero la maacutes adecuada paranuestro propoacutesito es una de las listas de palabras recopiladas y contribuidas aldominio puacuteblico por Ismael Olea (see httpoleaorgproyectoslemarios) Estalista de 87900 palabras se encuentra en la paacutegina de Olea con el nombre dearchivo lemario-general-del-espanoltxt Tambieacuten es posible descargar una copiadesde httpsgithubcomJuliaIntroIntroAJuliajlblobmasterdatapalabrastxt

Este archivo es un archivo de texto simple por lo que puede ser abierto con uneditor de texto o leiacutedo con Julia La funcioacuten integrada open toma el nombre delarchivo como paraacutemetro y devuelve un objeto archivo que puede ser usado parala lectura del archivo

IOStream(ltfilehometravisbuildJuliaIntroIntroAJuliajlsrcdatapalabrastxtgt)

juliagt fin = open(palabrastxt)IOStream(ltfile palabrastxtgt)

fin es un objeto archivo que puede ser utilizado como entrada y cuando se dejade utilizar debe cerrarse con close(fin)

Julia tiene integradas varias funciones de lectura entre ellas readline que lee loscaracteres del archivo hasta que llega a un salto de liacutenea devolviendo elresultado como una cadena

juliagt readline(fin)a

La primera palabra en esta lista particular es a que indica direccioacuten intervalode tiempo finalidad entre otros

El objeto archivo lleva registro de doacutende quedoacute por uacuteltima vez por lo que sillama a readline nuevamente se obtendraacute la siguiente palabra

Leer listas de palabras 113

juliagt readline(fin)a-

La siguiente palabra es a- que es un prefijo que indica privacioacuten

Tambieacuten se puede usar un archivo como parte de un bucle for El siguienteprograma lee palabrastxt e imprime cada palabra una por liacutenea

for line in eachline(palabrastxt) println(line)end

Ejercicios

Ejercicio 9-1

Escriba un programa que lea palabrastxt e imprima solo las palabras con maacutes de20 caracteres (sin contar espacios en blanco)

Ejercicio 9-2

En 1927 Enrique Jardiel Poncela publicoacute cinco historias cortas omitiendo encada una de ellas una vocal Estas historias incluyen El Chofer Nuevonarracioacuten escrita sin la letra a y Un marido sin vocacioacuten sin la letra e Dadoque la letra e es la maacutes frecuente del espantildeol esto no es faacutecil de lograr

De hecho es difiacutecil pensar oraciones que no utilicen esta letra Intentarlo escomplicado pero con la praacutectica se vuelve maacutes faacutecil

Bueno volviendo al tema importante

Escriba una funcioacuten llamada notiene_e que devuelva true si una palabra dada notiene la letra e

Modifique su programa de la seccioacuten anterior para que imprima solo las palabrasque no tienen e y que ademaacutes calcule el porcentaje de palabras en la lista queno tengan e

Ejercicio 9-3

Escriba una funcioacuten llamada evitar que tome como argumentos una palabra yuna cadena de letras prohibidas y que devuelva true si la palabra no usaninguna de las letras prohibidas

Modifique su programa de la seccioacuten anterior para solicitar al usuario queingrese una cadena de letras prohibidas y que luego imprima el nuacutemero de

114 Capiacutetulo 9 Estudio de Caso Juego de Palabras

palabras que no contengan ninguna de ellas iquestEs posible encontrar unacombinacioacuten de 5 letras prohibidas que excluya la menor cantidad de palabras

Ejercicio 9-4

Escriba una funcioacuten llamada usasolo que tome una palabra y una cadena deletras y que devuelva true si la palabra contiene solo letras de la lista iquestPuedehacer una oracioacuten usando solo las letras oneacmil Aparte de iquestEl camino

Ejercicio 9-5

Escriba una funcioacuten llamada usatodo que tome una palabra y una cadena deletras y que devuelva true si la palabra usa todas las letras requeridas al menosuna vez iquestCuaacutentas palabras usan todas las vocales aeiou

Ejercicio 9-6

Escriba una funcioacuten llamada esabecedaria que devuelva true si las letras de unapalabra aparecen en orden alfabeacutetico iquestCuaacutentas palabras de este tipo hay

BuacutesquedaTodos los ejercicios en la seccioacuten anterior tienen algo en comuacuten se puedenresolver con el patroacuten de buacutesqueda El ejemplo maacutes simple es

function notiene_e(palabra) for letra in palabra if letra == e return false end end trueend

El bucle for recorre los caracteres de palabra Si encontramos la letra e puededevolver inmediatamente false de lo contrario hay que pasar a la siguiente letraSi se sale del bucle normalmente eso significa que no se encontroacute una e por loque la funcioacuten devuelve true

Esta funcioacuten podriacutea ser escrita de manera maacutes concisa usando el operador notin(notin TAB) pero se comienza con esta versioacuten porque muestra la loacutegica delpatroacuten de buacutesqueda

evita es una versioacuten maacutes general de notiene_e pero tiene la misma estructura

Buacutesqueda 115

function evita(palabra prohibidas) for letra in palabra if letter isin prohibidas return false end end trueend

Se devuelve false tan pronto como se encuentre una letra prohibida si llegamosal final del ciclo se devuelve true

usasolo es similar excepto que el sentido de la condicioacuten se invierte

function usasolo(palabra disponibles) for letra in palabra if letra notin disponibles return false end end trueend

En vez de un conjunto de letras prohibidas se tiene un conjunto de letrasdisponibles Si se encuentra una letra en palabra que no estaacute en disponible sedevuelve false

usatodo es similar excepto que se invierte el papel de la palabra y la cadena deletras

function usatodo(palabra requeridas) for letra in requeridas if letra notin palabra return false end end trueend

En lugar de recorrer las letras de la palabra el bucle recorre las letrasrequeridas Si alguna de las letras requeridas no aparece en la palabra sedevuelve false

Si se pensara como un informaacutetico se reconoceriacutea que usatodo es una instanciade un problema previamente resuelto y se podriacutea haber escrito

116 Capiacutetulo 9 Estudio de Caso Juego de Palabras

function usatodo(palabra requeridas) usasolo(requeridas palabra)end

Este es un ejemplo de una forma de desarrollar programas llamada reduccioacuten aun problema resuelto previamente lo que significa que se reconoce el problemaen el que se estaacute trabajando como una instancia de un problema ya resuelto y seaplica la solucioacuten existente

Bucle con iacutendicesLas funciones de la seccioacuten anterior fueron escritas con ciclos for porque solo senecesitaban los caracteres en las cadenas y no hubo necesidad de trabajar conlos iacutendices

Para esabecedaria tenemos que comparar letras adyacentes lo cual es un pococomplicado con un ciclo for

function esabecedaria(palabra) i = firstindex(palabra) previa = palabra[i] j = nextind(palabra i) for c in palabra[jend] if c lt previa return false end previa = c end trueend

Otra alternativa es usar recursividad

function esabecedaria(palabra) if length(palabra) lt= 1 return true end i = firstindex(palabra) j = nextind(palabra i) if palabra[i] gt palabra[j] return false end esabecedaria(palabra[jend])end

Una tercera opcioacuten es usar un ciclo while

Bucle con iacutendices 117

function esabecedaria(palabra) i = firstindex(palabra) j = nextind(palabra 1) while j lt= sizeof(palabra) if palabra[j] lt palabra[i] return false end i = j j = nextind(palabra i) end trueend

El ciclo comienza en i=1 y j=nextind(palabra 1) y termina cuandojgtsizeof(palabra) En cada iteracioacuten se compara el caraacutecter ieacutesimo (que sepuede considerar como el caraacutecter actual) con el caraacutecter jeacutesimo (que se puedeconsiderar como el siguiente)

Si el siguiente caraacutecter es menor (va antes en el alfabeto) que el actual entoncesla palabra no tiene sus letras en orden alfabeacutetico y se devuelve false

Si se llega al final del ciclo sin encontrar letras que imposibiliten el ordenalfabeacutetico entonces la palabra pasa la prueba Para convencerse de que el ciclotermina correctamente considere como ejemplo la palabra Abel

A continuacioacuten se muestra una versioacuten de espalindromo que usa dos iacutendices unocomienza al principio de la palabra y aumenta su valor y el otro comienza al finaly disminuye su valor

function espalindromo(palabra) i = firstindex(palabra) j = lastindex(palabra) while iltj if palabra[i] = palabra[j] return false end i = nextind(palabra i) j = prevind(palabra j) end trueend

O podriacuteamos reducir este problema a uno previamente resuelto y escribir

118 Capiacutetulo 9 Estudio de Caso Juego de Palabras

function espalindromo(palabra) isreverse(palabra palabra)end

Usando esreverso de Seccioacuten 813

DepuracioacutenComprobar el correcto funcionamiento de los programas es difiacutecil Las funcionesde este capiacutetulo son relativamente faacuteciles de probar porque se pueden verificarlos resultados a mano Aun asiacute es casi imposible elegir un conjunto de palabrasque permitan evaluar todos los posibles errores

Tomando notiene_e como ejemplo hay dos casos obvios que verificar laspalabras que tienen una e deberiacutean devolver false y las palabras que nodeberiacutean devolver true No deberiacutean haber problemas para encontrar un ejemplode cada uno

Dentro de cada caso hay algunos subcasos menos obvios Entre las palabras quetienen una e se deben probar las palabras con una e al principio al final y almedio Ademaacutes se deben probar palabras largas cortas y muy cortas como unacadena vaciacutea La cadena vaciacutea es un ejemplo de un caso especial no obviodonde pueden originarse errores

Ademaacutes de las instancias de prueba generadas tambieacuten puede probar suprograma con una lista de palabras como palabrastxt Al escanear el resultadoes posible que pueda detectar errores pero tenga cuidado puede detectar untipo de error (palabras que no deberiacutean incluirse pero lo estaacuten) y no otro(palabras que deberiacutean incluirse pero no lo estaacuten)

Por lo general las pruebas pueden ayudarlo a encontrar errores pero no es faacutecilgenerar un buen conjunto de instancias de prueba e incluso si lo hace no puedeestar seguro de que su programa sea correcto Seguacuten un informaacutetico muyfamoso

Las pruebas de programa se pueden usar para mostrar la presencia deerrores iexclpero nunca para mostrar su ausencia

mdash Edsger W Dijkstra

Glosarioobjeto archivo o file stream

Un valor que representa un archivo abierto

Depuracioacuten 119

reduccioacuten a un problema previamente resueltoUna manera de resolver un problema expresaacutendolo como una instancia deun problema previamente resuelto

caso especialUna instancia de prueba que es atiacutepica o no obvia (y por lo tanto menosprobable que se maneje correctamente)

Ejercicios

Ejercicio 9-7

Esta pregunta se basa en un Puzzle que se transmitioacute en el programa de radioCar Talk (httpswwwcartalkcompuzzlerbrowse)

Se tiene una secuencia de nuacutemeros y se desea saber cuaacutel es el siguiente Losnuacutemeros son 4 6 12 18 30 42 60 y luego X

Pista 1 Todos los nuacutemeros de la secuencia son pares Pista 2 El nuacutemero queva despueacutes del que estoy buscando es 102

iquestCuaacutel es el nuacutemero

Primero piense el patroacuten que busca y luego escriba un programa que le permitaencontrar el nuacutemero que sigue este patroacuten que se encuentra entre 60 y 102

Ejercicio 9-8

A continuacioacuten se muestra otro puzzle de Car Talk (httpswwwcartalkcompuzzlerbrowse)

120 Capiacutetulo 9 Estudio de Caso Juego de Palabras

Estaba conduciendo por la autopista el otro diacutea y vi mi odoacutemetro Como lamayoriacutea de los odoacutemetros muestra seis diacutegitos y solo en kiloacutemetros enterosEntonces si mi automoacutevil tuviera un kilometraje de 300000 por ejemploseriacutea 3-0-0-0-0-0

Ahora lo que vi ese diacutea fue muy interesante Noteacute que los uacuteltimos 4 diacutegitoseran palindroacutemicos es decir se leiacutean igual hacia adelante que hacia atraacutesPor ejemplo 5-4-4-5 es un paliacutendromo por lo que mi odoacutemetro podriacuteahaberse leiacutedo 3-1-5-4-4-5

Un kiloacutemetro despueacutes los uacuteltimos 5 nuacutemeros fueron palindroacutemicos Porejemplo podriacutea haberse leiacutedo 3-6-5-4-5-6 Un kiloacutemetro despueacutes de eso los 4nuacutemeros del medio eran palindroacutemicos iquestYhellip estaacutes listo para esto iexclUnkiloacutemetro despueacutes los 6 eran palindroacutemicos

La pregunta es iquestqueacute nuacutemero estaba en el odoacutemetro cuando mireacute porprimera vez

Escriba un programa de Julia que pruebe todos los nuacutemeros de seis diacutegitos eimprima cualquier nuacutemero que satisfaga estos requisitos

Ejercicio 9-9

Aquiacute hay otro puzzle de Car Talk que puede resolver con una buacutesqueda(httpswwwcartalkcompuzzlerbrowse)

Hace poco visiteacute a mi madre y nos dimos cuenta de que los dos diacutegitos quecomponen mi edad cuando se invertiacutean daban como resultado su edad Porejemplo si tiene 73 antildeos yo tengo 37 Nos preguntamos con queacute frecuenciaesto ha sucedido a lo largo de los antildeos pero nos desviamos de otros temas ynunca obtuvimos una respuesta

Cuando llegueacute a casa descubriacute que los diacutegitos de nuestras edades han sidoreversibles seis veces hasta ahora Tambieacuten descubriacute que si teniacuteamos suertevolveriacutea a suceder en unos antildeos y si tenemos mucha suerte sucederiacutea unavez maacutes despueacutes de eso En otras palabras habriacutea sucedido 8 vecesEntonces la pregunta es iquestcuaacutentos antildeos tengo ahora

Escriba un programa de Julia que busque soluciones para este puzzle

OBSERVACIOacuteN Puede encontrar la funcioacuten lpad uacutetil

Ejercicios 121

Capiacutetulo 10 ArreglosEste capiacutetulo presenta uno de los tipos maacutes uacutetiles de Julia los arreglos Tambieacutense trataraacuten objetos y lo que puede suceder cuando se tiene maacutes de un nombrepara el mismo objeto

Un arreglo es una secuenciaAl igual que una cadena de texto un arreglo es una secuencia de valores En unacadena los valores son caracteres en un arreglo pueden ser de cualquier tipoLos valores en un arreglo se denominan elementos o a veces items

Hay varias formas de crear un nuevo arreglo la maacutes sencilla es encerrar loselementos entre corchetes ([ ])

[10 20 30 40][abadejo falsiacutea estrambote]

El primer ejemplo es un arreglo de cuatro enteros El segundo es un arreglo detres cadenas de texto Los elementos de un arreglo no tienen por queacute ser delmismo tipo El siguiente arreglo contiene una cadena un nuacutemero de puntoflotante un entero y otro arreglo

[spam 20 5 [10 20]]

Se dice que un arreglo dentro de otro arreglo estaacute anidado

Un arreglo que no contiene elementos se llama arreglo vaciacuteo y se puede crearuno con corchetes vaciacuteos []

Como es de esperar se pueden asignar valores de arreglos a variables

juliagt quesos = [Cheddar Edam Gouda]

juliagt numeros = [42 123]

juliagt vacio = []

juliagt print(quesos numeros vacio)[Cheddar Edam Gouda] [42 123] Any[]

La funcioacuten typeof se puede usar para conocer el tipo del arreglo

122 Capiacutetulo 10 Arreglos

juliagt typeof(quesos)ArrayString1juliagt typeof(numeros)ArrayInt641juliagt typeof(vacio)ArrayAny1

El tipo del arreglo se especifica entre llaves y se compone de un tipo y unnuacutemero El nuacutemero indica las dimensiones El conjunto vaciacuteo contiene valores detipo Any es decir puede contener valores de todos los tipos

Los arreglos son mutablesLa sintaxis para acceder a los elementos de un arreglo es el mismo que paraacceder a los caracteres de una cadena el operador corchete La expresioacutendentro de los corchetes especifica el iacutendice Recuerde que los iacutendices comienzanen 1

juliagt quesos[1]Cheddar

A diferencia de las cadenas los arreglos son mutables lo que significa quepodemos cambiar sus elementos Se puede modificar uno de sus elementosusando el operador corchetes en el lado izquierdo de una asignacioacuten

juliagt numeros[2] = 55juliagt print(numeros)[42 5]

El segundo elemento de numeros que era 123 ahora es 5

Figura 11 muestra los diagramas de estado para quesos numeros y vacio

Figura 11 Diagrama de estado

Los arreglos son representados mediante cuadros con elementos del arreglo en

Los arreglos son mutables 123

su interior El arreglo quesos hace referencia a un arreglo con tres elementosindexados 1 2 y 3 El arreglo numeros contiene dos elementos El diagramamuestra que el valor del segundo elemento de numeros se ha reasignado de 123a 5 Finalmente vacio hace referencia a un arreglo sin elementos

Los iacutendices de un arreglo funcionan de la misma manera que los iacutendices de unacadena (pero sin los problemas generados por la codificacioacuten UTF-8)

bull Cualquier expresioacuten entera se puede usar como iacutendice

bull Si se intenta leer o escribir un elemento que no existe se obtiene unBoundsError

bull La palabra reservada end indica el uacuteltimo iacutendice del arreglo

El operador isin tambieacuten funciona en arreglos

juliagt Edam isin quesostruejuliagt Brie in quesosfalse

Recorriendo un ArregloLa forma maacutes comuacuten de recorrer los elementos de un arreglo es con un ciclo forLa sintaxis es la misma que para las cadenas

for queso in quesos println(queso)end

Esto funciona bien si solo se necesita leer los elementos del arreglo pero si sedesea escribir o actualizar los elementos es necesario utilizar iacutendices Una formacomuacuten de hacerlo es usando la funcioacuten integrada eachindex

for i in eachindex(numeros) numeros[i] = numeros[i] 2end

Este bucle recorre el arreglo y actualiza cada elemento En cada iteracioacuten delciclo i representa el iacutendice del elemento actual La sentencia de asignacioacuten usanumeros[i] para leer el valor original del elemento y asignar el nuevo valor

Por otra parte length devuelve el nuacutemero de elementos en el arreglo

Un ciclo for sobre un arreglo vaciacuteo nunca ejecuta el cuerpo del bucle

124 Capiacutetulo 10 Arreglos

for x in [] println(Esto nunca pasa)end

Aunque un arreglo puede contener otro arreglo este arreglo anidado cuentacomo un elemento uacutenico Por ejemplo la longitud de este arreglo es cuatro

[spam 1 [Brie Roquefort Camembert] [1 2 3]]

Porciones de arreglos

El operador porcioacuten tambieacuten funciona en arreglos

juliagt t = [a b c d e f]

juliagt print(t[13])[a b c]juliagt print(t[3end])[c d e f]

El operador porcioacuten [] hace una copia de todo el arreglo

juliagt print(t[])[a b c d e f]

Como los arreglos son mutables es uacutetil hacer una copia antes de realizaroperaciones que las modifiquen

Un operador porcioacuten en el lado izquierdo de una asignacioacuten puede actualizarvarios elementos

juliagt t[23] = [x y]

juliagt print(t)[a x y d e f]

Libreriacutea de ArreglosJulia tiene funciones integradas que operan en arreglos Por ejemplo pushagrega un nuevo elemento al final de un arreglo

Porciones de arreglos 125

juliagt t = [a b c]

juliagt push(t d)

juliagt print(t)[a b c d]

append agrega elementos de un arreglo al final de otro

juliagt t1 = [a b c]

juliagt t2 = [d e]

juliagt append(t1 t2)

juliagt print(t1)[a b c d e]

En este ejemplo t2 no es modificado

sort ordena los elementos de un arreglo de menor a mayor

juliagt t = [d c e b a]

juliagt sort(t)

juliagt print(t)[a b c d e]

sort devuelve una copia ordenada de los elementos de un arreglo

juliagt t1 = [d c e b a]

juliagt t2 = sort(t1)

juliagt print(t1)[d c e b a]juliagt print(t2)[a b c d e]

NOTA Como convencioacuten en Julia se agrega a los nombres de lasfunciones que modifican sus argumentos

126 Capiacutetulo 10 Arreglos

Mapear Filtrar y ReducirPara sumar todos los nuacutemeros en un arreglo se puede usar un ciclo como este

function sumartodo(t) total = 0 for x in t total += x end totalend

total se inicializa en 0 En cada iteracioacuten con += se antildeade un elemento delarreglo a la suma total El operador += es una forma simple de actualizar estavariable Esta sentencia de asignacioacuten aumentada

total += x

es equivalente a

total = total + x

A medida que se ejecuta el ciclo total acumula la suma de los elementos A vecesse denomina acumulador a una variable utilizada de esta manera

Sumar los elementos de un arreglo es una operacioacuten tan comuacuten que Julia tieneuna funcioacuten integrada para ello sum

juliagt t = [1 2 3 4]

juliagt sum(t)10

Una operacioacuten como esta que combina una secuencia de elementos en un solovalor a veces se denomina operacioacuten de reduccioacuten

Es comuacuten querer recorrer un arreglo mientras se construye otro Por ejemplo lasiguiente funcioacuten toma un arreglo de cadenas y devuelve un nuevo arreglo quecontiene las mismas cadenas pero en mayuacutesculas

Mapear Filtrar y Reducir 127

function todoenmayusculas(t) res = [] for s in t push(res uppercase(s)) end resend

res se inicializa con un arreglo vaciacuteo y en cada iteracioacuten se le agrega un nuevoelemento De esta manera res es otro tipo de acumulador

Una operacioacuten como todoenmayusculas a veces se denomina mapeo porqueasigna una funcioacuten (en este caso uppercase) a cada uno de los elementos deuna secuencia

Otra operacioacuten comuacuten es seleccionar solo algunos de los elementos de un arregloy devolver una sub-arreglo Por ejemplo la siguiente funcioacuten toma un arreglo decadenas y devuelve un arreglo que contiene solamente las cadenas enmayuacutesculas

function solomayusculas(t) res = [] for s in t if s == uppercase(s) push(res s) end end resend

Operaciones como solomayusculas se llaman filtro porque seleccionan soloalgunos elementos filtrando otros

Las operaciones de arreglos maacutes comunes son una combinacioacuten de mapeo filtroy reduccioacuten

Sintaxis de puntoPara cada operador binario como por ejemplo ^ existe un operador puntocorrespondiente ^ que automaacuteticamente define la operacioacuten ^ para cadaelemento de un arreglo Por ejemplo [1 2 3] ^ 3 no estaacute definido pero [12 3] ^ 3 se define como el resultado de realizar la operacioacuten ^ en cadaelemento [1^3 2^3 3^3]

128 Capiacutetulo 10 Arreglos

juliagt print([1 2 3] ^ 3)[1 8 27]

Cualquier funcioacuten f de Julia puede ser aplicada a cada elemento de cualquierarreglo con la sintaxis de punto Por ejemplo para poner en mayuacutesculas unarreglo de cadenas no es necesario un bucle expliacutecito

juliagt t = uppercase([abc def ghi])

juliagt print(t)[ABC DEF GHI]

Esta es una forma elegante de crear un mapeo Siguiendo esta loacutegica la funcioacutentodoenmayusculas puede implementarse con una liacutenea

function todoenmayusculas(t) uppercase(t)end

Borrando (Insertando) ElementosHay varias formas de eliminar elementos de un arreglo Si se conoce el iacutendice delelemento que se desea eliminar se puede usar splice

juliagt t = [a b c]

juliagt splice(t 2)b ASCIIUnicode U+0062 (category Ll Letter lowercase)juliagt print(t)[a c]

splice modifica el arreglo y devuelve el elemento que se eliminoacute

pop elimina y devuelve el uacuteltimo elemento

juliagt t = [a b c]

juliagt pop(t)c ASCIIUnicode U+0063 (category Ll Letter lowercase)juliagt print(t)[a b]

popfirst elimina y devuelve el primer elemento

Borrando (Insertando) Elementos 129

juliagt t = [a b c]

juliagt popfirst(t)a ASCIIUnicode U+0061 (category Ll Letter lowercase)juliagt print(t)[b c]

Las funciones pushfirst y push insertan un elemento al principio y al final delarreglo respectivamente

Si no se necesita el valor eliminado se puede usar la funcioacuten deleteat

juliagt t = [a b c]

juliagt print(deleteat(t 2))[a c]

La funcioacuten insert inserta un elemento en un iacutendice dado

juliagt t = [a b c]

juliagt print(insert(t 2 x))[a x b c]

Arreglos y CadenasUna cadena es una secuencia de caracteres y un arreglo es una secuencia devalores pero un arreglo de caracteres no es lo mismo que una cadena Paraconvertir una cadena a un arreglo de caracteres se puede usar la funcioacutencollect

juliagt t = collect(spam)

juliagt print(t)[s p a m]

La funcioacuten collect divide una cadena u otra secuencia en elementos individuales

Si desea dividir una cadena en palabras puede usar la funcioacuten split

juliagt t = split(En un lugar de la Mancha)

juliagt print(t)SubStringString[En un lugar de la Mancha]

130 Capiacutetulo 10 Arreglos

Un argumento opcional llamado delimitador especifica queacute caracteres usar comoliacutemites de palabra El siguiente ejemplo usa un guioacuten como delimitador

juliagt t = split(hola-hola-hola -)

juliagt print(t)SubStringString[hola hola hola]

join es el inverso de split Toma un arreglo de cadenas y concatena loselementos

juliagt t = [En un lugar de la Mancha]

juliagt s = join(t )En un lugar de la Mancha

En este caso el delimitador es un caraacutecter de espacio en blanco Para concatenarcadenas sin espacios no especifique un delimitador

Objeto y ValoresUn objeto es algo a lo que una variable puede referirse Hasta ahora podriacutea usarobjeto y valor indistintamente

Si ejecutamos estas sentencias de asignacioacuten

a = bananab = banana

Se sabe que a y b apuntan a una cadena pero no se sabe si estaacuten apuntando a lamisma cadena Hay dos estados posibles los cuales se muestran en la Figura 10-2

Figura 12 Diagramas de estado

En un caso a y b se refieren a dos objetos diferentes que tienen el mismo valorEn el segundo caso se refieren al mismo objeto

Para verificar si dos variables se refieren al mismo objeto se puede usar eloperador equiv (equiv TAB)) o ===

Objeto y Valores 131

juliagt a = bananabananajuliagt b = bananabananajuliagt a equiv btrue

En este ejemplo Julia solo creoacute un objeto de cadena y ambas variables a y bapuntan a ella Pero cuando se crean dos arreglos se obtienen dos objetos

juliagt a = [1 2 3]

juliagt b = [1 2 3]

juliagt a equiv bfalse

Entonces el diagrama de estado se ve asiacute Figura 13

Figura 13 Diagrama de estado

En este caso se podriacutea decir que los dos arreglos son equivalentes porquetienen los mismos elementos pero no ideacutenticos ya que no son el mismo objetoSi dos objetos son ideacutenticos tambieacuten son equivalentes pero si son equivalentesno son necesariamente ideacutenticos

Para ser precisos un objeto tiene un valor Si se evaluacutea [1 2 3] se obtendraacute unobjeto arreglo cuyo valor es una secuencia de enteros Si otro arreglo tiene losmismos elementos se dice que tiene el mismo valor pero no es el mismo objeto

Alias (poner sobrenombres)Si a apunta a un objeto y se asigna b = a entonces ambas variables se refierenal mismo objeto

juliagt a = [1 2 3]

juliagt b = a

juliagt b equiv atrue

El diagrama de estado seriacutea como este Figura 14

132 Capiacutetulo 10 Arreglos

Figura 14 Diagrama de estado

La asociacioacuten de una variable con un objeto se llama referencia En este ejemplohay dos referencias al mismo objeto

Un objeto con maacutes de una referencia tiene maacutes de un nombre por lo quedecimos que el objeto tiene un alias

Si el objeto con alias es mutable los cambios hechos a un alias afectan al otro

juliagt b[1] = 4242juliagt print(a)[42 2 3]

AVISOAunque este comportamiento puede ser uacutetil a veces puede inducira errores En general es maacutes seguro evitar los alias cuando setrabaje con objetos mutables

No hay problema con los alias al trabajar con objetos inmutables tales comocadenas de texto En este ejemplo

a = bananab = banana

Casi nunca es relevante que a y b se refieran a la misma cadena o no

Arreglos como argumentosCuando se pasa un arreglo como argumento de una funcioacuten en realidad se pasauna referencia a ella Si la funcioacuten modifica el arreglo el que hizo la llamadaveraacute el cambio Por ejemplo la funcioacuten borrarprimero elimina el primer elementode un arreglo

function borrarprimero(t) popfirst(t)end

Aquiacute se aprecia el uso de borrarprimero

Arreglos como argumentos 133

juliagt letras = [a b c]

juliagt borrarprimero(letras)

juliagt print(letras)[b c]

El paraacutemetro t y la variable letras son alias de un mismo objeto El diagrama deestado es asiacute Figura 15

Figura 15 Diagrama de estado

Como el arreglo estaacute compartido por dos marcos se dibuja entre ambos

Es importante distinguir entre operaciones que modifiquen arreglos yoperaciones que creen nuevas arreglos Por ejemplo push modifica un arreglopero vcat crea un nuevo arreglo

Aquiacute hay un ejemplo de push

juliagt t1 = [1 2]

juliagt t2 = push(t1 3)

juliagt print(t1)[1 2 3]

t2 es un alias de t1

Aquiacute hay un ejemplo de vcat

juliagt t3 = vcat(t1 [4])

juliagt print(t1)[1 2 3]juliagt print(t3)[1 2 3 4]

El resultado de vcat es un nuevo arreglo El arreglo original no ha sufridocambios

Esta diferencia es importante al momento de escribir funciones que modificanarreglos

134 Capiacutetulo 10 Arreglos

Por ejemplo esta funcioacuten no elimina el primer elemento de un arrreglo

function noborrarprimero(t) t = t[2end] MALOend

El operador porcioacuten crea un nuevo arreglo y la asignacioacuten hace que t se refiera aella pero eso no afecta al arreglo t fuera de la funcioacuten

juliagt t4 = noborrarprimero(t3)

juliagt print(t3)[1 2 3 4]juliagt print(t4)[2 3 4]

Al comienzo de noborrarprimero t y t3 se refieren al mismo arreglo Al final t serefiere a un nuevo arreglo pero t3 todaviacutea se refiere al arreglo original nomodificado

Una alternativa es escribir una funcioacuten que cree y devuelva un nuevo arregloPor ejemplo la funcioacuten cola devuelve todos menos el primer elemento de unarreglo

function cola(t) t[2end]end

Esta funcioacuten no modifica el arreglo original y se usa de la siguiente manera

juliagt letras = [a b c]

juliagt demas = cola(letras)

juliagt print(demas)[b c]

DepuracioacutenUn uso inadecuado de los arreglos (y otros objetos mutables) puede llevar alargas horas de depuracioacuten A continuacioacuten se muestran algunos errorescomunes y coacutemo evitarlos

bull La mayoriacutea de las funciones que operan en arreglos modifican el argumentoEsto es lo opuesto a lo que ocurre en las funciones que operan en cadenas

Depuracioacuten 135

de texto que devuelven una nueva cadena y dejan la original sinmodificaciones

Si estaacute acostumbrado a escribir coacutedigo con cadenas de texto como este

nueva_palabra = strip(palabra)

Puede parecer tentador escribir coacutedigo con arreglos como este

t2 = sort(t1)

Pero como sort devuelve el arreglo original t1 modificado t2 es un alias det1

OBSERVACIOacuteN

Antes de utilizar funciones y operadores dearreglos debe leer la documentacioacutendetenidamente y luego probarla en modointeractivo

bull Escoja una expresioacuten y queacutedese con ella

Parte del problema con los arreglos es que hay demasiadas formas de hacerlas cosas Por ejemplo para eliminar un elemento de un arreglo se puedeusar pop popfirst delete_at o incluso una asignacioacuten de porcioacuten Paraagregar un elemento se puede usar push pushfirst insert or vcatSuponiendo que t es un arreglo y x es un elemento estas formas soncorrectas

insert(t 4 x)push(t x)append(t [x])

Y estas incorrectas

insert(t 4 [x]) MALOpush(t [x]) MALOvcat(t [x]) MALO

bull Haga copias para evitar usar alias

Si se desea utilizar una funcioacuten como sort que modifica el argumento perotambieacuten se necesita mantener el arreglo original es posible hacer unacopia

136 Capiacutetulo 10 Arreglos

juliagt t = [3 1 2]

juliagt t2 = t[] t2 = copy(t)

juliagt sort(t2)

juliagt print(t)[3 1 2]juliagt print(t2)[1 2 3]

En este ejemplo tambieacuten podriacutea usar la funcioacuten incorporada sort quedevuelve un nuevo arreglo ordenado y no modifica el original

juliagt t2 = sort(t)

juliagt println(t)[3 1 2]juliagt println(t2)[1 2 3]

Glosarioarreglo

Una secuencia de valores

elementoUno de los valores de un arreglo (u otra secuencia) tambieacuten llamado iacutetem

lista anidadaUn arreglo que es elemento de otro arreglo

acumuladorUna variable utilizada en un ciclo para sumar o acumular un resultado

asignacioacuten aumentadaUna sentencia que actualiza el valor de una variable usando un operadorcomo +=

operador puntoOperador binario que se aplica a cada elemento de un arreglo

Glosario 137

sintaxis de puntoSintaxis utilizada para aplicar una funcioacuten a todos los elementos decualquier arreglo

operacioacuten de reduccioacutenUn patroacuten de procesamiento que recorre una secuencia y acumula loselementos en un solo resultado

mapeoUn patroacuten de procesamiento que recorre una secuencia y realiza unaoperacioacuten en cada elemento

filtroUn patroacuten de procesamiento que recorre una secuencia y selecciona loselementos que satisfacen alguacuten criterio

objetoUna cosa a la que se puede referir una variable Un objeto tiene tipo y valor

equivalenteTener el mismo valor

ideacutenticoSer el mismo objeto (lo que implica equivalencia)

referenciaLa asociacioacuten entre una variable y su valor

aliasMuacuteltiples variables que contienen referencias al mismo objeto

argumentos opcionalesArgumentos que no son necesarios

delimitadorUn caraacutecter o cadena utilizado para indicar donde debe cortarse unacadena

Ejercicios

estaordenada (generic function with 1 method)

138 Capiacutetulo 10 Arreglos

Ejercicio 10-1

Escriba una funcioacuten llamada sumaanidada que tome un arreglo de arreglos deenteros y sume los elementos de todos los arreglos anidados Por ejemplo

juliagt t = [[1 2] [3] [4 5 6]]

juliagt sumaanidada(t)21

Ejercicio 10-2

Escriba una funcioacuten llamada sumaacumulada que tome un arreglo de nuacutemeros ydevuelva la suma acumulativa es decir un nuevo arreglo donde el eacutesimoelemento es la suma de los primeros elementos del arreglo original Porejemplo

juliagt t = [1 2 3]

juliagt print(sumaacumulada(t))Any[1 3 6]

Ejercicio 10-3

Escriba una funcioacuten llamada interior que tome un arreglo y devuelva un nuevoarreglo que contenga todos los elementos excepto el primero y el uacuteltimo Porejemplo

juliagt t = [1 2 3 4]

juliagt print(interior(t))[2 3]

Ejercicio 10-4

Escriba una funcioacuten llamada interior que tome un arreglo lo modifiqueeliminando el primer y el uacuteltimo elemento y que no devuelva un valor Porejemplo

Ejercicios 139

juliagt t = [1 2 3 4]

juliagt interior(t)

juliagt print(t)[2 3]

Ejercicio 10-5

Escriba una funcioacuten llamada estaordenada que tome un arreglo como paraacutemetroy devuelva true si el arreglo se ordena en orden ascendente y false de locontrario Por ejemplo

juliagt estaordenada([1 2 2])truejuliagt estaordenada([b a])false

Ejercicio 10-6

Dos palabras son anagramas si se pueden ordenar las letras de una para escribirla otra Escriba una funcioacuten llamada esanagrama que tome dos cadenas ydevuelva true si son anagramas

Ejercicio 10-7

Escriba una funcioacuten llamada repetido que tome un arreglo y devuelva true si hayalguacuten elemento que aparece maacutes de una vez No debe modificar el arreglooriginal

Ejercicio 10-8

Este ejercicio se relaciona con la llamada paradoja del cumpleantildeos sobre la cualpuede leer en httpseswikipediaorgwikiParadoja_del_cumpleaC3B1os

Si hay 23 estudiantes en su clase iquestcuaacuteles son las posibilidades de que dos deustedes tengan el mismo cumpleantildeos Puede estimar esta probabilidadgenerando muestras aleatorias de 23 cumpleantildeos y buscando coincidencias

OBSERVACIOacuteN Puede generar cumpleantildeos aleatorios con rand(1365)

Ejercicio 10-9

Escriba una funcioacuten que lea el archivo palabrastxt y construya un arreglo con unelemento por palabra Escriba dos versiones de esta funcioacuten una con push y la

140 Capiacutetulo 10 Arreglos

otra con la expresioacuten t = [t x] iquestCuaacutel tarda maacutes en ejecutarse iquestPor queacute

Ejercicio 10-10

Para verificar si una palabra estaacute en el arreglo de palabras se puede usar eloperador isin Esto seriacutea lento pues este operador busca las palabras en orden

Debido a que las palabras estaacuten en orden alfabeacutetico se puede acelerar laverificacioacuten con una buacutesqueda de biseccioacuten (tambieacuten conocida como buacutesquedabinaria) que es similar a lo que se hace cuando se busca una palabra en eldiccionario Se comienza en el medio y se verifica si la palabra que se estaacutebuscando va antes que la palabra localizada en el medio Si es asiacute se busca en laprimera mitad de la matriz de la misma manera De lo contrario se busca en lasegunda mitad

En ambos casos se reduce el espacio de buacutesqueda restante a la mitad Si elarreglo de palabras tiene 113809 palabras se necesitaraacuten unos 17 pasos paraencontrar la palabra o concluir que no estaacute alliacute

Escriba una funcioacuten llamada enbiseccion que tome un arreglo ordenado y unvalor objetivo y devuelva true si la palabra estaacute en el arreglo y false si no lo estaacute

Ejercicio 10-11

Dos palabras son un par inverso si cada una es la inversa de la otra Escriba unprograma llamado parinverso que encuentre todos los pares inversos en elarreglo de palabras

Ejercicio 10-12

Dos palabras se entrelazan si al tomar letras alternando entre cada palabra seforma una nueva palabra Por ejemplo pi y as se entrelazan para formarpais

Creacutedito Este ejercicio estaacute inspirado en un ejemplo de httppuzzlersorg

1 Escriba un programa que encuentre todos los pares de palabras que seentrelazan

OBSERVACIOacuteN iexclNo enumere todos los pares

2 iquestPuede encontrar tres palabras que se entrelacen es decir cada terceraletra forma una palabra empezando de la primera segunda o tercera letrade la palabra

Ejercicios 141

Capiacutetulo 11 DiccionariosEste capiacutetulo presenta otro tipo integrado llamado diccionario

Un Diccionario es un MapeoUn diccionario es como una matriz pero maacutes general En una matriz los iacutendicestienen que ser enteros en un diccionario pueden ser (casi) de cualquier tipo

Un diccionario contiene una coleccioacuten de iacutendices llamados claves y unacoleccioacuten de valores Cada clave estaacute asociada a un solo valor La asociacioacutenentre una clave y un valor se denomina par clave-valor o a veces item

En lenguaje matemaacutetico un diccionario representa un mapeo de las claves a losvalores es decir cada clave apunta a un valor A modo de ejemplo se crea undiccionario que asocia palabras en espantildeol con palabras en ingleacutes En estediccionario las claves y los valores son cadenas

La funcioacuten Dict crea un nuevo diccionario sin elementos Como Dict es el nombrede una funcioacuten integrada de Julia debe evitar usarla como nombre de variable

juliagt ing_a_esp = Dict()DictAnyAny()

El tipo de este diccionario estaacute compuesto por el tipo de las claves y de losvalores entre llaves En este caso las claves y los valores son de tipo Any

El diccionario estaacute vaciacuteo Para agregar elementos a eacutel se pueden usar corchetes

juliagt ing_a_esp[one] = uno

Esta liacutenea de coacutedigo crea un elemento con la clave one que apunta al valoruno Si se imprime el diccionario nuevamente se ve un par clave-valor con unaflecha =gt entre la clave y el valor

juliagt ing_a_espDictAnyAny with 1 entry one =gt uno

Este formato de salida tambieacuten es un formato de entrada Por ejemplo se puedecrear un nuevo diccionario con tres iacutetems de la siguiente manera

142 Capiacutetulo 11 Diccionarios

juliagt ing_a_esp = Dict(one =gt uno two =gt dos three =gt tres)DictStringString with 3 entries two =gt dos one =gt uno three =gt tres

Todas las claves y valores iniciales son cadenas por lo que se crea unDictStringString

AVISO

El orden de los pares clave-valor podriacutea no ser el mismo Siescribe el mismo ejemplo en su computadora podriacutea obtener unresultado diferente En general el orden de los elementos en undiccionario es impredecible

Esto no significa un problema ya que los elementos de un diccionario nunca seindexan con iacutendices enteros En lugar de ello se utilizan las claves para buscarlos valores correspondientes

juliagt ing_a_esp[two]dos

La clave two da el valor dos asiacute que el orden de los iacutetems no importa

Si la clave no estaacute en el diccionario se da un mensaje de error

juliagt ing_a_esp[four]ERROR KeyError key four not found

La funcioacuten length tambieacuten funciona con diccionarios y devuelve el nuacutemero depares clave-valor

juliagt length(ing_a_esp)3

La funcioacuten keys devuelve una coleccioacuten con las claves del diccionario

juliagt ks = keys(ing_a_esp)

juliagt print(ks)[two one three]

Tambieacuten se puede usar el operador isin para ver si algo es una clave en undiccionario

Un Diccionario es un Mapeo 143

juliagt one isin kstruejuliagt uno isin ksfalse

Para ver si algo es un valor en un diccionario se puede usar la funcioacuten valuesque devuelve una coleccioacuten de valores y luego usar el operador isin

juliagt vs = values(ing_a_esp)

juliagt uno isin vstrue

El operador isin utiliza diferentes algoritmos para matrices y diccionarios Para lasmatrices busca los elementos de la matriz en orden como en Seccioacuten 88 Eltiempo de buacutesqueda es directamente proporcional al largo de la matriz

Para los diccionarios Julia usa un algoritmo llamado tabla hash que tiene unapropiedad importante el operador isin toma aproximadamente la misma cantidadde tiempo sin importar cuaacutentos elementos haya en el diccionario

Diccionario como una Coleccioacuten de FrecuenciasSuponga que tiene una cadena y desea contar cuaacutentas veces aparece cada letraHay varias formas de hacerlo

bull Podriacutea crear 27 variables una para cada letra del alfabeto Luego recorrerla cadena y para cada caraacutecter incrementar el contador correspondienteprobablemente utilizando condiciones encadenadas

bull Podriacutea crear una matriz con 27 elementos Luego podriacutea convertir cadacaraacutecter en un nuacutemero (usando la funcioacuten integrada Int) usar el nuacutemerocomo iacutendice en la matriz e incrementar el contador apropiado

bull Puede crear un diccionario con caracteres como claves y contadores comolos valores correspondientes La primera vez que vea un caraacutecter agregariacuteaun elemento al diccionario Despueacutes de eso incrementariacutea el valor de unelemento existente

Cada una de estas opciones realiza el mismo caacutelculo pero la implementacioacuten esdiferente

Una implementacioacuten es una forma de realizar un caacutelculo Algunasimplementaciones son mejores que otras por ejemplo una ventaja de laimplementacioacuten del diccionario es que no hace falta saber de antemano queacuteletras aparecen en la cadena y solo hay que agregar las letras que aparecen

144 Capiacutetulo 11 Diccionarios

Asiacute es como se veriacutea el coacutedigo

function histograma(s) d = Dict() for c in s if c notin keys(d) d[c] = 1 else d[c] += 1 end end dend

La funcioacuten se llama histograma que es un teacutermino en estadiacutestica para unacoleccioacuten de frecuencias (o conteos)

La primera liacutenea de la funcioacuten crea un diccionario vaciacuteo El ciclo for recorre lacadena s En cada iteracioacuten de este ciclo si el caraacutecter c no estaacute en eldiccionario se crea un nuevo elemento con la clave c y el valor inicial 1 (ya quehemos visto esta letra una vez) Si c ya estaacute en el diccionario se incrementa d[c]

Asiacute es como funciona

juliagt h = histograma(brontosaurus)DictAnyAny with 8 entries n =gt 1 s =gt 2 a =gt 1 r =gt 2 t =gt 1 o =gt 2 u =gt 2 b =gt 1

El histograma indica que las letras a y b aparecen una vez o aparece dosveces y asiacute sucesivamente

Los diccionarios tienen una funcioacuten llamada get que toma como argumentos undiccionario una clave y un valor predeterminado Si la clave aparece en eldiccionario get devuelve el valor correspondiente de lo contrario devuelve elvalor predeterminado Por ejemplo

Diccionario como una Coleccioacuten de Frecuencias 145

juliagt h = histograma(a)DictAnyAny with 1 entry a =gt 1juliagt get(h a 0)1juliagt get(h b 0)0

Ejercicio 11-1

Use get para escribir la funcioacuten histograma de manera maacutes concisa Deberiacuteapoder eliminar la declaracioacuten if

Iteracioacuten y DiccionariosEs posible recorrer las claves del diccionario con un ciclo for Por ejemploimprimirhist imprime cada clave y su valor correspondiente

function imprimirhist(h) for c in keys(h) println(c h[c]) endend

Asiacute es como se ve la salida

juliagt h = histograma(perros)

juliagt imprimirhist(h)s 1e 1p 1r 2o 1

Nuevamente las claves no estaacuten en un orden particular Para recorrer las clavesen orden puede usar sort y collect

146 Capiacutetulo 11 Diccionarios

juliagt for c in sort(collect(keys(h))) println(c h[c]) ende 1o 1p 1r 2s 1

Buacutesqueda inversaDado un diccionario d y una clave k es faacutecil encontrar el valor correspondiente v= d[k] Esta operacioacuten se llama buacutesqueda

Pero iquestqueacute pasa si se tiene v y se quiere encontrar k Existen dos problemasprimeramente puede haber maacutes de una clave que apunta al valor v Dependiendode lo que se quiera es posible que se pueda elegir una de estas claves o que setenga que hacer una matriz que las contenga a todas En segundo lugar no hayuna sintaxis simple para hacer una buacutesqueda inversa solo se debe buscar

A continuacioacuten se muestra una funcioacuten que toma un valor y que devuelve laprimera clave que apunta a ese valor

function busquedainversa(d v) for k in keys(d) if d[k] == v return k end end error(Error de Busqueda)end

Esta funcioacuten es otro ejemplo del patroacuten de buacutesqueda pero utiliza una funcioacutenque no hemos visto antes error La funcioacuten error se usa para producir unErrorException que interrumpe el flujo normal En este caso tiene el mensajeError de Busqueda que indica que no existe una clave

Si llega al final del ciclo eso significa que v no aparece en el diccionario como unvalor por lo que se produce una excepcioacuten

A continuacioacuten se muestra un ejemplo de una buacutesqueda inversa exitosa

juliagt h = histograma(perros)

juliagt key = busquedainversa(h 2)r ASCIIUnicode U+0072 (category Ll Letter lowercase)

Buacutesqueda inversa 147

y una no exitosa

juliagt key = busquedainversa(h 3)ERROR Error de Busqueda

El efecto cuando generamos una excepcioacuten es el mismo que cuando Julia generauna se imprime un trazado inverso y un mensaje de error

Julia proporciona una forma optimizada de hacer una buacutesqueda inversafindall(isequal(3)h)

AVISO

Una buacutesqueda inversa es mucho maacutes lenta que una buacutesquedadirecta Si tiene que hacer buacutesquedas inversas con frecuencia o siel diccionario es muy grande el rendimiento de su programa severaacute afectado

Diccionarios y MatricesLas matrices pueden aparecer como valores en un diccionario Por ejemplo si setiene un diccionario que asigna frecuencias a letras y se quiere invertir es decirtener un diccionario que asigne letras a frecuencias Dado que pueden habervarias letras con la misma frecuencia cada valor en el diccionario invertidodeberiacutea ser una matriz de letras

Aquiacute hay una funcioacuten que invierte un diccionario

function invertirdic(d) inverso = Dict() for clave in keys(d) val = d[clave] if val notin keys(inverso) inverso[val] = [clave] else push(inverso[val] clave) end end inversoend

Cada vez que se recorre el bucle se asigna a la variable clave una clave de d y aval el valor correspondiente Si val no estaacute en el diccionario inverso significa queno se ha visto este valor antes por lo que se crea un nuevo item y se inicializacon un singleton (una matriz que contiene un solo elemento) De lo contrario seha visto este valor antes por lo que se agrega la clave correspondiente a lamatriz

148 Capiacutetulo 11 Diccionarios

Aquiacute hay un ejemplo

juliagt hist = histograma(perros)

juliagt inverso = invertirdic(hist)DictAnyAny with 2 entries 2 =gt [r] 1 =gt [s e p o]

Figura 16 Diagrama de estado

Figura 16 es un diagrama de estado que muestra hist e inverso Un diccionariose representa como un cuadro con los pares clave-valor dentro En este libro silos valores son enteros nuacutemeros de punto flotante o cadenas de texto se dibujandentro del cuadro y las matrices (generalmente) se dibujan fuera del cuadrosolo para mantener el diagrama simple

NOTA

Anteriormente se mencionoacute que un diccionario se implementausando una tabla hash (tambieacuten llamada matriz asociativahashing mapa hash tabla de dispersioacuten o tabla fragmentada) locual significa que las claves deben ser hashable

Un hash es una funcioacuten que toma un valor (de cualquier tipo) ydevuelve un entero Los diccionarios usan estos enteros llamadosvalores hash para almacenar y buscar pares clave-valor

PistasSi estuvo jugando con la funcioacuten fibonacci de Seccioacuten 67 es posible que hayanotado que cuanto maacutes grande el argumento que le da maacutes tiempo tarda lafuncioacuten en ejecutarse Maacutes auacuten el tiempo de ejecucioacuten aumenta muyraacutepidamente

Para entender por queacute considere Figura 17 que muestra el graacutefico de llamadaspara la funcioacuten fibonacci con n = 4

Pistas 149

Figura 17 Graacutefico de llamadas

Un graacutefico de llamadas muestra un conjunto de cuadros de funciones con liacuteneasque conectan cada cuadro con los cuadros de las funciones a las que llama En laparte superior del graacutefico fibonacci con n = 4 llama a fibonacci con n = 3 y n =2 A su vez fibonacci con n = 3 llama a fibonacci con n = 2 y n = 1 Y asiacutesucesivamente

Cuente cuaacutentas veces se llama a fibonacci(0) y fibonacci(1) Esta es una solucioacutenineficiente al problema y empeora a medida que el argumento aumenta entamantildeo

Una solucioacuten es llevar un registro de los valores que ya se han calculadoalmacenaacutendolos en un diccionario Un valor que ya ha sido calculado yalmacenado para un uso posterior se le denomina pista Aquiacute hay unaimplementacioacuten de fibonacci con pistas

anteriores = Dict(0=gt0 1=gt1)

function fibonacci(n) if n isin keys(anteriores) return anteriores[n] end res = fibonacci(n-1) + fibonacci(n-2) anteriores[n] = res resend

El diccionario llamado anteriores mantiene un registro de los valores deFibonacci que ya conocemos El programa comienza con dos pares 0corresponde a 1 y 1 corresponde a 1

Siempre que se llama a fibonacci se comprueba si el diccionario contiene elresultado ya calculado Si estaacute ahiacute la funcioacuten puede devolver el valorinmediatamente Si no tiene que calcular el nuevo valor antildeadirlo al diccionario ydevolverlo

150 Capiacutetulo 11 Diccionarios

Si ejecuta esta versioacuten de fibonacci y la compara con la original se daraacute cuentaque es mucho maacutes raacutepida

Variables GlobalesEn el ejemplo anterior el diccionario anteriores se crea fuera de la funcioacuten porlo que pertenece al marco especial llamado Main Las variables en Main a vecesson llamadas globales porque se puede acceder a ellas desde cualquier funcioacutenA diferencia de las variables locales que desaparecen cuando finaliza su funcioacutenlas variables globales existen de una llamada de funcioacuten a la siguiente

Es comuacuten usar variables globales como flags o banderas es decir variablesbooleanas que indican si una condicioacuten es verdadera Por ejemplo algunosprogramas usan una bandera llamada verbosa para controlar el nivel de detalleen la salida

verbose = true

function ejemplo1() if verbosa println(Ejecutando ejemplo1) endend

Si intenta reasignar una variable global se sorprenderaacute El siguiente ejemplotrata de llevar registro sobre si se ha llamado o no a una funcioacuten

ha_sido_llamada = false

function ejemplo2() ha_sido_llamada = true MALOend

Pero si lo ejecuta veraacute que el valor de ha_sido_llamada no cambia El problemaes que ejemplo2 + crea una nueva variable local llamada +ha_sido_llamada Lavariable local desaparece cuando finaliza la funcioacuten y no tiene efecto en lavariable global

Para reasignar una variable global dentro de una funcioacuten debe declarar lavariable global antes de usarla (reasignacioacuten

Variables Globales 151

been_called = false

function ejemplo2() global ha_sido_llamada ha_sido_llamada = trueend

La sentencia global le dice al inteacuterprete algo como esto ldquoEn esta funcioacuten cuandodigo ha_sido_llamada me refiero a la variable global asiacute que no crees unavariable local

A continuacioacuten se muestra un ejemplo que intenta actualizar una variable global

conteo = 0

function ejemplo3() conteo = conteo + 1 MALOend

Si lo ejecuta obtiene

juliagt ejemplo3()ERROR UndefVarError conteo not defined

Julia asume que conteo es local y bajo esa suposicioacuten lo estaacute leyendo antes deescribirlo La solucioacuten nuevamente es declarar conteo como global

conteo = 0

function ejemplo3() global conteo conteo += 1end

Si una variable global se refiere a un valor mutable puede modificar el valor sindeclarar la variable global

anteriores = Dict(0=gt0 1=gt1)

function ejemplo4() anteriores[2] = 1end

Por lo tanto puede agregar eliminar y reemplazar elementos de una matriz

152 Capiacutetulo 11 Diccionarios

global o diccionario pero si desea reasignar la variable debe declararla global

anteriores = Dict(0=gt0 1=gt1)

function ejemplo5() global anteriores anteriores = Dict()end

Para mejorar el rendimiento puede declarar la variable global como constanteCon esto ya no se puede reasignar la variable pero si se refiere a un valormutable siacute se puede modificar el valor

const known = Dict(0=gt0 1=gt1)

function example4() known[2] = 1end

AVISOLas variables globales pueden ser uacutetiles pero si tiene muchas deellas y las modifica con frecuencia pueden dificultar ladepuracioacuten y empeorar el desempentildeo de los programas

DepuracioacutenA medida que trabaja con conjuntos de datos maacutes grandes la depuracioacutenmediante la impresioacuten y verificacioacuten de la salida de manera manual puedetornarse difiacutecil Aquiacute hay algunas sugerencias para depurar grandes conjuntos dedatos

bull Reduzca la entrada

Si es posible reduzca el tamantildeo del conjunto de datos Por ejemplo si elprograma lee un archivo de texto comience con solo las primeras 10 liacuteneaso con el ejemplo maacutes pequentildeo que pueda encontrar que produzca erroresNo debe editar los archivos sino modificar el programa para que solo lea lasprimeras liacuteneas

Si hay un error puede reducir al valor maacutes pequentildeo que manifieste elerror y luego aumentarlo gradualmente a medida que encuentre y corrijaerrores

bull Revisar resuacutemenes y tipos

En lugar de imprimir y verificar todo el conjunto de datos considereimprimir resuacutemenes de los datos Por ejemplo el nuacutemero de elementos en

Depuracioacuten 153

un diccionario o el total de una serie de nuacutemeros

Una causa comuacuten de los errores de tiempo de ejecucioacuten son los valores detipo incorrecto Para depurar este tipo de error generalmente es suficienteimprimir el tipo de un valor

bull Escribir autocomprobaciones

Puede escribir coacutedigo que verifique errores automaacuteticamente Por ejemplosi estaacute calculando el promedio de una matriz de nuacutemeros puede verificarque el resultado no sea mayor que el elemento maacutes grande de la matriz omenor que el maacutes pequentildeo Esto se llama prueba de cordura

Otro tipo de verificacioacuten compara los resultados de dos caacutelculos diferentespara ver si son consistentes Esta se llama prueba de consistencia

bull Formatear la salida

Formatear la salida de depuracioacuten puede hacer que sea maacutes faacutecil detectarun error Vimos un ejemplo en Seccioacuten 69

Nuevamente el tiempo que dedica a construir andamiaje puede reducir eltiempo que dedica a la depuracioacuten

Glosariomapeo

Una relacioacuten en la que cada elemento de un conjunto corresponde a unelemento de otro conjunto

diccionarioUna asignacioacuten de claves a sus valores correspondientes

par clave-valorLa representacioacuten de la asociacioacuten entre una clave y un valor

itemEn un diccionario otro nombre para un par clave-valor

claveUn objeto que aparece en un diccionario como la primera parte de un parclave-valor

valorUn objeto que aparece en un diccionario como la segunda parte de un parclave-valor Este teacutermino es maacutes especiacutefico que nuestro uso previo de lapalabra valor

154 Capiacutetulo 11 Diccionarios

implementacioacutenUna forma de realizar un caacutelculo

tabla hashEl algoritmo utilizado para implementar los diccionarios de Julia

funcioacuten hashUna funcioacuten utilizada por una tabla hash para calcular la ubicacioacuten de unaclave

hashableUn tipo que tiene una funcioacuten hash

buacutesquedaUna operacioacuten sobre un diccionario que toma una clave y encuentra el valorcorrespondiente

buacutesqueda inversaUna operacioacuten sobre un diccionario que toma un valor y encuentra una omaacutes claves que se asignan a eacutel

singletonUna matriz (u otra secuencia) con un solo elemento

graacutefico de llamadaUn diagrama que muestra cada cuadro creado durante la ejecucioacuten de unprograma con una flecha entre cada funcioacuten y sus respectivas funcionesllamadas

pistaValor precalculado y almacenado temporalmente para evitar caacutelculosredundantes

variable globalUna variable definida fuera de una funcioacuten Se puede acceder a las variablesglobales desde cualquier funcioacuten

sentencia globalUna sentencia que declara un nombre de variable global

banderaUna variable booleana utilizada para indicar si una condicioacuten es verdadera

Glosario 155

declaracioacutenUna sentencia como global que le dice al inteacuterprete algo sobre una variable

variable global constanteUna variable global que no se puede reasignar

Ejercicios

Ejercicio 11-2

Escriba una funcioacuten que lea las palabras en palabrastxt y las almacene comoclaves en un diccionario No importa cuaacuteles sean los valores Luego puede usar eloperador isin como una forma raacutepida de verificar si una cadena estaacute en eldiccionario

Si hizo Seccioacuten 101510 puede comparar la velocidad de esta implementacioacutencon el operador array isin y la buacutesqueda binaria

Ejercicio 11-3

Lea la documentacioacuten de la funcioacuten que opera sobre diccionarios get y uacuteselapara escribir una versioacuten maacutes concisa de invertirdic

Ejercicio 11-4

Use pistas en la funcioacuten de Ackermann de Seccioacuten 6112 y vea si esto permiteevaluar la funcioacuten con argumentos de mayor tamantildeo

Ejercicio 11-5

Si hizo Seccioacuten 10157 ya tiene una funcioacuten llamada repetido que toma unamatriz como paraacutemetro y devuelve true si hay alguacuten objeto que aparece maacutes deuna vez en la matriz

Use un diccionario para escribir una versioacuten maacutes raacutepida y simple de repetido

Ejercicio 11-6

Dos palabras son pares desplazados si puede desplazar una de ellas y obtenerla otra (vea desplazarpalabra en Seccioacuten 8155)

Escriba un programa que lea una matriz de palabras y encuentre todos los paresdesplazados

156 Capiacutetulo 11 Diccionarios

Ejercicio 11-7

Aquiacute hay otro Puzzle de Car Talk (httpswwwcartalkcompuzzlerbrowse)

This was sent in by a fellow named Dan OrsquoLeary He came upon a commonone-syllable five-letter word recently that has the following unique propertyWhen you remove the first letter the remaining letters form a homophone ofthe original word that is a word that sounds exactly the same Replace thefirst letter that is put it back and remove the second letter and the result isyet another homophone of the original word And the question is whatrsquos theword

Now Irsquom going to give you an example that doesnrsquot work Letrsquos look at thefive-letter word lsquowrackrsquo W-R-A-C-K you know like to lsquowrack with painrsquo If Iremove the first letter I am left with a four-letter word rsquoR-A-C-Krsquo As inlsquoHoly cow did you see the rack on that buck It must have been a nine-pointerrsquo Itrsquos a perfect homophone If you put the lsquowrsquo back and remove thelsquorrsquo instead yoursquore left with the word lsquowackrsquo which is a real word itrsquos justnot a homophone of the other two words

But there is however at least one word that Dan and we know of which willyield two homophones if you remove either of the first two letters to maketwo new four-letter words The question is whatrsquos the word

You can use the dictionary from Seccioacuten 11101 to check whether a string is inthe word array

OBSERVACIOacuteNTo check whether two words are homophones you canuse the CMU Pronouncing Dictionary You can downloadit from httpwwwspeechcscmueducgi-bincmudict

Write a program that lists all the words that solve the Puzzler

Ejercicios 157

Capiacutetulo 12 TuplasEste capiacutetulo presenta otro tipo integrado las tuplas Luego muestra coacutemo losarreglos los diccionarios y las tuplas funcionan en conjunto Tambieacuten se presentauna caracteriacutestica uacutetil para los arreglos de longitud variable como argumento losoperadores de recopilacioacuten y dispersioacuten

Las Tuplas son ImmutablesUna tupla es una secuencia de valores Estos valores pueden ser de cualquiertipo y estaacuten indexados por enteros por lo que las tuplas son muy parecidas a losarreglos La diferencia maacutes importante es que las tuplas son inmutables y quecada elemento puede tener su propio tipo

Una tupla es una lista de valores separados por comas

juliagt t = a b c d e(a b c d e)

Aunque no es necesario es comuacuten encerrar las tuplas entre pareacutentesis

juliagt t = (a b c d e)(a b c d e)

Para crear una tupla con un solo elemento se debe incluir una coma final

juliagt t1 = (a)(a)juliagt typeof(t1)TupleChar

AVISO

Un valor entre pareacutentesis sin coma no es una tupla

juliagt t2 = (a)a ASCIIUnicode U+0061 (category Ll Letter lowercase)juliagt typeof(t2)Char

Otra forma de crear una tupla es la funcioacuten de tupla integrada en Julia Sinargumento esta funcioacuten crea una tupla vaciacutea

juliagt tuple()()

158 Capiacutetulo 12 Tuplas

Si se tienen muacuteltiples argumentos el resultado es una tupla con los argumentosdados

juliagt t3 = tuple(1 a pi)(1 a π)

Ya que tuple es el nombre de una funcioacuten integrada debe evitar usarla comonombre de variable

La mayoriacutea de los operadores de arreglos tambieacuten sirven en las tuplas Eloperador corchete indexa un elemento

juliagt t = (a b c d e)

juliagt t[1]a ASCIIUnicode U+0061 (category Ll Letter lowercase)

Y el operador porcioacuten selecciona un rango de elementos

juliagt t[24](b c d)

Pero si se intenta modificar uno de los elementos de la tupla se obtendraacute unerror

juliagt t[1] = AERROR MethodError no method matching setindex(NTuple5Char CharInt64)

Como las tuplas son inmutables sus elementos no se pueden modificar

Los operadores relacionales funcionan con las tuplas y otras secuencias Juliacomienza comparando el primer elemento de cada secuencia Si son igualespasa a los siguientes elementos y asiacute sucesivamente hasta que encuentraelementos que difieren Los elementos posteriores no se consideran (incluso sison realmente grandes)

juliagt (0 1 2) lt (0 3 4)truejuliagt (0 1 2000000) lt (0 3 4)true

Las Tuplas son Immutables 159

Asignacioacuten de tuplaDe vez en cuando es uacutetil intercambiar los valores de dos variables Para hacerlocon sentencias de asignacioacuten convencionales se debe usar una variable temporalPor ejemplo para intercambiar a y b

temp = aa = bb = temp

Esta solucioacuten resulta aparatosa La asignacioacuten de tuplas soluciona este problemaelegantemente

a b = b a

El lado izquierdo es una tupla de variables y el lado derecho es una tupla deexpresiones Cada valor se asigna a su respectiva variable Todas las expresionesdel lado derecho se evaluacutean antes de las asignaciones

El nuacutemero de variables de la izquierda tiene que ser menor o igual que el nuacutemerode valores a la derecha

juliagt (a b) = (1 2 3)(1 2 3)juliagt a b c = 1 2ERROR BoundsError attempt to access (1 2) at index [3]

El lado derecho puede ser cualquier tipo de secuencia (cadena arreglo o tupla)Por ejemplo para dividir una direccioacuten de correo electroacutenico en nombre deusuario y dominio se puede escribir

juliagt addr = juliocesarromajuliocesarromajuliagt unombre dominio = split(addr )

El valor de retorno de split es un arreglo con dos elementos el primer elementose asigna a unombre y el segundo a dominio

juliagt unombrejuliocesarjuliagt dominioroma

160 Capiacutetulo 12 Tuplas

Tuplas como valor de retornoEstrictamente hablando una funcioacuten solo puede devolver un valor pero si elvalor es una tupla el efecto es el mismo que devolver muacuteltiples valores Porejemplo si desea dividir dos enteros y calcular el cociente y el resto esineficiente calcular x divide y y luego x y Es mejor calcular ambos al mismotiempo

La funcioacuten integrada divrem toma dos argumentos y devuelve una tupla de dosvalores el cociente y el resto El resultado puede ser almacenado como unatupla

juliagt t = divrem(7 3)(2 1)

Tambieacuten se puede utilizar asignacioacuten de tuplas para almacenar los elementos porseparado

juliagt q r = divrem(7 3)

juliagt show q rq = 2r = 1

Aquiacute hay un ejemplo de una funcioacuten que devuelve una tupla

function minmax(t) minimum(t) maximum(t)end

maximum y minimum son funciones integradas que encuentran los elementosmaacutes grandes y maacutes pequentildeos de una secuencia respectivamente La funcioacutenminmax calcula ambos y devuelve una tupla de dos valores Otra alternativa esutilizar la funcioacuten integrada extrema lo cual es maacutes eficiente

Tupla con Argumentos de Longitud VariableLas funciones pueden tomar un nuacutemero variable de argumentos Un nombre deparaacutemetro que termina con recopila argumentos en una tupla Por ejemploimprimirtodo toma cualquier nuacutemero de argumentos y los imprime

function imprimirtodo(args) println(args)end

Tuplas como valor de retorno 161

El paraacutemetro de recopilacioacuten puede tener cualquier nombre pero la convencioacutenes llamarlo args A continuacioacuten se muestra coacutemo funciona la funcioacuten

juliagt imprimirtodo(1 20 3)(1 20 3)

El opuesto de la recopilacioacuten es la dispersioacuten Si tiene una secuencia de valores ydesea pasarla a una funcioacuten como argumento muacuteltiple puede usar el operador Por ejemplo divrem toma exactamente dos argumentos y no funciona contuplas

juliagt t = (7 3)

juliagt divrem(t)ERROR MethodError no method matching divrem(TupleInt64Int64)

No obstante si dispersamos la tupla funciona

juliagt divrem(t)(2 1)

Muchas de las funciones integradas usan tuplas con argumentos de longitudvariable Por ejemplo max y min pueden tomar cualquier nuacutemero deargumentos

juliagt max(1 2 3)3

Pero sum no

juliagt sum(1 2 3)ERROR MethodError no method matching sum(Int64 Int64 Int64)

Ejercicio 12-1

Escriba una funcioacuten llamada sumartodo que tome cualquier nuacutemero deargumentos y devuelva su suma

En el mundo de Julia generalmente se le llama ldquoslurprdquo (sorber en espantildeol) areunir y splat (plaf en espantildeol como el ruido cuando cae algo) a dispersar

162 Capiacutetulo 12 Tuplas

Arreglos y tuplaszip es una funcioacuten integrada que toma dos o maacutes secuencias y devuelve unacoleccioacuten de tuplas donde cada tupla contiene un elemento de cada secuencia Elnombre de la funcioacuten se refiere a una cremallera que une e intercala dos filas dedientes

Este ejemplo une e intercala una cadena y un arreglo

juliagt s = abc

juliagt t = [1 2 3]

juliagt zip(s t)zip(abc [1 2 3])

El resultado es un objeto zip que permite iterar a traveacutes de los pares El uso maacutescomuacuten de zip es en un bucle for

juliagt for par in zip(s t) println(par) end(a 1)(b 2)(c 3)

Un objeto zip es un tipo de iterador que es cualquier objeto que itera a traveacutes deuna secuencia Los iteradores son en cierto modo similares a los arreglos peroa diferencia de estos uacuteltimos no se puede usar un iacutendice para seleccionar unelemento de un iterador

Si desea usar operadores y funciones de arreglos puede usar un objeto zip parahacer un arreglo

juliagt collect(zip(s t))3-element ArrayTupleCharInt641 (a 1) (b 2) (c 3)

El resultado es una serie de tuplas En este ejemplo cada tupla contiene uncaraacutecter de la cadena y el elemento correspondiente del arreglo

Si las secuencias no tienen la misma longitud el resultado tiene la longitud de lamaacutes corta

Arreglos y tuplas 163

juliagt collect(zip(Juan Gabriel))4-element ArrayTupleCharChar1 (J G) (u a) (a b) (n r)

Se puede usar asignacioacuten de tuplas en un bucle for para recorrer un arreglo detuplas

juliagt t = [(a 1) (b 2) (c 3)]

juliagt for (letra numero) in t println(numero letra) end1 a2 b3 c

En cada iteracioacuten del ciclo Julia selecciona la siguiente tupla en el arreglo yasigna estos elementos a letra y nuacutemero Los pareacutentesis de (letra nuacutemero) sonobligatorios

Combinando zip for y asignacioacuten de tuplas se obtiene una forma para recorrerdos (o maacutes) secuencias al mismo tiempo Por ejemplo la funcioacuten coinciden tomados secuencias t1 y t2 y devuelve true si hay un iacutendice i tal que t1[i] == t2[i]

function coinciden(t1 t2) for (x y) in zip(t1 t2) if x == y return true end end falseend

Si se necesita recorrer los elementos de una secuencia y sus iacutendices se puedeusar la funcioacuten integrada enumerate

juliagt for (indice elemento) in enumerate(abc) println(indice elemento) end1 a2 b3 c

164 Capiacutetulo 12 Tuplas

El resultado de enumerate es un objeto enumerate el cual hace una iteracioacutensobre una secuencia de pares doacutende cada par contiene un iacutendice (a partir de 1) yun elemento de la secuencia dada

Diccionarios y TuplasLos diccionarios se pueden usar como iteradores que iteran sobre los paresclave-valor Puede usarlos en un bucle for como este

juliagt d = Dict(a=gt1 b=gt2 c=gt3)

juliagt for (key value) in d println(key value) enda 1c 3b 2

Como es de esperar en un diccionario los elementos no estaacuten en un ordenparticular

Ahora si se quiere hacer lo contrario se puede usar una serie de tuplas parainicializar un nuevo diccionario

juliagt t = [(a 1) (c 3) (b 2)]

juliagt d = Dict(t)DictCharInt64 with 3 entries a =gt 1 c =gt 3 b =gt 2

Al combinar Dict con zip podemos crear un diccionario de una manera muysimple

juliagt d = Dict(zip(abc 13))DictCharInt64 with 3 entries a =gt 1 c =gt 3 b =gt 2

Es comuacuten usar tuplas como claves en los diccionarios Por ejemplo un directoriotelefoacutenico puede asignar nuacutemeros de teleacutefono a una tupla con apellido y nombreSuponiendo que se ha definido apellido nombre y numero podriacuteamos escribir

Diccionarios y Tuplas 165

directorio[apellido nombre] = numero

La expresioacuten entre pareacutentesis es una tupla Se podriacutea usar asignacioacuten de tuplaspara recorrer este diccionario

for ((apellido nombre) numero) in directorio println(nombre apellido numero)end

Este bucle recorre los pares clave-valor en directorio los cuales son tuplasAsigna los elementos de la clave de cada tupla a apellido y nombre y el valor anumero luego imprime el nombre y el nuacutemero de teleacutefono correspondiente

Hay dos formas de representar tuplas en un diagrama de estado La versioacuten maacutesdetallada muestra los iacutendices y elementos tal como aparecen en un arreglo Porejemplo la tupla (Cortaacutezar Julio) se veriacutea como en Figura 18

Figura 18 Diagrama de estado

Pero en un diagrama maacutes grande es posible que desee omitir algunos detallesPor ejemplo un diagrama del directorio telefoacutenico puede verse como en Figura19

Figura 19 Diagrama de estado

Aquiacute las tuplas se muestran usando la sintaxis de Julia para tener un esquemamaacutes simple El nuacutemero de teleacutefono del diagrama es el nuacutemero de reclamos de laBBC asiacute que no intentes llamar

Secuencias de SecuenciasHasta ahora el capiacutetulo se ha centrado en los arreglos de tuplas pero casi todoslos ejemplos que se han visto tambieacuten funcionan con arreglos de arreglos tuplasde tuplas y tuplas de arreglos Para evitar enumerar todas las posiblescombinaciones a veces es maacutes faacutecil hablar sobre secuencias de secuencias

En muchos contextos los diferentes tipos de secuencias (cadenas arreglos ytuplas) se pueden usar indistintamente Entonces iquestcoacutemo elegir uno u otro

166 Capiacutetulo 12 Tuplas

Para comenzar con lo mas obvio las cadenas son maacutes limitadas que las demaacutessecuencias porque los elementos deben ser caracteres Ademaacutes son inmutablesSi se necesita poder cambiar los caracteres en una cadena (en vez de crear unanueva) puede que lo mas adecuado sea elegir un arreglo de caracteres

Los arreglos se usan con mas frecuencia que las tuplas principalmente porqueson mutables No obstante hay algunos casos donde es posible que seapreferible usar tuplas

bull En algunos contextos como en una sentencia return resultasintaacutecticamente maacutes simple crear una tupla que un arreglo

bull Si se pasa una secuencia como argumento de una funcioacuten el uso de tuplasreduce los comportamientos potencialmente indeseados debido a lacreacioacuten de alias

bull Por rendimiento El compilador puede especializarse en este tipo

Dado que las tuplas son inmutables no tienen funciones como sort y reverseque modifiquen arreglos ya existentes Sin embargo Julia proporciona lasfunciones integradas sort que toma un arreglo y devuelve una secuencia nuevacon los mismos elementos ordenados y reverse que toma cualquier secuencia ydevuelve una secuencia nueva del mismo tipo con los mismos elementos en elorden contrario

DepuracioacutenLos arreglos diccionarios y tuplas son ejemplos de estructuras de datos En estecapiacutetulo se empiezan a ver estructuras de datos compuestas como arreglos otuplas y diccionarios que contienen tuplas como claves y arreglos como valoresLas estructuras de datos compuestas son uacutetiles aunque tambieacuten resultanpropensas a lo que se llaman errores de forma es decir errores causados cuandouna estructura de datos tiene el tipo tamantildeo o estructura incorrecta Porejemplo si estaacute esperando una lista con un entero y se le pasa simplemente unentero (no en una lista) no funcionaraacute

Julia permite antildeadir el tipo a elementos de una secuencia Esto se detalla enCapiacutetulo 17 Especificar el tipo elimina muchos errores de forma

Glosariotupla

Una secuencia inmutable de elementos donde cada elemento puede tener supropio tipo

asignacioacuten en tuplaUna asignacioacuten con una secuencia en el lado derecho y una tupla devariables en el izquierdo Primero se evaluacutea el lado derecho y luego sus

Depuracioacuten 167

elementos son asignados a las variables de la izquierda

reunirLa operacioacuten de armar una tupla con argumentos de longitud variable

dispersarLa operacioacuten de tratar una secuencia como una lista de argumentos

objeto zipEl resultado de llamar a la funcioacuten integrada zip un objeto que itera atraveacutes de una secuencia de tuplas

iteradorUn objeto que puede iterar a traveacutes de una secuencia pero que no tiene losoperadores y funciones de arreglos

estructura de datosUna coleccion de valores relacionados a menudo organizados en arreglosdiccionarios tuplas etc

error de formaUn error causado porque un valor tiene la forma incorrecta es decir el tipoo tamantildeo incorrecto

Ejercicios

Ejercicio 12-2

Escriba una funcioacuten llamada masfrecuente que tome una cadena e imprima lasletras en orden decreciente de frecuencia Encuentre muestras de texto de variosidiomas diferentes y vea coacutemo la frecuencia de las letras variacutea entre idiomasCompare sus resultados con las tablas en httpsenwikipediaorgwikiLetter_frequencies

Ejercicio 12-3

iexclMaacutes anagramas

1 Escriba un programa que lea una lista de palabras de un archivo (veaSeccioacuten 91) e imprima todos los conjuntos de palabras que son anagramas

Aquiacute hay un ejemplo de coacutemo se veriacutea la salida

168 Capiacutetulo 12 Tuplas

[brazo zobra broza zarbo][palabra parlaba][vida diva][gato toga gota]

OBSERVACIOacuteN

Es posible que desee crear un diccionario queasigne a una coleccioacuten de letras una serie depalabras que se puedan deletrear con esas letrasLa pregunta es iquestcoacutemo representar la coleccioacuten deletras de una manera que pueda usarse comoclave

2 Modifique el programa anterior para que imprima primero el arreglo maacuteslargo de anagramas seguido del segundo maacutes larga y asiacute sucesivamente

3 En Scrabble un bingo es cuando juegas las siete fichas de tu atril juntocon una letra del tablero para formar una palabra de ocho letras iquestQueacutecoleccioacuten de 8 letras forman parte del bingo maacutes probable

Ejercicio 12-4

Dos palabras metatizan si se puede transformar una en la otra intercambiandodos letras como es el caso de conversar y conservar Escriba un programaque encuentre todos los pares de metaacutetesis en el diccionario

OBSERVACIOacuteN No pruebe con todos los pares de palabras ni tampococon todos los intercambios posibles

Creacuteditos Este ejercicio estaacute inspirado en un ejemplo de httppuzzlersorg

Ejercicio 12-5

Aquiacute hay otro Puzzle de Car Talk (httpswwwcartalkcompuzzlerbrowse)

Ejercicios 169

iquestCuaacutel es la palabra en espantildeol maacutes larga que sigue siendo una palabra enespantildeol vaacutelida a medida que se eliminan sus letras una a una

Las letras se pueden eliminar de cualquier extremo o del medio pero no sepuede reordenar ninguna de ellas Cada vez que elimina una letra se quedacon otra palabra en espantildeol Eventualmente terminaraacute con una letra la cualtambieacuten seraacute una palabra en espantildeol que puede encontrar en el diccionarioSe desea saber cuaacutel es la palabra maacutes larga y cuaacutentas letras tiene

A modo de ejemplo piense en la palabra Palote iquestDe acuerdo Comienza conpalote elimina la letra p y queda alote luego se quita la t y queda aloe setoma la e y se tiene alo quitando la o se tiene al y finalmente eliminando lal queda a

Escriba un programa que encuentre todas las palabras que se pueden reducir deesta manera y luego encuentre la maacutes larga

OBSERVACIOacuteN

Este ejercicio es un poco maacutes desafiante que el resto asiacuteque aquiacute hay algunas sugerencias

1 Es posible que quiera escribir una funcioacuten que tomeuna palabra y calcule un arreglo de todas laspalabras que se pueden formar al eliminar unaletra Estos son los hijos de la palabra

2 De manera recursiva una palabra es reducible sialguno de sus hijos es reducible Como caso basepuede considerar la cadena vaciacutea reducible

3 La lista de palabras palabrastxt no tiene la cadenavaciacutea por lo que tendraacute que agregarla

4 Para mejorar el rendimiento de su programa esposible que desee guardar las palabras que se sabeque son reducibles

170 Capiacutetulo 12 Tuplas

Capiacutetulo 13 Estudio de Caso Seleccioacuten deEstructura de DatosHasta ahora hemos aprendido sobre las principales estructuras de datos de Juliay hemos visto algunos de los algoritmos que las utilizan

Este capiacutetulo presenta un estudio de caso con ejercicios que le permitenpracticar la eleccioacuten de estructuras de datos y su uso

Anaacutelisis de Frecuencia de PalabrasComo de costumbre se recomienda intentar resolver los ejercicios antes de leerlas soluciones

Ejercicio 13-1

Escriba un programa que lea un archivo divida cada liacutenea en palabras elimine elespacio en blanco y la puntuacioacuten de las palabras y luego las convierta enminuacutesculas

OBSERVACIOacuteN La funcioacuten isletter permite saber si un caraacutecterpertenece al alfabeto

Ejercicio 13-2

Vaya a la paacutegina de Proyecto Gutenberg (httpsgutenbergorg) y descargue sulibro favorito sin derechos de autor en formato de texto plano La mayoriacutea de loslibros estaacuten en ingleacutes pero existen algunos en espantildeol

Modifique su programa del ejercicio anterior para leer el libro que descargoacuteomita la informacioacuten del encabezado al comienzo del archivo y procese el restode las palabras tal como en el ejercicio previo

Luego modifique el programa para contar la cantidad total de palabras en ellibro y la cantidad de veces que se usa cada palabra

Imprima la cantidad de palabras diferentes que se usan en el libro Comparediferentes libros de diferentes autores escritos en diferentes eacutepocas iquestQueacute autorusa un vocabulario maacutes extenso

Ejercicio 13-3

Modifique el programa del ejercicio anterior para imprimir las 20 palabras maacutesutilizadas en el libro

Anaacutelisis de Frecuencia de Palabras 171

Ejercicio 13-4

Modifique el programa anterior para que lea una lista de palabras y luegoimprima todas las palabras del libro que no esteacuten en la lista de palabrasiquestCuaacutentos de ellos son errores tipograacuteficos iquestCuaacutentos de ellos son palabrascomunes que deberiacutean estar en la lista de palabras iquest Cuaacutentos de ellos sonteacuterminos realmente macabros

Nuacutemeros aleatoriosDadas las mismas entradas la mayor parte de los programas generan la mismasalida cada vez que los ejecutamos por lo que se dice que son deterministasNormalmente el determinismo es algo bueno ya que esperamos que un caacutelculonos entregue siempre el mismo resultado Para algunas aplicaciones sinembargo queremos que el computador sea impredecible Por ejemplo en losjuegos entre otros casos

Hacer que un programa sea realmente no determinista resulta difiacutecil pero hayformas de que hacer que al menos parezca no determinista Una de ellas es usaralgoritmos para generar nuacutemeros pseudoaleatorios Los nuacutemerospseudoaleatorios no son verdaderamente aleatorios porque se generan medianteun caacutelculo determinista pero al mirar estos nuacutemeros es casi imposibledistinguirlos de lo aleatorio

La funcioacuten rand devuelve un numero de punto flotante entre 00 y 10(incluyendo 00 pero no 10) Cada vez que usted llama a rand obtiene elsiguiente numero de una larga serie Para ver un ejemplo ejecute este bucle

for i in 110 x = rand() println(x)end

La funcioacuten rand puede tomar un iterador o arreglo como argumento y devuelveun elemento aleatorio de ellos

for i in 110 x = rand(16) print(x )end

Ejercicio 13-5

Escriba una funcioacuten llamada escogerdelhistograma que tome un histogramadefinido como en Seccioacuten 112 y devuelva un valor aleatorio del histogramaelegido con probabilidad proporcional a la frecuencia Por ejemplo para este

172 Capiacutetulo 13 Estudio de Caso Seleccioacuten de Estructura de Datos

histograma

juliagt t = [a a b]

juliagt histograma(t)DictAnyAny with 2 entries a =gt 2 b =gt 1

su funcioacuten debe devolver a con probabilidad y b con probabilidad

Histograma de PalabrasDebe hacer los ejercicios anteriores antes de continuar Tambieacuten necesitaraacutehttpsgithubcomJuliaIntroIntroAJuliajlblobmasterdataDonQuijotetxt

Aquiacute hay un programa que lee un archivo y construye un histograma de laspalabras en el archivo

function procesararchivo(nombrearchivo) hist = Dict() for linea in eachline(nombrearchivo) procesarlinea(linea hist) end histend

function procesarlinea(linea hist) linea = replace(linea - =gt ) for palabra in split(linea) palabra = string(filter(isletter [palabra])) palabra = lowercase(palabra) hist[palabra] = get(hist palabra 0) + 1 endend

Histograma de Palabras 173

DictAnyAny with 23607 entries enojoacute =gt 1 angosta =gt 1 hurto =gt 10 sirviesen =gt 2 solene =gt 1 coronan =gt 1 endereacutecese =gt 2 alteza =gt 15 rescatarlos =gt 1 enderezador =gt 1 libertad =gt 81 abundante =gt 5 bajeza =gt 4 embotoacute =gt 1 estime =gt 1 renovaban =gt 1 acreciente =gt 4 debieron =gt 8 garci =gt 1 ⋮ =gt ⋮

hist = procesararchivo(DonQuijotetxt)

Este programa lee DonQuijotetxt que contiene el texto de Don Quijote deMiguel de Cervantes

procesararchivo recorre las liacuteneas del archivo pasando una liacutenea a la vez aprocesarlinea El histograma hist se estaacute utilizando como acumulador

procesarlinea usa la funcioacuten replace para reemplazar los guiones por espaciosantes de usar split para dividir la liacutenea en un arreglo de cadenas Recorre elconjunto de palabras y usa filter isletter y lowercase para eliminar los signos depuntuacioacuten y convertir las palabras a minuacutesculas (Decir que las cadenas seconvierten es incorrecto recuerde que las cadenas son inmutables por lo queuna funcioacuten como lowercase devuelve cadenas nuevas)

Finalmente procesarlinea actualiza el histograma creando un nuevo elemento oincrementando uno existente

Para contar el nuacutemero total de palabras en el archivo podemos sumar lasfrecuencias en el histograma

function palabrastotales(hist) sum(values(hist))end

174 Capiacutetulo 13 Estudio de Caso Seleccioacuten de Estructura de Datos

El nuacutemero de palabras diferentes es el nuacutemero de elementos en el diccionario

function palabrasdiferentes(hist) length(hist)end

Para imprimir los resultados se puede usar el siguiente coacutedigo

juliagt println(Nuacutemero total de palabras palabrastotales(hist))Nuacutemero total de palabras 385925

juliagt println(Nuacutemero de palabras diferentes palabrasdiferentes(hist))Nuacutemero de palabras diferentes 23607

Observacioacuten No se considera el encabezado del archivo de texto soacutelo el libro

Palabras Maacutes ComunesPara encontrar las palabras maacutes comunes podemos hacer un arreglo de tuplasdonde cada tupla contiene una palabra y su frecuencia y ordenarlas Lasiguiente funcioacuten toma un histograma y devuelve un arreglo de tuplas defrecuencia de palabras

function mascomun(hist) t = [] for (clave valor) in hist push(t (valorclave)) end reverse(sort(t))end

En cada tupla la frecuencia aparece primero por lo que el arreglo resultante seordena por frecuencia A continuacioacuten se muestra un bucle que imprime las 10palabras maacutes comunes

t = mascomun(hist)println(Las palabras maacutes comunes son)for (frec palabra) in t[110] println(palabra t frec)end

En este ejemplo utilizamos un caraacutecter de tabulacioacuten (t) como separador envez de un espacio por lo que la segunda columna estaacute alineada A continuacioacutense muestran los resultados de Don Quijote

Palabras Maacutes Comunes 175

Las palabras maacutes comunes sonque 20626de 18217y 18188la 10363a 9881en 8241el 8210no 6345los 4748se 4690

OBSERVACIOacuteN

Este coacutedigo se puede simplificar usando comoargumento la palabra reservada rev de la funcioacuten sortPuede leer sobre esto en httpsdocsjulialangorgenv1basesortBasesort

Parametros OpcionalesSe han tratado funciones integradas de Julia que toman argumentos opcionalesTambieacuten es posible escribir funciones definidas por el programador conargumentos opcionales Por ejemplo aquiacute hay una funcioacuten que imprime laspalabras maacutes comunes en un histograma

function imprimirmascomun(hist num=10) t = mascomun(hist) println(Las palabras maacutes comunes son ) for (frec palabra) in t[1num] println(palabra t frec) endend

El primer paraacutemetro es obligatorio y el segundo es opcional El valorpredeterminado de num es 10

Si solo pasas un argumento

imprimirmascomun(hist)

num toma el valor predeterminado Si pasas dos argumentos

imprimirmascomun(hist 20)

num toma el valor del argumento En otras palabras el argumento opcional

176 Capiacutetulo 13 Estudio de Caso Seleccioacuten de Estructura de Datos

anula el valor predeterminado

Si una funcioacuten tiene paraacutemetros obligatorios y opcionales los paraacutemetrosobligatorios deben ir primero seguidos de los opcionales

Resta de DiccionarioEncontrar las palabras de un libro que no estaacuten en la lista de palabras depalabrastxt es un problema similar a una resta de conjuntos es decir se quiereencontrar todas las palabras de un conjunto (las palabras en el libro) que noestaacuten en el otro (las palabras en la lista)

resta toma los diccionarios d1 y d2 y devuelve un nuevo diccionario que contienetodas las claves de d1 que no estaacuten en d2 Como realmente no importan losvalores se fijan como nothing

function resta(d1 d2) res = Dict() for clave in keys(d1) if clave notin keys(d2) res[clave] = nothing end end resend

Para encontrar las palabras en el libro que no estaacuten en palabrastxt se ouedeusar procesararchivo para construir un histograma para palabrastxt y luego lafuncioacuten resta

palabras = procesararchivo(palabrastxt)dif = resta(hist palabras)

println(Palabras en el libro que no estaacuten en la lista de palabras)for palabra in keys(dif) print(palabra )end

Estos son algunos de los resultados de Don Quijote

Palabras en el libro que no estaacuten en la lista de palabrasenojoacute angosta coronan sirviesen solene endereacutecese rescatarlos embotoacuteestime renovaban

Algunas de estas palabras son conjugaciones de verbos Otros como solene yano son de uso comuacuten iexclPero algunas son palabras comunes que deberiacutean estar en

Resta de Diccionario 177

la lista

Ejercicio 13-6

Julia proporciona una estructura de datos llamada Set que permite muchasoperaciones comunes de conjuntos Puede leer sobre ellas en Seccioacuten 202 oconsultar la documentacioacuten en httpsdocsjulialangorgenv1basecollectionsSet-Like-Collections-1

Escriba un programa que use la resta de conjuntos para encontrar palabras en ellibro que no estaacuten en la lista de palabras

Palabras al AzarPara elegir una palabra aleatoria del histograma el algoritmo maacutes simple esconstruir un arreglo con muacuteltiples copias de cada palabra de acuerdo con lafrecuencia observada y luego elegir una palabra del arreglo

function palabraalazar(h) t = [] for (palabra frec) in h for i in 1frec push(t palabra) end end rand(t)end

Este algoritmo funciona pero no es muy eficiente ya que cada vez que elige unapalabra aleatoria reconstruye el arreglo que es tan grande como el librooriginal Una mejora es construir el arreglo una vez y luego hacer muacuteltiplesselecciones pero el arreglo sigue siendo grande

Una alternativa es

1 Use las claves para obtener un arreglo de palabras del libro

2 Cree un arreglo que contenga la suma acumulada de las frecuencias depalabras (vea Seccioacuten 10152) El uacuteltimo elemento en este arreglo es elnuacutemero total de palabras en el libro

3 Elija un nuacutemero aleatorio del 1 al Use buacutesqueda binaria (vea Seccioacuten101510) para encontrar el iacutendice donde se insertaraacute el nuacutemero aleatorio enla suma acumulada

4 Use el iacutendice para encontrar la palabra correspondiente en el arreglo depalabras

178 Capiacutetulo 13 Estudio de Caso Seleccioacuten de Estructura de Datos

Ejercicio 13-7

Escriba un programa que use este algoritmo para elegir una palabra aleatoriadel libro

Anaacutelisis de MarkovSi elige palabras del libro al azar puede tener una idea del vocabulario usadopero probablemente no se va a obtener una oracioacuten

rocinante plaacuteticas sazoacuten ojos Dulcinea Dios

Una serie de palabras aleatorias rara vez tiene sentido porque no hay relacioacutenentre palabras sucesivas Por ejemplo en una oracioacuten real se esperariacutea que unartiacuteculo como el fuese seguido por un sustantivo y probablemente no un verboo un adverbio

Una forma de medir este tipo de relaciones es con el anaacutelisis de Markov quedefine para una secuencia dada de palabras la probabilidad de las palabras quepodriacutean venir despueacutes Por ejemplo en la cancioacuten La vida es un carnaval (deCeliz Cruz)

Todo aquelQue piense que la vida siempre es cruelTiene que saber que no es asiacuteQue tan solo hay momentos malosY todo pasa

Todo aquelQue piense que esto nunca va cambiarTiene que saber que no es asiacuteQue al mal tiempo buena caraY todo cambia

Ay no hay que llorar (No hay que llorar)Que la vida es un carnavalQue es maacutes bello vivir cantando

En este texto la frase que piense siempre va seguida de la palabra que perola frase piense que puede ir seguida de la o esto

El resultado del anaacutelisis de Markov es un mapeo de cada prefijo (como quepiense y piense que) a todos los sufijos posibles (como la y esto)

Dada esta asignacioacuten se puede generar un texto aleatorio comenzando concualquier prefijo y eligiendo aleatoriamente entre los posibles sufijos A

Anaacutelisis de Markov 179

continuacioacuten puede combinar el final del prefijo y el nuevo sufijo para formar elsiguiente prefijo y repetir

Por ejemplo si comienza con el prefijo Que la la siguiente palabra seraacute vidaporque el prefijo solo aparece dos veces en el texto y siempre estaacute seguido deeste sufijo El siguiente prefijo es la vida por lo que el siguiente sufijo podriacuteaser siempre o es

En este ejemplo la longitud del prefijo siempre es dos pero puede hacer anaacutelisisde Markov con un prefijo de cualquier longitud

Ejercicio 13-8

Anaacutelisis de Markov

1 Escriba un programa que lea un texto desde un archivo y realice un anaacutelisisde Markov El resultado debe ser un diccionario que asocie prefijos y unacoleccioacuten de posibles sufijos La coleccioacuten puede ser un arreglo tupla odiccionario depende de usted hacer una eleccioacuten adecuada Puede probarsu programa con una longitud de prefijo de dos pero debe escribir elprograma de manera tal que sea faacutecil probar con otras longitudes

2 Agregue una funcioacuten al programa anterior para generar un texto aleatoriobasado en anaacutelisis de Markov Aquiacute hay un ejemplo de Don Quijote conlongitud de prefijo 2

Trifaldi habiacutea de Troya ni por la majestad real Y con mis quejasDesechaacutesteme iexcloh estremo su friacuteo del agravio a la espada tenieacutendolapor aca y maacutes que soacutelo se trueca y con el cual encendiacutea el ejemplo deaquellos cazadores

Para este ejemplo se dejoacute la puntuacioacuten anexa a las palabras El resultadoes casi sintaacutecticamente correcto Semaacutenticamente casi tiene sentido perono del todo

iquestQueacute sucede si aumenta la longitud del prefijo iquestEl texto aleatorio tiene maacutessentido

3 Una vez que su programa esteacute funcionando podriacutea probar combinandotexto de dos o maacutes libros El texto aleatorio que genere combinaraacute elvocabulario y las frases de las fuentes de maneras interesantes

Creacutedito Este estudio de caso se basa en un ejemplo de Kernighan y Pike ThePractice of Programming Addison-Wesley 1999

OBSERVACIOacuteN Debe hacer este ejercicio antes de continuar

180 Capiacutetulo 13 Estudio de Caso Seleccioacuten de Estructura de Datos

Estructuras de DatosUsar anaacutelisis de Markov para generar texto aleatorio es divertido pero ademaacuteseste ejercicio tiene un trasfondo la seleccioacuten de la estructura de datos En los losejercicios anteriores teniacutea que elegir

bull Coacutemo representar los prefijos

bull Coacutemo representar la coleccioacuten de los posibles sufijos

bull Coacutemo representar la asociacioacuten de cada prefijo con la coleccioacuten de posiblessufijos

El uacuteltimo es faacutecil un diccionario es la opcioacuten obvia para una asociacioacuten entreclaves y valores correspondientes

Para los prefijos las opciones maacutes obvias son cadena arreglo de cadenas o tuplade cadenas

Para los sufijos puede ser un arreglo o un histograma (diccionario)

iquestCoacutemo se elige El primer paso es pensar en las operaciones que deberaacuteimplementar para cada estructura de datos Para los prefijos se debe ser capazde eliminar palabras del principio y agregarlas al final Por ejemplo si el prefijoactual es que piense y la siguiente palabra es que debe poder formar elsiguiente prefijo piense que

Para los prefijos podriacutea elegir un arreglo ya que en eacutel es faacutecil agregar y eliminarelementos

Para la coleccioacuten de sufijos las operaciones que se deben realizar incluyenagregar un nuevo sufijo (o aumentar la frecuencia de uno existente) y elegir unsufijo aleatorio

Agregar un nuevo sufijo es igualmente faacutecil para la implementacioacuten del arreglo odel histograma Elegir un elemento aleatorio de un arreglo es faacutecil pero elegireficientemente de un histograma es maacutes difiacutecil (ver Seccioacuten 1371)

Hasta ahora se ha hablado principalmente sobre la facilidad de implementacioacutenpero hay otros factores a considerar al elegir las estructuras de datos Uno es eltiempo de ejecucioacuten A veces hay una razoacuten teoacuterica para esperar que unaestructura de datos sea maacutes raacutepida que otra Por ejemplo anteriormente semencionoacute que el operador in es maacutes raacutepido para los diccionarios que para losarreglos al menos cuando el nuacutemero de elementos es grande

Aunque generalmente no se sabe de antemano queacute implementacioacuten seraacute maacutesraacutepida una opcioacuten es implementar ambos y ver cuaacutel es mejor Este enfoque sellama benchmarking Una alternativa praacutectica es elegir la estructura de datosque sea maacutes faacutecil de implementar y luego ver si es lo suficientemente raacutepida parala aplicacioacuten prevista Si es asiacute no hay necesidad de continuar Si no hay

Estructuras de Datos 181

herramientas como el moacutedulo Profile que pueden identificar los lugares en unprograma que toman maacutes tiempo

El otro factor a considerar es el espacio de almacenamiento Por ejemplo usar unhistograma para la coleccioacuten de sufijos puede tomar menos espacio porque solotiene que almacenar cada palabra una vez sin importar cuaacutentas veces aparezcaen el texto En algunos casos ahorrar espacio tambieacuten puede hacer que suprograma se ejecute maacutes raacutepido En el peor de los casos su programa podriacutea noejecutarse si se queda sin memoria pero para muchas aplicaciones el espacio esuna consideracioacuten secundaria despueacutes del tiempo de ejecucioacuten

Una uacuteltima reflexioacuten en esta discusioacuten se ha dado a entender que se deberiacuteausar una estructura de datos para el anaacutelisis y la generacioacuten Pero dado queestas son fases separadas tambieacuten seriacutea posible usar una estructura para elanaacutelisis y luego convertirla en otra estructura para la generacioacuten Esto seriacuteaconveniente si el tiempo ahorrado durante la generacioacuten excede el tiempodedicado a la conversioacuten

OBSERVACIOacuteNEl paquete de Julia DataStructures (verhttpsgithubcomJuliaCollectionsDataStructuresjl)implementa una variedad de estructuras de datos

DepuracioacutenCuando estaacute depurando un programa y especialmente si estaacute tratando deresolver un error difiacutecil hay cinco cosas que puede probar

LeeExamine su coacutedigo leacutealo y verifique que dice lo que queriacutea decir

EjecutaExperimente haciendo cambios y ejecutando diferentes versiones Amenudo si muestra lo correcto en el lugar correcto del programa elproblema se vuelve obvio pero para ello a veces tiene que desarrollarandamiaje

ReflexionaiexclToacutemese un tiempo para pensar iquestQueacute tipo de error es de sintaxis tiempode ejecucioacuten o semaacutentica iquestQueacute informacioacuten puede obtener de los mensajesde error o de la salida del programa iquestQueacute tipo de error podriacutea causar elproblema que estaacutes viendo iquestQueacute cambioacute antes de que apareciera elproblema

HablaSi le explica el problema a otra persona a veces puede encontrar larespuesta incluso antes de terminar de hacer la pregunta Generalmente no

182 Capiacutetulo 13 Estudio de Caso Seleccioacuten de Estructura de Datos

es necesaria otra persona incluso se podriacutea hablar con un pato de gomaEste es el origen de la conocida estrategia llamada depuracioacuten del pato degoma Esto es real vea httpsenwikipediaorgwikiRubber_duck_debugging

Vuelve atraacutesEn ocasiones lo mejor que puede hacer es retroceder deshacer los cambiosrecientes hasta regresar a un programa que funcione y que comprenda Unavez logrado esto puede comenzar a reconstruir

Los programadores principiantes a veces se atascan en una de estas actividadesy olvidan las otras Cada actividad viene con su propia forma de fallar

Por ejemplo leer su coacutedigo podriacutea ayudar si el problema es un error tipograacuteficopero no si el problema es un malentendido conceptual Si no comprende lo quehace su programa puede leerlo 100 veces y nunca ver el error porque el errorestaacute en su cabeza

Ejecutar experimentos puede ayudar especialmente si ejecuta pruebas pequentildeasy simples pero si ejecuta experimentos sin pensar o leer su coacutedigo puede caeren un patroacuten llamado programacioacuten de caminata aleatoria que es el proceso dehacer cambios aleatorios hasta que el programa haga lo correcto No hace faltadecir que la programacioacuten de caminata aleatoria puede llevar mucho tiempo

La persona que programa tiene que tomarse su tiempo para pensar Ladepuracioacuten es como una ciencia experimental Debe tener al menos una hipoacutetesissobre la causa del problema Si hay dos o maacutes opciones trate de pensar en unaprueba que elimine una de ellas

Incluso las mejores teacutecnicas de depuracioacuten fallaraacuten si hay demasiados errores osi el coacutedigo que estaacute tratando de corregir es demasiado grande y complicado Aveces la mejor opcioacuten es volver atraacutes simplificando el programa hasta quellegue a algo que funcione y que comprenda

Los programadores principiantes a menudo son reacios a volver atraacutes porque nopueden soportar eliminar una liacutenea de coacutedigo (incluso si es incorrecto) Si le hacesentir mejor copie su programa en otro archivo antes de comenzar a eliminarloLuego puede copiar las piezas una por una

Encontrar un error difiacutecil requiere leer ejecutar reflexionar y a veces volveratraacutes Si se queda atascado en una de estas actividades pruebe las otras

Glosariodeterminiacutestico

Perteneciente a un programa que hace lo mismo cada vez que se ejecuta apartir de las mismas entradas

Glosario 183

pseudoaleatorioPerteneciente a una secuencia de nuacutemeros que parecen ser aleatorios peroque son generados por un programa determinista

valor por defecto (o valor por omisioacuten)El valor dado a un paraacutemetro opcional si no se proporciona un argumento

anularReemplazar un valor por defecto con un argumento

benchmarkingEl proceso de elegir entre estructuras de datos implementando alternativasy probaacutendolas con una muestra de las posibles entradas

depuracioacuten del pato de gomaDepuracioacuten en doacutende se explica el problema a un objeto inanimado talcomo un pato de goma Articular el problema puede ayudarle a resolverloincluso si el pato de goma no sabe de Julia

Ejercicios

Ejercicio 13-9

El rango de una palabra es su posicioacuten en un arreglo de palabras ordenadaspor frecuencia la palabra maacutes comuacuten tiene rango 1 la segunda maacutes comuacuten tienerango 2 etc

La ley de Zipf describe una relacioacuten entre los rangos y las frecuencias de laspalabras en idiomas naturales (httpsenwikipediaorgwikiZipfs_law)Especiacuteficamente predice que la frecuencia de la palabra con rango es

donde y son paraacutemetros que dependen del idioma y el texto Si aplicaslogaritmo a ambos lados de esta ecuacioacuten obtienes

Entonces si se grafica versus se deberiacutea obtener una liacutenea recta conpendiente e intercepto

Escriba un programa que lea un texto de un archivo cuente las frecuencias delas palabras e imprima una liacutenea para cada palabra en orden descendente defrecuencia con y

Instale una libreriacutea para graficar

184 Capiacutetulo 13 Estudio de Caso Seleccioacuten de Estructura de Datos

(v10) pkggt add Plots

Su uso es muy sencillo

using Plotsx = 110y = x^2plot(x y)

Use la libreriacutea Plots para graficar los resultados y verificar si forman una liacutenearecta

Ejercicios 185

Capiacutetulo 14 ArchivosEste capiacutetulo presenta el concepto de persistencia que alude a los programasque mantienen los datos en almacenamiento permanente y muestra coacutemo usardiferentes tipos de almacenamiento permanente tales como archivos y bases dedatos

PersistenciaLa mayoriacutea de los programas que hemos visto hasta ahora han sido transitorioses decir se ejecutan por un tiempo corto y generan una salida pero cuandofinalizan sus datos desaparecen Si ejecuta el programa nuevamente estecomienza de cero

Otros programas en cambio son persistentes se ejecutan durante un largoperiacuteodo de tiempo (o todo el tiempo) mantienen al menos parte de sus datos enalmacenamiento permanente (en un disco duro por ejemplo) y si se apagan yvuelven a comenzar retoman donde lo dejaron

Ejemplos de programas persistentes son los sistemas operativos que se ejecutansiempre que una computadora esteacute encendida y los servidores web que seejecutan todo el tiempo esperando a que lleguen solicitudes a la red

Una de las formas maacutes simples para que los programas mantengan sus datos esleyendo y escribiendo archivos de texto Ya se han visto programas que leenarchivos de texto y en este capiacutetulo se van a ver programas que los escriben

Otra alternativa es almacenar el estado del programa en una base de datos Eneste capiacutetulo tambieacuten se presentaraacute coacutemo usar una base de datos simple

Lectura y EscrituraUn archivo de texto es una secuencia de caracteres almacenados en un mediopermanente como un disco duro o una memoria flash Ya se vio coacutemo abrir y leerun archivo en Seccioacuten 91

Para escribir un archivo debe abrirlo usando el modo w (de write) comosegundo paraacutemetro

juliagt fout = open(salidatxt w)IOStream(ltfile salidatxtgt)

Si el archivo ya existe abrirlo en modo de escritura borra los datos antiguos ycomienza de nuevo iexclasiacute que tenga cuidado Si el archivo no existe se crea unonuevo open devuelve un objeto de archivo y la funcioacuten write escribe datos en elarchivo

186 Capiacutetulo 14 Archivos

juliagt linea1 = El Cid convoca a sus vasallosn

juliagt write(fout linea1)31

El valor de retorno es el nuacutemero de caracteres que se escribieron El objeto dearchivo fout lleva el registro de doacutende se quedoacute por uacuteltima vez por lo que sillama a write nuevamente esta agrega nuevos datos al final del archivo

juliagt linea2 = eacutestos se destierran con eacuteln

juliagt write(fout linea2)30

Cuando el usuario haya terminado de escribir debe cerrar el archivo

juliagt close(fout)

Si no cierra el archivo este se cierra cuando finaliza el programa

FormateoEl argumento de write tiene que ser una cadena por lo que si queremos ponerotros valores en un archivo tenemos que convertirlos a cadenas La forma maacutesfaacutecil de hacerlo es con la funcioacuten string o con interpolacioacuten de cadenas

juliagt fout = open(salidatxt w)IOStream(ltfile salidatxtgt)juliagt write(fout string(150))3

Otra alternativa es utilizar la familia de funciones de print(ln)

juliagt camellos = 4242juliagt println(fout He visto $camellos camellos)

OBSERVACIOacuteN

Una alternativa maacutes potente es la macro printf queimprime utilizando cadenas con especificacioacuten deformato al maacutes puro estilo C Puede leer maacutes sobre estoen httpsdocsjulialangorgenv1stdlibPrintf

Formateo 187

Nombre de Archivo y RutaLos archivos estaacuten organizados en directorios (tambieacuten llamados carpetas)Cada programa en ejecucioacuten tiene su propio directorio actual que es eldirectorio que usaraacute por defecto para para la mayoriacutea de las operaciones Porejemplo cuando abre un archivo para leer Julia lo busca en el directorio actual

La funcioacuten pwd (en ingleacutes print working directory) devuelve el nombre deldirectorio actual

juliagt cwd = pwd()homeben

cwd significa directorio del trabajo actual (en ingleacutes ldquocurrent workingdirectoryrdquo) El resultado en este ejemplo es homeben que es el directorio deinicio de un usuario llamado ben

Una cadena como homeben que identifica un archivo o directorio se llamaruta o path

Un nombre de archivo simple como memotxt tambieacuten se considera una rutaaunque es una ruta relativa porque comienza en el directorio actual Si eldirectorio actual es homeben el nombre de archivo memotxt se refiere ahomebenmemotxt

Una ruta que comienza con no depende del directorio actual Este tipo de rutase llama ruta absoluta Para encontrar la ruta absoluta de un archivo puede usarabspath

juliagt abspath(memotxt)homebenmemotxt

Julia tambieacuten tiene otras funciones para trabajar con nombres de archivo y rutasPor ejemplo ispath comprueba si existe un archivo o directorio

juliagt ispath(memotxt)true

Si existe isdir comprueba si es un directorio

juliagt isdir(memotxt)falsejuliagt isdir(homeben)true

188 Capiacutetulo 14 Archivos

Del mismo modo isfile comprueba que se trate de un archivo

readdir devuelve un arreglo de los archivos (y otros directorios) en el directoriodado

juliagt readdir(cwd)3-element ArrayString1 memotxt musica fotos

Para mostrar el comportamiento de estas funciones el siguiente ejemplorecorre un directorio imprime los nombres de todos los archivos y se llama a siacutemisma de manera recursiva en todos los directorios

function recorrer(nombredir) for nombre in readdir(nombredir) ruta = joinpath(nombredir nombre) if isfile(ruta) println(ruta) else recorrer(ruta) end endend

joinpath toma un directorio y un nombre de archivo y los une en una rutacompleta

OBSERVACIOacuteN

Julia tiene una funcioacuten integrada llamada walkdir (veahttpsdocsjulialangorgenv1basefileBaseFilesystemwalkdir) que es similar a esta pero maacutesversaacutetil Como ejercicio lea la documentacioacuten y uacuteselapara imprimir los nombres de los archivos en undirectorio dado y sus subdirectorios

Captura de ExcepcionesMuchas cosas pueden salir mal al intentar leer y escribir archivos Al intentarabrir un archivo que no existe se obtiene un SystemError

juliagt fin = open(archivo_malo)ERROR SystemError opening file archivo_malo No such file or directory

Si el usuario intenta abrir un archivo pero no tiene permiso para acceder a eacutel

Captura de Excepciones 189

obtiene el error de sistema Permission denied (Permiso denegado)

Para evitar estos errores se podriacutean usar funciones como ispath e isfile perotomariacutea mucho tiempo y liacuteneas de coacutedigo verificar todas las posibilidades

Es maacutes faacutecil intentar lidiar con los problemas a medida que ocurren que esexactamente lo que hace la sentencia try La sintaxis es similar a una sentenciaif

try fin = open(archivo_malotxt)catch exc println(Algo salioacute mal $exc)end

Julia comienza ejecutando el bloque try Si nada falla se saltaraacute el bloque catch yfinalizaraacute Si ocurre una excepcioacuten Julia saltaraacute fuera del bloque try y ejecutaraacuteel bloque catch

Gestionar una excepcioacuten con try recibe el nombre de capturar una excepcioacuten Eneste ejemplo el bloque catch muestra un mensaje de error que no es muy uacutetil Engeneral capturar una excepcioacuten da la oportunidad de corregir el problemavolverlo a intentar o al menos terminar el programa con elegancia

Cuando el coacutedigo realiza cambios de estado o usa recursos como archivosgeneralmente se deben hacer ciertas cosas al finalizar la programacioacuten delcoacutedigo como por ejemplo cerrar los archivos Las excepciones pueden complicaresta tarea ya que se podriacutea salir antes de lo esperado de un bloque de coacutedigo Lapalabra reservada finally permite ejecutar un coacutedigo al salir de un bloque decoacutedigo determinado independientemente de coacutemo salga

f = open(salidatxt)try linea = readline(f) println(linea)finally close(f)end

En este ejemplo la funcioacuten close siempre se ejecutaraacute

Bases de datosUna base de datos es un archivo que estaacute organizado para almacenar datos Lamayoriacutea de las bases de datos estaacuten organizadas como diccionarios en el sentidode que realizan asociaciones entre claves y valores La diferencia maacutes importanteentre un diccionario y una base de datos es que la base de datos se encuentra en

190 Capiacutetulo 14 Archivos

el disco (u otro almacenamiento permanente) de modo que su contenido seconserva despueacutes de que el programa haya finalizado

IntroAJulia proporciona una interfaz para GDBM (GNU dbm) que permite creary actualizar archivos de base de datos A modo de ejemplo se crea una base dedatos que contiene pies de foto para archivos de imagen

Abrir una base de datos es similar a abrir otros archivos

juliagt using IntroAJulia

juliagt bd = DBM(piedefoto c)DBM(ltpiedefotogt)

El modo c significa que la base de datos debe crearse si no existe El resultadoes un objeto de base de datos que se puede usar (para la mayoriacutea de lasoperaciones) como un diccionario

Cuando se crea un nuevo elemento GDBM actualiza el archivo de base de datos

juliagt bd[luismipng] = Foto de Luis MiguelFoto de Luis Miguel

Cuando accede a uno de los elementos GDBM lee el archivo

juliagt bd[luismipng]Foto de Luis Miguel

Si realiza otra asignacioacuten a una clave existente GDBM reemplaza el valoranterior

juliagt bd[luismipng] = Foto de Luis Miguel cantandoFoto de Luis Miguel cantandojuliagt bd[luismipng]Foto de Luis Miguel cantando

Algunas funciones que tienen un diccionario como argumento con claves yvalores no funcionan con objetos de base de datos No obstante la iteracioacuten conun bucle for siacute

for (clave valor) in bd println(clave valor)end

Al igual que con otros archivos debe cerrar la base de datos cuando haya

Bases de datos 191

terminado

juliagt close(bd)

SerializacioacutenUna limitacioacuten de GDBM es que las claves y los valores deben ser cadenas oconjuntos de bytes Si intenta utilizar cualquier otro tipo se produciraacute un error

Las funciones serialize y deserialize pueden ser uacutetiles Traducen casi cualquiertipo de objeto en un arreglo de bytes (un iobuffer) adecuado para elalmacenamiento en una base de datos y luego traducen los arreglos de bytesnuevamente en objetos

juliagt using Serialization

juliagt io = IOBuffer()

juliagt t = [1 2 3]

juliagt serialize(io t)24juliagt print(take(io))UInt8[0x37 0x4a 0x4c 0x0a 0x04 0x00 0x00 0x00 0x15 0x00 0x080xe2 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x02 0x00 0x000x00 0x00 0x00 0x00 0x00 0x03 0x00 0x00 0x00 0x00 0x00 0x000x00]

El formato no es intuitivo para nosotros pero es faacutecil de interpretar para Juliadeserialize reconstituye el objeto

juliagt io = IOBuffer()

juliagt t1 = [1 2 3]

juliagt serialize(io t1)24juliagt s = take(io)

juliagt t2 = deserialize(IOBuffer(s))

juliagt print(t2)[1 2 3]

serialize y deserialize escriben y leen desde un objeto iobuffer que representa unIO stream en memoria La funcioacuten take recupera el contenido del iobuffer como

192 Capiacutetulo 14 Archivos

un arreglo de bytes y reestablece el iobuffer a su estado inicial

Aunque el nuevo objeto tiene el mismo valor que el anterior no es (en general) elmismo objeto

juliagt t1 == t2truejuliagt t1 equiv t2false

En otras palabras la serializacioacuten y luego la deserializacioacuten tienen el mismoefecto que copiar el objeto

Esto se puede usar para almacenar valores que no sean cadenas en una base dedatos

OBSERVACIOacuteN

De hecho el almacenamiento de valores que no soncadenas en una base de datos es tan comuacuten que se haencapsulado en un paquete llamado JLD2 (consultehttpsgithubcomJuliaIOJLD2jl)

Objetos de ComandoLa mayoriacutea de los sistemas operativos proporcionan una interfaz de liacutenea decomandos tambieacuten conocida como shell Las shells generalmente proporcionancomandos para navegar por el sistema de archivos y ejecutar aplicaciones Porejemplo en Unix puede cambiar los directorios con cd mostrar el contenido deun directorio con ls e iniciar un navegador web escribiendo (por ejemplo) firefox

Cualquier programa que se pueda iniciar desde la shell tambieacuten puede iniciarsedesde Julia usando un objeto de comando

juliagt cmd = `echo hola``echo hola`

Las comillas invertidas se usan para delimitar el comando

La funcioacuten run ejecuta el comando

juliagt run(cmd)hola

hola es la salida del comando echo enviado a STDOUT La funcioacuten run devuelveun objeto de proceso y genera un ErrorException si el comando externo no se

Objetos de Comando 193

ejecuta correctamente

Si se desea leer la salida del comando externo se puede usar read en su lugar

juliagt a = read(cmd String)holan

Por ejemplo la mayoriacutea de los sistemas Unix tienen un comando llamadomd5sum o md5 que lee el contenido de un archivo y calcula una suma deverificacioacuten Puede leer sobre Md5 en httpsenwikipediaorgwikiMd5 Estecomando proporciona una manera eficiente de verificar si dos archivos tienen elmismo contenido La probabilidad de que diferentes contenidos produzcan lamisma suma de comprobacioacuten es muy pequentildea

Puede usar un objeto de comando para ejecutar md5 desde Julia y obtener elresultado

juliagt nombrearchivo = salidatxtsalidatxtjuliagt cmd = `md5 $nombrearchivo``md5 salidatxt`juliagt res = read(cmd String)ERROR IOError could not spawn `md5 salidatxt` no such file ordirectory (ENOENT)

Modulos

Supongamos que tenemos un archivo llamado wcjl con el siguiente coacutedigo

function contarlineas(nombrearchivo) conteo = 0 for linea in eachline(nombrearchivo) conteo += 1 end conteoend

print(contarlineas(wcjl))

Si ejecuta este programa se leen las liacuteneas de coacutedigo y se imprime el nuacutemero deliacuteneas en el archivo que es 9 Tambieacuten puede incluirlo en REPL de esta manera

juliagt include(wcjl)9

194 Capiacutetulo 14 Archivos

Los moacutedulos permiten crear espacios de trabajo separados es decir nuevosglobal scopes (aacutembitos de tipo global) Una sentencia tiene global scope si tieneefecto en todo el programa

Un moacutedulo comienza con la palabra reservada module y termina con end Al usarmoacutedulos se evitan los conflictos de nombres entre sus propias definiciones denivel superior y las que se encuentran en el coacutedigo de otra persona importpermite controlar queacute nombres de otros moacutedulos estaacuten visibles y exportespecifica cuaacuteles de sus nombres son puacuteblicos es decir aquellos que se puedenusar fuera del moacutedulo sin tener el prefijo del nombre del moacutedulo

module ContarLineas export contarlineas

function contarlineas(nombrearchivo) conteo = 0 for linea in eachline(nombrearchivo) conteo += 1 end conteo endend

El moacutedulo ContarLineas proporciona la funcioacuten contarlineas

juliagt using ContarLineas

juliagt contarlineas(wcjl)11

Ejercicio 14-1

Escriba este ejemplo en un archivo llamado wcjl incluacuteyalo en REPL (coninclude) y escriba using ContarLineas

AVISO

Si importa un moacutedulo que ya se ha importado Julia no hace nadaNo se vuelve a leer el archivo incluso si ha sido modificado

Si desea volver a cargar un moacutedulo debe reiniciar REPL Elpaquete Revise puede ayudarlo a no reiniciar tan seguido (veahttpsgithubcomtimholyRevisejl)

DepuracioacutenAl leer y escribir archivos el usuario puede tener problemas con los espacios enblanco Estos errores pueden ser difiacuteciles de depurar porque los espacios las

Depuracioacuten 195

tabulaciones y las nuevas liacuteneas son generalmente invisibles

juliagt s = 1 2t 3n 4

juliagt println(s)1 2 3 4

Las funciones integradas repr o dump pueden ser de ayuda Toman cualquierobjeto como argumento y devuelven una representacioacuten de tipo cadena delobjeto

1 2t 3n 4

juliagt repr(s)1 2t 3n 4juliagt dump(s)String 1 2t 3n 4

Esto puede ser uacutetil para la depuracioacuten

Otro problema con el que es faacutecil encontrarse es que en diferentes sistemasoperativos se usan diferentes caracteres para indicar el final de una liacuteneaAlgunos sistemas usan una nueva liacutenea representada por n Otros usan uncaraacutecter de retorno r Algunos usan ambos Si un archivo es usado en diferentessistemas estas inconsistencias podriacutean causar problemas

Para la mayoriacutea de los sistemas hay aplicaciones para convertir de un formato aotro Puede encontrarlas (y leer maacutes sobre este tema) enhttpsenwikipediaorgwikiNewline O por supuesto podriacutea escribir una ustedmismo

Glosariopersistente

Perteneciente a un programa que se ejecuta indefinidamente y mantiene almenos algunos de sus datos en almacenamiento permanente

archivo de textoUna secuencia de caracteres almacenados en almacenamiento permanentetal como en un disco duro

directorioUna coleccioacuten de archivos con nombre tambieacuten llamada carpeta

196 Capiacutetulo 14 Archivos

rutaUna cadena que identifica a un archivo

ruta relativaUna ruta que comienza en el directorio actual

ruta absolutaUna ruta que comienza en el directorio superior del sistema de archivos

capturar (catch)Evitar que una excepcioacuten haga terminar un programa utilizando lassentencias try catch finally

base de datosUn archivo cuyo contenido estaacute organizado como un diccionario con clavesque corresponden a valores

shellUn programa que permite a los usuarios escribir comandos y luegoejecutarlos iniciando otros programas

objeto de comandoUn objeto que representa un comando de shell Esto permite que unprograma de Julia ejecute comandos y lea los resultados

Ejercicios

Ejercicio 14-2

Escriba una funcioacuten llamada sed que tome como argumentos una cadena depatrones una cadena de reemplazo y dos nombres de archivo La funcioacuten debeleer el primer archivo y escribir el contenido en el segundo archivo (creaacutendolo sies necesario) Si la cadena de patrones aparece en alguacuten lugar del archivo debereemplazarse con la cadena de reemplazo

Si se produce un error al abrir leer escribir o cerrar los archivos su programadebe detectar la excepcioacuten imprimir un mensaje de error y terminar

Ejercicio 14-3

Si hizo Seccioacuten 12102 recordaraacute que debiacutea crear un diccionario que asociabauna cadena ordenada de letras al conjunto de palabras que se podiacutea deletrearcon esas letras Por ejemplo cuaderno estaba asociado al arreglo [cuadernoeducaron encuadro]

Escriba un moacutedulo que importe conjuntoanagramas y proporcione dos nuevas

Ejercicios 197

funciones almacenaranagramas que almacena el diccionario de anagramasusando JLD2 (vea httpsgithubcomJuliaIOJLD2jl) y leeranagramas que buscauna palabra y devuelve un arreglo de sus anagramas

Ejercicio 14-4

En una gran coleccioacuten de archivos MP3 puede haber maacutes de una copia de lamisma cancioacuten almacenada en diferentes directorios o con diferentes nombresde archivo El objetivo de este ejercicio es buscar duplicados

1 Escriba un programa que busque un directorio y todos sus subdirectoriosde forma recursiva y devuelva un arreglo de rutas completas para todos losarchivos con un sufijo dado (como mp3)

2 Para reconocer duplicados puede usar md5sum o md5 para calcular unasuma de verificacioacuten para cada archivo Si dos archivos tienen la mismasuma de verificacioacuten probablemente tengan el mismo contenido

3 Para verificarlo puede usar el comando de Unix diff

198 Capiacutetulo 14 Archivos

Capiacutetulo 15 Estructuras y ObjetosA esta altura ya debe saber coacutemo usar funciones para tener un coacutedigo maacutesorganizado y coacutemo usar los tipos integrados de Julia para organizar sus datos Elsiguiente paso es aprender a construir sus propios tipos para organizar tanto elcoacutedigo como los datos Este es un gran tema y por lo tanto tomaraacute un par decapiacutetulos abarcar todo

Tipos CompuestosSe han utilizado muchos tipos integrados en Julia y ahora se va a definir unnuevo tipo A modo de ejemplo se crea un tipo llamado Punto que representa unpunto en un espacio bidimensional

En notacioacuten matemaacutetica los puntos suelen escribirse entre pareacutentesis con unacoma que separa las coordenadas Por ejemplo representa el origen y representa el punto localizado unidades a la derecha y unidades hacia arribadel origen

Hay varias formas en que se podriacutean representar puntos del plano cartesiano enJulia

bull Almacenando las coordenadas por separado en dos variables x e y

bull Almacenando las coordenadas como elementos de un arreglo o tupla

bull Creando un nuevo tipo para representar puntos como objetos

Crear un nuevo tipo exige un poco maacutes de esfuerzo que las otras dos opcionespero tiene algunas ventajas como pronto se veraacute

Un tipo compuesto definido por el programador tambieacuten se denomina estructura(struct en ingleacutes) La definicioacuten de estructura de un punto se ve asiacute

struct Punto x yend

El encabezado indica que la nueva estructura se llama Punto El cuerpo definelos atributos o campos de la estructura La estructura de Punto tiene doscampos x e y

Una estructura es como una faacutebrica que crea objetos Para crear un punto sedebe llamar a Punto como si fuera una funcioacuten que tiene como argumentos losvalores de los campos Cuando Punto se usa como una funcioacuten se llamaconstructor

Tipos Compuestos 199

juliagt p = Punto(30 40)Punto(30 40)

El valor de retorno es una referencia a un objeto Punto el cual es asignado a p

La creacioacuten de un nuevo objeto se llama instanciacioacuten y el objeto creado es unainstancia del tipo

Cuando se imprime una instancia Julia dice a queacute tipo pertenece y cuaacuteles son losvalores de los atributos

Cada objeto es una instancia de alguacuten tipo por lo que objeto e instancia sonintercambiables No obstante en este capiacutetulo se utiliza instancia para indicarque se estaacute hablando de un tipo definido por el programador

Un diagrama de estado que muestra un objeto y sus atributos se denominadiagrama de objeto (ver Figura 20)

Figura 20 Diagrama de objeto

Las Estructuras son Inmutables

Puede obtener los valores de los campos utilizando la notacioacuten

juliagt x = px30juliagt py40

La expresioacuten px significa Vaya al objeto al que se apunta p y obtenga el valorde x En el ejemplo se asigna ese valor a una variable llamada x No hayconflicto entre la variable x y el atributo x

Puede usar esa notacioacuten de punto como parte de cualquier expresioacuten Porejemplo

juliagt distancia = sqrt(px^2 + py^2)50

Sin embargo las estructuras son inmutables por defecto y despueacutes de laconstruccioacuten los campos no pueden cambiar su valor

200 Capiacutetulo 15 Estructuras y Objetos

juliagt py = 10ERROR setfield immutable struct of type Punto cannot be changed

Esto puede parecer extrantildeo al principio pero tiene varias ventajas

bull Puede ser maacutes eficiente

bull No es posible violar las invariantes (requisitos que deberiacutean cumplirse entodos los objetos en todo momento) de los constructores de un tipocompuesto (ver Seccioacuten 174)

bull El coacutedigo que usa objetos inmutables puede ser maacutes faacutecil de entender

Estructuras MutablesDe ser necesario se pueden declarar tipos compuestos mutables con la palabrareservada mutable struct A continuacioacuten se muestra la definicioacuten de un puntomutable

mutable struct MPunto x yend

Puede asignar valores a una instancia de una estructura mutable utilizandonotacioacuten de punto ()

juliagt blanco = MPunto(00 00)MPunto(00 00)juliagt blancox = 3030juliagt blancoy = 4040

RectaacutengulosA veces decidir cuaacuteles deberiacutean ser los campos de un objeto es faacutecil pero enotros casos no Por ejemplo imagine que se quiere un tipo que represente unrectaacutengulo iquestQueacute campos usariacutea para especificar la ubicacioacuten y el tamantildeo de unrectaacutengulo Puede ignorar el aacutengulo Para simplificar las cosas suponga que elrectaacutengulo es vertical u horizontal

Hay al menos dos posibilidades

bull Puede especificar una esquina del rectaacutengulo (o el centro) el ancho y laaltura

Estructuras Mutables 201

bull Puede especificar dos esquinas opuestas

Es difiacutecil decir que una opcioacuten es mejor que la otra por lo que implementaremosla primera a modo de ejemplo

Representa un rectaacutengulo

atributos ancho alto esquinastruct Rectangulo ancho alto esquinaend

El texto escrito entre comillas triples es llamado cadena de documentacioacuten (odocstring) y permite documentar La documentacioacuten es el acto de comentarconvenientemente cada una de las partes que tiene el programa

En este ejemplo la cadena de documentacioacuten (o docstring) enumera losatributos Los atributos ancho y alto son nuacutemeros y esquina es un objeto Puntoque especifica la esquina inferior izquierda

Para representar un rectaacutengulo debe crear una instancia del tipo Rectangulo

juliagt origen = MPunto(00 00)MPunto(00 00)juliagt caja = Rectangulo(1000 2000 origen)Rectangulo(1000 2000 MPunto(00 00))

Figura 21 muestra el estado de este objeto Un objeto es embebido si es atributode otro objeto Debido a que el atributo esquina se refiere a un objeto mutablese dibuja fuera del objeto Rectangulo

Figura 21 Diagrama de objeto

Instancias como ArgumentosPodemos pasar una instancia como argumento de la manera habitual Porejemplo

202 Capiacutetulo 15 Estructuras y Objetos

function imprimirpunto(p) println(($(px) $(py)))end

imprimirpunto toma un Punto como argumento y lo muestra en notacioacutenmatemaacutetica Puede llamar a imprimirpunto con un argumento p

juliagt imprimirpunto(blanco)(30 40)

Ejercicio 15-1

Escriba una funcioacuten llamada distanciaentrepuntos que tome dos puntos comoargumentos y devuelva la distancia entre ellos

Si un objeto de estructura mutable se pasa a una funcioacuten como argumento lafuncioacuten puede modificar los campos del objeto Por ejemplo moverpunto tomaun objeto mutable Punto y dos nuacutemeros dx y dy los cuales suma a los atributos xe y de Punto respectivamente

function moverpunto(p dx dy) px += dx py += dy nothingend

Aquiacute hay un ejemplo que muestra como funciona

juliagt origen = MPunto(00 00)MPunto(00 00)juliagt moverpunto(origen 10 20)

juliagt origenMPunto(10 20)

Dentro de la funcioacuten p es un alias de origen por lo que cuando la funcioacutenmodifica p origen tambieacuten cambia

Al pasar un objeto inmutable Punto a moverpunto se produce un error

juliagt moverpunto(p 10 20)ERROR setfield immutable struct of type Punto cannot be changed

Sin embargo se puede modificar el valor de un atributo mutable de un objeto

Instancias como Argumentos 203

inmutable Por ejemplo moverrectangulo tiene como argumentos un objetoRectangulo y dos nuacutemeros dx y dy Esta funcioacuten usa moverpunto para mover laesquina del rectaacutengulo

function moverrectangulo(rect dx dy) moverpunto(rectesquina dx dy)end

Ahora p en moverpunto es un alias para rectesquina por lo que cuando p semodifica rectesquina tambieacuten cambia

juliagt cajaRectangulo(1000 2000 MPunto(00 00))juliagt moverrectangulo(caja 10 20)

juliagt cajaRectangulo(1000 2000 MPunto(10 20))

AVISO

No puede reasignar un atributo mutable de un objeto inmutable

juliagt cajaesquina = MPunto(10 20)ERROR setfield immutable struct of type Rectangulo cannotbe changed

Instancias como Valores de RetornoLas funciones pueden devolver instancias Por ejemplo encontrarcentro toma unRectangulo como argumento y devuelve un Punto que contiene las coordenadasdel centro del rectaacutengulo

function encontrarcentro(rect) Punto(rectesquinax + rectancho 2 rectesquinay + rectalto 2)end

La expresioacuten rectcornerx significa ldquoVaya al objeto al que rect apunta yseleccione el atributo llamado esquina Luego vaya a ese objeto y seleccione elatributo llamado x

A continucioacuten se observa un ejemplo que toma caja como argumento y asigna elPunto resultante a centro

juliagt centro = encontrarcentro(caja)Punto(510 1020)

204 Capiacutetulo 15 Estructuras y Objetos

CopiadoEl uso de alias puede hacer que un programa sea difiacutecil de leer ya que loscambios hechos en un lugar pueden tener efectos inesperados en otro lugar Esdifiacutecil estar al tanto de todas las variables a las que puede apuntar un objetodado

Copiar un objeto es muchas veces una alternativa a la creacioacuten de un alias Juliaprovee una funcioacuten llamada copy que puede duplicar cualquier objeto

juliagt p1 = MPunto(30 40)MPunto(30 40)juliagt p2 = deepcopy(p1)MPunto(30 40)juliagt p1 equiv p2falsejuliagt p1 == p2false

El operador equiv indica que p1 y p2 no son el mismo objeto lo cual es esperable Loque no es del todo esperable es que == no devuelva true aunque estos puntoscontengan los mismos datos Resulta que para los objetos mutables elcomportamiento predeterminado del operador == es el mismo que el operador=== es decir comprueba la identidad del objeto no la equivalencia del objetoEsto se debe a que Julia no sabe queacute deberiacutea considerarse equivalente para lostipos compuestos mutables Al menos no todaviacutea

Ejercicio 15-2

Cree una instancia de Punto haga una copia y verifique la equivalencia y laigualdad de ambas El resultado puede sorprenderlo pero explica por queacute elalias no es un problema para un objeto inmutable

DepuracioacutenAl comenzar a trabajar con objetos es probable que encuentre algunasexcepciones nuevas Si intenta acceder a un campo que no existe obtendraacute

juliagt p = Punto(30 40)Punto(30 40)juliagt pz = 10ERROR type Punto has no field z

Si no estaacute seguro del tipo de un objeto puede saberlo de la siguiente manera

Copiado 205

juliagt typeof(p)Punto

Tambieacuten puede usar isa para verificar si un objeto es una instancia de un tipoespeciacutefico

juliagt p isa Puntotrue

Si no estaacute seguro de si un objeto tiene un atributo particular puede usar lafuncioacuten fieldnames

juliagt fieldnames(Punto)(x y)

o la funcioacuten isdefined

juliagt isdefined(p x)truejuliagt isdefined(p z)false

El primer argumento puede ser cualquier objeto y el segundo argumento es elsiacutembolo seguido del nombre del atributo

Glosarioestructura

Un tipo compuesto

constructorUna funcioacuten con el mismo nombre que un tipo que crea instancias de estetipo

instanciaUn objeto que pertenece a un tipo

instanciarCrear un nuevo objeto

atributo o campoUn valor con nombre asociado un objeto

206 Capiacutetulo 15 Estructuras y Objetos

objeto embebidoUn objeto que se almacena como atributo de otro objeto

deep copy o copia profundaCopiar el contenido de un objeto y cualquier objeto embebido en eacutel y a suvez cualquier objeto embebido en ellos y asiacute sucesivamente Implementadopor la funcioacuten deepcopy

diagrama de objetoUn diagrama que muestra objetos sus atributos y valores de atributos

Ejercicios

Ejercicio 15-3

1 Escriba una definicioacuten de un tipo llamado Circulo que tenga atributos centroy radio y doacutende centro sea un objeto Punto y radio un nuacutemero

2 Cree una instancia de un objeto Circulo que represente a un ciacuterculo concentro en y radio 75

3 Escriba una funcioacuten llamada puntoencirculo que tome un objeto Circulo y unobjeto Punto y devuelva true si el punto se encuentra dentro o en el liacutemitedel ciacuterculo

4 Escriba una funcioacuten llamada rectencirculo que tome un objeto Circulo y unobjeto Rectangulo y devuelva true si el rectaacutengulo se encuentracompletamente dentro o en el liacutemite del ciacuterculo

5 Escriba una funcioacuten llamada sobreposicionrectcirc que tome un objetoCirculo y un objeto Rectangulo y devuelva true si alguna de las esquinas delrectaacutengulo cae dentro del ciacuterculo Una versioacuten maacutes desafiante es escribiruna funcioacuten que devuelva true si alguna parte del rectaacutengulo (nonecesariamente una esquina) cae dentro del ciacuterculo

Ejercicio 15-4

1 Escriba una funcioacuten llamada dibujarrect que tome como argumentos unobjeto turtle y un objeto Rectaacutengulo y use turtle para dibujar el rectaacutenguloConsulte el Capiacutetulo 4 para ver ejemplos que usen objetos Turtle

2 Escriba una funcioacuten llamada dibujarcirculo que tome como argumentos unobjeto Turtle y un objeto Circulo y dibuje el ciacuterculo

Ejercicios 207

Capiacutetulo 16 Estructuras y FuncionesAhora que se ha tratado coacutemo crear tipos compuestos el siguiente paso esescribir funciones que tomen objetos definidos por el programador comoparaacutemetros y que devuelvan otros como resultados En este capiacutetulo tambieacuten sepresenta el estilo de programacioacuten funcional y dos nuevas formas dedesarrollar programas

TiempoComo otro ejemplo de tipo compuesto se define una estructura llamada Horaque registra la hora del diacutea La definicioacuten de esta estructura se muestra acontinuacioacuten

Representa la hora del diacutea

atributos hora minuto segundostruct Hora hora minuto segundoend

Observacioacuten Time es una palabra reservada de Julia

juliagt tiempo = Hora(11 59 30)Hora(11 59 30)

El diagrama de objeto para el objeto Hora luce asiacute Figura 22

Figura 22 Diagrama de objeto

Ejercicio 16-1

Escriba una funcioacuten llamada imprimirhora que tome un objeto Hora y lo imprimacon el formato horaminutosegundo Printf de la macro printf del moacuteduloStdLib permite imprimir un nuacutemero entero con el formato 02d es decirutilizando al menos dos diacutegitos incluido un cero inicial si es necesario

208 Capiacutetulo 16 Estructuras y Funciones

Ejercicio 16-2

Escriba una funcioacuten booleana llamada estadespues que tome dos objetos Horat1 y t2 y devuelva true si la hora t1 estaacute despueacutes que t2 y false de lo contrarioDesafiacuteo no use sentencias if

Funciones PurasEn las siguientes secciones se escriben dos versiones de una funcioacuten que calculala suma de horas La primera versioacuten muestra un tipo de funcioacuten llamado funcioacutenpura y la segunda un tipo llamado modificador Ademaacutes estas versionespermitiraacuten mostrar un nuevo plan de desarrollo de programas llamado desarrollode prototipos una forma de abordar un problema complejo comenzando con unprototipo simple y lidiando gradualmente con las complicaciones

Este es un primer prototipo de la funcioacuten sumahora

function sumahora(t1 t2) Hora(t1hora + t2hora t1minuto + t2minuto t1segundo +t2segundo)end

La funcioacuten crea un nuevo objeto Hora inicializa sus atributos y devuelve unareferencia al nuevo objeto A esto se le llama funcioacuten pura porque no modificaninguno de los objetos que se le pasan como argumento y no tiene efectos (comomostrar un valor o tomar una entrada del usuario) maacutes que devolver un valor

Para probar esta funcioacuten se crean dos objetos Hora inicio que contiene la horade inicio de una peliacutecula como Roma y duracion que contiene la duracioacuten de lapeliacutecula que es dos horas y 15 minutos

sumahora calcula cuaacutendo se terminaraacute la peliacutecula

imprimirhora (generic function with 1 method)

juliagt inicio = Hora(9 50 0)

juliagt duracion = Hora(2 15 0)

juliagt finaliza = sumahora(inicio duracion)

juliagt imprimirhora(finaliza)116500

El resultado 116500 no es lo que se buscaba El problema es que esta funcioacuten

Funciones Puras 209

no considera los casos en los que el nuacutemero de segundos o minutos suma maacutesque sesenta Cuando esto ocurre debemos acarrear (como en una suma) lossegundos sobrantes a la columna de los minutos o los minutos extras a lacolumna de las horas He aquiacute una versioacuten corregida de la funcioacuten

function sumahora(t1 t2) segundo = t1segundo + t2segundo minuto = t1minuto + t2minuto hora = t1hora + t2hora if segundo gt= 60 segundo -= 60 minuto += 1 end if minuto gt= 60 minuto -= 60 hora += 1 end Hora(hora minuto segundo)end

Aunque esta funcioacuten es correcta es muy larga Maacutes adelante se exploraraacute unaalternativa maacutes corta

ModificadoresHay veces en las que es uacutetil que una funcioacuten modifique uno o maacutes de los objetosque recibe como paraacutemetros En ese caso los cambios son visibles en el nivel endonde se ubica la sentencia de llamada Estas funciones se llaman modificadores

La funcioacuten incrementar que agrega un nuacutemero dado de segundos a un objetoHora puede escribirse naturalmente como un modificador Aquiacute se muestra unprototipo de la funcioacuten

function incrementar(tiempo segundos) tiemposegundo += segundos if tiemposegundo gt= 60 tiemposegundo -= 60 tiempominute += 1 end if tiempominuto gt= 60 tiempominuto -= 60 tiempohora += 1 endend

La primera liacutenea realiza la suma de los segundos y las restantes se ocupan de los

210 Capiacutetulo 16 Estructuras y Funciones

casos especiales vistos anteriormente

iquestEs correcta esta funcioacuten iquestQueacute ocurre si el paraacutemetro segundos es muchomayor que sesenta

En tal caso no es suficiente con acarrear una vez debemos seguir hacieacutendolohasta que tiemposegundo sea menor que sesenta Una solucioacuten es sustituir lassentencias if por sentencias while Esta funcioacuten seriacutea correcta pero no es lasolucioacuten maacutes eficiente

Ejercicio 16-3

Escriba una versioacuten correcta de incrementar sin bucles

Todo lo que se pueda hacer con modificadores tambieacuten puede lograrse confunciones puras De hecho algunos lenguajes de programacioacuten solo permitenfunciones puras Hay ciertas evidencias de que los programas que usanfunciones puras son maacutes raacutepidos de desarrollar y menos propensos a errores quelos programas que usan modificadores Sin embargo a veces los modificadoresson uacutetiles y en algunos casos los programas funcionales (es decir con funcionespuras) tienden a ser menos eficientes

En general recomendamos que escriba funciones puras siempre que searazonable y recurra a los modificadores soacutelo si hay una ventaja convincente Esteenfoque podriacutea llamarse estilo de programacioacuten funcional

Ejercicio 16-4

Escriba una versioacuten pura de incrementar que cree y devuelva un nuevo objetoHora en vez de modificar el paraacutemetro

Desarrollo de prototipos frente a la planificacioacutenEl desarrollo de programas que veremos ahora se llama ldquodesarrollo deprototiposrdquo En cada una de las funciones anteriores escribimos un prototipoque realizaba el caacutelculo baacutesico y luego lo probamos sobre unos cuantos casoscorrigiendo los errores a medida que iban apareciendo

Este enfoque puede ser efectivo especialmente si auacuten no tiene un conocimientoprofundo del problema No obstante las correcciones incrementales puedengenerar coacutedigo innecesariamente complicado (que considere muchos casosespeciales) y poco confiable (es difiacutecil saber si ha encontrado todos los errores)

Una alternativa es el desarrollo planificado en el que la comprensioacuten delproblema en profundidad puede facilitar en gran medida la programacioacuten En elcaso de sumahora se puede ver un objeto Hora como iexclun nuacutemero de tres diacutegitosen base 60 (vea httpsenwikipediaorgwikiSexagesimal ) El atributo segundoes la ldquocolumna de unidadesrdquo el atributo minuto es la ldquocolumna de los sesentasrdquo y

Desarrollo de prototipos frente a la planificacioacuten 211

el atributo hora es la ldquocolumna de los tres mil seiscientosrdquo

Cuando se escribiacutea sumahora e incrementar efectivamente se estaba sumandoen base 60 por eso se tuvo que acarrear de una columna a la siguiente

Esta observacioacuten sugiere otro enfoque para el problema se pueden convertir losobjetos Hora en enteros y aprovechar el hecho de que la computadora saberealizar aritmeacutetica con enteros

La siguiente funcioacuten convierte un objeto Hora en un entero

function horaaentero(tiempo) minutos = tiempohora 60 + tiempominuto segundos = minutos 60 + tiemposegundoend

Ahora para convertir un entero en un objeto Hora (recuerde que divrem divideel primer argumento por el segundo y devuelve el cociente y el resto como unatupla)

function enteroahora(segundos) (minutos segundo) = divrem(segundos 60) hora minuto = divrem(minutos 60) Hora(hora minuto segundo)end

Puede que tenga que pensar un poco y realizar algunas pruebas paraconvencerse de que estas funciones son correctas Una forma de probarlas esverificar que horaaentero((enteroahora(x)) == x para muchos valores de x Estees un ejemplo de prueba de consistencia

Una vez que esteacute convencido puede usar estas funciones para reescribirsumahora

function sumahora(t1 t2) segundos = horaaentero(t1) + horaaentero(t2) enteroahora(segundos)end

Esta versioacuten es maacutes corta que la original y maacutes faacutecil de verificar

Ejercicio 16-5

Reescriba incrementar usando horaaentero y enteroahora

Convertir de base 60 a base 10 y viceversa es maacutes difiacutecil que solo trabajar con

212 Capiacutetulo 16 Estructuras y Funciones

los tiempos El cambio de base es maacutes abstracto pero la intuicioacuten humana paratratar con las horas es mejor

Si al usuario se le ocurre tratar los tiempos como nuacutemeros de base 60 e invierteun poco de tiempo en escribir las funciones de conversioacuten (horaaentero yenteroahora) obtiene un programa maacutes corto faacutecil de leer y depurar y confiable

El cambio de base tambieacuten hace que sea maacutes faacutecil antildeadir funcionalidadesposteriormente Por ejemplo imagine restar dos Horas para hallar el intervaloentre ellas El enfoque simple seriacutea implementar una resta con preacutestamo perousar funciones de conversioacuten seriacutea maacutes faacutecil y con mayor probabilidad correcto

Iroacutenicamente a veces hacer un poblema maacutes complejo (o maacutes general) lo hacemaacutes faacutecil porque hay menos casos especiales y por lo tanto el margen de errores menor

DepuracioacutenUn objeto Hora estaacute bien definido si los valores de minuto y segundo estaacuten entre0 y 60 (incluido 0 pero no 60) y si hora es positivo hora y minuto deben servalores enteros pero se podriacutea permitir que segundo sea fraccional

Los requisitos como estos se denominan invariantes porque siempre deben serverdaderos Dicho de otra manera si no son ciertos algo estaacute mal

Escribir coacutedigo para verificar invariantes puede ayudar a detectar errores yencontrar sus causas Por ejemplo podriacutea tener una funcioacuten como eshoravalidaque tome un objeto Hora y devuelva false si viola una invariante

function eshoravalida(tiempo) if tiempohora lt 0 || tiempominuto lt 0 || tiemposegundo lt 0 return false end if tiempominuto gt= 60 || tiemposegundo gt= 60 return false end trueend

Al comienzo de cada funcioacuten puede verificar los argumentos para asegurarse deque sean vaacutelidos

Depuracioacuten 213

function sumahora(t1 t2) if eshoravalida(t1) || eshoravalida(t2) error(objeto Hora en sumahora es invaacutelido) end segundos = horaaentero(t1) + horaaentero(t2) enteroahora(segundos)end

O podriacutea usar una macro assert que verifica un invariante dado y genera unaexcepcioacuten si falla

function sumahora(t1 t2) assert(eshoravalida(t1) ampamp eshoravalida(t2) objeto Hora en sumahoraes invaacutelido) segundos = horaaentero(t1) + horaaentero(t2) enteroahora(segundos)end

Las macros assert son uacutetiles porque permiten distinguir el coacutedigo que tratacondiciones normales del coacutedigo que verifica los errores

Glosariodesarrollo de prototipos

Una forma de desarrollar programas que involucra generar un prototipo delprograma hacer pruebas y corregir errores a medida que son encontrados

desarrollo planificadoUna forma de desarrollar programas que implica una profunda comprensioacutendel problema y maacutes planificacioacuten que desarrollo incremental o desarrollo deprototipos

funcioacuten puraUna funcioacuten que no modifica los objetos que recibe como paraacutemetros Lamayoriacutea de las funciones puras son productivas

modificadorUna funcioacuten que modifica uno o maacutes de los objetos que recibe comoparaacutemetros La mayoriacutea de los modificadores son nulos es decir entreganresultado nothing

estilo funcional de programacioacutenUn estilo de programacioacuten en el que la mayoriacutea de las funciones son puras

214 Capiacutetulo 16 Estructuras y Funciones

invarianteUna condicioacuten que nunca deberiacutea cambiar durante la ejecucioacuten de unprograma

Ejercicios

Ejercicio 16-6

Escriba una funcioacuten llamada multhora que tome un objeto Hora y un nuacutemero ydevuelva un nuevo objeto Hora que contenga el producto entre Hora original y elnuacutemero

Luego use multhora para escribir una funcioacuten que tome un objeto Hora querepresente el tiempo de duracioacuten de una carrera y un nuacutemero que represente ladistancia y devuelva un objeto Hora que represente el ritmo promedio (minutospor kiloacutemetro)

Ejercicio 16-7

Julia proporciona objetos de tiempo similares a los objetos Hora de este capiacutetulopero que tienen un amplio conjunto de funciones y operadores Lea ladocumentacioacuten en httpsdocsjulialangorgenv1stdlibDates

1 Escriba un programa que tome la fecha actual e imprima el diacutea de lasemana

2 Escriba un programa que tome como entrada una fecha de cumpleantildeos eimprima la edad del usuario y la cantidad de diacuteas horas minutos ysegundos hasta su proacuteximo cumpleantildeos

3 Para dos personas nacidas en diacuteas diferentes hay un diacutea en que una tiene eldoble de edad que la otra Ese es su Diacutea Doble Escriba un programa quetome dos cumpleantildeos y calcule su Diacutea doble

4 Desafiacuteo Escriba una versioacuten maacutes general que calcule el diacutea en que unapersona es veces mayor que la otra

Ejercicios 215

Capiacutetulo 17 Dispatch MuacuteltipleJulia permite escribir coacutedigo que puede funcionar con diferentes tipos Esto sellama programacioacuten geneacuterica

En este capiacutetulo se discutiraacute sobre las declaraciones de tipo en Julia Ademaacutes sepresentan los meacutetodos que son formas de implementar diferentescomportamientos en una funcioacuten dependiendo del tipo de sus argumentos Estoes conocido como dispatch muacuteltiple

Declaraciones de Tipo

El operador asocia anotaciones de tipo con expresiones y variables

juliagt (1 + 2) Float64ERROR TypeError in typeassert expected Float64 got a value of typeInt64juliagt (1 + 2) Int643

Esto ayuda a verificar que el programa funciona de la manera esperada

El operador tambieacuten se puede agregar al lado izquierdo de una asignacioacuten ocomo parte de una declaracioacuten

juliagt function devolverfloat() xFloat64 = 100 x enddevolverfloat (generic function with 1 method)juliagt x = devolverfloat()1000juliagt typeof(x)Float64

La variable x siempre es de tipo Float64 y su valor se convierte en un puntoflotante si es necesario

Tambieacuten se puede antildeadir una anotacioacuten de tipo al encabezado de una definicioacutende funcioacuten

216 Capiacutetulo 17 Dispatch Muacuteltiple

function sinc(x)Float64 if x == 0 return 1 end sin(x)(x)end

El valor de retorno de sinc siempre se convierte al tipo Float64

En Julia cuando se omiten los tipos los valores pueden ser de cualquier tipo(Any)

MeacutetodosEn Capiacutetulo 16 definimos una estructura llamada Hora y en Seccioacuten 161escribimos una funcioacuten llamada imprimirhora

using Printf

struct Hora hora Int64 minuto Int64 segundo Int64end

function imprimirhora(tiempo) printf(02d02d02d tiempohora tiempominuto tiemposegundo)end

Para mejorar el rendimiento se pueden (y deben) agregar las declaraciones detipo a los atributos en una definicioacuten de estructura

Para llamar a esta funcioacuten debe pasarle un objeto Hora como argumento

juliagt inicio = Hora(9 45 0)Hora(9 45 0)juliagt imprimirhora(inicio)094500

Para agregar un meacutetodo a la funcioacuten imprimirhora con el fin de que esta soloacepte como argumento un objeto Hora todo lo que hay que hacer es agregar seguido de Hora al argumento tiempo en la definicioacuten de funcioacuten

Meacutetodos 217

function imprimirhora(tiempoHora) printf(02d02d02d tiempohora tiempominuto tiemposegundo)end

Un meacutetodo es una definicioacuten de funcioacuten con una especificacioacuten imprimirhoratiene un argumento de tipo Hora

Llamar a la funcioacuten imprimirhora con un objeto Hora produce el mismo resultadoque antes

juliagt imprimirhora(inicio)094500

Se redefine el primer meacutetodo sin la anotacioacuten de tipo lo cual permite unargumento de cualquier tipo

function imprimirhora(tiempo) println(No seacute coacutemo imprimir el tiempo del argumento)end

Si se llama a la funcioacuten imprimirhora con un objeto diferente de Hora seobtendraacute

juliagt imprimirhora(150)No seacute coacutemo imprimir el tiempo del argumento

Ejercicio 17-1

Reescriba horaaentero y enteroahora (de Seccioacuten 164) especificando el tipo delos argumentos

enteroahora (generic function with 1 method)

Ejemplos AdicionalesAquiacute hay una versioacuten de la funcioacuten incrementar (Ejercicio 16-5 de Seccioacuten 163)reescrita especificando el tipo de los argumentos

function incrementar(tiempoHora segundosInt64) segundos += horaaentero(tiempo) enteroahora(segundos)end

218 Capiacutetulo 17 Dispatch Muacuteltiple

Tenga en cuenta que ahora incrementar es una funcioacuten pura no un modificador

Asiacute es como se llama a la funcioacuten incrementar

juliagt inicio = Hora(9 45 0)Hora(9 45 0)juliagt incrementar(inicio 1337)Hora(10 7 17)

Si se colocan los argumentos en el orden incorrecto se obtiene un error

juliagt incrementar(1337 inicio)ERROR MethodError no method matching incrementar(Int64 Hora)

La especificacioacuten del meacutetodo es incrementar(tiempoHora segundosInt64) noincrementar(segundosInt64 tiempoHora)

Al reescribir estadespues (Ejercicio 16-2 de Seccioacuten 163) para que solo acepteobjetos Hora se tiene

function estadespues(t1Hora t2Hora) (t1hora t1minuto t1segundo) gt (t2hora t2minuto t2segundo)end

Hace falta destacar que los argumentos opcionales permiten definir muacuteltiplesmeacutetodos Por ejemplo esta definicioacuten

function f(a=1 b=2) a + 2bend

se traduce en los siguientes tres meacutetodos

f(a b) = a + 2bf(a) = f(a 2)f() = f(1 2)

Estas expresiones son definiciones vaacutelidas de meacutetodos de Julia Esta es unanotacioacuten abreviada para definir funcionesmeacutetodos

ConstructoresUn constructor es una funcioacuten especial que se llama para crear un objeto Losmeacutetodos por defecto del constructor Hora tienen las siguientes especificaciones

Constructores 219

Hora(hora minuto segundo)Hora(horaInt64 minutoInt64 segundoInt64)

Tambieacuten se pueden agregar meacutetodos propios de constructores externos

function Hora(tiempoHora) Hora(tiempohora tiempominuto tiemposegundo)end

Este meacutetodo se llama constructor de copia porque el nuevo objeto Hora es unacopia de su argumento

Para imponer invariantes se necesitan meacutetodos de constructor interno

struct Hora hora Int64 minuto Int64 segundo Int64 function Hora(horaInt64=0 minutoInt64=0 segundoInt64=0) assert(0 le minuto lt 60 Minuto no estaacute entre 0 y 60) assert(0 le segundo lt 60 Segundo no estaacute entre 0 y 60) new(hora minuto segundo) endend

La estructura Hora tiene ahora 4 meacutetodos de constructor interno

Hora()Hora(horaInt64)Hora(horaInt64 minutoInt64)Hora(horaInt64 minutoInt64 segundoInt64)

Un meacutetodo de constructor interno siempre se define dentro del bloque de unadeclaracioacuten de tipo y tiene acceso a una funcioacuten especial llamada new que creaobjetos del tipo recieacuten declarado

AVISOSi se define alguacuten constructor interno el constructor por defectoya no estaacute disponible Se tienen que escribir expliacutecitamente todoslos constructores internos necesarios

Tambieacuten existe un meacutetodo sin argumentos de la funcioacuten local new

220 Capiacutetulo 17 Dispatch Muacuteltiple

mutable struct Hora hora Int64 minuto Int64 segundo Int64 function Hora(horaInt64=0 minutoInt64=0 segundoInt64=0) assert(0 le minuto lt 60 Minuto estaacute entre 0 y 60) assert(0 le segundo lt 60 Segundo estaacute entre 0 y 60) tiempo = new() tiempohora = hora tiempominuto = minuto tiemposegundo = segundo tiempo endend

Esto permite construir estructuras de datos recursivas es decir una estructuradonde uno de los atributos es la estructura misma En este caso la estructuradebe ser mutable ya que sus atributos se modifican despueacutes de la creacioacuten deinstancias

showshow es una funcioacuten especial que devuelve la representacioacuten de cadena de unobjeto A continuacioacuten se muestra el meacutetodo show para objetos Hora

using Printf

function Baseshow(ioIO tiempoHora) printf(io 02d02d02d tiempohora tiempominutotiemposegundo)end

Esta funcioacuten guarda como cadena de texto una hora dada en el archivo al que iohace referencia

El prefijo Base es necesario si se quiere agregar un nuevo meacutetodo a la funcioacutenBaseshow

Cuando se imprime un objeto Julia llama a la funcioacuten show (esto ocurre siemprey como agregamos un nuevo meacutetodo a la funcioacuten Baseshow entonces se muestraHora con el formato que queremos)

juliagt tiempo = Hora(9 45 0)094500

Al escribir un nuevo tipo compuesto casi siempre es preferible empezar

show 221

escribiendo un constructor externo puesto que facilita la creacioacuten de instanciasde objetos y show que es uacutetil para la depuracioacuten

Ejercicio 17-2

Escriba un meacutetodo de constructor externo para la clase Punto que tome x e ycomo paraacutemetros opcionales y los asigne a los atributos correspondientes

incrementar (generic function with 1 method)

Sobrecarga de OperadoresEs posible cambiar la definicioacuten de los operadores cuando se aplican a tiposdefinidos por el usuario Esto se hace definiendo meacutetodos del operador Porejemplo si se define un meacutetodo llamado + con dos argumentos Hora se puedeusar el operador + en los objetos Hora

Asiacute es como se veriacutea la definicioacuten

import Base+

function +(t1Hora t2Hora) segundos = horaaentero(t1) + horaaentero(t2) enteroahora(segundos)end

La sentencia import agrega el operador + al aacutembito local (local scope) para quese puedan agregar meacutetodos

A continuacioacuten se muestra coacutemo usar este operador para objetos Hora

juliagt inicio = Hora(9 45)094500juliagt duracion = Hora(1 35 0)013500juliagt inicio + duracion112000

Al aplicar el operador + a objetos Hora Julia invoca el meacutetodo recieacuten agregadoCuando REPL muestra el resultado Julia invoca a show iexclHay muchas cosasocurriendo pero que no se observan

Ampliar el comportamiento de los operadores de modo que funcionen con tiposdefinidos por el usuarioprogramador se denomina sobrecarga del operador

222 Capiacutetulo 17 Dispatch Muacuteltiple

Dispatch MuacuteltipleEn la seccioacuten anterior se sumaron dos objetos Hora Imagine que ahora se quieresumar un nuacutemero entero a un objeto Hora

function +(tiempoHora segundosInt64) incrementar(tiempo segundos)end

He aquiacute un ejemplo que usa el operador + con un objeto Hora y un entero

juliagt inicio = Hora(9 45)094500juliagt inicio + 1337100717

La suma es un operador conmutativo por lo que se debe agregar otro meacutetodo

function +(segundosInt64 tiempoHora) tiempo + segundosend

Y se obtiene el mismo resultado

juliagt 1337 + inicio100717

La eleccioacuten del meacutetodo a ejecutar cuando se aplica una funcioacuten se llamadispatch Julia permite que el proceso de dispatch elija a cuaacutel de los meacutetodos deuna funcioacuten llamar en funcioacuten del nuacutemero y tipo de los argumentos dados El usode todos los argumentos de una funcioacuten para elegir el meacutetodo que se debeinvocar se conoce como dispatch muacuteltiple

Ejercicio 17-3

Escriba los siguientes meacutetodos + para objetos Punto

bull Si ambos operandos son objetos Punto el meacutetodo deberiacutea devolver un nuevoobjeto Punto cuya coordenada x sea la suma de las coordenadas x de losoperandos De manera anaacuteloga haga lo mismo para la coordenada y

bull Si el primer o el segundo operando es una tupla el meacutetodo debe agregar elprimer elemento de la tupla a la coordenada x y el segundo elemento a lacoordenada y y devolver un nuevo objeto Punto con el resultado

Dispatch Muacuteltiple 223

Programacioacuten GeneacutericaEl dispatch muacuteltiple es uacutetil cuando es necesario pero (afortunadamente) nosiempre lo es A menudo puede evitarse escribiendo funciones que funcionencorrectamente para argumentos de diferentes tipos

Muchas de las funciones que se han visto para cadenas tambieacuten funcionan paraotros tipos de secuencia Por ejemplo en Seccioacuten 112 se usa histograma paracontar la cantidad de veces que cada letra aparece en una palabra

function histograma(s) d = Dict() for c in s if c notin keys(d) d[c] = 1 else d[c] += 1 end end dend

Esta funcioacuten tambieacuten funciona para listas tuplas e incluso diccionarios siemprey cuando los elementos de s sean hashables ya que asiacute pueden usarse comoclaves de d

juliagt t = (spam huevo spam spam tocino spam)(spam huevo spam spam tocino spam)juliagt histograma(t)DictAnyAny with 3 entries spam =gt 4 huevo =gt 1 tocino =gt 1

Las funciones que pueden tomar paraacutemetros de diferentes tipos se llamanpolimoacuterficas El polimorfismo puede facilitar la reutilizacioacuten del coacutedigo

Por ejemplo la funcioacuten integrada sum que suma los elementos de una secuenciafunciona siempre que los elementos de la secuencia permitan la suma

Como se antildeadioacute el meacutetodo + para los objetos Hora entonces se puede usar sumpara Hora

224 Capiacutetulo 17 Dispatch Muacuteltiple

juliagt t1 = Hora(1 7 2)010702juliagt t2 = Hora(1 5 8)010508juliagt t3 = Hora(1 5 0)010500juliagt sum((t1 t2 t3))031710

Si todas las operaciones realizadas dentro de la funcioacuten se pueden aplicar al tipola funcioacuten se puede aplicar al tipo

El mejor tipo de polimorfismo es el que no se busca cuando usted descubre queuna funcioacuten que habiacutea escrito se puede aplicar a un tipo para el que nunca lahabiacutea planeado

Interfaz e implementacioacutenUno de los objetivos del dispatch muacuteltiple es hacer que el software sea maacutes faacutecilde mantener lo que significa poder mantener el programa funcionando cuandootras partes del sistema cambian y modificar el programa para cumplir con losnuevos requisitos

Una teacutecnica de disentildeo que ayuda a lograr ese objetivo es mantener las interfacesseparadas de las implementaciones Esto significa que los meacutetodos que tienen unargumento con anotacioacuten de tipo no deberiacutean depender de coacutemo se representanlos atributos de ese tipo

Por ejemplo en este capiacutetulo se desarrolla una estructura que representa unahora del diacutea Los meacutetodos que tienen un argumento con anotacioacuten de este tipoincluyen horaaentero estadespues y +

Se pueden implementar esos meacutetodos de varias maneras Los detalles de laimplementacioacuten dependen de coacutemo se represente Hora En este capiacutetulo losatributos de un objeto Hora son hora minuto y segundo

Otra opcioacuten seriacutea reemplazar estos atributos con un solo entero que representeel nuacutemero de segundos desde la medianoche Esta implementacioacuten hariacutea quealgunas funciones como estadespues sean maacutes faacuteciles de escribir pero hace queotras sean maacutes difiacuteciles

Despueacutes de implementar un tipo puede descubrir una mejor implementacioacuten Siotras partes del programa estaacuten usando su tipo cambiar la interfaz puede llevarmucho tiempo y ser propenso a errores No obstante si hizo un buen disentildeoacute deinterfaz puede cambiar la implementacioacuten sin cambiar la interfaz lo quesignifica que otras partes del programa no tienen que cambiar

Interfaz e implementacioacuten 225

DepuracioacutenLlamar a una funcioacuten con los argumentos correctos puede ser difiacutecil cuando seespecifica maacutes de un meacutetodo para la funcioacuten Julia permite examinar lasespecificaciones de los meacutetodos de una funcioacuten

Para saber queacute meacutetodos estaacuten disponibles para una funcioacuten determinada puedeusar la funcioacuten methods

juliagt methods(imprimirhora) 2 methods for generic function imprimirhora[1] printtime(timeMyTime) in Main at REPL[3]2[2] printtime(time) in Main at REPL[4]2

En este ejemplo la funcioacuten imprimirhora tiene 2 meacutetodos uno con un argumentoHora y otro con un argumento Any

Glosarioanotacioacuten de tipo

El operador seguido de un tipo que indica que una expresioacuten o unavariable es de ese tipo

meacutetodoUna definicioacuten de un posible comportamiento de una funcioacuten

dispatchLa eleccioacuten de queacute meacutetodo ejecutar cuando se ejecuta una funcioacuten

especificacioacutenEl nuacutemero y tipo de argumentos de un meacutetodo que permite al dispatchseleccionar el meacutetodo maacutes especiacutefico de una funcioacuten durante la llamada afuncioacuten

constructor externoConstructor definido fuera de la definicioacuten de tipo para definir meacutetodosuacutetiles para crear un objeto

constructor internoConstructor definido dentro de la definicioacuten de tipo para imponerinvariantes o para construir objetos recursivos

constructor por defectoConstructor interno que estaacute disponible cuando el usuario no defineconstructores internos

226 Capiacutetulo 17 Dispatch Muacuteltiple

constructor de copiaMeacutetodo de constructor externo de un tipo que tiene como uacutenico argumentoun objeto del tipo Crea un nuevo objeto que es una copia del argumento

sobrecarga de operadoresAmpliar el comportamiento de los operadores como ++ de modo quetrabajen con tipos definidos por el usuario

dispatch muacuteltipleDispatch basado en todos los argumentos de una funcioacuten

programacioacuten geneacutericaEscribir coacutedigo que pueda funcionar con maacutes de un tipo

Ejercicios

Ejercicio 17-4

Cambie los atributos de Hora para que sea un solo nuacutemero entero querepresente los segundos desde la medianoche Luego modifique los meacutetodosdefinidos en este capiacutetulo para que funcionen con la nueva implementacioacuten

Ejercicio 17-5

Escriba una definicioacuten para un tipo llamado Canguro con un atributo llamadocontenidodemarsupio de tipo Arreglo y los siguientes meacutetodos

bull Un constructor que inicialice contenidodemarsupio a un arreglo vaciacuteo

bull Un meacutetodo llamado ponerenmarsupio que tome un objeto Canguro y unobjeto de cualquier tipo y lo agregue a contenidodemarsupio

bull Un meacutetodo show que devuelva una representacioacuten de cadena del objetoCanguro y el contenido del marsupio

Pruebe su coacutedigo creando dos objetos Canguro asignaacutendolos a variablesllamadas cangu y ro y luego agregando ro al contenido del marsupio de cangu

Ejercicios 227

Capiacutetulo 18 SubtiposEn el capiacutetulo anterior se presentoacute el dispatch muacuteltiple y los meacutetodospolimoacuterficos Al no especificar el tipo de los argumentos de un meacutetodo este sepuede invocar con argumentos de cualquier tipo Ahora se veraacute coacutemo especificarun subconjunto de tipos permitidos en las especificaciones de un meacutetodo

En este capiacutetulo se explica el concepto de subtipo usando tipos que representannaipes mazos de naipes y manos de poacuteker

Si usted nunca ha jugado poacuteker puede leer sobre eacutel en httpseswikipediaorgwikiPC3B3quer aunque no es necesario ya que se explicaraacute todo lonecesario para los ejercicios

NaipesHay cincuenta y dos naipes en una baraja inglesa cada uno de los cualespertenece a uno de los cuatro palos y tiene un valor Los palos son Picas (spades)Corazones (hearts) Diamantes (diams) y Treacuteboles (clubs) Los valores son As (A) 2 3 4 5 67 8 9 10 Jota (J) Reina (Q) y Rey (K) Dependiendo del tipo de juego el valordel As puede ser mayor que al Rey o inferior al 2

Si queremos definir un nuevo objeto para representar un naipe son obvios losatributos que deberiacutea tener valor y palo Lo que no es tan obvio es el tipo que sedebe dar a estos atributos Una opcioacuten es usar cadenas de caracteres quecontengan palabras como Picas para los palos y Reina para los valores Unproblema de esta implementacioacuten es que no seriacutea faacutecil comparar naipes para vercuaacutel tiene mayor valor o palo

Una alternativa es usar nuacutemeros enteros para codificar los valores y palos Eneste contexto codificar significa definir una asociacioacuten entre nuacutemeros y paloso entre nuacutemeros y valores Este tipo de codificacioacuten no estaacute relacionada concifrar o traducir a un coacutedigo secreto (eso seriacutea cifrado)

Por ejemplo esta tabla muestra una correspondencia entre palos y coacutedigos(nuacutemeros) enteros

bull spades 4

bull hearts 3

bull diams 2

bull clubs 1

Este coacutedigo facilita la comparacioacuten de naipes los palos maacutes altos se asignan a losnuacutemeros maacutes altos por lo tanto podemos comparar los palos al comparar suscoacutedigos

228 Capiacutetulo 18 Subtipos

Estamos usando el siacutembolo para dejar en claro que estas asignaciones no sonparte de Julia Forman parte del disentildeo del programa pero no aparecenexpliacutecitamente en el coacutedigo

La definicioacuten de estructura de Naipe se ve asiacute

struct Naipe palo Int64 valor Int64 function Naipe(paloInt64 valorInt64) assert(1 le palo le 4 el palo no estaacute entre 1 y 4) assert(1 le valor le 13 el valor no estaacute entre 1 y 13) new(palo valor) endend

Para crear un Naipe se debe llamar a Naipe con el palo y el valor del naipedeseado

juliagt reina_de_diamantes = Naipe(2 12)Naipe(2 12)

Variables GlobalesPara poder imprimir los objetos Naipe de una manera que sea faacutecil de leer senecesita establecer una correspondencia entre los coacutedigos enteros y suscorrespondientes palos y valores Una manera natural de hacer esto es conarreglos de cadenas

const nombres_palo = [clubs diams hearts spades]const nombres_valor = [A 2 3 4 5 6 7 8 9 10J Q K]

Las variables nombres_palo y nombres_valor son variables globales Ladeclaracioacuten const significa que la variable solo se puede asignar una vez Estoresuelve el problema de rendimiento de las variables globales

Ahora se puede implementar un meacutetodo show apropiado

function Baseshow(ioIO naipeNaipe) print(io nombres_valor[naipevalor] nombres_palo[naipepalo])end

La expresioacuten nombres_valor[naipevalor] significa use el atributo valor delobjeto naipe como iacutendice en el arreglo nombres_valor y seleccione la cadena

Variables Globales 229

correspondiente

Con los meacutetodos que se tienen hasta ahora se pueden crear e imprimir naipes

juliagt Naipe(3 11)Jhearts

Comparacioacuten de naipesPara los tipos integrados existen operadores relacionales (lt gt == etc) quecomparan valores y determinan cuaacutendo uno es mayor menor o igual a otro Paralos tipos definidos por el usuario se puede sustituir el comportamiento de estosoperadores si se proporciona un meacutetodo llamado lt

El orden correcto de los naipes no es obvio Por ejemplo iquestcuaacutel es mejor el 3 deTreacuteboles o el 2 de Diamantes Uno tiene un valor mayor pero el otro tiene unpalo mayor Para hacer que los naipes sean comparables se debe decidir queacute esmaacutes importante valor o palo

La respuesta puede depender del tipo de juego pero para simplificar las cosasse establece la eleccioacuten arbitraria de que el palo es maacutes importante por lo quetodas los treacuteboles superan a todos los diamantes y asiacute sucesivamente

Con esa decisioacuten tomada se puede escribir lt

import Baselt

function lt(c1Naipe c2Naipe) (c1palo c1valor) lt (c2palo c2valor)end

Ejercicio 18-1

Escriba un meacutetodo lt para objetos Hora Puede usar comparacioacuten de tuplas ocomparacioacuten de enteros

Prueba unitariaUna prueba unitaria permite verificar el correcto funcionamiento de su coacutedigocomparando los resultados obtenidos con los esperados Esto puede ser uacutetil paraverificar que su coacutedigo funciona correctamente despueacutes de haberlo modificado ytambieacuten es una forma de predefinir el comportamiento correcto de su coacutedigodurante el desarrollo

Se pueden realizar pruebas unitarias simples con las macros test

230 Capiacutetulo 18 Subtipos

juliagt using Test

juliagt test Naipe(1 4) lt Naipe(2 4)Test Passedjuliagt test Naipe(1 3) lt Naipe(1 4)Test Passed

test devuelve Test Passed (Prueba aprobada) si la expresioacuten que sigue estrue Test Failed (Prueba fallida) si es false y Error Result (Resultado deerror) si no se pudo evaluar

MazosAhora que ya tenemos Naipes el proacuteximo paso es definir Mazos Como un mazoestaacute compuesto de naipes naturalmente cada Mazo contendraacute un arreglo denaipes como atributo

A continuacioacuten se muestra una definicioacuten para Mazo El constructor crea elatributo naipes y genera la baraja estaacutendar de cincuenta y dos naipes

struct Mazo naipes ArrayNaipe 1end

function Mazo() mazo = Mazo(Naipe[]) for palo in 14 for valor in 113 push(mazonaipes Naipe(palo valor)) end end mazoend

La forma maacutes faacutecil de poblar el mazo es mediante un bucle anidado El bucleexterior enumera los palos desde 1 hasta 4 El bucle interior enumera los valoresdesde 1 hasta 13 Cada iteracioacuten crea un nuevo Naipe con el palo y valor actualy lo agrega a mazonaipes

Este es un meacutetodo show para Mazo

Mazos 231

function Baseshow(ioIO mazoMazo) for naipe in mazonaipes print(io naipe ) end println()end

Asiacute es como se ve el resultado

juliagt Mazo()Aclubs 2clubs 3clubs 4clubs 5clubs 6clubs 7clubs 8clubs 9clubs 10clubs Jclubs Qclubs Kclubs Adiams 2diams 3diams 4diams 5diams 6diams 7diams 8diams 9diams 10diams JdiamsQdiams Kdiams Ahearts 2hearts 3hearts 4hearts 5hearts 6hearts 7hearts 8hearts 9hearts 10hearts Jhearts Qhearts Khearts Aspades 2spades 3spades 4spades 5spades 6spades 7spades 8spades 9spades10spades Jspades Qspades Kspades

Antildeadir Eliminar Barajar y OrdenarPara repartir los naipes se debe tener una funcioacuten que elimine un naipe delmazo y lo devuelva La funcioacuten pop proporciona una forma conveniente derealizar esto

function Basepop(mazoMazo) pop(mazonaipes)end

Como pop elimina el uacuteltimo naipe en el arreglo se estaacute repartiendo desde elextremo inferior del mazo

Para antildeadir un naipe se puede usar la funcioacuten push

function Basepush(mazoMazo naipeNaipe) push(mazonaipes naipe) mazoend

Un meacutetodo como este que usa otro meacutetodo sin hacer mucho maacutes se llamaenchapado La metaacutefora proviene de la carpinteriacutea donde un enchapado es unacapa fina de madera de alta calidad que se pega a la superficie de una pieza demadera de baja calidad para mejorar su apariencia

En este caso push es un meacutetodo fino que expresa una operacioacuten de arreglosadecuada para los mazos Mejora la apariencia o interfaz de la implementacioacuten

Tambieacuten podemos escribir un meacutetodo llamado shuffle (barajar en ingleacutes) usandola funcioacuten Randomshuffle

232 Capiacutetulo 18 Subtipos

using Random

function Randomshuffle(mazoMazo) shuffle(mazonaipes) mazoend

Ejercicio 18-2

Escriba una funcioacuten llamada sort (ordenar en ingleacutes) que use la funcioacuten sortpara ordenar las cartas en un Mazo sort usa el meacutetodo isless que definimospara determinar el orden

Tipos Abstractos y SubtiposSe busca que un tipo represente una mano es decir los naipes que tiene unjugador Una mano es similar a un mazo ambos estaacuten compuestos de unconjunto de naipes y ambos requieren de operaciones tales como agregar yeliminar una carta

Una mano es diferente de un mazo en ciertos aspectos ya que existen ciertasoperaciones sobre una mano que no tendriacutean sentido sobre un mazo Porejemplo en el poker se debe comparar una mano con otra para ver quieacuten ganaEn bridge se necesita calcular el puntaje de la mano para asiacute poder hacer lasubasta

Por lo tanto hace falta una forma de agrupar los tipos concretos que estaacutenrelacionados En Julia esto se hace definiendo un abstract type (tipo abstracto eningleacutes) que sea padre de Mazo y Mano A esto se le llama crear subtipos

Se llama al tipo abstracto ConjuntoDeCartas

abstract type ConjuntoDeCartas end

Se puede crear un nuevo tipo abstracto con la palabra reservada abstract typeDe manera opcional se puede especificar un tipo padre de una estructuracolocando despueacutes del nombre de esta el siacutembolo lt seguido del nombre de untipo abstracto existente

Cuando no se proporciona un supertipo el supertipo por defecto es Any es decirun tipo abstracto predefinido del que todos los objetos son instancias y del quetodos los tipos son subtipos

Ahora se puede expresar que Mazo es un hijo de ConjuntoDeCartas

Tipos Abstractos y Subtipos 233

struct Mazo lt ConjuntoDeCartas naipes ArrayNaipe 1end

function Mazo() mazo = Mazo(Naipe[]) for palo in 14 for valor in 113 push(mazonaipes Naipe(palo valor)) end end mazoend

El operador isa comprueba si un objeto es de un tipo dado

juliagt mazo = Mazo()

juliagt mazo isa ConjuntoDeCartastrue

Una mano tambieacuten es un ConjuntoDeCartas

struct Mano lt ConjuntoDeCartas naipes ArrayNaipe 1 etiqueta Stringend

function Mano(etiquetaString=) Mano(Naipe[] etiqueta)end

En lugar de llenar la mano con 52 naipes nuevos el constructor de Manoinicializa naipes a un arreglo vaciacuteo Se puede etiquetar a la Mano pasando unargumento opcional al constructor

juliagt mano = Mano(nueva mano)Mano(Naipe[] nueva mano)

Tipos Abstractos y FuncionesAhora podemos expresar las operaciones que tienen en comuacuten Mazo y Mano alser funciones que tienen como argumento a ConjuntoDeCartas

234 Capiacutetulo 18 Subtipos

function Baseshow(ioIO cdcConjuntoDeCartas) for naipe in cdcnaipes print(io naipe ) endend

function Basepop(cdcConjuntoDeCartas) pop(cdcnaipes)end

function Basepush(cdcConjuntoDeCartas naipeNaipe) push(cdcnaipes naipe) nothingend

Se puede usar pop y push para repartir una carta

juliagt mazo = Mazo()Aclubs 2clubs 3clubs 4clubs 5clubs 6clubs 7clubs 8clubs 9clubs 10clubs Jclubs Qclubs Kclubs Adiams 2diams 3diams 4diams 5diams 6diams 7diams 8diams 9diams 10diams JdiamsQdiams Kdiams Ahearts 2hearts 3hearts 4hearts 5hearts 6hearts 7hearts 8hearts 9hearts 10hearts Jhearts Qhearts Khearts Aspades 2spades 3spades 4spades 5spades 6spades 7spades 8spades 9spades10spades Jspades Qspades Kspadesjuliagt shuffle(mazo)10clubs 9hearts 7spades 2spades Ahearts 4clubs Jhearts 2diams 6clubs Qclubs 8diams 8hearts 3hearts 7clubs 3diams 2clubs Jclubs 8clubs 9diams 6spades 3spades 5spades Adiams Aclubs10hearts 4spades Qhearts Jdiams Kspades 10diams Khearts Kclubs 5clubs 5hearts 5diams 10spades 7diams 3clubs 9spades Aspades 2hearts 7hearts 9clubs Qdiams 6hearts 8spades Jspades 4diamsQspades 6diams Kdiams 4heartsjuliagt naipe = pop(mazo)4heartsjuliagt push(mano naipe)

A continuacioacuten se encapsula este coacutedigo en una funcioacuten llamada mover

function mover(cdc1ConjuntoDeCartas cdc2ConjuntoDeCartas nInt) assert 1 le n le length(cs1naipes) for i in 1n naipe = pop(cdc1) push(cdc2 naipe) end nothingend

mover toma tres argumentos dos objetos ConjuntoDeCartas y el nuacutemero decartas a repartir Modifica ambos objetos ConjuntoDeCartas y devuelve nothing

En algunos juegos las cartas se mueven de una mano a otra o de una mano almazo Puede usar mover para cualquiera de estas operaciones cdc1 y cdc2pueden ser un Mazo o una Mano

Tipos Abstractos y Funciones 235

Diagramas de tiposHasta ahora se han visto diagramas de pila que muestran el estado de unprograma y diagramas de objetos que muestran los atributos de un objeto y susvalores Estos diagramas son como una foto sacada durante la ejecucioacuten de unprograma por lo que cambian a medida que se ejecuta el programa

Tambieacuten son muy detallados en algunos casos demasiado detallados Undiagrama de tipos es una representacioacuten maacutes abstracta de la estructura de unprograma En vez de mostrar objetos individuales muestra los tipos y lasrelaciones entre ellos

Hay varias formas de relacioacuten entre tipos

bull Los objetos de un tipo concreto pueden contener referencias a objetos deotro tipo Por ejemplo cada Rectaacutengulo contiene una referencia a un Puntoy cada Mazo contiene referencias a un conjunto de Naipes Este tipo derelacioacuten se llama TIENE-UN como por ejemplo un Rectaacutengulo tiene unPunto

bull Un tipo concreto puede tener un tipo abstracto como supertipo Estarelacioacuten se llama ES-UN como por ejemplo una Mano es unConjuntoDeCartas

bull Un tipo puede depender de otro si los objetos de un tipo toman objetos delsegundo tipo como paraacutemetros o usan objetos del segundo tipo como partede un caacutelculo Este tipo de relacioacuten se llama dependencia

Figura 23 Diagrama de tipo

Cada una de las flechas superiores representa una relacioacuten ES-UN En este casoindica que Mano tiene como supertipo a ConjuntoDeCartas

Cada una de las flechas inferiores representa una relacioacuten TIENE-UN en estecaso un Mazo tiene referencias a objetos Naipe

El asterisco () cerca de la flecha es una multiplicidad e indica cuaacutentos Naipestiene un Mazo Una multiplicidad puede ser un nuacutemero simple como 52 unrango como 57 o un asterisco lo cual indica que un Mazo puede tener cualquiernuacutemero de Naipes

236 Capiacutetulo 18 Subtipos

No hay dependencias en este diagrama Normalmente se mostrariacutean con unaflecha achurada Si hay muchas dependencias a veces se omiten

Un diagrama maacutes detallado podriacutea mostrar que un Mazo en realidad contiene unarreglo de Naipes pero los tipos integrados como arreglos y diccionariosgeneralmente no se incluyen en los diagramas de tipos

DepuracioacutenUtilizar subtipos puede dificultar la depuracioacuten ya que al llamar a una funcioacutencon un objeto como argumento puede ser complicado determinar queacute meacutetodo seinvocaraacute

Al escribir una funcioacuten que funciona con objetos Mano se busca que funcionecon todo tipo de Manos como ManoDePoker ManoDeBridge etc Si el usuarioinvoca un meacutetodo como sort podriacutea obtener el meacutetodo definido para un tipoabstracto Mano pero si existiera un meacutetodo sort que tuviera como argumentocualquiera de estos subtipos de Mano obtendriacutea esa versioacuten Estecomportamiento suele ser algo bueno pero puede ser confuso

function Basesort(manoMano) sort(manonaipes)end

Si usted no estaacute seguro del flujo de ejecucioacuten de un programa la solucioacuten maacutessimple es agregar sentencias de impresioacuten al inicio de sus meacutetodos maacutesrelevantes Si shuffle imprimiera un mensaje como Ejecutando shuffle en Mazodurante la ejecucioacuten del programa seriacutea posible rastrear el flujo de ejecucioacuten

Una mejor alternativa es la macro which

juliagt which sort(mano)sort(manoMano) in Main at REPL[5]1

Entonces el meacutetodo sort de mano es el que tiene como argumento un objeto detipo Mano

Una sugerencia para el disentildeo del programa cuando anula un meacutetodo lainterfaz del nuevo meacutetodo deberiacutea ser la misma que la anterior Deberiacutea tomarlos mismos paraacutemetros devolver el mismo tipo y obedecer las mismascondiciones previas y posteriores Si sigue esta regla cualquier funcioacuten disentildeadapara funcionar con una instancia de un supertipo como un ConjuntoDeCartastambieacuten funcionaraacute con instancias de sus subtipos Mazo y Mano

Si viola esta regla llamada principio de sustitucioacuten de Liskov su coacutedigocolapsaraacute como un castillo de naipes (jeje)

Depuracioacuten 237

La funcioacuten supertype permite encontrar el supertipo directo de un tipo

juliagt supertype(Mazo)ConjuntoDeCartas

Encapsulado de DatosLos capiacutetulos anteriores muestran un plan de desarrollo que podriacuteamos llamardisentildeo orientado a tipos Se identifican los objetos necesarios como PuntoRectaacutengulo y Hora y se definen estructuras para representarlos En cada casohay una correspondencia obvia entre el objeto y alguna entidad en el mundo real(o al menos en el mundo matemaacutetico)

A veces no es tan obvio saber queacute objetos se necesitan y coacutemo estos debeninteractuar En ese caso se necesita un plan de desarrollo diferente Lo mismoque ocurre con interfaces de funciones por encapsulado y generalizacioacuten ocurrecon interfaces de tipo por encapsulado de datos

El anaacutelisis de Markov de Seccioacuten 138 es un buen ejemplo Si descarga el coacutedigodesde httpsgithubcomBenLauwensThinkJuliajlblobmastersrcsolutionschap13jl veraacute que se usan dos variables globales sufijos y prefijo las cuales seleen y escriben desde varias funciones

sufijos = Dict()prefijos = []

Debido a que estas variables son globales solo se puede ejecutar un anaacutelisis a lavez Si se leen dos textos sus prefijos y sufijos se agregariacutean a las mismasestructuras de datos (lo que generariacutea un texto interesante)

Para ejecutar muacuteltiples anaacutelisis y mantenerlos separados se puede encapsular elestado de cada anaacutelisis en un objeto Asiacute es como se veriacutea

struct Markov orden Int64 sufijos DictTupleStringVarargString ArrayString 1 prefijo ArrayString 1end

function Markov(ordenInt64=2) new(orden DictTupleStringVarargString ArrayString 1()ArrayString 1())end

A continuacioacuten se transforman las funciones en meacutetodos Por ejemplo para

238 Capiacutetulo 18 Subtipos

procesarpalabra

function procesarpalabra(markovMarkov palabraString) if length(markovprefijo) lt markovorden push(markovprefijo palabra) return end get(markovsufijos (markovprefijo) ArrayString 1()) push(markovsufijos[(markovprefijo)] palabra) popfirst(markovprefijo) push(markovprefijo palabra)end

Transformar un programa asiacute (cambiando el disentildeo sin cambiar elcomportamiento) es otro ejemplo de refactorizacioacuten (vea Seccioacuten 47)

Este ejemplo sugiere el siguiente plan de desarrollo para disentildear tipos

bull Comience escribiendo funciones que lean y escriban variables globales(cuando sea necesario)

bull Una vez que el programa esteacute funcionando busque asociaciones entre lasvariables globales y las funciones que las usan

bull Encapsule variables relacionadas como atributos de una estructura

bull Transforme las funciones asociadas en meacutetodos que tengan comoargumentos objetos del nuevo tipo

Exercise 18-3

Descargue el coacutedigo de Markov de httpsgithubcomBenLauwensThinkJuliajlblobmastersrcsolutionschap13jl y siga los pasos descritos anteriormente paraencapsular las variables globales como atributos de una nueva estructurallamada Markov

Glosariocodificar

Representar un conjunto de valores utilizando otro conjunto de valoresgenerando una asociacioacuten entre ellos

prueba unitariaManera estandarizada de probar que el coacutedigo estaacute correcto

enchapadoUn meacutetodo o funcioacuten que mejora la interfaz de otra funcioacuten sin hacermuchos caacutelculos

Glosario 239

crear subtiposLa capacidad de definir una jerarquiacutea de tipos relacionados

tipo abstractoUn tipo que puede ser padre de otro tipo

tipo concretoUn tipo que se puede construir

subtipoUn tipo que tiene como padre un tipo abstracto

supertipoUn tipo abstracto que es el padre de otro tipo

relacioacuten ES-UNUna relacioacuten entre un subtipo y su supertipo

relacioacuten TIENE-UNUna relacioacuten entre dos tipos donde las instancias de un tipo contienenreferencias a instancias del otro

dependenciaUna relacioacuten entre dos tipos donde las instancias de un tipo usan instanciasdel otro tipo pero no las almacenan como atributos

diagrama de tiposUn diagrama que muestra los tipos en un programa y las relaciones entreellos

multiplicidadUna notacioacuten en un diagrama de tipo que muestra para una relacioacutenTIENE-UN cuaacutentas referencias hay a instancias de otra clase

encapsulado de datosUn plan de desarrollo de programas que implica hacer un prototipo que usevariables globales y una versioacuten final que convierta las variables globales enatributos de instancia

Ejercicios

Ejercicio 18-4

Para el siguiente programa dibuje un diagrama de tipos que muestre estos tiposy las relaciones entre ellos

240 Capiacutetulo 18 Subtipos

abstract type PadrePingPong end

struct Ping lt PadrePingPong pong PadrePingPongend

struct Pong lt PadrePingPong pings ArrayPing 1 function Pong(pings=ArrayPing 1()) new(pings) endend

function agregarping(pongPong pingPing) push(pongpings ping) nothingend

pong = Pong()ping = Ping(pong)agregarping(pong ping)

Ejercicio 18-5

Escriba un meacutetodo llamado repartir que tome tres paraacutemetros un Mazo elnuacutemero de manos y el nuacutemero de naipes por mano Deberiacutea crear el nuacutemeroapropiado de objetos Mano repartir el nuacutemero apropiado de naipes por mano ydevolver un arreglo de Manos

Ejercicio 18-6

Las siguientes son las posibles manos en el poacuteker en orden de valor creciente yprobabilidad decreciente

parejaDos cartas del mismo nuacutemero

doble parejaDos pares de cartas del mismo nuacutemero

triacuteoTres cartas del mismo nuacutemero

escaleraCinco cartas consecutivas (los ases pueden ser considerados altos o bajospor lo tanto As-2-3-4-5 es escalera 10-Jota-Reina-Rey-As tambieacuten pero

Ejercicios 241

Reina-Rey-As-2-3 no)

colorCinco cartas del mismo palo

fullTres cartas iguales en su valor maacutes otras dos iguales en su valor

poacutekerCuatro cartas iguales en su valor

escalera de colorCinco cartas consecutivas del mismo palo

El objetivo de este ejercicio es estimar la probabilidad de tener cada una de estasmanos

1 Agregue meacutetodos llamados tienepareja tienedoblepareja etc quedevuelvan true o false seguacuten si la mano cumple o no con los criteriosrelevantes Su coacutedigo deberiacutea funcionar correctamente para manos quecontengan cualquier nuacutemero de naipes (aunque 5 y 7 son los tamantildeos maacutescomunes)

2 Escriba un meacutetodo llamado clasificar que descubra la clasificacioacuten de mayorvalor para una mano y defina el atributo etiqueta con esta clasificacioacuten Porejemplo una mano de 7 cartas que contiene un color y una pareja debeetiquetarse como color

3 Cuando esteacute convencido de que sus meacutetodos de clasificacioacuten estaacutenfuncionando correctamente estime las probabilidades de las distintasmanos Escriba una funcioacuten que baraje un mazo de naipes la divida endiferentes manos clasifique las manos y cuente la cantidad de veces queaparecen varias clasificaciones

4 Imprima una tabla de las clasificaciones y sus probabilidades Ejecute suprograma con un nuacutemero cada vez mayor de manos hasta que los valores desalida converjan con un grado razonable de precisioacuten Compare susresultados con los valores en httpsenwikipediaorgwikiHand_rankings

242 Capiacutetulo 18 Subtipos

Capiacutetulo 19 Extra SintaxisUno de los objetivos de este libro es ensentildearle lo justo y necesario de Julia Seexplica una sola forma de hacer las cosas y en ocasiones se deja como ejercicioal lector una segunda manera

Ahora se veraacuten algunos temas que se han dejado de lado pero que son uacutetilesJulia proporciona una serie de caracteriacutesticas que no son realmente necesarias(se puede escribir un buen coacutedigo sin ellas) pero a veces permiten escribir uncoacutedigo maacutes conciso legible yo eficiente

En este capiacutetulo y el siguiente se discute aquello que se ha omitido en loscapiacutetulos anteriores

bull maacutes sintaxis

bull funciones tipos y macros disponibles directamente de Base

bull funciones tipos y macros de la Biblioteca Estaacutendar (Standard Library)

Tuplas con nombreEs posible colocarle nombre a los componentes de una tupla creando una tuplacon nombre

juliagt x = (a=1 b=1+1)(a = 1 b = 2)juliagt xa1

En las tuplas con nombre se puede acceder a los atributos con su nombreutilizando la sintaxis de punto (xa)

FuncionesLas funciones en Julia tambieacuten se pueden definir mediante una sintaxiscompacta de la siguiente forma

juliagt f(xy) = x + yf (generic function with 1 method)

Funciones Anonimas

Podemos definir una funcioacuten sin especificar su nombre

Tuplas con nombre 243

juliagt x -gt x^2 + 2x - 11 (generic function with 1 method)juliagt function (x) x^2 + 2x - 1 end3 (generic function with 1 method)

Estos son ejemplos de funciones anoacutenimas Las funciones anoacutenimasgeneralmente se usan como argumento de otra funcioacuten

juliagt using Plots

juliagt plot(x -gt x^2 + 2x - 1 0 10 xlabel=x ylabel=y)

Figura 24 muestra el resultado del comando plot (graficar en ingleacutes)

Figura 24 Plot

Argumentos con nombre

Tambieacuten se puede poner nombre a los argumentos de una funcioacuten

juliagt function migrafico(x y style=continua width=1 color=negro) endmigrafico (generic function with 1 method)juliagt migrafico(010 010 style=dotted color=blue)

Los argumentos con nombre en una funcioacuten se especifican despueacutes de un punto ycoma en la especificacioacuten pero al llamar a la funcioacuten se pueden utilizar solocomas

244 Capiacutetulo 19 Extra Sintaxis

Clausuras

Una clausura es una teacutecnica que permite que una funcioacuten capture una variabledefinida fuera del aacutembito de la funcioacuten

juliagt foo(x) = ()-gtxfoo (generic function with 1 method)

juliagt bar = foo(1)1 (generic function with 1 method)

juliagt bar()1

En este ejemplo la funcioacuten foo devuelve una funcioacuten anoacutenima que tiene acceso alargumento x de la funcioacuten foo bar apunta a la funcioacuten anoacutenima y devuelve elvalor del argumento de foo

BloquesUn bloque es una forma de agrupar varias sentencias Un bloque comienza con lapalabra reservada begin y termina con end

En Capiacutetulo 4 se presentoacute la macro svg

ὂ = Turtle()svg begin forward(ὂ 100) turn(ὂ -90) forward(ὂ 100)end

En este ejemplo la macro svg tiene un uacutenico argumento un bloque queagrupa 3 llamadas a funciones

Bloques let

Un bloque let es uacutetil para crear nuevas ligaduras (o bindings) es decir variableslocales que pueden apuntar a valores

Bloques 245

juliagt x y z = -1 -1 -1

juliagt let x = 1 z show x y z endx = 1y = -1ERROR UndefVarError z not definedjuliagt show x y zx = -1y = -1z = -1

En el ejemplo la primera macro show muestra la variable local x la variableglobal y y la variable local indefinida z Las variables globales se mantienenintactas

Bloques do

En Seccioacuten 142 se cierra el archivo despueacutes de terminar de escribir en eacutel Estose puede hacer automaacuteticamente usando un Bloque do

juliagt datos = El Cid convoca a sus vasallosneacutestos se destierran coneacutelnEl Cid convoca a sus vasallosneacutestos se destierran con eacutelnjuliagt open(salidatxt w) do fout write(fout datos) end61

En este ejemplo fout es el archivo stream utilizado para la salida

Esto es equivalente a

juliagt f = fout -gt begin write(fout datos) end3 (generic function with 1 method)juliagt open(f salidatxt w)61

La funcioacuten anoacutenima se utiliza como primer argumento de la funcioacuten open

246 Capiacutetulo 19 Extra Sintaxis

function open(fFunction args) io = open(args) try f(io) finally close(io) endend

Un bloque do puede capturar variables de su aacutembito envolvente (enclosedscope) Por ejemplo la variable datos en el ejemplo anterior de open do escapturada desde el aacutembito externo

Estructuras de control

Operador ternario

El operador ternario puede utilizarse en vez de una sentencia if-elseif Estasentencia se usa cuando se necesita elegir entre diferentes expresiones con valoruacutenico

juliagt a = 150150juliagt a 2 == 0 println(par) println(impar)par

La expresioacuten que va antes de es una expresioacuten de condicioacuten Si la condicioacuten estrue se evaluacutea la expresioacuten que va antes de De lo contrario se evaluacutea laexpresioacuten que va despueacutes de

Evaluacioacuten de cortocircuito

Los operadores ampamp y || realizan una evaluacioacuten de cortocircuito es decir seevaluacutea el siguiente argumento solo cuando es necesario para determinar el valorfinal

Por ejemplo una funcioacuten factorial recursiva podriacutea definirse asiacute

function fact(nInteger) n gt= 0 || error(n debe ser no negativo) n == 0 ampamp return 1 n fact(n-1)end

Estructuras de control 247

Tarea (o Corrutina)

Una tarea es una estructura de control que puede ceder el control de formacooperativa sin hacer return En Julia una tarea puede implementarse como unafuncioacuten con un objeto Channel como primer argumento Se usa un channel parapasar valores de la funcioacuten a la sentencia que la llama

El teacutermino cooperativo alude a que los programas deben cooperar para quetodo el esquema de programacioacuten funcione

La secuencia de Fibonnaci se puede generar mediante una tarea

function fib(cChannel) a = 0 b = 1 put(c a) while true put(c b) (a b) = (b a+b) endend

put almacena valores en un objeto channel y take lee valores desde eacutel

juliagt fib_gen = Channel(fib)

juliagt take(fib_gen)0juliagt take(fib_gen)1juliagt take(fib_gen)1juliagt take(fib_gen)2juliagt take(fib_gen)3

El constructor Channel crea la tarea La funcioacuten fib se suspende despueacutes de cadallamada a put y se reanuda al llamar a take Por razones de rendimiento sealmacenan varios valores de la secuencia en el objeto channel durante un ciclode reanudacioacutensuspensioacuten

Un objeto channel tambieacuten se puede usar como iterador

248 Capiacutetulo 19 Extra Sintaxis

juliagt for val in Channel(fib) print(val ) val gt 20 ampamp break end0 1 1 2 3 5 8 13 21

Tipos

Tipos Primitivos

Un tipo concreto compuesto por bits se llama tipo primitivo A diferencia de lamayoriacutea de los lenguajes en Julia se puede declarar nuestros propios tiposprimitivos Los tipos primitivos estaacutendar se definen de la misma manera

primitive type Float64 lt AbstractFloat 64 endprimitive type Bool lt Integer 8 endprimitive type Char lt AbstractChar 32 endprimitive type Int64 lt Signed 64 end

El nuacutemero en las sentencias especifica cuaacutentos bits son necesarios

El siguiente ejemplo crea un tipo primitivo Byte y un constructor

juliagt primitive type Byte 8 end

juliagt Byte(valUInt8) = reinterpret(Byte val)Bytejuliagt b = Byte(0x01)Byte(0x01)

La funcioacuten reinterpret se usa para almacenar los bits de un entero sin signo con8 bits (UInt8) en el byte

Tipos Parameacutetricos

El sistema de tipos de Julia es parameacutetrico lo que significa que los tipos puedentener paraacutemetros

Los paraacutemetros de un tipo se colocan despueacutes del nombre del tipo entre llaves

struct PuntoTltReal xT yTend

Tipos 249

Con esto se define un nuevo tipo parameacutetrico PuntoTltReal que contiene doscoordenadas de tipo T que puede ser cualquier tipo que tenga Real comosupertipo

juliagt Punto(00 00)PuntoFloat64(00 00)

Ademaacutes de los tipos compuestos los tipos abstractos y los tipos primitivostambieacuten pueden tener paraacutemetros

OBSERVACIOacuteN

Para mejorar el rendimiento es totalmenterecomendable tener tipos concretos como atributos deuna estructura por lo que esta es una buena manera dehacer que Punto sea raacutepido y flexible

Union de Tipo

Una union de tipo es un tipo parameacutetrico abstracto que puede actuar comocualquiera de los tipos de sus argumentos

juliagt EnteroOCadena = UnionInt64 StringUnionInt64 Stringjuliagt 150 EnteroOCadena150juliagt Julia EnteroOCadenaJulia

Una unioacuten de tipos es en la mayoriacutea de los lenguajes informaacuteticos unaconstruccioacuten interna para trabajar con tipos Sin embargo Julia pone adisposicioacuten esta caracteriacutestica para sus usuarios ya que permite generar uncoacutedigo eficiente (cuando la unioacuten es entre pocos tipos) Esta caracteriacutestica otorgauna gran flexibilidad para controlar el dispatch

Meacutetodos

Meacutetodos Parameacutetricos

Las definiciones de meacutetodos tambieacuten pueden tener paraacutemetros de tipo quelimiten su especificacioacuten

250 Capiacutetulo 19 Extra Sintaxis

juliagt espuntoentero(pPuntoT) where T = (T === Int64)espuntoentero (generic function with 1 method)juliagt p = Punto(1 2)PuntoInt64(1 2)juliagt espuntoentero(p)true

Objetos Similares a Funciones

Cualquier objeto arbitrario de Julia puede hacerse invocable Tales objetosinvocables a veces se denominan funtores

struct PolinomioR coefVectorRend

function (pPolinomio)(x) val = pcoef[end] for coef in pcoef[end-1-11] val = val x + coef end valend

Para evaluar el polinomio simplemente debemos llamarlo

juliagt p = Polinomio([110100])PolinomioInt64([1 10 100])juliagt p(3)931

ConstructoresLos tipos parameacutetricos se pueden construir expliacutecita o impliacutecitamente

juliagt Punto(12) T implicitoPuntoInt64(1 2)juliagt PuntoInt64(1 2) T explicitoPuntoInt64(1 2)juliagt Punto(125) T implicitoERROR MethodError no method matching Punto(Int64 Float64)

Se generan constructores internos y externos por defecto para cada T

Constructores 251

struct PuntoTltReal xT yT PuntoT(xy) where TltReal = new(xy)end

Punto(xT yT) where TltReal = PuntoT(xy)

y tanto x como y deben ser del mismo tipo

Cuando x e y son de tipos diferentes se puede definir el siguiente constructorexterno

Punto(xReal yReal) = Punto(promote(xy))

La funcioacuten promote se detalla en Seccioacuten 1982

Conversioacuten y PromocioacutenJulia tiene un sistema para convertir argumentos de diferentes tipos a un tipocomuacuten Esto es llamado promocioacuten y aunque no es automaacutetico se puede realizarfaacutecilmente

Conversioacuten

Un valor se puede convertir de un tipo a otro

juliagt x = 1212juliagt typeof(x)Int64juliagt convert(UInt8 x)0x0cjuliagt typeof(ans)UInt8

Se pueden agregar nuestros propios meacutetodos convert

juliagt Baseconvert(TypePuntoT xArrayT 1) where TltReal =Punto(x)

juliagt convert(PuntoInt64 [1 2])PuntoInt64(1 2)

252 Capiacutetulo 19 Extra Sintaxis

Promocioacuten

Promocioacuten es la conversioacuten de valores de diferentes tipos a un solo tipo comuacuten

juliagt promote(1 25 3)(10 25 30)

Generalmente los meacutetodos para la funcioacuten promote no se definen directamentesino que se usa la funcioacuten auxiliar promot_rule para especificar las reglas de lapromocioacuten

promote_rule(TypeFloat64 TypeInt32) = Float64

MetaprogramacioacutenUn coacutedigo de Julia se puede representar como una estructura de datos del mismolenguaje Esto permite que un programa escriba y manipule su propio coacutedigo

Expresiones

Cada programa de Julia comienza como una cadena

juliagt prog = 1 + 21 + 2

El siguiente paso es analizar cada cadena en un objeto llamado expresioacutenrepresentado por el tipo de Julia Expr

juliagt ex = Metaparse(prog)(1 + 2)juliagt typeof(ex)Exprjuliagt dump(ex)Expr head Symbol call args ArrayAny((3)) 1 Symbol + 2 Int64 1 3 Int64 2

La funcioacuten dump muestra objetos expr con anotaciones

Las expresiones se pueden construir directamente con el prefijo entrepareacutentesis o usando un bloque quote

Metaprogramacioacuten 253

juliagt ex = quote 1 + 2 end

eval

Julia puede evaluar un objeto de expresioacuten usando la funcioacuten eval

juliagt eval(ex)3

Cada moacutedulo tiene su propia funcioacuten eval que evaluacutea las expresiones de suaacutembito

AVISO Generalmente si un coacutedigo tiene muchas llamadas a eval significaque algo estaacute mal eval se considera malo

Macros

Las macros pueden incluir coacutedigo generado en un programa Una macro asociauna tupla de objetos Expr directamente con una expresioacuten compilada

Aquiacute hay una macro simple

macro contenedorvariable(contenedor elemento) return esc(($(Symbol(contenedorelemento)) = $contenedor[$elemento]))end

Las macros se llaman anteponiendo (arroba) a su nombre La llamada a lamacro contenedorvariable letras 1 se reemplaza por

(letras1 = letras[1])

macroexpand contenedorvariable letras 1 returns this expression which isextremely useful for debugging

Este ejemplo ilustra coacutemo una macro puede acceder al nombre de susargumentos algo que una funcioacuten no puede hacer Se debe escapar de laexpresioacuten de retorno con esc porque debe resolverse en el entorno de la macrollamada

254 Capiacutetulo 19 Extra Sintaxis

NOTA

iquestPor queacute usar Macros

Las macros generan e incluyen fragmentos de coacutedigopersonalizado durante el tiempo de anaacutelisis es decir antes deejecutar el programa completo

Funciones Generadas

La macro generated crea coacutedigo especializado para meacutetodos dependiendo deltipo de los argumentos

generated function cuadrado(x) println(x) (x x)end

El cuerpo devuelve una expresioacuten citada como una macro

Para la sentencia que llama la funcioacuten generada se comporta como una funcioacutennormal

juliagt x = cuadrado(2) nota la salida es de la instruccioacuten println ()que estaacute en el cuerpoInt64juliagt x ahora imprimimos x4juliagt y = cuadrado(spam)Stringjuliagt yspamspam

Datos FaltantesLos datos faltantes se pueden representar a traveacutes del objeto missing que es lainstancia uacutenica del tipo Missing

Los arreglos pueden contener datos que faltan missing values en ingleacutes

juliagt a = [1 missing]2-element ArrayUnionMissing Int641 1 missing

El tipo de dicho arreglo es UnionMissing T doacutende T es el tipo de los valoresque realmente tenemos en el arreglo

Datos Faltantes 255

Las funciones de reduccioacuten devuelven missing cuando se invocan con arreglosque contienen valores que faltan

juliagt sum(a)missing

En este caso se puede usar la funcioacuten skipmissing para omitir los valores quefaltan

juliagt sum(skipmissing([1 missing]))1

Llamar a Coacutedigo de C y FortranSe escribe mucho coacutedigo en C o Fortran Reutilizar un coacutedigo que ya ha sidoprobado generalmente es mejor que escribir su propia versioacuten en otro lenguajeJulia puede llamar directamente a las bibliotecas C o Fortran existentesutilizando la sintaxis ccall

En Seccioacuten 146 se presentoacute una interfaz de Julia de la biblioteca GDBM defunciones de base de datos La biblioteca estaacute escrita en C Para cerrar la base dedatos se debe hacer una llamada a la funcioacuten close(db)

Baseclose(dbmDBM) = gdbm_close(dbmhandle)

function gdbm_close(handlePtrCvoid) ccall((gdbm_close libgdbm) Cvoid (PtrCvoid) handle)end

Un objeto dbm tiene un atributo handle de tipo PtrCvoid Este atributocontiene un puntero de C que apunta a la base de datos Para cerrar la base dedatos debe llamarse a la funcioacuten de C gdbm_close teniendo como uacutenicoargumento el puntero C apuntando a la base de datos sin valor de retorno Juliahace esto directamente con la funcioacuten ccall que tiene como argumentos

bull una tupla que consiste en un siacutembolo que contiene el nombre de la funcioacutenque queremos llamar gdbm_close y la libreriacutea compartida especificadacomo una cadena +libgdm

bull el tipo de retorno Cvoid

bull una tupla de tipos de argumentos (PtrCvoid)

bull los valores del argumento handle

Una visioacuten completa de la libreriacutea GDBM se puede encontrar como ejemplo enlas fuentes de ThinkJulia

256 Capiacutetulo 19 Extra Sintaxis

Glossaryclausura

Funcioacuten que captura variables del aacutembito en doacutende estaacute definida

bloque letBloque de asignacioacuten de nuevas ligaduras variables

funcioacuten anoacutenimaFuncioacuten definida sin nombre

tupla con nombreTupla con componentes con nombre

argumentos con nombreArgumentos identificados por su nombre en vez de solo por la posicioacuten queocupan

bloque doConstruccioacuten usada para definir y llamar a una funcioacuten anoacutenima parecida aun bloque de coacutedigo normal

operador ternarioOperador de estructura de control que toma tres operandos una condicioacutenuna expresioacuten que se ejecutaraacute si la condicioacuten devuelve true y una expresioacutenque se ejecutaraacute si la condicioacuten devuelve false

evaluacioacuten de cortocircuitoEvaluacioacuten de un operador booleano para el que se ejecuta o evaluacutea elsegundo argumento solo si el primero no es suficiente para determinar elvalor de la expresioacuten

tareas (corrutina)Caracteriacutestica de las estructuras de control que permite suspender yreanudar caacutelculos de manera flexible

tipo primitivoTipo concreto cuyos datos estaacuten compuestos de bits

unioacuten de tiposTipo que incluye todas las instancias de cualquiera de sus tipos deparaacutemetros como objetos

Glossary 257

tipo parameacutetricoTipo que tiene paraacutemetros

funtorObjeto con un meacutetodo asociado para que sea invocable

conversioacutenPermite convertir un valor de un tipo a otro

promocioacutenConversioacuten de valores de diferentes tipos a un solo tipo comuacuten

expresioacutenTipo de Julia que contiene una construccioacuten de lenguaje

macroForma de incluir el coacutedigo generado en el cuerpo final de un programa

funciones generadasFunciones capaces de generar coacutedigo especializado seguacuten el tipo de losargumentos

datos faltantesInstancias que representan datos sin valor

258 Capiacutetulo 19 Extra Sintaxis

Capiacutetulo 20 Extra Base y Libreriacutea EstaacutendarJulia tiene todo lo necesario El moacutedulo Base contiene las funciones tipos ymacros maacutes uacutetiles los cuales estaacuten disponibles directamente en Julia

Julia tambieacuten posee una gran cantidad de moacutedulos especializados en suBiblioteca Estaacutendar (moacutedulos para fechas computacioacuten distribuida aacutelgebralineal perfiles nuacutemeros aleatorios entre otros) Las funciones los tipos y lasmacros definidos en la Biblioteca Estaacutendar deben importarse antes de poderusarse

bull import _Module_ importa el modulo y _Modulefn_(x) llama a la funcioacuten _fn_

bull using _Module_ importa todas las funciones tipos y macros exportadas de_Module_

Ademaacutes es posible agregar maacutes funciones a una gran cantidad de paquetes(httpsjuliaobservercom)

Este capiacutetulo no es un reemplazo de la documentacioacuten oficial de Julia Soacutelo sedan algunos ejemplos para ilustrar lo que es posible hacer sin ser exhaustivoLas funciones ya vistas no estaacuten incluidas Se puede encontrar una explicacioacutenmaacutes completa en httpsdocsjulialangorg

Midiendo el RendimientoHemos visto que algunos algoritmos funcionan mejor que otros fibonnaci enSeccioacuten 116 es mucho maacutes raacutepido que fib en Seccioacuten 67 La macro timepermite cuantificar la diferencia

juliagt fib(1)1juliagt fibonacci(1)1juliagt time fib(40) 0567546 seconds (5 allocations 176 bytes)102334155juliagt time fibonacci(40) 0000012 seconds (8 allocations 1547 KiB)102334155

time imprime el tiempo que tardoacute en ejecutarse la funcioacuten el nuacutemero deasignaciones (allocations) y la memoria asignada antes de devolver el resultadoLa funcioacuten fibonacci que guarda resultados previos es mucho maacutes raacutepida peronecesita maacutes memoria

Midiendo el Rendimiento 259

El teorema No free lunch dice que no existe un uacutenico modelo que funcionemejor en todos los casos

OBSERVACIOacuteN

Para comparar dos algoritmos estos debenimplementarse como funciones Una funcioacuten en Julia secompila la primera vez que se ejecuta por lo tanto sedebe excluir la primera vez que se llama a estasfunciones al medir el rendimiento De lo contrariotambieacuten se mediriacutea el tiempo de compilacioacuten

El paquete BenchmarkTools (httpsgithubcomJuliaCIBenchmarkToolsjl) proporciona la macro btime querealiza una evaluacioacuten comparativa de la maneracorrecta iexclAsiacute que uacutesela

Colecciones y Estructuras de DatosEn Seccioacuten 136 se usan diccionarios para encontrar las palabras que apareciacuteanen un documento y que no apareciacutean en un arreglo de palabras La funcioacuten quese escribioacute tomaba d1 que conteniacutea las palabras del documento como claves yd2 que conteniacutea el arreglo de palabras Y devolviacutea un diccionario que conteniacutealas claves de d1 que no estaban en d2

function resta(d1 d2) res = Dict() for clave in keys(d1) if clave notin keys(d2) res[clave] = nothing end end resend

En todos estos diccionarios los valores son nothing porque nunca son usadosCon esto se estaacute desperdiciando espacio de almacenamiento

Julia ofrece otro tipo integrado llamado conjunto que se comporta como unacoleccioacuten de claves de diccionario sin valores Agregar elementos a un conjuntoes raacutepido y tambieacuten lo es verificar si un elemento forma parte de eacutel Ademaacutes losconjuntos proporcionan funciones y operadores para calcular operaciones deconjuntos

Por ejemplo la resta de conjuntos estaacute disponible como una funcioacuten llamadasetdiff Entonces reescribiendo resta

260 Capiacutetulo 20 Extra Base y Libreriacutea Estaacutendar

function resta(d1 d2) setdiff(d1 d2)end

El resultado es un conjunto en vez de un diccionario

Algunos de los ejercicios en este libro se pueden hacer de manera eficiente yconcisa con conjuntos Por ejemplo a continuacioacuten se muestra una solucioacuten pararepetido de Seccioacuten 10157 que usa un diccionario

function repetido(t) d = Dict() for x in t if x isin d return true end d[x] = nothing end falseend

Cuando un elemento aparece por primera vez se agrega al diccionario Si elmismo elemento aparece nuevamente la funcioacuten devuelve true

Usando conjuntos podemos escribir la misma funcioacuten

function repetido(t) length(Set(t)) lt length(t)end

Un elemento solo puede aparecer en un conjunto una vez por lo que si unelemento en t aparece maacutes de una vez el conjunto seraacute maacutes pequentildeo que t Si nohay elementos repetidos el conjunto tendraacute el mismo tamantildeo que t

Tambieacuten podemos usar conjuntos para hacer algunos de los ejercicios deCapiacutetulo 9 Por ejemplo aquiacute hay una versioacuten de usasolo con un bucle

function usasolo(palabra disponibles) for letra in palabra if letra notin disponibles return false end end trueend

Colecciones y Estructuras de Datos 261

usasolo comprueba si todas las letras en palabra estaacuten en disponibles Podemosreescribir esta funcioacuten

function usasolo(palabra disponibles) Set(palabra) sube Set(disponibles)end

El operador sube (subseteq TAB) verifica si un conjunto es un subconjunto deotro incluida la posibilidad de que sean iguales lo cual es cierto si todas lasletras en palabra aparecen en disponibles

Exercise 20-1

Reescriba la funcioacuten evita de Capiacutetulo 9 usando conjuntos

MatemaacuteticasTambieacuten se pueden usar nuacutemeros complejos en Julia La constante global im estaacuteasociada al nuacutemero complejo que representa la raiacutez cuadrada principal de

Ahora se puede verificar la identidad de Euler

juliagt ℯ^(imπ)+100 + 12246467991473532e-16im

El siacutembolo ℯ (euler TAB) es la base de los logaritmos naturales

Se puede analizar la naturaleza compleja de las funciones trigonomeacutetricas

Se puede probar esta foacutermula para diferentes valores de

juliagt x = 0012π000162juliagt cos(x) == 05(ℯ^(imx)+ℯ^(-imx))true

Aquiacute se muestra otro ejemplo del operador punto Julia tambieacuten permite usarvalores numeacutericos con identificadores (siacutembolos leacutexicos que nombran entidadescomo π) como en 2π

262 Capiacutetulo 20 Extra Base y Libreriacutea Estaacutendar

CadenasEn Capiacutetulo 8 y Capiacutetulo 9 se realizan algunas buacutesquedas en cadenas AdemaacutesJulia puede usar expresiones regulares (o regexes) compatibles con Perl lo quefacilita la tarea de encontrar patrones complejos en cadenas

La funcioacuten usasolo se puede implementar como una expresioacuten regular

function usasolo(palabra disponibles) r = Regex([^$(disponibles)]) occursin(r palabra)end

La expresioacuten regular busca un caraacutecter que no estaacute en la cadena disponible yoccursin devuelve true si el patroacuten se encuentra en palabra

juliagt usasolo(banana abn)truejuliagt usasolo(bananas abn)false

Las expresiones regulares tambieacuten se pueden construir como literales de cadenano estaacutendar con el prefijo r

juliagt match(r[^abn] banana)

juliagt m = match(r[^abn] bananas)RegexMatch(s)

En este caso la interpolacioacuten de cadenas no estaacute permitida La funcioacuten matchdevuelve nothing si no se encuentra el patroacuten de lo contrario devuelve un objetoregexmatch

Podemos extraer la siguiente informacioacuten de un objeto regexmatch

bull La subcadena que coincide mmatch

bull Las subcadenas que coinciden en forma de arreglo de cadenas mcaptures

bull La primera posicioacuten en la que se encuentra el patroacuten moffset

bull Las posiciones de las subcadenas que coinciden en forma de arreglomoffsets

Cadenas 263

juliagt mmatchsjuliagt moffset7

Las expresiones regulares son extremadamente poderosas y el manual de PERLhttpperldocperlorgperlrehtml explica coacutemo realizar hasta las buacutesquedas maacutesextrantildeas

ArreglosEn el Capiacutetulo 10 se usa un objeto de arreglo unidimensional con un iacutendice paraacceder a sus elementos Sin embargo en Julia las matrices sonmultidimensionales

Se puede crear una matriz de ceros de 2 por 3

juliagt z = zeros(Float64 2 3)2times3 ArrayFloat642 00 00 00 00 00 00juliagt typeof(z)ArrayFloat642

El tipo de esta matriz es un arreglo que contiene nuacutemeros de punto flotante Estamatriz es de 2 dimensiones

La funcioacuten size devuelve una tupla con el nuacutemero de elementos en cadadimensioacuten

juliagt size(z)(2 3)

La funcioacuten ones construye una matriz con elementos de valor unitario

juliagt s = ones(String 1 3)1times3 ArrayString2

El elemento de valor unitario de una cadena es una cadena vaciacutea

264 Capiacutetulo 20 Extra Base y Libreriacutea Estaacutendar

AVISO

s no es un arreglo unidimensional

juliagt s == [ ]false

s es un vector fila y [ ] es un vector columna

Se puede crear una matriz usando espacios para separar elementos en una fila ypunto y coma para separar filas

juliagt a = [1 2 3 4 5 6]2times3 ArrayInt642 1 2 3 4 5 6

Se pueden usar corchetes para modificar elementos de una matriz

juliagt z[12] = 11juliagt z[23] = 11juliagt z2times3 ArrayFloat642 00 10 00 00 00 10

Se pueden usar porciones en cada dimensioacuten para seleccionar un subgrupo deelementos

juliagt u = z[2end]2times2 ArrayFloat642 10 00 00 10

El operador aplica una operacioacuten en todas las dimensiones

juliagt ℯ^(imu)2times2 ArrayComplexFloat642 0540302+0841471im 10+00im 10+00im 0540302+0841471im

Arreglos 265

InterfacesJulia especifica algunas interfaces informales para definir comportamientos esdecir meacutetodos con un objetivo especiacutefico Cuando se extienden estos meacutetodospara un tipo los objetos de ese tipo se pueden usar para construir estoscomportamientos

Si parece un pato nada como un pato y grazna como un pato entoncesprobablemente sea un pato

En Seccioacuten 67 implementamos la funcioacuten fib que devuelve el elemento -eacutesimode la secuencia de Fibonnaci

Recorrer los valores de una coleccioacuten lo cual recibe el nombre de iteracioacuten esuna interfaz de este tipo Se puede crear un iterador que devuelva la secuenciade Fibonacci

struct FibonacciTltReal endFibonacci(dDataType) = dltReal Fibonaccid() error(No Real type)

Baseiterate(FibonacciT) where TltReal = (zero(T) (one(T) one(T)))Baseiterate(FibonacciT stateTupleT T) where TltReal =(state[1] (state[2] state[1] + state[2]))

Se implementa un tipo parameacutetrico Fibonacci sin atributos un constructorexterno y dos meacutetodos iterate Se llama al primer meacutetodo iterate para inicializarel iterador y este devuelve una tupla que consta de un primer valor 0 y unestado El estado en este caso es una tupla que contiene el segundo y el tercervalor 1 y 1

Se llama al segundo meacutetodo iterate para obtener el siguiente valor de lasecuencia de Fibonacci y devuelve una tupla que tiene como primer elemento elsiguiente valor y como segundo elemento el estado que es una tupla con los dosvalores siguientes

Ahora se puede usar Fibonacci en un bucle for

juliagt for e in Fibonacci(Int64) e gt 100 ampamp break print(e ) end0 1 1 2 3 5 8 13 21 34 55 89

Parece sacado debajo de la manga pero la explicacioacuten es simple Un bucle for enJulia

266 Capiacutetulo 20 Extra Base y Libreriacutea Estaacutendar

for i in iter bodyend

se traduce en

next = iterate(iter)while next == nothing (i state) = next body next = iterate(iter state)end

Este es un ejemplo de coacutemo una interfaz bien definida permite que unaimplementacioacuten use todas las funciones disponibles en esta interfaz

Moacutedulo Interactive UtilitiesYa se ha visto el moacutedulo InteractiveUtils en Seccioacuten 1810 La macro which essolo una de las tantas opciones

La biblioteca LLVM transforma el coacutedigo de Julia en coacutedigo de maacutequina envarios pasos Podemos visualizar la salida de cada etapa

Aquiacute se muestra un ejemplo simple

function sumacuadrada(aFloat64 bFloat64) a^2 + b^2end

El primer paso es mirar el coacutedigo de bajo nivel (lowered code)

juliagt using InteractiveUtils

juliagt code_lowered sumacuadrada(30 40)CodeInfo(1 1 = Coreapply_type(BaseVal 2) 2 = (1)() 3 = Baseliteral_pow(^ a 2) 4 = Coreapply_type(BaseVal 2) 5 = (4)() 6 = Baseliteral_pow(^ b 5) 7 = 3 + 6 return 7)

Moacutedulo Interactive Utilities 267

La macro code_lowered devuelve un arreglo de una representacioacuten intermediadel coacutedigo que utiliza el compilador para generar coacutedigo optimizado

El siguiente paso antildeade informacioacuten del tipo

juliagt code_typed sumacuadrada(30 40)CodeInfo(1 1 = Basemul_float(a a)Float64 2 = Basemul_float(b b)Float64 3 = Baseadd_float(1 2)Float64 return 3) =gt Float64

El tipo de resultados intermedios y el valor de retorno se infiere correctamente

Esta representacioacuten del coacutedigo se transforma en coacutedigo LLVM

juliagt code_llvm sumacuadrada(30 40) none1 within `sumacuadradadefine double julia_sumacuadrada_6080(double double) top none2 within `sumacuadrada intfuncsjl296 within `literal_pow floatjl405 within ` 2 = fmul double 0 0 3 = fmul double 1 1 floatjl401 within `+ 4 = fadd double 2 3 ret double 4

Y finalmente se genera el coacutedigo de maacutequina

268 Capiacutetulo 20 Extra Base y Libreriacutea Estaacutendar

juliagt code_native sumacuadrada(30 40) text none2 within `sumacuadrada intfuncsjl296 within `literal_pow floatjl405 within ` vmulsd xmm0 xmm0 xmm0 vmulsd xmm1 xmm1 xmm1 floatjl401 within `+ vaddsd xmm1 xmm0 xmm0 retq nopl (rax)

DepuracioacutenLas macros Logging son una alternativa al andamiaje con sentencias deimpresioacuten

juliagt warn iexclOh vosotros los que entraacuteis abandonad la depuracioacuten conprintf Warning iexclOh vosotros los que entraacuteis abandonad la depuracioacuten conprintf Main REPL[1]1

Las sentencias de depuracioacuten (debug) no tienen que eliminarse del coacutedigo Porejemplo en contraste con el warn anterior

juliagt debug La suma de algunos valores $(sum(rand(100)))

debug por defecto no produce salida En este caso sum(rand(100)) nunca seevaluaraacute a menos que debug logging esteacute habilitado

El nivel de logging puede seleccionarse mediante la variable de entornoJULIA_DEBUG

$ JULIA_DEBUG=all julia -e debug La suma de algunos valores$(sum(rand(100))) Debug La suma de algunos valores 47116520814555024 Main none1

Aquiacute hemos utilizado all para obtener toda la informacioacuten de depuracioacuten perotambieacuten se puede optar por generar salida solo para un archivo o moacuteduloespeciacutefico

Depuracioacuten 269

Glosarioregex

Expresioacuten regular una secuencia de caracteres que definen un patroacuten debuacutesqueda

matrizArreglo bidimensional

representacioacuten intermediaEstructura de datos utilizada internamente por un compilador pararepresentar el coacutedigo fuente

coacutedigo de maacutequinaInstrucciones que pueden ser ejecutadas directamente por la unidad centralde procesamiento de una computadora

debug loggingAlmacenar mensajes de depuracioacuten en un registro (log)

270 Capiacutetulo 20 Extra Base y Libreriacutea Estaacutendar

Capiacutetulo 21 DepuracioacutenAl depurar es necesario distinguir entre los diferentes tipos de errores pararastrearlos maacutes raacutepidamente

bull Los errores de sintaxis se descubren cuando el inteacuterprete traduce el coacutedigofuente a coacutedigo de bytes Estos errores indican que hay una falla en laestructura del programa Por ejemplo omitir la palabra reservada end alfinal de un bloque de funciones genera el mensaje ERROR LoadErrorsyntax incomplete function requires end

bull Los errores en tiempo de ejecucioacuten se presentan si algo falla mientras seejecuta el programa La mayoriacutea de los mensajes de error en tiempo deejecucioacuten indican doacutende ocurrioacute el error y queacute funciones se estabanejecutando Ejemplo Una recursioacuten infinita eventualmente causa el error entiempo de ejecucioacuten ERROR StackOverflowError

bull Los errores semaacutenticos ocurren cuando un programa se ejecuta sin generarmensajes de error pero no hace lo que deberiacutea Por ejemplo una expresioacutenpuede no evaluarse en el orden esperado generando un resultadoincorrecto

El primer paso en la depuracioacuten es averiguar el tipo de error al que se enfrentaAunque las siguientes secciones estaacuten organizadas por tipo de error algunasteacutecnicas son aplicables en maacutes de una situacioacuten

Errores de SintaxisLos errores de sintaxis suelen ser faacuteciles de corregir una vez se descubre cuaacutelesson Desafortunadamente muchas veces los mensajes de error no son uacutetiles Losmensajes maacutes comunes son

ERROR LoadError syntax incomplete premature end of input

y

ERROR LoadError syntax unexpected =

los cuales no son muy informativos

Por otro lado el mensaje indica en queacute parte del programa se produjo elproblema En realidad indica doacutende Julia notoacute que habiacutea un problema que no esnecesariamente doacutende estaacute el error A veces el error es anterior a la ubicacioacutendel mensaje de error generalmente en la liacutenea anterior

Si estaacute programando incrementalmente el usuario deberiacutea tener casi localizadoel error ya que estaraacute en la uacuteltima liacutenea que agregoacute

Si estaacute copiando coacutedigo de un libro comience comparando su coacutedigo con el

Errores de Sintaxis 271

coacutedigo del libro y verifique cada letra Al mismo tiempo recuerde que el libropuede contener errores por lo que si ve algo que parece un error de sintaxis esposible que lo sea

Aquiacute hay algunas formas de evitar los errores de sintaxis maacutes comunes

1 Aseguacuterese de no estar usando una palabra reservada de Julia en un nombrede variable

2 Compruebe que tiene la palabra reservada end al final de cada sentenciacompuesta incluyendo los bloques for while if y function

3 Aseguacuterese de que las cadenas tengan su par de comillas de apertura ycierre Aseguacuterese de que todas las comillas sean comillas rectas y no otrotipo de comillas

4 Si tiene cadenas que ocupan varias liacuteneas con triples comillas aseguacuterese deque ha terminado la cadena correctamente Una cadena sin terminar puedeprovocar un error invalid token al final de su programa o puede hacer quela siguiente parte del programa sea tratada como una cadena hasta llegar ala siguiente cadena iexclEl segundo caso podriacutea no presentar mensaje de error

5 Un pareacutentesis sin cerrar mdash( or [mdash hace que Julia continuacutee con la liacuteneasiguiente como parte de la sentencia actual Generalmente se produce unerror casi inmediatamente en la siguiente liacutenea

6 Verifique el claacutesico error que se produce al ocupar = en lugar de == dentrode un condicional

7 Si tiene caracteres que no son ASCII en el coacutedigo (incluidas cadenas ycomentarios) esto podriacutea causar un problema aunque Julia generalmentemaneja caracteres no ASCII Tenga cuidado si pega texto de una paacutegina webu otra fuente

Si nada funciona pase a la siguiente seccioacuten hellip

Sigo haciendo cambios y no hay diferencia

Si el REPL dice que hay un error y usted no lo ve podriacutea deberse a que usted y elREPL no estaacuten viendo el mismo coacutedigo Verifique su entorno de programacioacutenpara asegurarse de que el programa que estaacute editando es el que Julia estaacutetratando de ejecutar

Si no estaacute seguro intente poner un error de sintaxis obvio y deliberado alcomienzo del programa Ahora ejecuacutetelo de nuevo Si REPL no encuentra elnuevo error no estaacute ejecutando el nuevo coacutedigo

Estas son algunas de las posibles razones

bull Editoacute el archivo y olvidoacute guardar los cambios antes de ejecutarlonuevamente Algunos entornos de programacioacuten hacen esto por usted pero

272 Capiacutetulo 21 Depuracioacuten

otros no

bull Cambioacute el nombre del archivo pero auacuten estaacute ejecutando el archivo con elnombre anterior

bull Algo en su entorno de desarrollo estaacute configurado incorrectamente

bull Si estaacute escribiendo un moacutedulo y estaacute usando using aseguacuterese de no darle asu moacutedulo el mismo nombre que uno de los moacutedulos estaacutendar de Julia

bull Si estaacute usando using para importar un moacutedulo recuerde que debe reiniciarREPL cuando modifique el coacutedigo en el moacutedulo Si vuelve a importar elmoacutedulo no ocurre nada

Si se queda atascado y no puede darse cuenta de lo que estaacute sucediendo unenfoque es comenzar de nuevo con un nuevo programa como iexclHola Mundo yasegurarse de que puede ejecutar este programa ya conocido Luego puedeagregar gradualmente las piezas del programa original al nuevo

Errores en Tiempo de EjecucioacutenUna vez que su programa es sintaacutecticamente correcto Julia puede leerlo y almenos comenzar a ejecutarlo iquestQueacute podriacutea salir mal

Mi programa no hace absolutamente nada

Este problema es comuacuten cuando su archivo consta de funciones y clases pero enrealidad no llama a ninguna funcioacuten para iniciar la ejecucioacuten Esto puede serintencional si soacutelo se busca importar este moacutedulo para suministrar clases yfunciones

Si no es intencional aseguacuterese de que haya una llamada a la funcioacuten en elprograma y aseguacuterese de que el flujo de ejecucioacuten pase por esta llamada (veaSeccioacuten 21223)

Mi programa se congela

Si un programa se detiene y parece no estar haciendo nada estaacute congeladoGeneralmente eso significa que estaacute atrapado en un bucle infinito o en unarecursioacuten infinita

bull Si hay un bucle en particular que le resulta sospechoso de poder provocar elproblema agregue una sentencia de impresioacuten justo antes del bucle quediga entrando al bucle y otra inmediatamente posterior que diga saliendodel bucle

Ejecute el programa Si recibe el primer mensaje y no el segundo tiene unbucle infinito Vea Seccioacuten 21221

bull La mayoriacutea de las veces una recursioacuten infinita haraacute que el programa se

Errores en Tiempo de Ejecucioacuten 273

ejecute por un rato y luego produzca un error ERROR LoadErrorStackOverflowError Si eso sucede vea Seccioacuten 21222

Si no obtiene este error pero sospecha que hay un problema con un meacutetodoo funcioacuten recursiva igual puede utilizar las teacutecnicas de Seccioacuten 21222

bull Si ninguno de esos pasos funciona comience a probar otros bucles y otrasfunciones y meacutetodos recursivos

bull Si esto no funciona quizaacutes es porque usted no entiende el flujo de ejecucioacutende su programa Vea Seccioacuten 21223

Bucle Infinito

Si cree tener un bucle infinito y cree saber cuaacutel es antildeada una sentencia deimpresioacuten que imprima los valores de las variables de la condicioacuten al final delbucle junto con el valor de la condicioacuten

Por ejemplo

while x gt 0 ampamp y lt 0 hacer algo con x hacer algo con y debug variables x y debug condicion x gt 0 ampamp y lt 0end

Ahora cuando ejecute el programa en modo de depuracioacuten veraacute el valor de lasvariables y la condicioacuten en cada iteracioacuten En la uacuteltima iteracioacuten la condicioacutendebe ser false Si el ciclo continuacutea podraacute ver los valores de x e y y podraacuteaveriguar por queacute no se actualizan correctamente

Recursioacuten Infinita

La mayoriacutea de las veces una recursioacuten infinita hace que el programa se ejecutedurante un tiempo y luego produzca un error

ERROR LoadError StackOverflowError

Si sospecha que una funcioacuten o un meacutetodo estaacute causando una recursioacuten infinitacomience por asegurarse de que hay un caso base En otras palabras deberiacuteahaber una condicioacuten que haga que la funcioacuten devuelva un valor sin hacer otrallamada recursiva Si no necesita revisar el algoritmo y encontrar ese caso base

Si hay un caso base pero el programa no parece llegar hasta eacutel antildeada unasentencia de impresioacuten al inicio de la funcioacuten que imprima los paraacutemetrosAhora cuando ejecute el programa veraacute el valor de los paraacutemetros cada vez quese llame la funcioacuten Si los paraacutemetros no se acercan al caso base eso le daraacute

274 Capiacutetulo 21 Depuracioacuten

alguna idea de por queacute no lo hace

Flujo de Ejecucioacuten

Si no estaacute seguro del flujo de ejecucioacuten en su programa antildeada sentencias deimpresioacuten al principio de cada funcioacuten con mensajes como ldquoentrando a la funcioacutenfunrdquo donde fun sea el nombre de la funcioacuten

Ahora cuando ejecute el programa se imprimiraacute una mensaje en cada funcioacuten amedida que estas sean llamadas

Cuando ejecuto el programa recibo una excepcioacuten

Si algo sale mal durante la ejecucioacuten Julia imprime un mensaje que incluye elnombre de la excepcioacuten la liacutenea del programa donde sucedioacute el problema y untrazado inverso

El trazado inverso identifica la funcioacuten que se estaacute ejecutando y la funcioacuten que lallamoacute y luego la funcioacuten que llamoacute a esa y asiacute sucesivamente En otras palabrastraza la ruta de las llamadas a las funciones que le llevaron a donde seencuentra Tambieacuten incluye los nuacutemeros de las liacuteneas de su archivo doacutendesuceden todas esas llamadas

El primer paso es examinar el lugar del programa donde ocurrioacute el error y ver sipuede adivinar lo que sucedioacute Estos son algunos de los errores en tiempo deejecucioacuten maacutes comunes

ArgumentErrorUno de los argumentos para llamar a una funcioacuten no tiene la formaesperada

BoundsErrorSe estaacute tratando de acceder a un elemento de un arreglo fuera de los liacutemitesde indexacioacuten

DomainErrorEl argumento de una funcioacuten o constructor no pertenece al dominio vaacutelido

DivideErrorSe intentoacute dividir un entero por 0

EOFErrorNo habiacutea maacutes datos disponibles para leer desde un archivo o stream

InexactErrorNo se puede convertir a un tipo

Errores en Tiempo de Ejecucioacuten 275

KeyErrorSe estaacute tratando de acceder o eliminar un elemento inexistente de un objetoAbstractDict (Dict) o Set

MethodErrorNo existe un meacutetodo con la especificacioacuten de tipo requerida en la funcioacutengeneacuterica dada Alternativamente no existe un meacutetodo uacutenico maacutes especiacutefico

OutOfMemoryErrorUna operacioacuten asignoacute demasiada memoria para que el sistema o elrecolector de basura opere correctamente

OverflowErrorEl resultado de una expresioacuten es demasiado grande para el tipo especificadoy se produce un desbordamiento

StackOverflowErrorUna llamada a funcioacuten trata de usar maacutes espacio que el que estaacute disponibleen la pila de llamadas Esto generalmente ocurre cuando una llamada serepite infinitamente

StringIndexErrorSe produjo un error al intentar acceder a un iacutendice invaacutelido de una cadena

SystemErrorFalloacute una llamada al sistema y se muestra un mensaje de error

TypeErrorError de asercioacuten de tipo o error producido al llamar a una funcioacutenintegrada con un tipo de argumento incorrecto

UndefVarErrorUn siacutembolo en el entorno (o aacutembito) actual no estaacute definido

Puse tantas sentencias de impresioacuten que me ahogo eninformacioacuten

Uno de los problemas de usar sentencias print en la depuracioacuten es que puedeterminar ahogado por tanta informacioacuten Hay dos formas de resolver estosimplificar la salida o simplificar el programa

Para simplificar la salida puede eliminar o comentar (convertir en comentariosno evaluados coacutemo oacuterdenes del programa) las sentencias print que no sean uacutetileso combinarlas Tambieacuten puede dar a la salida un formato que la haga maacutescomprensible

276 Capiacutetulo 21 Depuracioacuten

Para simplificar el programa puede hacer varias cosas Primero puede reducir laescala del problema en el que estaacute trabajando el programa Por ejemplo si estaacutebuscando algo en una lista buacutesquelo en una lista pequentildea Si el programa aceptaentradas del usuario ingrese la entrada maacutes simple que provoque el problema

Segundo puede limpiar el programa Elimine el coacutedigo muerto y reorganice elprograma para hacerlo tan legible como sea posible Por ejemplo si sospechaque el problema estaacute en una parte del programa con un anidamiento (nesting)muy profundo pruebe a reescribir esa parte con una estructura maacutes simple Sisospecha de una funcioacuten muy larga trate de dividirla en funciones maacutes pequentildeasy prueacutebelas separadamente

Generalmente el proceso de encontrar el caso de prueba miacutenimo lleva el usuarioa encontrar el error Si encuentra que un programa funciona en una situacioacutenpero no en otra eso le daraacute una pista sobre lo que estaacute sucediendo

De forma parecida reescribir una porcioacuten de coacutedigo puede ayudarle a encontrarerrores sutiles Si realiza un cambio que cree que no deberiacutea afectar elprograma pero lo hace entonces eso puede darle una pista

Errores SemaacutenticosEn cierto modo los errores semaacutenticos son los maacutes difiacuteciles de corregir ya que elinteacuterprete no entrega informacioacuten sobre lo que estaacute mal Soacutelo usted sabe lo quese supone que debe hacer el programa

El primer paso es hacer una conexioacuten entre el coacutedigo y el comportamiento queestaacute viendo Necesita una hipoacutetesis sobre lo que realmente estaacute haciendo elprograma Una de las dificultades que nos encontramos es la alta velocidad delos computadores

A menudo seriacutea deseable ralentizar el programa a una velocidad humana Eltiempo que lleva colocar unas sentencias print en los lugares adecuados sueleser menor que el que lleva configurar un depurador poner y quitar puntos deinterrupcioacuten y ldquohacer avanzarrdquo al programa hasta donde se produce el error

Mi programa no funciona

Deberiacutea hacerse estas preguntas

bull iquestHay algo que se supone que deberiacutea hacer el programa pero que nosucede Busque la seccioacuten del coacutedigo que realiza esa funcioacuten y aseguacuterese deque se ejecuta cuando deberiacutea

bull iquestOcurre algo que no deberiacutea Busque el coacutedigo en su programa que realizaesa funcioacuten y vea si se ejecuta cuando no debe

bull iquestHay alguna seccioacuten del coacutedigo que cause un efecto que no esperabaAseguacuterese de que entiende el coacutedigo en cuestioacuten especialmente si incluye

Errores Semaacutenticos 277

funciones o meacutetodos de otros moacutedulos de Julia Lea la documentacioacuten de lasfunciones a las que llama Prueacutebelas escribiendo casos de prueba simples ycomprobando sus resultados

Para programar necesitaraacute tener un modelo mental de coacutemo funcionan losprogramas Si escribe un programa que no hace lo que esperaba de eacutel muchasveces el problema no estaraacute en el programa sino en su modelo mental

La mejor manera de corregir su modelo mental es dividiendo el programa en suscomponentes (normalmente en funciones y meacutetodos) y probando cadacomponente de forma independiente Una vez que encuentre la discrepanciaentre su modelo y la realidad podraacute solucionar el problema

Por supuesto deberiacutea ir haciendo y probando componentes a medida quedesarrolla el programa Si encuentra un problema soacutelo habriacutea que revisar unapequentildea cantidad de coacutedigo nuevo

Tengo una expresioacuten grande y peliaguda y no hace lo queespero

Estaacute bien escribir expresiones complejas mientras sean legibles pero pueden serdifiacuteciles de depurar Suele ser una buena idea dividir una expresioacuten compleja enuna serie de asignaciones de variables temporales

Por ejamplo

agregarcarta(juegomanos[i] sacarcarta(juegomanos[encontrarvecino(juegoi)]))

Puede reescribirse como

vecino = encontrarvecino(juego i)cartaseleccionada = sacarcarta(juegomanos[vecino])agregarcarta(juegomanos[i] cartaseleccionada)

La versioacuten expliacutecita es maacutes faacutecil de leer porque los nombres de variables nosentregan documentacioacuten adicional y es maacutes faacutecil de depurar porque se puedencomprobar los tipos de las variables intermedias y mostrar sus valores

Otro problema que puede suceder con las expresiones grandes es que el ordende evaluacioacuten puede no ser el que usted esperaba Por ejemplo si estaacutetraduciendo la expresioacuten a Julia podriacutea escribir

y = x 2 π

Esto no es correcto ya que la multiplicacioacuten y la divisioacuten tienen la misma

278 Capiacutetulo 21 Depuracioacuten

precedencia y se evaluacutean de izquierda a derecha De este modo la anteriorexpresioacuten calcula

Una buena forma de depurar expresiones es antildeadir pareacutentesis para que seaexpliacutecito el orden de evaluacioacuten

y = x (2 π)

Siempre que no esteacute seguro del orden de evaluacioacuten utilice pareacutentesis Elprograma no soacutelo seraacute correcto (en el sentido de que hace lo que usted quiere)sino que ademaacutes seraacute maacutes legible para otras personas que no hayan memorizadolas reglas de precedencia y que lean el coacutedigo

Tengo una funcioacuten que no devuelve lo que esperaba

Si tiene una sentencia return con una expresioacuten compleja no tendraacute laoportunidad de imprimir el valor de retorno antes de retornar De nuevo puedeusar una variable temporal Por ejemplo en lugar de

return sacarpares(juegomanos[i])

podriacutea escribir

contar = sacarpares(juegomanos[i])return contar

Ahora ya tiene la oportunidad de mostrar el valor de count antes de retornar

Estoy atascado de verdad y necesito ayuda

Primero intente alejarse del computador durante unos minutos Trabajar con uncomputador puede provocar estos efectos

bull Frustracioacuten yo furia

bull Creencias supersticiosas (ldquoel computador me odiardquo) y pensamiento maacutegico(ldquoel programa soacutelo funciona cuando me pongo la gorra hacia atraacutesrdquo)

bull Programar dando palos de ciego (el empentildeo de programar escribiendo todoslos programas posibles y eligiendo el que hace lo correcto)

Si se encuentra afectado por alguno de estos siacutentomas levaacutentese y deacute un paseoCuando esteacute calmado piense en el programa iquestQueacute es lo que hace iquestCuaacutelespueden ser las causas de tal comportamiento iquestCuaacutendo fue la uacuteltima vez que suprograma funcionaba y queacute fue lo siguiente que hizo

A veces lleva tiempo encontrar un error Muchas veces encontramos errores

Errores Semaacutenticos 279

cuando estamos lejos del computador y divagamos Algunos de los mejoreslugares para encontrar errores son los trenes las duchas y la cama justo antesde quedarse dormido

No de verdad necesito ayuda

Sucede Incluso los mejores programadores se atascan de vez en cuando A vecestrabaja durante tanto tiempo en un programa que no puede ver el error Lo quenecesita es un par de ojos nuevos

Antes de llamar a alguien aseguacuterese de estar preparado Su programa deberiacuteaser tan simple como sea posible y usted deberiacutea estar trabajando con la entradamiacutenima que provoca el error Deberiacutea tener sentencias print en los lugaresadecuados (y lo que dicen deberiacutea ser comprensible) y deberiacutea tambieacuten entenderel problema lo bastante bien como para describirlo de manera concisa

Cuando llame a alguien para que le ayude aseguacuterese de darle la informacioacuten quenecesitan

bull Si hay un mensaje de error iquestcuaacutel es y queacute parte del programa sentildeala

bull iquestQueacute fue lo uacuteltimo que hizo antes de que apareciera el error iquestCuaacuteles sonlas uacuteltimas liacuteneas de coacutedigo que escribioacute o cuaacutel es el nuevo caso de pruebaque falla

bull iquestQueacute ha intentado hasta ahora y queacute ha averiguado

Cuando encuentre el error toacutemese un momento para pensar acerca de lo quepodriacutea haber hecho para encontrarlo maacutes raacutepido La siguiente vez que vea algoparecido seraacute capaz de encontrar el error antes

Recuerde el objetivo no es solo hacer que el programa funcione El objetivo esaprender coacutemo hacer funcionar el programa

280 Capiacutetulo 21 Depuracioacuten

Apeacutendice A Entrada de UnicodeLa siguiente tabla muestra algunos de los muchos caraacutecteres Unicode quepueden ingresarse mediante abreviaciones similares a aquellas utilizadas enLatex en el REPL de Julia (y en muchos otros entornos de edicioacuten)

Caraacutecter Tab completionsequence

representacioacuten ASCII

sup2 ^2₁ _1₂ _2ἴ appleἴ bananaὂ camelἵ pearὂ turtlecap capequiv equiv ===

ℯ eulerisin in in

ge ge gt=

le le lt=

ne ne =

notin notinπ pi pi

sube subseteqε varepsilon

Apeacutendice A Entrada de Unicode 281

Apeacutendice B JuliaBoxJuliaBox permite ejecutar Julia en su navegador Ingrese a la paacuteginahttpswwwjuliaboxcom inicie sesioacuten y comience a usar el entorno Jupyter

La pantalla inicial se muestra en Figura 25 El botoacuten new (nuevo) permite lacreacioacuten de un notebook de Julia un archivo de texto (text file) una carpeta(folder) o una sesioacuten de terminal (terminal session)

En una sesioacuten de terminal el comando julia inicia REPL como se muestra enFigura 26

La interfaz del notebook permite mezclar texto (en modo Markdown) y coacutedigocon su respectiva salida Figura 27 muestra un ejemplo

Puedes encontrar maacutes documentacioacuten en el sitio web de Jupyterhttpjupyterorgdocumentation

Figura 25 Pantalla inicial

282 Apeacutendice B JuliaBox

Figura 26 Sesioacuten de terminal

Apeacutendice B JuliaBox 283

Figura 27 Notebook

284 Apeacutendice B JuliaBox

Apeacutendice C Cambios de ThinkJuliaEste libro es una traduccioacuten de ThinkJulia que estaacute disponible bajo la LicenciaCreative Commons Atribucioacuten-NoComercial 30 No portada Esta licenciarequiere que los trabajos derivados (como este libro) enumeren los cambiosrealizados en relacioacuten a la fuente

Las diferencias de este libro respecto a ThinkJulia incluyen lo siguiente

bull Traduccioacuten del ingleacutes al espantildeol

bull Se cambiaron muchas frases idiomaacuteticas que no seriacutean familiares para loshispanohablantes (Se cayoacute el centavo)

bull En vez de usar el texto de la novela Emma en el Capiacutetulo 13 se usa eltexto de Don Quijote

bull Debido a que OrsquoReilly no financioacute la traduccioacuten algunas de las referencias aOrsquoReilly en el prefacio fueron eliminadas

Apeacutendice C Cambios de ThinkJulia 285

Index 126 57=

veacutease ne 57

veacutease cadena vaciacutea 101

veacutease comillas triples 51hellip (comillas)

veacutease comillas 11

veacutease comentario 22$

veacutease interpolacioacuten de cadenas102

161veacutease operador moacutedulo 56

ampamp 247 57 21 21 (asterisco)

operador de multiplicacioacutenveacutease asterisco 9

+ 21+ (operador de suma)

veacutease suma 9+= 127 (coma)

no usar en enterosveacutease coma 11

- 21- (operador de resta)

veacutease subtraction 9 200 201 265

veacutease operador punto 128 21 (operador de divisioacuten)

veacutease division 10 206 253 244 25 265 64lt 57lt=

veacutease le 57=

veacutease sentencia de asignacioacuten 17== 105 205 57 75===

veacutease equiv 131=gt 142gt 57gt=

veacutease ge 57

veacutease help 51 247 254assert 214code_llvm 268code_lowered 267code_native 268code_typed 268contenedorvariable 254debug 269generated 255macroexpand 254printf 187show 73svg 43test 230time 259warn 269which 237 267[]

veacutease slice operator 125[]

veacutease operador corchete 97n 196r 196t 175 196] 42^ 21 21^ (circunflejo)

operador de exponenciacioacutenveacutease circunflejo 10

_ (guioacuten bajo)en enteros

veacutease guioacuten bajo (_) 11``

286 Index

veacutease comillas invertidas 193

veacutease llaves 142|| 247 57divide 161

veacutease operador divisioacuten entera 56hellip 161isin

veacutease in 104notin 115cap 177ne 57equiv 131 205le 57ge 57sube 262

Aabreviaturas tipo LaTeX 18abs 71 92abspath 188abstract type 233 233 240ack 83actualizacioacuten 94acumulador 127 137 174algoritmo 93 95alias 133 138 167 203 205ambas 105analizar 32andamiaje 154 73 83anidado 122anotacioacuten de tipo 226anular 177 184Any 123 142 217anaacutelisis de Markov 179anaacutelisis de sintaxis 12 15append 126arc 49archivo de texto 196arco 49 53areacirculo 74ArgumentError 27 275 64argumento 27 30 32 33 38argumento opcional 131 176argumentos con nombre 244 257argumentos opcionales 138

Arreglo 123arreglo 122 137 166arreglo vaciacuteo 122 124asignacioacuten 160 191 24asignacioacuten aumentada 137asignacioacuten de tupla 160 164asignacioacuten en tupla 168asignacioacuten muacuteltiple 86 94asterisco ()

operador de multiplicacioacuten 9atributo 199 206

Bbandera 151 155Base 243 259base de datos 191 197begin 245benchmarking 182 184Biblioteca Estaacutendar 243bloque 245bloque do 257bloque let 257Bool 57borrarprimero 133BoundsError 107 160 275break 89bucle 44 52 88bucle infinito 273 88 95bugs

veacutease errores 15Byte 249buacutesqueda 102 103 109 109 115 155buacutesqueda de biseccioacuten 178buacutesqueda inversa 155

Ccadena 166 97 97

concatenacioacutenveacutease concatenar 21

repeticioacutenveacutease repeticioacuten 22

cadena vaciacutea 101 108cadenas 10 14calculadora 26campo

veacutease atributo 199

Index 287

Canguro 227capturar 197capturar una excepcion 190Car Talk 120 157 169carpeta

veacutease directorio actual 188caraacutecter guioacuten bajo 18Caraacutecter Unicode 17caraacutecter Unicode 30 72caso base 63 66caso especial 119 120catch 190ccall 256cd 193Channel 248Char 112 97cifrado Ceacutesar 112Circulo 207circunflejo (^)

operador de exponenciacioacuten 10clasificar 242clausura 257clave 142 154close 113 187 192codificacioacuten UTF-8 108 99codificar 228 239coinciden 164cola 135collect 130 146 163coma ()

no usar en enteros 11coma final 158comentario 22 25comillas 30comillas (hellip)

entre 11comillas invertidas 193comillas triples 51comparacioacuten de cadenas 105componentes leacutexicos 11 15composicioacuten 29 33 39 74concatenacioacuten de cadenas 25concatenar 21 34concatenar_dos 34condicional alternativa 71condicional anidada 59 66

condicional encadenada 59 66condicioacuten 58 66conjetura de Collatz 89conjuntoanagramas 198ConjuntoDeCartas 233const 153 229constructor 199 206 219 251

copiaveacutease constructor de copia

220externo

veacutease constructor externo220

internoveacutease constructor interno

220constructor de copia 220 227constructor externo 220 226constructor interno 220 226constructor por defecto 226contador 104 109ContarLineas 195contarlineas 194conteo 109continue 90conversioacuten 252 258conversioacuten de tipo 27convert 252copia 125copiar 193 205copodenieve 69corchetes 142 265cos 33cuadrado 46cuatroveces 40cuenta regresiva 61cuentaregresiva 88cuerpo 30 38curva de Koch 69ciacuterculo 47 50coacutedigo ASCII 108 97coacutedigo de maacutequina 268coacutedigo muerto 277 71 82

Ddatos faltantes 255 258

288 Index

DBM 191de Cervantes

Miguel 174debug logging 269 270declaracioacuten 151 156decremento 88 94deepcopy 205 206 207definicioacuten circular 76definicioacuten de funcioacuten 29 38definicioacuten recursiva 76deleteat 130delimitador 131 138dependencia 236 240depuracioacuten 106 119 135 153 154

167 182 196 205 213 22623 269 37 52 65 72 81 93

emociones de la manejando las13

veacutease errores (bugs) probando15

depuracioacuten del pato de goma 183 184depuracioacuten experimental 37depuracioacuten por biseccioacuten 93desarrollo de prototipos 209 211 214desarrollo incremental 72 82desarrollo planificado 212 214deserialize 192desplazarpalabra 112 156determiniacutestico 172 183devolverfloat 216diaframa de estado 123diagrama

estadoveacutease diagrama de estado 17

graacutefico de llamadasveacutease graacutefico de llamadas

149objeto

veacutease diagrama de objeto200

pilaveacutease diagrama de pila 34

tiposveacutease diagrama de tipos 236

diagrama de estado 131 132 149166 166 17 24 86

diagrama de objeto 200 202 207diagrama de pila 134 34 39 62 68

78diagrama de tipos 236 240dibujarcirculo 207dibujarrect 207diccionario 142 154Dict 142Dijkstra

Edsger W 119dimensioacuten 264directorio 188 196disentildeo orientado a tipos 238dispatch 223 226dispatch muacuteltiple 223 227dispersar 168dispersioacuten 162distancia 72distanciaentrepuntos 203DivideError 275divisioacuten

operador de divisioacuten () 10divisioacuten entera 65divrem 161do 246docstring 202 51 53DomainError 275dosveces 40Doyle

Arthur Conan 37dump 196 253

Eeachindex 124eachline 114 194ejecucioacuten alternativa 58ejecutar 19 24elemento 122 137else 58elseif 59embebido 202emoji 97 99enbiseccion 141encabezado 30 38encapsulacioacuten 47encapsulado 53

Index 289

encapsulado de dato 238encapsulado de datos 240enchapado 232 239encontrarcentro 204end 101 124 190 195 199 245 30

44 58 98enteroahora 212 218entrelazan 141enumerate 164EOFError 275equivalente 132 138error 147 213

BaseEOFError 275KeyError 143StringIndexError 99SystemError 189

CoreArgumentError 27BoundsError 107DivideError 275DomainError 275InexactError 275MethodError 98OutOfMemoryError 276OverflowError 276StackOverflowError 63TypeError 216UndefVarError 34

semaacutenticoveacutease error semaacutentico 23

sintaxisveacutease error de sintaxis 18

tiempo de ejecucioacutenveacutease error de tiempo de

ejecucioacuten 23error de forma 168error de sintaxis 18 23 25 271 29error de tiempo de ejecucioacuten 23 25error en tiempo de ejecucioacuten 271 34error semaacutentico 23 25 271errores (bugs) 13

veacutease depuracioacuten 15errores de forma 167ES-UN 236esabecedaria 115 117

esanagrama 140esc 254escogerdelhistograma 173esdivisible 75eshoravalida 213espalindromo 110 118 84especificacioacuten 218 226 250espotencia 84esreverso 106 119estadespues 209 219estaordenada 140estilo de programacioacuten funcional 211estilo funcional de programacioacuten 214estimarpi 96estriangulo 68estructura 11 15estructura de dato 168estructuras de datos 167estructuras de datos recursivas 221eval 254 95evalbucle 96evaluacioacuten de cortocircuito 247 257evaluar 19 24evita 115 262evitar 114excepcioacuten

veacutease error de tiempo deejecucioacuten 23

exp 29export 195Expr 253expresioacuten 18 24 253 258expresioacuten booleana 57 66extension

jl 19extrema 161

Ffact 247 77 80 81factorial 78false 57faltantes 255fib 79Fibonacci 266fibonnaci 149 79file stream 113 119

290 Index

filter 174filtro 128 138finally 190findall 148findfirst 104findnext 104firstindex 99float 27flujo de ejecucioacuten 273 32 39 71 77

81 88for 44formateando 187formatting 154forward 42fractal 69funccioacuten

definida por el programadorconjuntoanagramas 198

funciondefinida por el programador

aacuterea 70funciones generadas 255 258funcioacuten 27 29 38

Baseabs 71abspath 188append 126buacutesqueda 109ccall 256coinciden 164collect 130conteo 109convert 252cos 33deepcopy 205 206deleteat 130divrem 161dump 196eachindex 124eachline 114enumerate 164error 147esc 254exp 29extrema 161factorial 78

filter 174findall 148firstindex 99float 27get 145get 156include 194insert 130isdefined 206isdir 188isequal 148isfile 189isletter 171ispath 188iterate 266join 131joinpath 189keys 143length 40log 28log10 28lpad 121match 263max 162maximum 161min 162minimum 161new 220nextind 99occursin 263ones 264open 113parse 27pop 129popfirst 129print 41promote 252promote_rule 253push 125pushfirst 130put 248pwd 188rand 140readdir 189readline 113 64reinterpret 249

Index 291

repr 196reverse 167reverse 167run 193setdiff 260show 36sin 28size 264sizeof 99skipmissing 256sort 126sort 126splice 129split 130sqrt 28string 28sum 127supertype 238take 192 248time 67trunc 27tupla 158uppercase 104values 144vcat 134walkdir 189write 186zeros 264zip 163

ContarLineascontarlineas 195

Coreeval 254 95

definida por el programadorack 83ambas 105areacirculo 74borrarprimero 133buacutesqueda 102clasificar 242cola 135concatenar_dos 34contarlineas 194copodenieve 69cuadrado 46cuatroveces 40

cuenta regresiva 61ciacuterculo 47desplazarpalabra 112devolverfloat 216dibujarcirculo 207dibujarrect 207distancia 72distanciaentrepuntos 203dosveces 40enbiseccion 141encontrarcentro 204enteroahora 212esabecedaria 115esanagrama 140escogerdelhistograma 173esdivisible 75eshoravalida 213espalindromo 84espotencia 84esreverso 106estadespues 209estaordenada 140estimarpi 96estriangulo 68evalbucle 96evita 114fact 77fib 79findfirst 104findnext 104histograma 145horaaentero 212imprimircuadricula 41imprimirdosveces 32imprimirhist 146imprimirhora 208imprimirmascomun 176imprimirpalabra 40imprimirpunto 202imprimirtodo 161incrementar 210interior 139interior 139invertirdic 148justificar_a_la_derecha 39koch 69

292 Index

leeranagramas 198mascomun 175masfrecuente 168mcd 85medio 84minmax 161miraiz 95mover 235moverpunto 203multhora 215noborrarprimero 135notiene_e 114palabraalazar 178palabrasdiferentes 175palabrastotales 174par inverso 141polyline 49poliacutegono 47ponerenmarsupio 227primera 84printn 62probarraiz 95procesararchivo 173procesarlinea 173procesarpalabra 239puntoencirculo 207recorrer 189rectencirculo 207recursioacuten 63repartir 241repetido 140repetirletras 30resta 177sed 197seq 89sinc 216sobreposicionrectcirc 207solomayusculas 128sumaacumulada 139sumaanidada 139sumacuadrada 267sumahora 209sumartodo 162tienedoblepareja 242tienepareja 242todoenmayusculas 127

ultima 84usasolo 115usatodo 115valorabsoluto 70verificarfermat 67

definido por el programadorimprimirletras 29

IntroAJuliaforward 42pendown 43penup 43turn 43

Metaparse 253 95

Plotsgraficar 185 244

programmer-definedarco 49

Randomshuffle 232

Serializacioacutendeserialize 192serialize 192

funcioacuten Ackermann 83funcioacuten anoacutenima 244 257funcioacuten booleana 75funcioacuten de Ackermann 156funcioacuten definida por el programador

29 33funcioacuten exponencial

veacutease exp 29funcioacuten factorial 77funcioacuten gamma 80funcioacuten hash 155funcioacuten logaritmo

veacutease log 28funcioacuten matemaacutetica 28funcioacuten nula 35 39funcioacuten productiva 35 39 70funcioacuten pura 209 214funcioacuten raiacutez

veacutease sqrt 28funcioacuten recursiva 61funcioacuten trigonomeacutetrica 28funcioacuten typeof 10function 29

Index 293

funtor 251 258

GGDBM 191generalizacioacuten 47 53get 145get 156 174global 151 99graficar 185graacutefico de llamada 155graacutefico de llamadas 149guardian 81guardiaacuten 83guioacuten bajo (_)

en enteros 11

Hhash 149hash table 144hashable 149 155help 51histograma 145 224Holmes

Sherlock 37Hora 208 217horaaentero 212 218

Iidentidad de Euler 262ideacutentico 132 138if 58im 262immutable 102 108 158 167 200implementacioacuten 144 155 225import 195 259imprimircuadricula 41imprimirdosveces 32imprimirhist 146imprimirhora 208 217imprimirletras 29imprimirmascomun 176imprimirpalabra 40imprimirpunto 202imprimirtodo 161in 100 124 143 156 44include 194

incrementar 218incrementar 210incremento 88 94indentacioacuten 46indicador 64

en REPL 14 9indice 98InexactError 275informaacuteticos habilidades de

veacutease programacioacuten 7inicializacioacuten 94initializacioacuten 87input 113insert 130 136instancia 200 206instanciacioacuten 200instanciar 206instrucciones

veacutease sentencias 7Int 112InteractiveUtils 237 267interfaz 225 266 48 53interior 139interior 139intermediate representation 270interpolacioacuten de cadenas 102 109

187 263IntroAJulia 42invariante 213 215invertirdic 148IOBuffer 192isa 206 234 80isdefined 206isdir 188isequal 148isfile 189isletter 171 174ispath 188item 122 142 154iteracioacuten 191 86 88 94iterador 163 168 266iterate 266

Jjoin 131joinpath 189

294 Index

Juliaejecutando 8

JuliaBox 19 8notebook graacutefico 42

justificar_a_la_derecha 39

KKeyError 143 276keys 143keyword

elseveacutease else 58

importveacutease import 259

koch 69

LLaTeX-like abbreviations 281leeranagramas 198lemario 113length 143 40 84 98lenguaje de programacioacuten 11 15lenguaje de programacioacuten completo 76lenguaje formal 11 15lenguaje natural 11 14ley de Zipf 184Linux 38lista anidada 137Llamada a funcioacuten 27 38llaves 142 249LLVM code 268log 28log10 28lookup 147lowercase 174lpad 121

Mmachine code 270macro 254 258 43

Baseassert 214debug 269generated 255macroexpand 254show 73

time 259warn 269

definida por el programadorcontenedorvariable 254

InteractiveUtilscode_llvm 268code_lowered 267code_native 268code_typed 268which 237

Luxorsvg 43

Printfprintf 187

Testtest 230

Mano 234map 128mapeo 138 142 154marco 34 39 62Markov 238mascomun 175masfrecuente 168match 263matemaacuteticas

operadores aritmeacuteticos 9matrix 264 270max 162maximum 161mayuacutescula 127Mazo 231mcd 85md5 194md5sum 194medio 84mensaje de error 23MethodError 101 159 162 219 276

98min 162minimum 161minmax 161miraiz 95Missing 255modelo mental 278modificador 210 214modo interactivo 19 24 36

Index 295

modo script 19 24 36module 195

ContarLineasveacutease ContarLineas 195

InteractiveUtilsveacutease InteractiveUtils 237

Randomveacutease Random 232

Testveacutease Test 230

modulo 42 52veacutease IntroAJulia 42

mover 235moverpunto 203MPunto 201multhora 215multiplicidad 236 240mutable 123 133 167mutable struct 201meacutetodo 217 226meacutetodo de Newton 91meacutetodos 226moacutedulo

Plotsveacutease Plots 184 244

Serializacioacutenveacutease Serializacioacuten 192

Nnada 39Naipe 229new 220nextind 99noborrarprimero 135norma Unicode 108 97notacioacuten de punto

veacutease 200nothing 177 36 36 70notiene_e 114 115nuacutemeros complejos 262

Oobjeto 131 138objeto de comando 193 197objeto de funcioacuten 38 40objeto embebido 207

objeto zip 163 168occursin 263ones 264open 113 186 246operacioacuten con cadenas 21operacioacuten de reduccioacuten 127 138operador

Base= 57 56+= 127 128lt 57lt= 57== 57gt 57gt= 57 247[] 125[] 97in 104isa 206 234divide 56isin 104notin 115cap 177ne 57equiv 131le 57ge 57sube 262

cadenas 21operador corchete 101 101 122 123

159 191 97operador de divisioacuten entera 56operador de exponenciacioacuten (^) 10operador de multiplicacioacuten () 9operador de resta (-) 9operador de suma (+) 9operador loacutegico 57 66operador moacutedulo 56 65operador porcioacuten 125 135 159operador punto 128 137operador relacional 159 57 66operador ternario 257

veacutease 247

296 Index

operadores 14 9aritmeacuteticos 9

operadores aritmeacuteticos 9operando 24orden alfabeacutetico 105orden de operaciones 21OutOfMemoryError 276output

sentencia de impresioacuten 14 9OverflowError 276

Ppalabra clave 18 24palabra reservada

abstract type 233begin 245break 89catch 190const 153 229continue 90do 246elseif 59export 195final 30finally 190for 44function 30global 151if 58import 195in 44module 195mutable struct 201quote 253return 62struct 199tipo primitivo 249try 190using 42while 88

palabraalazar 178palabrasdiferentes 175palabrastotales 174paliacutendromo 84PAPOMUDAS 21paquete 42 52

par clave-valor 142 154 165par inverso 141Paradoja del cumpleantildeos 140pares de metaacutetesis 169parse 253 64 95paraacutemetro 32 34 38pareacutentesis 158 164 21 27

vaciacuteos 30pendown 43penup 43persistente 186 196pi 17 28pista 150 155 156 170plan de desarrollo de programa 117

211 239 50 53 82plot 244Plots 184 244polimorfismo 225polimoacuterfica 224polygon 49polyline 49poliacutegono 47Poncela

Enrique Jardiel 114ponerenmarsupio 227pop 129 232 234popfirst 129 133porcioacuten 108 109 265postcondicioacuten 52 53 81precedencia del operador 25precondicioacuten 52 53 81prefijo 179primera 84Principal 35principio de sustitucioacuten de Liskov 237print 187 41println 187 41printn 62probarraiz 95procesararchivo 173procesarlinea 173procesarpalabra 239programacioacuten de caminata aleatoria

183programacioacuten geneacuterica 227programas 14 7

Index 297

promocioacuten 253 258promote 252 253promote_rule 253Proyecto Gutenberg 171prueba de consistencia 154prueba de cordura 154prueba unitaria 230 239pseudoaleatorio 172 184Ptr 256Punto 199 222puntoencirculo 207push 125 130 134 136 141 232

234pushfirst 130 136put 248pwd 188

Qquote 253

Rrama 59 66rand 140 172Random 232read 194readdir 189readline 113 64 90reasignacioacuten 151 204recopila 161recorrer 189recorrido 106 108 124 99Rectangulo 202rectencirculo 207recursividad 61recursioacuten 117 63 66 68 76 86 88recursioacuten infinita 274 63 67 80recursos en liacutenea

JuliaBox 8reduccioacuten a un problema previamente

resuelto 120reduccioacuten a un problema resuelto

previamente 117reducible 170reducir el tamantildeo 153refactorizacioacuten 239 50 53referencia 133 138 200

Regex 263regex 263 270RegexMatch 263reinterpret 249relacioacuten ES-UN 240relacioacuten TIENE-UN 240repartir 241repeticioacuten 22 34

veacutease iteracioacuten 8repetido 140 156 261repetirletras 30repetition 43REPL 281REPL (Read-Eval-Print Loop) 14 8replace 174repr 196representacioacuten intermedia 268resolucioacuten de problemas 14 7resta 177 260return 62reunir 168reverse 167 175reverse lookup 147reverse 167run 193ruta 188 197ruta absoluta 188 197ruta relativa 188 197

Ssangriacutea 30 60script 19 24secuencia 108 97 97secuencias de secuencias 166sed 197semaacutentica 25sentencia 19 24sentencia break 89 94sentencia compuesta 58 66sentencia condicional 58 66 76sentencia continue 90 95sentencia de asignacioacuten 123 17 86sentencia de asignacioacuten aumentada

127sentencia de depuracioacuten 269sentencia de impresioacuten 14

298 Index

funcioacuten println 9sentencia for 100 114 117 124 163

165 191 266 44 86 88sentencia global 152 155sentencia if 58sentencia print 81 94sentencia return 62 66 70sentencia try 190sentencia using 42 52sentencia while 117 88 94 99separador 175seq 89Serializacioacuten 192serialize 192Set 260setdiff 260shell 193 197show 221 227 229 234 36shuffle 232sin 28 32sinc 216singleton 148 155sintaxis 11 15sintaxis de punto 129 138 243size 264sizeof 99skipmissing 256slice 101sobrecarga de operadores 227sobrecarga del operador 222sobreposicionrectcirc 207solomayusculas 128sort 126 137 146 167 175sort 126 136 136 167 233splice 129split 130 160 174sqrt 28 73square 47StackOverflowError 274 276 63 80stacktrace 63String 97string 187 263 28StringIndexError 276 99strip 136struct 199 206subtipo 233 233 240 240

sufijo 179sum 127 162 224suma de verificacioacuten 194sumaacumulada 139sumaanidada 139sumacuadrada 267sumahora 209 213sumartodo 162supertipo 233 240supertype 238SVG picture 43Symbol 206SystemError 189 276

Ttabla hash 155take 192 248tarea 248 257teorema de Pitaacutegoras 72tesis de Turing 76Test 230TIENE-UN 236tienedoblepareja 242tienepareja 242Time 208time 67tipo 199 233

BaseAny 123 142Array 123Bool 57Channel 248Char 97Dict 142Expr 253IOBuffer 192Missing 255nothing 36Ptr 256Regex 263RegexMatch 263Set 260Symbol 206Tuple 158UInt8 249Union 250

Index 299

DatesTime 208

definida por el programadorByte 249Canguro 227Circulo 207ConjuntoDeCartas 233Fibonacci 266Hora 208Mano 234Markov 238Mazo 231MPunto 201Naipe 229Punto 199Rectangulo 202

IntroAJuliaDBM 191

LuxorTurtle 42

tipo compuesto 199tipo compuesto mutable 201tipo concreto 233 240tipo de punto flotante (Float64) 10 14tipo entero (Int64) 10 14tipo parameacutetrico 258tipo primitivo 249 257tipos 10 14

Float64veacutease tipo de punto flotante

10Int64

veacutease tipo entero 10String

veacutease cadenas 10tipos de datos

veacutease tipos 10todoenmayusculas 127 129Torvalds

Linus 38transitorio 186trazado inverso 35 39true 57trunc 27try 190tupla 158 158 166 167

tupla con nombre 243 257Tuple 158Turing

Alan 76turn 43Turtle 42TypeError 216 276typeof 122 158 205

UUInt8 249ultima 84UndefVarError 152 276 34 35 87Unicode character 281Union 250union de tipo 250unioacuten de tipos 257update 87uppercase 104usasolo 115 116 261 263usatodo 115 116using 259 42

Vvalor 131 142 154 17valor de retorno 27 39valor por defecto 184valor predeterminado 176valorabsoluto 70valores 10 14values 144variable 131 17 24

local 34variable de entorno 269variable global 151 155 229variable global constante 153 156variable local 34 38variable temporal 279 70 75 82vcat 134 136verificar 154verificar automaacuteticamente 154verificarfermat 67voto de confianza 78

Wwalkdir 189

300 Index

while 88write 186

Zzeros 264zip 163 165 167 167

Aacuteaacutembito 195aacuterea 70

Iacuteiacutendice 108 123

Uacuteuacuteltimo teorema de Fermat 67

Ππ

veacutease pi 17

ℯ 262

Index 301

  • Introduccioacuten a la Programacioacuten en Julia
  • Tabla de Contenido
  • Licencia
  • Dedicatoria
  • Prefacio
  • Capiacutetulo 1 El camino de la programacioacuten
  • Capiacutetulo 2 Variables expresiones y sentencias
  • Capiacutetulo 3 Funciones
  • Capiacutetulo 4 Estudio de Caso Disentildeo de Interfaz
  • Capiacutetulo 5 Condicionales y recursividad
  • Capiacutetulo 6 Funciones productivas
  • Capiacutetulo 7 Iteracioacuten
  • Capiacutetulo 8 Cadenas
  • Capiacutetulo 9 Estudio de Caso Juego de Palabras
  • Capiacutetulo 10 Arreglos
  • Capiacutetulo 11 Diccionarios
  • Capiacutetulo 12 Tuplas
  • Capiacutetulo 13 Estudio de Caso Seleccioacuten de Estructura de Datos
  • Capiacutetulo 14 Archivos
  • Capiacutetulo 15 Estructuras y Objetos
  • Capiacutetulo 16 Estructuras y Funciones
  • Capiacutetulo 17 Dispatch Muacuteltiple
  • Capiacutetulo 18 Subtipos
  • Capiacutetulo 19 Extra Sintaxis
  • Capiacutetulo 20 Extra Base y Libreriacutea Estaacutendar
  • Capiacutetulo 21 Depuracioacuten
  • Apeacutendice A Entrada de Unicode
  • Apeacutendice B JuliaBox
  • Apeacutendice C Cambios de ThinkJulia
  • Index
Page 6: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 7: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 8: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 9: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 10: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 11: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 12: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 13: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 14: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 15: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 16: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 17: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 18: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 19: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 20: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 21: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 22: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 23: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 24: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 25: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 26: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 27: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 28: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 29: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 30: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 31: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 32: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 33: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 34: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 35: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 36: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 37: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 38: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 39: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 40: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 41: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 42: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 43: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 44: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 45: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 46: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 47: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 48: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 49: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 50: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 51: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 52: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 53: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 54: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 55: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 56: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 57: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 58: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 59: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 60: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 61: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 62: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 63: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 64: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 65: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 66: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 67: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 68: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 69: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 70: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 71: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 72: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 73: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 74: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 75: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 76: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 77: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 78: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 79: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 80: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 81: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 82: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 83: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 84: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 85: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 86: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 87: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 88: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 89: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 90: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 91: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 92: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 93: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 94: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 95: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 96: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 97: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 98: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 99: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 100: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 101: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 102: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 103: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 104: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 105: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 106: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 107: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 108: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 109: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 110: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 111: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 112: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 113: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 114: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 115: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 116: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 117: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 118: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 119: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 120: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 121: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 122: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 123: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 124: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 125: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 126: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 127: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 128: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 129: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 130: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 131: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 132: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 133: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 134: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 135: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 136: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 137: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 138: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 139: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 140: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 141: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 142: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 143: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 144: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 145: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 146: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 147: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 148: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 149: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 150: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 151: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 152: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 153: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 154: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 155: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 156: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 157: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 158: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 159: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 160: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 161: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 162: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 163: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 164: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 165: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 166: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 167: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 168: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 169: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 170: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 171: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 172: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 173: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 174: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 175: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 176: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 177: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 178: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 179: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 180: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 181: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 182: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 183: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 184: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 185: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 186: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 187: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 188: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 189: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 190: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 191: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 192: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 193: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 194: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 195: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 196: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 197: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 198: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 199: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 200: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 201: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 202: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 203: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 204: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 205: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 206: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 207: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 208: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 209: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 210: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 211: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 212: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 213: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 214: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 215: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 216: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 217: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 218: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 219: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 220: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 221: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 222: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 223: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 224: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 225: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 226: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 227: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 228: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 229: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 230: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 231: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 232: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 233: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 234: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 235: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 236: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 237: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 238: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 239: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 240: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 241: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 242: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 243: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 244: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 245: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 246: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 247: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 248: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 249: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 250: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 251: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 252: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 253: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 254: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 255: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 256: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 257: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 258: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 259: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 260: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 261: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 262: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 263: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 264: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 265: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 266: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 267: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 268: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 269: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 270: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 271: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 272: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 273: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 274: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 275: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 276: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 277: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 278: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 279: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 280: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 281: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 282: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 283: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 284: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 285: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 286: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 287: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 288: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 289: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 290: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 291: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 292: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 293: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 294: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 295: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 296: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 297: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 298: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 299: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 300: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 301: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 302: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar
Page 303: Introducción a la Programación en Juliacomenzó la migración a Julia v1.0 • Robin Deits encontró algunos errores tipográficos en el Capítulo 2. • Mark Schmitz sugirió destacar