introducción a la programación en juliacomenzó la migración a julia v1.0 • robin deits...
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](https://reader035.vdocuments.site/reader035/viewer/2022070217/61215a5878ef7628d400e8a2/html5/thumbnails/1.jpg)
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