From a662e9f35ffe52f94262eec5115be02023dbec8f Mon Sep 17 00:00:00 2001 From: rrodriguze Date: Tue, 1 Oct 2019 21:35:49 +0200 Subject: add spanish traduction for hy --- es-es/hy-es.html.markdown | 176 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 176 insertions(+) create mode 100644 es-es/hy-es.html.markdown (limited to 'es-es') diff --git a/es-es/hy-es.html.markdown b/es-es/hy-es.html.markdown new file mode 100644 index 00000000..8b0532e3 --- /dev/null +++ b/es-es/hy-es.html.markdown @@ -0,0 +1,176 @@ +--- +language: hy +filename: learnhy-es.hy +contributors: +    - ["Abhishek L", "http://twitter.com/abhishekl"] +translators: +    - ["Roberto R", "https://github.com/rrodriguze"] +lang: es-es +--- + +Hy es un lenguaje de Lisp escrito sobre Python. Esto es posible convirtiendo +código Hy en un árbol abstracto de Python (ast). Por lo que, esto permite a +Hy llamar a código Pyhton nativo y viceversa. + +Este tutorial funciona para hy >= 0.9.12 + +```clojure +;; Esto es una intrucción muy básica a Hy, como la del siguiente enlace +;; http://try-hy.appspot.com +;; +; Comentarios usando punto y coma, como en otros LISPS + +;; Nociones básicas de expresiones +; Los programas List están hechos de expresiones simbólicas como la siguiente +(some-function args) +; ahora el esencial "Hola Mundo" +(print "hello world") + +;; Tipos de datos simples +; Todos los tipos de datos simples son exactamente semejantes a sus homólogos +; en python +42 ; => 42 +3.14 ; => 3.14 +True ; => True +4+10j ; => (4+10j) un número complejo + +; Vamos a comenzar con un poco de arimética simple +(+ 4 1) ;=> 5 +; el operador es aplicado a todos los argumentos, como en otros lisps +(+ 4 1 2 3) ;=> 10 +(- 2 1) ;=> 1 +(* 4 2) ;=> 8 +(/ 4 1) ;=> 4 +(% 4 2) ;=> 0 o operador módulo +; la exponenciación es representada por el operador ** como python +(** 3 2) ;=> 9 +; las funciones anidadas funcionan como lo esperado +(+ 2 (* 4 2)) ;=> 10 +; también los operadores lógicos igual o no igual se comportan como se espera +(= 5 4) ;=> False +(not (= 5 4)) ;=> True + +;; variables +; las variables se configuran usando SETV, los nombres de las variables pueden +; usar utf-8, excepto for ()[]{}",'`;#| +(setv a 42) +(setv π 3.14159) +(def *foo* 42) +;; otros tipos de datos de almacenamiento +; strings, lists, tuples & dicts +; estos son exactamente los mismos tipos de almacenamiento en python +"hello world" ;=> "hello world" +; las operaciones de cadena funcionan de manera similar en python +(+ "hello " "world") ;=> "hello world" +; Las listas se crean usando [], la indexación comienza en 0 +(setv mylist [1 2 3 4]) +; las tuplas son estructuras de datos inmutables +(setv mytuple (, 1 2)) +; los diccionarios son pares de valor-clave +(setv dict1 {"key1" 42 "key2" 21}) +; :nombre se puede usar para definir palabras clave en Hy que se pueden usar para claves +(setv dict2 {:key1 41 :key2 20}) +; usar 'get' para obtener un elemento en un índice/key +(get mylist 1) ;=> 2 +(get dict1 "key1") ;=> 42 +; Alternativamente, si se usan palabras clave que podrían llamarse directamente +(:key1 dict2) ;=> 41 + +;; funciones y otras estructuras de programa +; las funciones son definidas usando defn, o el último sexp se devuelve por defecto +(defn greet [name] +  "A simple greeting" ; un docstring opcional +  (print "hello " name)) + +(greet "bilbo") ;=> "hello bilbo" + +; las funciones pueden tener argumentos opcionales, así como argumentos-clave +(defn foolists [arg1 &optional [arg2 2]] +  [arg1 arg2]) + +(foolists 3) ;=> [3 2] +(foolists 10 3) ;=> [10 3] + +; las funciones anonimas son creadas usando constructores 'fn' y 'lambda' +; que son similares a 'defn' +(map (fn [x] (* x x)) [1 2 3 4]) ;=> [1 4 9 16] + +;; operaciones de secuencia +; hy tiene algunas utilidades incluidas para operaciones de secuencia, etc. +; recuperar el primer elemento usando 'first' o 'car' +(setv mylist [1 2 3 4]) +(setv mydict {"a" 1 "b" 2}) +(first mylist) ;=> 1 + +; corte listas usando 'slice' +(slice mylist 1 3) ;=> [2 3] + +; obtener elementos de una lista o dict usando 'get' +(get mylist 1) ;=> 2 +(get mydict "b") ;=> 2 +; la lista de indexación comienza a partir de 0, igual que en python +; assoc puede definir elementos clave/índice +(assoc mylist 2 10) ; crear mylist [1 2 10 4] +(assoc mydict "c" 3) ; crear mydict {"a" 1 "b" 2 "c" 3} +; hay muchas otras funciones que hacen que trabajar con secuencias sea  +; entretenido + +;; Python interop +;; los import funcionan exactamente como en python +(import datetime) +(import [functools [partial reduce]]) ; importa fun1 e fun2 del module1 +(import [matplotlib.pyplot :as plt]) ; haciendo una importación en foo como en bar +; todos los métodos de python incluídos etc. son accesibles desde hy +; a.foo(arg) is called as (.foo a arg) +(.split (.strip "hello world  ")) ;=> ["hello" "world"] + +;; Condicionales +; (if condition (body-if-true) (body-if-false) +(if (= passcode "moria") +  (print "welcome") +  (print "Speak friend, and Enter!")) + +; anidar múltiples cláusulas 'if else if' con condiciones +(cond + [(= someval 42) +  (print "Life, universe and everything else!")] + [(> someval 42) +  (print "val too large")] + [(< someval 42) +  (print "val too small")]) + +; declaraciones de grupo con 'do', son ejecutadas secuencialmente +; formas como defn tienen un 'do' implícito +(do + (setv someval 10) + (print "someval is set to " someval)) ;=> 10 + +; crear enlaces léxicos con 'let', todas las variables definidas de esta manera +; tienen alcance local +(let [[nemesis {"superman" "lex luther" +                "sherlock" "moriarty" +                "seinfeld" "newman"}]] +  (for [(, h v) (.items nemesis)] +    (print (.format "{0}'s nemesis was {1}" h v)))) + +;; clases +; las clases son definidas de la siguiente manera +(defclass Wizard [object] +  [[--init-- (fn [self spell] +             (setv self.spell spell) ; init the attr magic +             None)] +   [get-spell (fn [self] +              self.spell)]]) + +;; acesse hylang.org +``` + +### Otras lecturas + +Este tutorial apenas es una introducción básica para hy/lisp/python. + +Docs Hy: [http://hy.readthedocs.org](http://hy.readthedocs.org) + +Repo Hy en GitHub: [http://github.com/hylang/hy](http://github.com/hylang/hy) + +Acceso a freenode irc con #hy, hashtag en twitter: #hylang -- cgit v1.2.3 From b72dd03ed2ee63457d944a4e722003e0d81a5f87 Mon Sep 17 00:00:00 2001 From: rrodriguze Date: Tue, 1 Oct 2019 21:49:37 +0200 Subject: Modified yaml spacing --- es-es/hy-es.html.markdown | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'es-es') diff --git a/es-es/hy-es.html.markdown b/es-es/hy-es.html.markdown index 8b0532e3..bfad3b6e 100644 --- a/es-es/hy-es.html.markdown +++ b/es-es/hy-es.html.markdown @@ -1,11 +1,11 @@ --- -language: hy -filename: learnhy-es.hy +language: hy +filename: learnhy-es.hy contributors: -    - ["Abhishek L", "http://twitter.com/abhishekl"] + - ["Abhishek L", "http://twitter.com/abhishekl"] translators: -    - ["Roberto R", "https://github.com/rrodriguze"] -lang: es-es + - ["Roberto R", "https://github.com/rrodriguze"] +lang: es-es --- Hy es un lenguaje de Lisp escrito sobre Python. Esto es posible convirtiendo -- cgit v1.2.3 From fe13d4dbce8d05e8388e5a844f843bbc9c19b3e6 Mon Sep 17 00:00:00 2001 From: rrodriguze Date: Tue, 1 Oct 2019 22:36:43 +0200 Subject: Add spanish traduction for factor --- es-es/factor-es.html.markdown | 200 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 200 insertions(+) create mode 100644 es-es/factor-es.html.markdown (limited to 'es-es') diff --git a/es-es/factor-es.html.markdown b/es-es/factor-es.html.markdown new file mode 100644 index 00000000..67c60de7 --- /dev/null +++ b/es-es/factor-es.html.markdown @@ -0,0 +1,200 @@ +--- +language: factor +contributors: + - ["hyphz", "http://github.com/hyphz/"] +translators: + - ["Roberto R", "https://github.com/rrodriguze"] +filename: learnfactor-es.factor + +lang: es-es +--- +Factor es un lenguaje moderno basado en la pila, basado en Forth, creado por +Slava Pestov. + +El código de este archivo puede escribirse en Factor, pero no importa +directamente porque el encabezado del vocabulario de importación haria que el +comienzo fuera totalmente confuso. + +```factor +! Esto es un comentario + +! Como Forth, toda la programación se realiza mediante la manipulación de la +! pila. +! La intruducción de un valor literal lo coloca en la pila +5 2 3 56 76 23 65 ! No hay salida pero la pila se imprime en modo interactivo + +! Esos números se agregan a la pila de izquierda a derecha +! .s imprime la pila de forma no destructiva. +.s ! 5 2 3 56 76 23 65 + +! La aritmética funciona manipulando datos en la pila. +5 4 + ! Sem saída + +! `.` muestra el resultado superior de la pila y lo imprime. +. ! 9 + +! Más ejemplos de aritmética: +6 7 * . ! 42 +1360 23 - . ! 1337 +12 12 / . ! 1 +13 2 mod . ! 1 + +99 neg . ! -99 +-99 abs . ! 99 +52 23 max . ! 52 +52 23 min . ! 23 + +! Se proporcionan varias palabras para manipular la pila, conocidas +colectivamente como palabras codificadas. + +3 dup - ! duplica el primer item (1st ahora igual a 2nd): 3 - 3 +2 5 swap / ! intercambia el primero con el segundo elemento: 5 / 2 +4 0 drop 2 / ! elimina el primer item (no imprime en pantalla): 4 / 2 +1 2 3 nip .s ! elimina el segundo item (semejante a drop): 1 3 +1 2 clear .s ! acaba con toda la pila +1 2 3 4 over .s ! duplica el segundo item superior: 1 2 3 4 3 +1 2 3 4 2 pick .s ! duplica el tercer item superior: 1 2 3 4 2 3 + +! Creando Palabras +! La palabra `:` factoriza los conjuntos en modo de compilación hasta que vea +la palabra`;`. +: square ( n -- n ) dup * ; ! Sin salida +5 square . ! 25 + +! Podemos ver lo que las palabra hacen también. +! \ suprime la evaluación de una palabra y coloca su identificador en la pila. +\ square see ! : square ( n -- n ) dup * ; + +! Después del nombre de la palabra para crear, la declaración entre paréntesis +da efecto a la pila. +! Podemos usar los nombres que queramos dentro de la declaración: +: weirdsquare ( camel -- llama ) dup * ; + +! Mientras su recuento coincida con el efecto de pila de palabras: +: doubledup ( a -- b ) dup dup ; ! Error: Stack effect declaration is wrong +: doubledup ( a -- a a a ) dup dup ; ! Ok +: weirddoubledup ( i -- am a fish ) dup dup ; ! Além disso Ok + +! Donde Factor difiere de Forth es en el uso de las citaciones. +! Una citacion es un bloque de código que se coloca en la pila como un valor. +! [ inicia el modo de citación; ] termina. +[ 2 + ] ! La cita que suma dos queda en la pila +4 swap call . ! 6 + +! Y así, palabras de orden superior. TONOS de palabras de orden superior +2 3 [ 2 + ] dip .s ! Tomar valor de la parte superior de la pilar, cotizar, retroceder: 4 3 +3 4 [ + ] keep .s ! Copiar el valor desde la parte superior de la pila, cotizar, enviar copia: 7 4 +1 [ 2 + ] [ 3 + ] bi .s ! Ejecute cada cotización en el valor superior, empuje amabos resultados: 3 4 +4 3 1 [ + ] [ + ] bi .s ! Las citas en un bi pueden extraer valores más profundos de la pila: 4 5 ( 1+3 1+4 ) +1 2 [ 2 + ] bi@ .s ! Citar en primer y segundo valor +2 [ + ] curry ! Inyecta el valor dado al comienzo de la pila: [ 2 + ] se deja en la pila + +! Condicionales +! Cualquier valor es verdadero, excepto el valor interno f. +! no existe un valor interno, pero su uso no es esencial. +! Los condicionales son palabras de orden superior, como con los combinadores +! anteriores + +5 [ "Five is true" . ] when ! Cinco es verdadero +0 [ "Zero is true" . ] when ! Cero es verdadero +f [ "F is true" . ] when ! Sin salida +f [ "F is false" . ] unless ! F es falso +2 [ "Two is true" . ] [ "Two is false" . ] if ! Two es verdadero + +! Por defecto, los condicionales consumen el valor bajo prueba, pero las +! variantes con un +! asterisco se dejan solo si es verdad: + +5 [ . ] when* ! 5 +f [ . ] when* ! Sin salida, pila vacía, se consume porque f es falso + + +! Lazos +! Lo has adivinado... estas son palabras de orden superior también. + +5 [ . ] each-integer ! 0 1 2 3 4 +4 3 2 1 0 5 [ + . ] each-integer ! 0 2 4 6 8 +5 [ "Hello" . ] times ! Hello Hello Hello Hello Hello + +! Here's a list: +{ 2 4 6 8 } ! Goes on the stack as one item + +! Aqui está uma lista: +{ 2 4 6 8 } [ 1 + . ] each ! Exibe 3 5 7 9 +{ 2 4 6 8 } [ 1 + ] map ! Salida { 3 5 7 9 } de la pila + +! Reduzir laços ou criar listas: +{ 1 2 3 4 5 } [ 2 mod 0 = ] filter ! Solo mantenga miembros de la lista para los cuales la cita es verdadera: { 2 4 } +{ 2 4 6 8 } 0 [ + ] reduce . ! Como "fold" en lenguajes funcinales: exibe 20 (0+2+4+6+8) +{ 2 4 6 8 } 0 [ + ] accumulate . . ! Como reducir, pero mantiene los valores intermedios en una lista: { 0 2 6 12 } así que 20 +1 5 [ 2 * dup ] replicate . ! Repite la cita 5 veces y recoge los resultados en una lista: { 2 4 8 16 32 } +1 [ dup 100 < ] [ 2 * dup ] produce ! Repite la segunda cita hasta que la primera devuelva falso y recopile los resultados: { 2 4 8 16 32 64 128 } + +! Si todo lo demás falla, un propósito general a repetir. +1 [ dup 10 < ] [ "Hello" . 1 + ] while ! Escribe "Hello" 10 veces + ! Sí, es dificil de leer + ! Para eso están los bucles variantes + +! Variables +! Normalmente, se espera que los programas de Factor mantengan todos los datos +! en la pila. +! El uso de variables con nombre hace que la refactorización sea más difícil +! (y se llama Factor por una razón) +! Variables globales, si las necesitas: + +SYMBOL: name ! Crea un nombre como palabra de identificación +"Bob" name set-global ! Sin salída +name get-global . ! "Bob" + +! Las variables locales nombradas se consideran una extensión, pero están +! disponibles +! En una cita .. +[| m n ! La cita captura los dos valores principales de la pila en m y n + | m n + ] ! Leerlos + +! Ou em uma palavra.. +:: lword ( -- ) ! Tenga en cuenta los dos puntos dobles para invocar la extensión de variable léxica + 2 :> c ! Declara la variable inmutable c para contener 2 + c . ; ! Imprimirlo + +! En una palabra declarada de esta manera, el lado de entrada de la declaración +! de la pila +! se vuelve significativo y proporciona los valores de las variables en las que +! se capturan los valores de pila +:: double ( a -- result ) a 2 * ; + +! Las variables se declaran mutables al terminar su nombre con su signo de +! exclamación +:: mword2 ( a! -- x y ) ! Capture la parte superior de la pila en la variable mutable a + a ! Empujar a + a 2 * a! ! Multiplique por 2 y almacenar el resultado en a + a ; ! Empujar el nuevo valor de a +5 mword2 ! Pila: 5 10 + +! Listas y Secuencias +! Vimos arriba cómo empujar una lista a la pila + +0 { 1 2 3 4 } nth ! Acceder a un miembro específico de una lista: 1 +10 { 1 2 3 4 } nth ! Error: índice de secuencia fuera de los límites +1 { 1 2 3 4 } ?nth ! Lo mismo que nth si el índice está dentro de los límites: 2 +10 { 1 2 3 4 } ?nth ! Sin errores si está fuera de los límites: f + +{ "at" "the" "beginning" } "Append" prefix ! { "Append" "at" "the" "beginning" } +{ "Append" "at" "the" } "end" suffix ! { "Append" "at" "the" "end" } +"in" 1 { "Insert" "the" "middle" } insert-nth ! { "Insert" "in" "the" "middle" } +"Concat" "enate" append ! "Concatenate" - strings are sequences too +"Concatenate" "Reverse " prepend ! "Reverse Concatenate" +{ "Concatenate " "seq " "of " "seqs" } concat ! "Concatenate seq of seqs" +{ "Connect" "subseqs" "with" "separators" } " " join ! "Connect subseqs with separators" + +! Y si desea obtener meta, las citas son secuencias y se pueden desmontar +0 [ 2 + ] nth ! 2 +1 [ 2 + ] nth ! + +[ 2 + ] \ - suffix ! Quotation [ 2 + - ] + + +``` + +##Listo para más? + +* [Documentación de Factor](http://docs.factorcode.org/content/article-help.home.html) -- cgit v1.2.3 From cadc25ee89e505485e18df8cd36de679a5f51654 Mon Sep 17 00:00:00 2001 From: rrodriguze Date: Tue, 1 Oct 2019 23:01:34 +0200 Subject: Added spanish traduction for hq9+ --- es-es/hq9+-es.html.markdown | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 es-es/hq9+-es.html.markdown (limited to 'es-es') diff --git a/es-es/hq9+-es.html.markdown b/es-es/hq9+-es.html.markdown new file mode 100644 index 00000000..0e1a36e1 --- /dev/null +++ b/es-es/hq9+-es.html.markdown @@ -0,0 +1,44 @@ +--- +language: HQ9+ +filename: hq9+-es.html +contributors: + - ["Alexey Nazaroff", "https://github.com/rogaven"] +translators: + - ["Roberto R", "https://github.com/rrodriguze"] +lang: es-es +--- + +HQ9+ es una parodia de los lenguajes de programación esotéricos y fue creado +por Cliff Biffle. +El lenguaje tiene solo cuatro comandos y no está completo de Turing. + +``` +Solo hay cuatro comandos, representados por los siguientes cuatro caracteres +H: imprime "Hello, world!" +Q: imprime el código fuente del programa (ein Quine) +9: imprime la letra de "99 Bottles of Beer" ++: aumenta el acumulador en uno (el valod del acumulador no se puede leer) +Cualquier otro caracter es ignorado. + +Ok. Escribamos el programa: + HQ + +Resultado: + Hello world! + HQ + +HQ9+ es muy simple, pero te permite hacer cosas en él. Otros lenguajes son muy +difíciles.Por ejemplo, el siguiente programa imprime tres copias de sí mismo en +la pantalla: + QQQ +Esto imprime: + QQQ + QQQ + QQQ +``` + +Y esto es todo. Hay muchos intérpretes para HQ9+. +A continuación encontrarás uno de ellos. + ++ [One of online interpreters](https://almnet.de/esolang/hq9plus.php) ++ [HQ9+ official website](http://cliffle.com/esoterica/hq9plus.html) -- cgit v1.2.3 From 306b923cdc1bd2da0a418125f294c676b39619da Mon Sep 17 00:00:00 2001 From: rrodriguze Date: Tue, 1 Oct 2019 23:22:16 +0200 Subject: Added spanish traduction for pcre --- es-es/pcre-es.html.markdown | 84 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 es-es/pcre-es.html.markdown (limited to 'es-es') diff --git a/es-es/pcre-es.html.markdown b/es-es/pcre-es.html.markdown new file mode 100644 index 00000000..279c9a39 --- /dev/null +++ b/es-es/pcre-es.html.markdown @@ -0,0 +1,84 @@ +--- +language: PCRE +filename: pcre-es.txt +contributors: + - ["Sachin Divekar", "http://github.com/ssd532"] +translators: + - ["Roberto R", "https://github.com/rrodriguze"] +lang: es-es +--- + +Una expresión regular (regex o regexp para abreviar) es una cadena especial +utilizada para definir un patrón, por ejemplo, buscar una secuencia de +caracteres; por ejemplo, `/^[a-z]+:/` se puede usar para extraer `http:` +desde la URL `http://github.com/`. + +PCRE (Pearl Compatible Regular Expressions) es una biblioteca para expresiones +muy similar a la Perls, desde ahí el nombre. Se trata de una de las sintaxis +más comunes para escribir expresiones regulares. + +Hay dos tipos de metacaracteres (caracteres con una función especial): + +* Caracteres reconocidos en todas partes excepto corchetes + +``` + \ caracter de escape + ^ buscar al principio de la cadena (o línea, en modo multilínea) + $ busca al final de la cadena (o línea, en modo multilínea) + . cualquier caracter exceptoo las nuevas líneas + [ inicio de clase de caracter + | condiciones alternativas del separador + ( inicio del subpatrón + ) fin del subpatrón + ? cuantificador "0 o 1" + * quantificatore "0 o más" + + quantificatore "1 o más" + { inicio de cuantificador numérico +``` + +* Caracteres reconocidos entre corchetes + +``` + \ caracter de escape + ^ negar la clase si es el primer caracter + - indica una serie de caracteres + [ clase de caracteres POSIX (si sigue la sintaxis POSIX) + ] termina la clase de caracteres +``` + +PCRE también proporciona clases de caracteres predefinidas + +``` + \d cifra decimal + \D cifra NO decimal + \h espacio horizontal vacío + \H espacio horizontal NO vacío + \s espacio + \S NO esoacui + \v espacio vertical vacío + \V espacio vertical NO vacío + \w palabra + \W "NO palabra" +``` + +## Ejemplos + +Usaremos la siguiente cadena para nuestras pruebas: + +``` +66.249.64.13 - - [18/Sep/2004:11:07:48 +1000] "GET /robots.txt HTTP/1.0" 200 468 "-" "Googlebot/2.1" +``` + +Se trata de una línea de log del servidor web Apache. + +| Regex | Resultado | Comentario | +| :---- | :-------------- | :------ | +| `GET` | GET | Busque exactamente la cadena "GET" (distingue entre mayúsculas y minúsculas) | +| `\d+.\d+.\d+.\d+` | 66.249.64.13 | `\d+` identifica uno o más (cuantificador `+`) números [0-9], `\.` identifica el caracter `.` | +| `(\d+\.){3}\d+` | 66.249.64.13 | `(\d+\.){3}` busca el grupo (`\d+\.`) exactamente 3 veces. | +| `\[.+\]` | [18/Sep/2004:11:07:48 +1000] | `.+` identifica cualquier caracter, excepto las nuevas líneas; `.` indica cualquier carácter | +| `^\S+` | 66.249.64.13 | `^` buscar al inicio de la cadena, `\S+` identifica la primera cadena de caracteres que no sea espacio | +| `\+[0-9]+` | +1000 | `\+` identifica el caracter `+`. `[0-9]` indica una cifra de 0 a 9. La expresión es equivalente a `\+\d+` | + +## Otros recursos +[Regex101](https://regex101.com/) - probador de expresiones regulares -- cgit v1.2.3 From 97c80bff9e4c75d52ca7b7f4a3c3ce895863b00e Mon Sep 17 00:00:00 2001 From: Heitor Pascoal de Bittencourt Date: Tue, 8 Oct 2019 21:27:35 -0300 Subject: [c/es] Fix book link --- es-es/c-es.html.markdown | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'es-es') diff --git a/es-es/c-es.html.markdown b/es-es/c-es.html.markdown index 8bc1eabb..cae4349e 100644 --- a/es-es/c-es.html.markdown +++ b/es-es/c-es.html.markdown @@ -5,6 +5,7 @@ contributors: - ["Adam Bard", "http://adambard.com/"] translators: - ["Francisco García", "http://flaskbreaker.tumblr.com/"] + - ["Heitor P. de Bittencourt", "https://github.com/heitorPB/"] lang: es-es --- @@ -423,7 +424,7 @@ libro de C, escrito por Dennis Ritchie, creador de C y Brian Kernighan. Aún as se cuidadoso, es antiguo, contiene algunas inexactitudes, y algunas prácticas han cambiado. -Otro buen recurso es [Learn C the hard way](http://c.learncodethehardway.org/book/). +Otro buen recurso es [Learn C the hard way](http://learncodethehardway.org/c/). Si tienes una pregunta, lee [compl.lang.c Frequently Asked Questions](http://c-faq.com). -- cgit v1.2.3 From 8e0ceee41b8ace9ef28e4e1389f74e050e930c62 Mon Sep 17 00:00:00 2001 From: FedeHC Date: Tue, 14 Jan 2020 22:31:54 -0300 Subject: [sql/es] Translate SQL to Spanish --- es-es/sql-es.html.markdown | 115 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 es-es/sql-es.html.markdown (limited to 'es-es') diff --git a/es-es/sql-es.html.markdown b/es-es/sql-es.html.markdown new file mode 100644 index 00000000..8bb3aaac --- /dev/null +++ b/es-es/sql-es.html.markdown @@ -0,0 +1,115 @@ +--- +language: SQL +filename: learnsql-es.sql +contributors: + - ["Bob DuCharme", "http://bobdc.com/"] +translators: + - ["FedeHC", "https://github.com/FedeHC"] +lang: es-es +--- + +El lenguaje de consulta estructurada (SQL en inglés) es un lenguaje estándar ISO para crear y trabajar con bases de datos almacenados en un conjunto de tablas. Usualmente las implementaciones más usadas añaden sus propias extensiones al lenguaje; [Una comparación entre diferentes implementaciones de SQL](http://troels.arvin.dk/db/rdbms/) es una buena referencia sobre las diferencias entre distintos productos. + +Las implementaciones típicamente proveen de una línea de comandos donde uno puede introducir los comandos que se muestran aquí en forma interactiva, y también ofrecen una forma de ejecutar una serie de estos comandos almacenados en un archivo de script (mostrar que uno ha terminado con el prompt interactivo es un buen ejemplo de algo que no está estandarizado: la mayoría de las implementaciones de SQL soportan las palabras clave QUIT, EXIT, o ambas). + +Varios de estos comandos que sirven de ejemplo asumen que la [base de datos de empleados de muestra de MySQL](https://dev.mysql.com/doc/employee/en/) disponible en [github](https://github.com/datacharmer/test_db) ya ha sido cargada. Los archivos github son scripts de comandos, similares a los comandos que aparecen a continuación, que crean y cargan tablas de datos sobre los empleados de una empresa ficticia. La sintaxis para ejecutar estos scripts dependerá de la implementación de SQL que esté utilizando. Una aplicación que se ejecuta desde el prompt del sistema operativo suele ser lo habitual. + + +```sql +-- Los comentarios empiezan con dos guiones. Se termina cada comando con punto +-- y coma. + +-- SQL no distingue entre mayúsculas y minúsculas en palabras clave. Los +-- comandos de ejemplo que aquí se muestran siguen la convención de ser escritos +-- en mayúsculas porque hace más fácil distinguirlos de los nombres de las bases +-- de datos, de las tablas y de las columnas. + +-- A cont. se crea y se elimina una base de datos. Los nombres de la base de +-- datos y de la tabla son sensibles a mayúsculas y minúsculas. +CREATE DATABASE someDatabase; +DROP DATABASE someDatabase; + +-- Lista todas las bases de datos disponibles. +SHOW DATABASES; + +-- Usa una base de datos existente en particular. +USE employees; + +-- Selecciona todas las filas y las columnas de la tabla departments en la base +-- de datos actual. La actividad predeterminada es que el intérprete desplace +-- los resultados por la pantalla. +SELECT * FROM departments; + +-- Recupera todas las filas de la tabla departments, pero sólo las columnas +-- dept_no y dept_name. +-- Separar los comandos en varias líneas es aceptable. +SELECT dept_no, + dept_name FROM departments; + +-- Obtiene todas las columnas de departments, pero se limita a 5 filas. +SELECT * FROM departments LIMIT 5; + +-- Obtiene los valores de la columna dept_name desde la tabla departments cuando +-- dept_name tiene como valor la subcadena 'en'. +SELECT dept_name FROM departments WHERE dept_name LIKE '%en%'; + +-- Recuperar todas las columnas de la tabla departments donde la columna +-- dept_name comienza con una 'S' y tiene exactamente 4 caracteres después +-- de ella. +SELECT * FROM departments WHERE dept_name LIKE 'S____'; + +-- Selecciona los valores de los títulos de la tabla titles, pero no muestra +-- duplicados. +SELECT DISTINCT title FROM titles; + +-- Igual que el anterior, pero ordenado por los valores de title (se distingue +-- entre mayúsculas y minúsculas). +SELECT DISTINCT title FROM titles ORDER BY title; + +-- Muestra el número de filas de la tabla departments. +SELECT COUNT(*) FROM departments; + +-- Muestra el número de filas en la tabla departments que contiene 'en' como +-- subcadena en la columna dept_name. +SELECT COUNT(*) FROM departments WHERE dept_name LIKE '%en%'; + +-- Una unión (JOIN) de información desde varias tablas: la tabla titles muestra +-- quién tiene qué títulos de trabajo, según sus números de empleados, y desde +-- qué fecha hasta qué fecha. Se obtiene esta información, pero en lugar del +-- número de empleado se utiliza el mismo como una referencia cruzada a la +-- tabla employee para obtener el nombre y apellido de cada empleado (y se +-- limita los resultados a 10 filas). +SELECT employees.first_name, employees.last_name, + titles.title, titles.from_date, titles.to_date +FROM titles INNER JOIN employees ON + employees.emp_no = titles.emp_no LIMIT 10; + +-- Se enumera todas las tablas de todas las bases de datos. Las implementaciones +-- típicamente proveen sus propios comandos para hacer esto con la base de datos +-- actualmente en uso. +SELECT * FROM INFORMATION_SCHEMA.TABLES +WHERE TABLE_TYPE='BASE TABLE'; + +-- Crear una tabla llamada tablename1, con las dos columnas mostradas, a partir +-- de la base de datos en uso. Hay muchas otras opciones disponibles para la +-- forma en que se especifican las columnas, como por ej. sus tipos de datos. +CREATE TABLE tablename1 (fname VARCHAR(20), lname VARCHAR(20)); + +-- Insertar una fila de datos en la tabla tablename1. Se asume que la tabla ha +-- sido definida para aceptar estos valores como aptos. +INSERT INTO tablename1 VALUES('Richard','Mutt'); + +-- En tablename1, se cambia el valor de fname a 'John' para todas las filas que +-- tengan un valor en lname igual a 'Mutt'. +UPDATE tablename1 SET fname='John' WHERE lname='Mutt'; + +-- Se borra las filas de la tabla tablename1 donde el valor de lname comience +-- con 'M'. +DELETE FROM tablename1 WHERE lname like 'M%'; + +-- Se borra todas las filas de la tabla tablename1, dejando la tabla vacía. +DELETE FROM tablename1; + +-- Se elimina toda la tabla tablename1 por completo. +DROP TABLE tablename1; +``` -- cgit v1.2.3 From 43cb5213104d3a7e1958eccb3fa3531a4ca511e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20Hern=C3=A1ndez=20Blas?= <1096022+nihilismus@users.noreply.github.com> Date: Wed, 5 Feb 2020 13:41:55 -0600 Subject: Limit document to 80 columns, where possible --- es-es/clojure-es.html.markdown | 40 +++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-) (limited to 'es-es') diff --git a/es-es/clojure-es.html.markdown b/es-es/clojure-es.html.markdown index 150d0bb2..937a7d95 100644 --- a/es-es/clojure-es.html.markdown +++ b/es-es/clojure-es.html.markdown @@ -10,8 +10,10 @@ lang: es-es --- Clojure es un lenguaje de la familia Lisp desarrollado sobre la Máquina Virtual -de Java. Tiene un énfasis mayor en la [programación funcional](https://es.wikipedia.org/wiki/Programación_funcional) pura -que Common Lisp, pero incluyendo la posibilidad de usar [SMT](https://es.wikipedia.org/wiki/Memoria_transacional) para manipular +de Java. Tiene un énfasis mayor en la +[programación funcional](https://es.wikipedia.org/wiki/Programación_funcional) +pura que Common Lisp, pero incluyendo la posibilidad de usar +[SMT](https://es.wikipedia.org/wiki/Memoria_transacional) para manipular el estado según se presente. Esta combinación le permite gestionar la concurrencia de manera muy sencilla @@ -19,7 +21,6 @@ y a menudo automáticamente. (Necesitas la versión de Clojure 1.2 o posterior) - ```clojure ; Los comentatios comienzan con punto y coma. @@ -29,8 +30,8 @@ y a menudo automáticamente. ; El "reader" (lector) de Clojure asume que el primer objeto es una ; función o una macro que se va a llamar, y que el resto son argumentos. -; El primer form en un archivo debe ser ns, para establecer el namespace (espacio de -; nombres) +; El primer form en un archivo debe ser ns, para establecer el namespace +; (espacio de nombres) (ns learnclojure) ; Algunos ejemplos básicos: @@ -78,9 +79,9 @@ y a menudo automáticamente. ; Colecciones & Secuencias ;;;;;;;;;;;;;;;;;;; -; Las Listas están basadas en las listas enlazadas, mientras que los Vectores en -; arrays. -; ¡Los Vectores y las Listas también son clases de Java! +; Las Listas están basadas en las listas enlazadas, mientras que los Vectores +; en arrays. +; Los Vectores y las Listas también son clases de Java! (class [1 2 3]); => clojure.lang.PersistentVector (class '(1 2 3)); => clojure.lang.PersistentList @@ -168,7 +169,8 @@ x ; => 1 (hello3 "Jake") ; => "Hello Jake" (hello3) ; => "Hello World" -; Las funciones pueden usar argumentos extras dentro de un seq utilizable en la función +; Las funciones pueden usar argumentos extras dentro de un seq utilizable en +; la función (defn count-args [& args] (str "You passed " (count args) " args: " args)) (count-args 1 2 3) ; => "You passed 3 args: (1 2 3)" @@ -183,8 +185,8 @@ x ; => 1 ; Mapas ;;;;;;;;;; -; Mapas de Hash y mapas de arrays comparten una misma interfaz. Los mapas de Hash -; tienen búsquedas más rápidas pero no mantienen el orden de las claves. +; Mapas de Hash y mapas de arrays comparten una misma interfaz. Los mapas de +; Hash tienen búsquedas más rápidas pero no mantienen el orden de las claves. (class {:a 1 :b 2 :c 3}) ; => clojure.lang.PersistentArrayMap (class (hash-map :a 1 :b 2 :c 3)) ; => clojure.lang.PersistentHashMap @@ -193,7 +195,8 @@ x ; => 1 ; Los mapas pueden usar cualquier tipo para sus claves, pero generalmente las ; keywords (palabras clave) son lo habitual. -; Las keywords son parecidas a cadenas de caracteres con algunas ventajas de eficiencia +; Las keywords son parecidas a cadenas de caracteres con algunas ventajas de +; eficiencia (class :a) ; => clojure.lang.Keyword (def stringmap {"a" 1, "b" 2, "c" 3}) @@ -250,8 +253,8 @@ keymap ; => {:a 1, :b 2, :c 3} ; Patrones útiles ;;;;;;;;;;;;;;;;; -; Las construcciones lógicas en clojure son macros, y presentan el mismo aspecto -; que el resto de forms. +; Las construcciones lógicas en clojure son macros, y presentan el mismo +; aspecto que el resto de forms. (if false "a" "b") ; => "b" (if false "a") ; => nil @@ -352,8 +355,10 @@ keymap ; => {:a 1, :b 2, :c 3} ; Actualiza un atom con swap! ; swap! toma una función y la llama con el valor actual del atom ; como su primer argumento, y cualquier argumento restante como el segundo -(swap! my-atom assoc :a 1) ; Establece my-atom al resultado de (assoc {} :a 1) -(swap! my-atom assoc :b 2) ; Establece my-atom al resultado de (assoc {:a 1} :b 2) +(swap! my-atom assoc :a 1) ; Establece my-atom al resultado +; de (assoc {} :a 1) +(swap! my-atom assoc :b 2) ; Establece my-atom al resultado +; de (assoc {:a 1} :b 2) ; Usa '@' para no referenciar al atom sino para obtener su valor my-atom ;=> Atom<#...> (Regresa el objeto Atom) @@ -377,7 +382,8 @@ my-atom ;=> Atom<#...> (Regresa el objeto Atom) ; Agents: http://clojure.org/agents ### Lectura adicional -Ésto queda lejos de ser exhaustivo, pero espero que sea suficiente para que puedas empezar tu camino. +Ésto queda lejos de ser exhaustivo, pero espero que sea suficiente para que +puedas empezar tu camino. Clojure.org tiene muchos artículos: [http://clojure.org/](http://clojure.org/) -- cgit v1.2.3 From e60cd7ecddd5873dac7cd462ea05a2c4f97b09d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20Hern=C3=A1ndez=20Blas?= <1096022+nihilismus@users.noreply.github.com> Date: Thu, 6 Feb 2020 12:38:28 -0600 Subject: Update translation --- es-es/clojure-es.html.markdown | 234 ++++++++++++++++++++++++----------------- 1 file changed, 136 insertions(+), 98 deletions(-) (limited to 'es-es') diff --git a/es-es/clojure-es.html.markdown b/es-es/clojure-es.html.markdown index 937a7d95..62935ebe 100644 --- a/es-es/clojure-es.html.markdown +++ b/es-es/clojure-es.html.markdown @@ -9,29 +9,30 @@ translators: lang: es-es --- -Clojure es un lenguaje de la familia Lisp desarrollado sobre la Máquina Virtual +Clojure es un lenguaje de la familia Lisp desarrollado para la Máquina Virtual de Java. Tiene un énfasis mayor en la [programación funcional](https://es.wikipedia.org/wiki/Programación_funcional) -pura que Common Lisp, pero incluyendo la posibilidad de usar +pura que Common Lisp, pero incluye varias utilidades de [SMT](https://es.wikipedia.org/wiki/Memoria_transacional) para manipular el estado según se presente. -Esta combinación le permite gestionar la concurrencia de manera muy sencilla -y a menudo automáticamente. +Esta combinación le permite gestionar el procesamiento concurrente de manera +muy sencilla, y a menudo automáticamente. + +(Necesitas la versión de Clojure 1.2 o reciente) -(Necesitas la versión de Clojure 1.2 o posterior) ```clojure -; Los comentatios comienzan con punto y coma. +; Los comentarios comienzan con punto y coma. -; Clojure se escribe mediante "forms" (patrones), los cuales son -; listas de objectos entre paréntesis, separados por espacios en blanco. +; Clojure se escribe mediante patrones ("forms"), los cuales son +; listas de cosas entre paréntesis, separados por espacios en blanco. -; El "reader" (lector) de Clojure asume que el primer objeto es una -; función o una macro que se va a llamar, y que el resto son argumentos. +; El lector ("reader") de Clojure asume que la primera cosa es una +; función o una macro a llamar, y el resto son argumentos. -; El primer form en un archivo debe ser ns, para establecer el namespace -; (espacio de nombres) +; La primera llamada en un archivo debe ser ns, para establecer el espacio de +; nombres ("namespace") (ns learnclojure) ; Algunos ejemplos básicos: @@ -52,69 +53,70 @@ y a menudo automáticamente. ; También es necesaria la negación para las operaciones lógicas (not true) ; => false -; Cuando se anidan Los patrones, estos funcionan de la manera esperada +; Los patrones anidados funcionan como esperas (+ 1 (- 3 2)) ; = 1 + (3 - 2) => 2 ; Tipos ;;;;;;;;;;;;; -; Clojure usa los tipos de objetos de Java para booleanos, strings (cadenas de -; caracteres) y números. -; Usa class para saber de qué tipo es. -(class 1); Los enteros son java.lang.Long por defecto -(class 1.); Los numeros en coma flotante son java.lang.Double -(class ""); Los strings van entre comillas dobles, y son -; son java.lang.String -(class false); Los Booleanos son java.lang.Boolean +; Clojure usa los tipos de objetos de Java para booleanos, cadenas de +; caracteres ("strings") y números. +; Usa class para inspeccionarlos. +(class 1); Los números enteros literales son java.lang.Long por defecto +(class 1.); Los números en coma flotante literales son java.lang.Double +(class ""); Los strings siempre van entre comillas dobles, y son + ; java.lang.String +(class false); Los booleanos son java.lang.Boolean (class nil); El valor "null" se escribe nil -; Si quieres crear una lista de datos, precedela con una comilla -; simple para evitar su evaluación +; Si quieres crear una lista literal de datos, usa ' para evitar su evaluación '(+ 1 2) ; => (+ 1 2) -; (que es una abreviatura de (quote (+ 1 2)) ) +; (que es una abreviatura de (quote (+ 1 2))) -; Puedes evaluar una lista precedida por comilla con eval +; Puedes evaluar una lista precedida por una comilla con eval (eval '(+ 1 2)) ; => 3 ; Colecciones & Secuencias ;;;;;;;;;;;;;;;;;;; -; Las Listas están basadas en las listas enlazadas, mientras que los Vectores -; en arrays. -; Los Vectores y las Listas también son clases de Java! +; Las Listas están basadas en listas enlazadas, mientras que los Vectores en +; arreglos. +; ¡Los Vectores y las Listas también son clases de Java! (class [1 2 3]); => clojure.lang.PersistentVector (class '(1 2 3)); => clojure.lang.PersistentList -; Una lista podría ser escrita como (1 2 3), pero debemos ponerle una -; comilla simple delante para evitar que el reader piense que es una función. +; Una lista podría ser escrita como (1 2 3), pero debemos precederle una +; comilla para evitar que el lector ("reader") piense que es una función. ; Además, (list 1 2 3) es lo mismo que '(1 2 3) -; Las "Colecciones" son solo grupos de datos -; Tanto las listas como los vectores son colecciones: +; Las Colecciones ("collections") son solo grupos de datos +; Tanto las Listas como los Vectores son colecciones: (coll? '(1 2 3)) ; => true (coll? [1 2 3]) ; => true -; Las "Secuencias" (seqs) son descripciones abstractas de listas de datos. -; Solo las listas son seqs. +; Las Secuencias ("seqs") son descripciones abstractas de listas de datos. +; Solo las listas son secuencias ("seqs"). (seq? '(1 2 3)) ; => true (seq? [1 2 3]) ; => false -; Una seq solo necesita proporcionar una entrada cuando es accedida. -; Así que, las seqs pueden ser perezosas -- pueden establecer series infinitas: +; Una secuencia solo necesita proporcionar uno de sus elementos cuando es +; accedido. +; Así que, las secuencias pueden ser perezosas -- pueden definir series +; infinitas: (range 4) ; => (0 1 2 3) (range) ; => (0 1 2 3 4 ...) (una serie infinita) (take 4 (range)) ; (0 1 2 3) -; Usa cons para agregar un elemento al inicio de una lista o vector +; Usa cons para agregar un elemento al inicio de una Lista o Vector (cons 4 [1 2 3]) ; => (4 1 2 3) (cons 4 '(1 2 3)) ; => (4 1 2 3) ; conj agregará un elemento a una colección en la forma más eficiente. -; Para listas, se añade al inicio. Para vectores, al final. +; Para Listas, se añade al inicio. Para vectores, al final. (conj [1 2 3] 4) ; => [1 2 3 4] (conj '(1 2 3) 4) ; => (4 1 2 3) -; Usa concat para concatenar listas o vectores +; Usa concat para concatenar Listas o Vectores (concat [1 2] '(3 4)) ; => (1 2 3 4) ; Usa filter y map para actuar sobre colecciones @@ -126,7 +128,7 @@ y a menudo automáticamente. ; = (+ (+ (+ 1 2) 3) 4) ; => 10 -; reduce puede tener un argumento indicando su valor inicial. +; reduce puede tomar un argumento como su valor inicial también (reduce conj [] '(3 2 1)) ; = (conj (conj (conj [] 3) 2) 1) ; => [3 2 1] @@ -138,44 +140,42 @@ y a menudo automáticamente. ; su última expresión (fn [] "Hello World") ; => fn -; (Necesitas rodearlo con paréntesis para invocarla) +; (Necesitas rodearlo con paréntesis para llamarla) ((fn [] "Hello World")) ; => "Hello World" -; Puedes crear una var (variable) mediante def +; Puedes definir una variable ("var") mediante def (def x 1) x ; => 1 -; Asigna una función a una var +; Asignar una función a una variable ("var") (def hello-world (fn [] "Hello World")) (hello-world) ; => "Hello World" -; Puedes defn como atajo para lo anterior +; Puedes usar defn como atajo para lo anterior (defn hello-world [] "Hello World") -; El [] es el vector de argumentos de la función. +; El [] es el Vector de argumentos de la función. (defn hello [name] (str "Hello " name)) (hello "Steve") ; => "Hello Steve" -; Otra abreviatura para crear funciones es: +; Puedes usar esta abreviatura para definir funciones: (def hello2 #(str "Hello " %1)) (hello2 "Fanny") ; => "Hello Fanny" -; Puedes tener funciones multi-variadic: funciones con un numero variable de -; argumentos +; Puedes tener funciones multi-variables ("multi-variadic") también (defn hello3 ([] "Hello World") ([name] (str "Hello " name))) (hello3 "Jake") ; => "Hello Jake" (hello3) ; => "Hello World" -; Las funciones pueden usar argumentos extras dentro de un seq utilizable en -; la función +; Las funciones pueden empaquetar argumentos extras en una secuencia para ti (defn count-args [& args] (str "You passed " (count args) " args: " args)) (count-args 1 2 3) ; => "You passed 3 args: (1 2 3)" -; Y puedes mezclarlos con el resto de argumentos declarados de la función. +; Puedes combinar los argumentos regulares y los empaquetados (defn hello-count [name & args] (str "Hello " name ", you passed " (count args) " extra args")) (hello-count "Finn" 1 2 3) @@ -185,18 +185,18 @@ x ; => 1 ; Mapas ;;;;;;;;;; -; Mapas de Hash y mapas de arrays comparten una misma interfaz. Los mapas de -; Hash tienen búsquedas más rápidas pero no mantienen el orden de las claves. +; Los Mapas de Hash ("HashMap") y Mapas de Arreglo ("ArrayMap") comparten una +; interfaz. Los Mapas de Hash tienen búsquedas más rápidas pero no mantienen el +; orden de las llaves. (class {:a 1 :b 2 :c 3}) ; => clojure.lang.PersistentArrayMap (class (hash-map :a 1 :b 2 :c 3)) ; => clojure.lang.PersistentHashMap -; Los mapas de arrays se convertidos en mapas de Hash en la mayoría de -; operaciones si crecen mucho, por lo que no debes preocuparte. +; Los Mapas de Arreglo se convierten automáticamente en Mapas de Hash en la +; mayoría de operaciones si crecen mucho, por lo que no debes preocuparte. -; Los mapas pueden usar cualquier tipo para sus claves, pero generalmente las -; keywords (palabras clave) son lo habitual. -; Las keywords son parecidas a cadenas de caracteres con algunas ventajas de -; eficiencia +; Los Mapas pueden usar cualquier tipo para sus llaves, pero generalmente las +; Claves ("keywords") son lo habitual. +; Las Claves son como strings con algunas ventajas de eficiencia (class :a) ; => clojure.lang.Keyword (def stringmap {"a" 1, "b" 2, "c" 3}) @@ -208,28 +208,28 @@ keymap ; => {:a 1, :c 3, :b 2} ; Por cierto, las comas son equivalentes a espacios en blanco y no hacen ; nada. -; Recupera un valor de un mapa tratandolo como una función +; Recupera un valor de un Mapa tratándola como una función (stringmap "a") ; => 1 (keymap :a) ; => 1 -; ¡Las keywords pueden ser usadas para recuperar su valor del mapa, también! +; ¡Las Claves pueden ser usadas para recuperar su valor del mapa, también! (:b keymap) ; => 2 ; No lo intentes con strings. ;("a" stringmap) ; => Exception: java.lang.String cannot be cast to clojure.lang.IFn -; Si preguntamos por una clave que no existe nos devuelve nil +; Recuperando una clave no existente nos devuelve nil (stringmap "d") ; => nil -; Usa assoc para añadir nuevas claves a los mapas de Hash +; Usa assoc para añadir nuevas claves a los Mapas de Hash (def newkeymap (assoc keymap :d 4)) newkeymap ; => {:a 1, :b 2, :c 3, :d 4} ; Pero recuerda, ¡los tipos de Clojure son inmutables! keymap ; => {:a 1, :b 2, :c 3} -; Usa dissoc para eliminar llaves +; Usa dissoc para eliminar claves (dissoc keymap :a :b) ; => {:c 3} ; Conjuntos @@ -241,50 +241,86 @@ keymap ; => {:a 1, :b 2, :c 3} ; Añade un elemento con conj (conj #{1 2 3} 4) ; => #{1 2 3 4} -; Elimina elementos con disj +; Elimina uno con disj (disj #{1 2 3} 1) ; => #{2 3} -; Comprueba su existencia usando el conjunto como una función: +; Comprueba su existencia usando al Conjunto como una función: (#{1 2 3} 1) ; => 1 (#{1 2 3} 4) ; => nil -; Hay más funciones en el namespace clojure.sets +; Hay más funciones en el espacio de nombres clojure.sets ; Patrones útiles ;;;;;;;;;;;;;;;;; -; Las construcciones lógicas en clojure son macros, y presentan el mismo -; aspecto que el resto de forms. +; Los operadores lógicos en clojure son solo macros, y presentan el mismo +; aspecto que el resto de patrones. (if false "a" "b") ; => "b" (if false "a") ; => nil -; Usa let para crear un binding (asociación) temporal +; Usa let para definir ("binding") una variable temporal (let [a 1 b 2] (> a b)) ; => false -; Agrupa expresiones mediante do +; Agrupa sentencias mediante do (do (print "Hello") "World") ; => "World" (prints "Hello") -; Las funciones tienen implicita la llamada a do +; Las funciones tienen un do implícito (defn print-and-say-hello [name] (print "Saying hello to " name) (str "Hello " name)) (print-and-say-hello "Jeff") ;=> "Hello Jeff" (prints "Saying hello to Jeff") -; Y el let también +; Y let también (let [name "Urkel"] (print "Saying hello to " name) (str "Hello " name)) ; => "Hello Urkel" (prints "Saying hello to Urkel") +; Usa las macros de tubería ("threading", "arrow", "pipeline" o "chain") +; (-> y ->>) para expresar la transformación de datos de una manera más clara. + +; La macro Tubería-primero ("Thread-first") (->) inserta en cada patrón el +; resultado de los previos, como el primer argumento (segundo elemento) +(-> + {:a 1 :b 2} + (assoc :c 3) ;=> (assoc {:a 1 :b 2} :c 3) + (dissoc :b)) ;=> (dissoc (assoc {:a 1 :b 2} :c 3) :b) + +; Esta expresión podría ser escrita como: +; (dissoc (assoc {:a 1 :b 2} :c 3) :b) +; y evalua a {:a 1 :c 3} + +; La macro Tubería-último ("Thread-last") hace lo mismo, pero inserta el +; resultado de cada línea al *final* de cada patrón. Esto es útil para las +; operaciones de colecciones en particular: +(->> + (range 10) + (map inc) ;=> (map inc (range 10) + (filter odd?) ;=> (filter odd? (map inc (range 10)) + (into [])) ;=> (into [] (filter odd? (map inc (range 10))) + ; Result: [1 3 5 7 9] + +; Cuando estés en una situación donde quieras tener más libertad en donde +; poner el resultado de transformaciones previas de datos en una expresión, +; puedes usar la macro as->. Con ella, puedes asignar un nombre especifico +; a la salida de la transformaciones y usarlo como identificador en tus +; expresiones encadenadas ("chain"). + +(as-> [1 2 3] input + (map inc input);=> You can use last transform's output at the last position + (nth input 2) ;=> and at the second position, in the same expression + (conj [4 5 6] input [8 9 10])) ;=> or in the middle ! + + ; Módulos ;;;;;;;;;;;;;;; ; Usa use para obtener todas las funciones del módulo (use 'clojure.set) -; Ahora podemos usar más operaciones de conjuntos +; Ahora podemos usar más operaciones de Conjuntos (intersection #{1 2 3} #{2 3 4}) ; => #{2 3} (difference #{1 2 3} #{2 3 4}) ; => #{1} @@ -294,19 +330,18 @@ keymap ; => {:a 1, :b 2, :c 3} ; Usa require para importar un módulo (require 'clojure.string) -; Usa / para llamar a las funciones de un módulo +; Usa / para llamar las funciones de un módulo ; Aquí, el módulo es clojure.string y la función es blank? (clojure.string/blank? "") ; => true -; Puedes asignarle una abreviatura a un modulo al importarlo +; Puedes asignarle una sobrenombre a un modulo al importarlo (require '[clojure.string :as str]) (str/replace "This is a test." #"[a-o]" str/upper-case) ; => "THIs Is A tEst." -; (#"" es una expresión regular) +; (#"" es una expresión regular literal) -; Puedes usar require (y use, pero no lo hagas) desde un espacio de nombre +; Puedes usar require (y use, pero no lo hagas) desde un espacio de nombres ; usando :require, -; No necesitas preceder con comilla simple tus módulos si lo haces de esta -; forma. +; No necesitas preceder con comilla tus módulos si lo haces de esta manera. (ns test (:require [clojure.string :as str] @@ -315,8 +350,8 @@ keymap ; => {:a 1, :b 2, :c 3} ; Java ;;;;;;;;;;;;;;;;; -; Java tiene una enorme librería estándar, por lo que resulta util -; aprender como interactuar con ella. +; Java tiene una enorme y útil librería estándar, por lo que querrás +; aprender como hacer uso de ella. ; Usa import para cargar un módulo de java (import java.util.Date) @@ -329,14 +364,15 @@ keymap ; => {:a 1, :b 2, :c 3} ; Usa el nombre de la clase con un "." al final para crear una nueva instancia (Date.) ; -; Usa "." para llamar a métodos o usa el atajo ".método" +; Usa "." para llamar métodos. O, usa el atajo ".método" (. (Date.) getTime) ; -(.getTime (Date.)) ; exactamente la misma cosa +(.getTime (Date.)) ; exactamente lo mismo. ; Usa / para llamar métodos estáticos. (System/currentTimeMillis) ; (System siempre está presente) -; Usa doto para hacer frente al uso de clases (mutables) más tolerable +; Usa doto para lidiar con el uso de clases (mutables) de una manera más +; tolerable (import java.util.Calendar) (doto (Calendar/getInstance) (.set 2000 1 1 0 0 0) @@ -345,9 +381,9 @@ keymap ; => {:a 1, :b 2, :c 3} ; STM ;;;;;;;;;;;;;;;;; -; Software Transactional Memory es un mecanismo que usa clojure para gestionar -; el estado persistente. Hay unas cuantas construcciones en clojure que -; hacen uso de este mecanismo. +; La Memoria Transaccional ("Software Transactional Memory" / "STM") es un +; mecanismo que usa clojure para gestionar la persistecia de estado. Hay unas +; cuantas construcciones en clojure que hacen uso de él. ; Un atom es el más sencillo. Se le da un valor inicial (def my-atom (atom {})) @@ -356,15 +392,15 @@ keymap ; => {:a 1, :b 2, :c 3} ; swap! toma una función y la llama con el valor actual del atom ; como su primer argumento, y cualquier argumento restante como el segundo (swap! my-atom assoc :a 1) ; Establece my-atom al resultado -; de (assoc {} :a 1) + ; de (assoc {} :a 1) (swap! my-atom assoc :b 2) ; Establece my-atom al resultado -; de (assoc {:a 1} :b 2) + ; de (assoc {:a 1} :b 2) -; Usa '@' para no referenciar al atom sino para obtener su valor +; Usa '@' para no referenciar al atom y obtener su valor my-atom ;=> Atom<#...> (Regresa el objeto Atom) @my-atom ; => {:a 1 :b 2} -; Un sencillo contador usando un atom sería +; Aquí está un sencillo contador usando un atom (def counter (atom 0)) (defn inc-counter [] (swap! counter inc)) @@ -377,23 +413,25 @@ my-atom ;=> Atom<#...> (Regresa el objeto Atom) @counter ; => 5 -; Otros forms que utilizan STM son refs y agents. +; Otras construcciones de STM son refs y agents. ; Refs: http://clojure.org/refs ; Agents: http://clojure.org/agents +``` + ### Lectura adicional -Ésto queda lejos de ser exhaustivo, pero espero que sea suficiente para que +Ésto queda lejos de ser exhaustivo, pero ojalá que sea suficiente para que puedas empezar tu camino. Clojure.org tiene muchos artículos: -[http://clojure.org/](http://clojure.org/) +[http://clojure.org](http://clojure.org) Clojuredocs.org contiene documentación con ejemplos para la mayoría de funciones principales (pertenecientes al core): -[http://clojuredocs.org/quickref/Clojure%20Core](http://clojuredocs.org/quickref/Clojure%20Core) +[http://clojuredocs.org/quickref](http://clojuredocs.org/quickref) 4Clojure es una genial forma de mejorar tus habilidades con clojure/FP: [http://www.4clojure.com/](http://www.4clojure.com/) -Clojure-doc.org (sí, de verdad) tiene un buen número de artículos con los que iniciarse en Clojure: -[http://clojure-doc.org/](http://clojure-doc.org/) +Clojure-doc.org (sí, de verdad) tiene un buen número de artículos con los que +iniciarse en Clojure: [http://clojure-doc.org](http://clojure-doc.org) -- cgit v1.2.3 From 48068a92425a3b3c5f8a11d45489120297aababc Mon Sep 17 00:00:00 2001 From: FedeHC Date: Fri, 7 Feb 2020 16:31:40 -0300 Subject: Update es-es/sql-es.html.markdown MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Antonio Hernández Blas <1096022+nihilismus@users.noreply.github.com> --- es-es/sql-es.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'es-es') diff --git a/es-es/sql-es.html.markdown b/es-es/sql-es.html.markdown index 8bb3aaac..c20ebca0 100644 --- a/es-es/sql-es.html.markdown +++ b/es-es/sql-es.html.markdown @@ -8,7 +8,7 @@ translators: lang: es-es --- -El lenguaje de consulta estructurada (SQL en inglés) es un lenguaje estándar ISO para crear y trabajar con bases de datos almacenados en un conjunto de tablas. Usualmente las implementaciones más usadas añaden sus propias extensiones al lenguaje; [Una comparación entre diferentes implementaciones de SQL](http://troels.arvin.dk/db/rdbms/) es una buena referencia sobre las diferencias entre distintos productos. +El lenguaje de consulta estructurada (SQL en inglés) es un lenguaje estándar ISO para crear y trabajar con bases de datos almacenados en un conjunto de tablas. Las implementaciones generalmente añaden sus propias extensiones al lenguaje; [Comparación entre diferentes implementaciones de SQL](http://troels.arvin.dk/db/rdbms/) es una buena referencia sobre las diferencias entre distintos productos. Las implementaciones típicamente proveen de una línea de comandos donde uno puede introducir los comandos que se muestran aquí en forma interactiva, y también ofrecen una forma de ejecutar una serie de estos comandos almacenados en un archivo de script (mostrar que uno ha terminado con el prompt interactivo es un buen ejemplo de algo que no está estandarizado: la mayoría de las implementaciones de SQL soportan las palabras clave QUIT, EXIT, o ambas). -- cgit v1.2.3 From 57ef3f1377a636b20abeb9e2f91cea8ddb3bfce0 Mon Sep 17 00:00:00 2001 From: FedeHC Date: Fri, 7 Feb 2020 16:31:57 -0300 Subject: Update es-es/sql-es.html.markdown MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Antonio Hernández Blas <1096022+nihilismus@users.noreply.github.com> --- es-es/sql-es.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'es-es') diff --git a/es-es/sql-es.html.markdown b/es-es/sql-es.html.markdown index c20ebca0..3aa6ce7c 100644 --- a/es-es/sql-es.html.markdown +++ b/es-es/sql-es.html.markdown @@ -10,7 +10,7 @@ lang: es-es El lenguaje de consulta estructurada (SQL en inglés) es un lenguaje estándar ISO para crear y trabajar con bases de datos almacenados en un conjunto de tablas. Las implementaciones generalmente añaden sus propias extensiones al lenguaje; [Comparación entre diferentes implementaciones de SQL](http://troels.arvin.dk/db/rdbms/) es una buena referencia sobre las diferencias entre distintos productos. -Las implementaciones típicamente proveen de una línea de comandos donde uno puede introducir los comandos que se muestran aquí en forma interactiva, y también ofrecen una forma de ejecutar una serie de estos comandos almacenados en un archivo de script (mostrar que uno ha terminado con el prompt interactivo es un buen ejemplo de algo que no está estandarizado: la mayoría de las implementaciones de SQL soportan las palabras clave QUIT, EXIT, o ambas). +Las implementaciones típicamente proveen de una línea de comandos donde uno puede introducir los comandos que se muestran aquí en forma interactiva, y también ofrecen una forma de ejecutar una serie de estos comandos almacenados en un archivo de script (mostrar que uno ha terminado con el prompt interactivo es un buen ejemplo de algo que no está estandarizado - la mayoría de las implementaciones de SQL soportan las palabras clave QUIT, EXIT, o ambas). Varios de estos comandos que sirven de ejemplo asumen que la [base de datos de empleados de muestra de MySQL](https://dev.mysql.com/doc/employee/en/) disponible en [github](https://github.com/datacharmer/test_db) ya ha sido cargada. Los archivos github son scripts de comandos, similares a los comandos que aparecen a continuación, que crean y cargan tablas de datos sobre los empleados de una empresa ficticia. La sintaxis para ejecutar estos scripts dependerá de la implementación de SQL que esté utilizando. Una aplicación que se ejecuta desde el prompt del sistema operativo suele ser lo habitual. -- cgit v1.2.3 From a46ac670a03a75d2d24edca46981f7746c64f854 Mon Sep 17 00:00:00 2001 From: FedeHC Date: Fri, 7 Feb 2020 16:33:05 -0300 Subject: Update es-es/sql-es.html.markdown MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Antonio Hernández Blas <1096022+nihilismus@users.noreply.github.com> --- es-es/sql-es.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'es-es') diff --git a/es-es/sql-es.html.markdown b/es-es/sql-es.html.markdown index 3aa6ce7c..1ee0d454 100644 --- a/es-es/sql-es.html.markdown +++ b/es-es/sql-es.html.markdown @@ -42,7 +42,7 @@ SELECT * FROM departments; -- Recupera todas las filas de la tabla departments, pero sólo las columnas -- dept_no y dept_name. --- Separar los comandos en varias líneas es aceptable. +-- Separar los comandos en varias líneas está permitido. SELECT dept_no, dept_name FROM departments; -- cgit v1.2.3 From 1adab9bc3f80d82123987ff34083568030735db7 Mon Sep 17 00:00:00 2001 From: Simon Shine Date: Wed, 12 Feb 2020 04:49:56 +0100 Subject: Rename Python 2 markdown files into 'pythonlegacy' ``` for f in $(find . -iname "*python*" | grep -vE 'python3|git|statcomp'); do flegacy=$(echo "$f" | sed 's/python/pythonlegacy/') git mv "$f" "$flegacy" done ``` --- es-es/python-es.html.markdown | 562 ------------------------------------ es-es/pythonlegacy-es.html.markdown | 562 ++++++++++++++++++++++++++++++++++++ 2 files changed, 562 insertions(+), 562 deletions(-) delete mode 100644 es-es/python-es.html.markdown create mode 100644 es-es/pythonlegacy-es.html.markdown (limited to 'es-es') diff --git a/es-es/python-es.html.markdown b/es-es/python-es.html.markdown deleted file mode 100644 index 2b8f498a..00000000 --- a/es-es/python-es.html.markdown +++ /dev/null @@ -1,562 +0,0 @@ ---- -language: python -contributors: - - ["Louie Dinh", "http://ldinh.ca"] -translators: - - ["Camilo Garrido", "http://www.twitter.com/hirohope"] - - ["Fabio Souto", "http://fabiosouto.me"] -lang: es-es -filename: learnpython-es.py ---- - -Python fue creado por Guido Van Rossum en el principio de los 90. Ahora es uno -de los lenguajes más populares que existen. Me enamoré de Python por su claridad sintáctica. -Es básicamente pseudocódigo ejecutable. - -¡Comentarios serán muy apreciados! Pueden contactarme en [@louiedinh](http://twitter.com/louiedinh) o louiedinh [at] [servicio de email de google] - -Nota: Este artículo aplica a Python 2.7 específicamente, pero debería ser aplicable a Python 2.x. ¡Pronto un recorrido por Python 3! - -```python -# Comentarios de una línea comienzan con una almohadilla (o signo gato) -""" Strings multilínea pueden escribirse - usando tres "'s, y comúnmente son usados - como comentarios. -""" - -#################################################### -## 1. Tipos de datos primitivos y operadores. -#################################################### - -# Tienes números -3 #=> 3 - -# Evidentemente puedes realizar operaciones matemáticas -1 + 1 #=> 2 -8 - 1 #=> 7 -10 * 2 #=> 20 -35 / 5 #=> 7 - -# La división es un poco complicada. Es división entera y toma la parte entera -# de los resultados automáticamente. -5 / 2 #=> 2 - -# Para arreglar la división necesitamos aprender sobre 'floats' -# (números de coma flotante). -2.0 # Esto es un 'float' -11.0 / 4.0 #=> 2.75 ahhh...mucho mejor - -# Resultado de la división de enteros truncada para positivos y negativos -5 // 3 # => 1 -5.0 // 3.0 # => 1.0 # funciona con números de coma flotante --5 // 3 # => -2 --5.0 // 3.0 # => -2.0 - -# El operador módulo devuelve el resto de una división entre enteros -7 % 3 # => 1 - -# Exponenciación (x elevado a y) -2**4 # => 16 - -# Refuerza la precedencia con paréntesis -(1 + 3) * 2 #=> 8 - -# Operadores booleanos -# Nota: "and" y "or" son sensibles a mayúsculas -True and False #=> False -False or True #=> True - -# Podemos usar operadores booleanos con números enteros -0 and 2 #=> 0 --5 or 0 #=> -5 -0 == False #=> True -2 == True #=> False -1 == True #=> True - -# Niega con 'not' -not True #=> False -not False #=> True - -# Igualdad es == -1 == 1 #=> True -2 == 1 #=> False - -# Desigualdad es != -1 != 1 #=> False -2 != 1 #=> True - -# Más comparaciones -1 < 10 #=> True -1 > 10 #=> False -2 <= 2 #=> True -2 >= 2 #=> True - -# ¡Las comparaciones pueden ser concatenadas! -1 < 2 < 3 #=> True -2 < 3 < 2 #=> False - -# Strings se crean con " o ' -"Esto es un string." -'Esto también es un string' - -# ¡Strings también pueden ser sumados! -"Hola " + "mundo!" #=> "Hola mundo!" - -# Un string puede ser tratado como una lista de caracteres -"Esto es un string"[0] #=> 'E' - -# % pueden ser usados para formatear strings, como esto: -"%s pueden ser %s" % ("strings", "interpolados") - -# Una forma más reciente de formatear strings es el método 'format'. -# Este método es la forma preferida -"{0} pueden ser {1}".format("strings", "formateados") -# Puedes usar palabras clave si no quieres contar. -"{nombre} quiere comer {comida}".format(nombre="Bob", comida="lasaña") - -# None es un objeto -None #=> None - -# No uses el símbolo de igualdad `==` para comparar objetos con None -# Usa `is` en lugar de -"etc" is None #=> False -None is None #=> True - -# El operador 'is' prueba la identidad del objeto. Esto no es -# muy útil cuando se trata de datos primitivos, pero es -# muy útil cuando se trata de objetos. - -# None, 0, y strings/listas vacíos(as) todas se evalúan como False. -# Todos los otros valores son True -bool(0) #=> False -bool("") #=> False - - -#################################################### -## 2. Variables y Colecciones -#################################################### - -# Imprimir es muy fácil -print "Soy Python. ¡Encantado de conocerte!" - - -# No hay necesidad de declarar las variables antes de asignarlas. -una_variable = 5 # La convención es usar guiones_bajos_con_minúsculas -una_variable #=> 5 - -# Acceder a variables no asignadas previamente es una excepción. -# Ve Control de Flujo para aprender más sobre el manejo de excepciones. -otra_variable # Levanta un error de nombre - -# 'if' puede ser usado como una expresión -"yahoo!" if 3 > 2 else 2 #=> "yahoo!" - -# Las listas almacenan secuencias -lista = [] -# Puedes empezar con una lista prellenada -otra_lista = [4, 5, 6] - -# Añadir cosas al final de una lista con 'append' -lista.append(1) # lista ahora es [1] -lista.append(2) # lista ahora es [1, 2] -lista.append(4) # lista ahora es [1, 2, 4] -lista.append(3) # lista ahora es [1, 2, 4, 3] -# Remueve del final de la lista con 'pop' -lista.pop() #=> 3 y lista ahora es [1, 2, 4] -# Pongámoslo de vuelta -lista.append(3) # Nuevamente lista ahora es [1, 2, 4, 3]. - -# Accede a una lista como lo harías con cualquier arreglo -lista[0] #=> 1 -# Mira el último elemento -lista[-1] #=> 3 - -# Mirar fuera de los límites es un error 'IndexError' -lista[4] # Levanta la excepción IndexError - -# Puedes mirar por rango con la sintáxis de trozo. -# (Es un rango cerrado/abierto para ustedes los matemáticos.) -lista[1:3] #=> [2, 4] -# Omite el inicio -lista[2:] #=> [4, 3] -# Omite el final -lista[:3] #=> [1, 2, 4] - -# Remueve elementos arbitrarios de una lista con 'del' -del lista[2] # lista ahora es [1, 2, 3] - -# Puedes sumar listas -lista + otra_lista #=> [1, 2, 3, 4, 5, 6] - Nota: lista y otra_lista no se tocan - -# Concatenar listas con 'extend' -lista.extend(otra_lista) # lista ahora es [1, 2, 3, 4, 5, 6] - -# Chequea la existencia en una lista con -1 in lista #=> True - -# Examina el tamaño de una lista con 'len' -len(lista) #=> 6 - - -# Las tuplas son como las listas, pero son inmutables. -tupla = (1, 2, 3) -tupla[0] #=> 1 -tupla[0] = 3 # Levanta un error TypeError - -# También puedes hacer todas esas cosas que haces con listas -len(tupla) #=> 3 -tupla + (4, 5, 6) #=> (1, 2, 3, 4, 5, 6) -tupla[:2] #=> (1, 2) -2 in tupla #=> True - -# Puedes desempacar tuplas (o listas) en variables -a, b, c = (1, 2, 3) # a ahora es 1, b ahora es 2 y c ahora es 3 -# Tuplas son creadas por defecto si omites los paréntesis -d, e, f = 4, 5, 6 -# Ahora mira que fácil es intercambiar dos valores -e, d = d, e # d ahora es 5 y e ahora es 4 - - -# Diccionarios almacenan mapeos -dicc_vacio = {} -# Aquí está un diccionario prellenado -dicc_lleno = {"uno": 1, "dos": 2, "tres": 3} - -# Busca valores con [] -dicc_lleno["uno"] #=> 1 - -# Obtén todas las llaves como una lista -dicc_lleno.keys() #=> ["tres", "dos", "uno"] -# Nota - El orden de las llaves del diccionario no está garantizada. -# Tus resultados podrían no ser los mismos del ejemplo. - -# Obtén todos los valores como una lista -dicc_lleno.values() #=> [3, 2, 1] -# Nota - Lo mismo que con las llaves, no se garantiza el orden. - -# Chequea la existencia de una llave en el diccionario con 'in' -"uno" in dicc_lleno #=> True -1 in dicc_lleno #=> False - -# Buscar una llave inexistente deriva en KeyError -dicc_lleno["cuatro"] # KeyError - -# Usa el método 'get' para evitar la excepción KeyError -dicc_lleno.get("uno") #=> 1 -dicc_lleno.get("cuatro") #=> None -# El método 'get' soporta un argumento por defecto cuando el valor no existe. -dicc_lleno.get("uno", 4) #=> 1 -dicc_lleno.get("cuatro", 4) #=> 4 - -# El método 'setdefault' es una manera segura de añadir nuevos pares -# llave-valor en un diccionario -dicc_lleno.setdefault("cinco", 5) #dicc_lleno["cinco"] es puesto con valor 5 -dicc_lleno.setdefault("cinco", 6) #dicc_lleno["cinco"] todavía es 5 - - -# Sets (conjuntos) almacenan ... bueno, conjuntos -conjunto_vacio = set() -# Inicializar un conjunto con montón de valores -un_conjunto = set([1,2,2,3,4]) # un_conjunto ahora es set([1, 2, 3, 4]) - -# Desde Python 2.7, {} puede ser usado para declarar un conjunto -conjunto_lleno = {1, 2, 2, 3, 4} # => {1 2 3 4} - -# Añade más valores a un conjunto -conjunto_lleno.add(5) # conjunto_lleno ahora es {1, 2, 3, 4, 5} - -# Haz intersección de conjuntos con & -otro_conjunto = {3, 4, 5, 6} -conjunto_lleno & otro_conjunto #=> {3, 4, 5} - -# Haz unión de conjuntos con | -conjunto_lleno | otro_conjunto #=> {1, 2, 3, 4, 5, 6} - -# Haz diferencia de conjuntos con - -{1,2,3,4} - {2,3,5} #=> {1, 4} - -# Chequea la existencia en un conjunto con 'in' -2 in conjunto_lleno #=> True -10 in conjunto_lleno #=> False - - -#################################################### -## 3. Control de Flujo -#################################################### - -# Hagamos sólo una variable -una_variable = 5 - -# Aquí está una declaración de un 'if'. ¡La indentación es importante en Python! -# imprime "una_variable es menor que 10" -if una_variable > 10: - print "una_variable es completamente mas grande que 10." -elif una_variable < 10: # Este condición 'elif' es opcional. - print "una_variable es mas chica que 10." -else: # Esto también es opcional. - print "una_variable es de hecho 10." - - -""" -For itera sobre listas -imprime: - perro es un mamifero - gato es un mamifero - raton es un mamifero -""" -for animal in ["perro", "gato", "raton"]: - # Puedes usar % para interpolar strings formateados - print "%s es un mamifero" % animal - -""" -`range(número)` retorna una lista de números -desde cero hasta el número dado -imprime: - 0 - 1 - 2 - 3 -""" -for i in range(4): - print i - -""" -While itera hasta que una condición no se cumple. -imprime: - 0 - 1 - 2 - 3 -""" -x = 0 -while x < 4: - print x - x += 1 # versión corta de x = x + 1 - -# Maneja excepciones con un bloque try/except - -# Funciona desde Python 2.6 en adelante: -try: - # Usa raise para levantar un error - raise IndexError("Este es un error de indice") -except IndexError as e: - pass # Pass no hace nada. Usualmente harias alguna recuperacion aqui. - - -#################################################### -## 4. Funciones -#################################################### - -# Usa 'def' para crear nuevas funciones -def add(x, y): - print "x es %s y y es %s" % (x, y) - return x + y # Retorna valores con una la declaración return - -# Llamando funciones con parámetros -add(5, 6) #=> imprime "x es 5 y y es 6" y retorna 11 - -# Otra forma de llamar funciones es con argumentos de palabras claves -add(y=6, x=5) # Argumentos de palabra clave pueden ir en cualquier orden. - -# Puedes definir funciones que tomen un número variable de argumentos -def varargs(*args): - return args - -varargs(1, 2, 3) #=> (1,2,3) - - -# Puedes definir funciones que toman un número variable de argumentos -# de palabras claves -def keyword_args(**kwargs): - return kwargs - -# Llamémosla para ver que sucede -keyword_args(pie="grande", lago="ness") #=> {"pie": "grande", "lago": "ness"} - -# Puedes hacer ambas a la vez si quieres -def todos_los_argumentos(*args, **kwargs): - print args - print kwargs -""" -todos_los_argumentos(1, 2, a=3, b=4) imprime: - (1, 2) - {"a": 3, "b": 4} -""" - -# ¡Cuando llames funciones, puedes hacer lo opuesto a varargs/kwargs! -# Usa * para expandir tuplas y usa ** para expandir argumentos de palabras claves. -args = (1, 2, 3, 4) -kwargs = {"a": 3, "b": 4} -todos_los_argumentos(*args) # es equivalente a foo(1, 2, 3, 4) -todos_los_argumentos(**kwargs) # es equivalente a foo(a=3, b=4) -todos_los_argumentos(*args, **kwargs) # es equivalente a foo(1, 2, 3, 4, a=3, b=4) - -# Python tiene funciones de primera clase -def crear_suma(x): - def suma(y): - return x + y - return suma - -sumar_10 = crear_suma(10) -sumar_10(3) #=> 13 - -# También hay funciones anónimas -(lambda x: x > 2)(3) #=> True - -# Hay funciones integradas de orden superior -map(sumar_10, [1,2,3]) #=> [11, 12, 13] -filter(lambda x: x > 5, [3, 4, 5, 6, 7]) #=> [6, 7] - -# Podemos usar listas por comprensión para mapeos y filtros agradables -[add_10(i) for i in [1, 2, 3]] #=> [11, 12, 13] -[x for x in [3, 4, 5, 6, 7] if x > 5] #=> [6, 7] - -#################################################### -## 5. Clases -#################################################### - -# Heredamos de object para obtener una clase. -class Humano(object): - - # Un atributo de clase es compartido por todas las instancias de esta clase - especie = "H. sapiens" - - # Constructor básico, se llama al instanciar la clase. - def __init__(self, nombre): - # Asigna el argumento al atributo nombre de la instancia - self.nombre = nombre - - # Un método de instancia. Todos los metodos toman self como primer argumento - def decir(self, msg): - return "%s: %s" % (self.nombre, msg) - - # Un metodo de clase es compartido a través de todas las instancias - # Son llamados con la clase como primer argumento - @classmethod - def get_especie(cls): - return cls.especie - - # Un metodo estático es llamado sin la clase o instancia como referencia - @staticmethod - def roncar(): - return "*roncar*" - - -# Instancia una clase -i = Humano(nombre="Ian") -print i.decir("hi") # imprime "Ian: hi" - -j = Humano("Joel") -print j.decir("hello") #imprime "Joel: hello" - -# Llama nuestro método de clase -i.get_especie() #=> "H. sapiens" - -# Cambia los atributos compartidos -Humano.especie = "H. neanderthalensis" -i.get_especie() #=> "H. neanderthalensis" -j.get_especie() #=> "H. neanderthalensis" - -# Llama al método estático -Humano.roncar() #=> "*roncar*" - - -#################################################### -## 6. Módulos -#################################################### - -# Puedes importar módulos -import math -print math.sqrt(16) #=> 4.0 - -# Puedes obtener funciones específicas desde un módulo -from math import ceil, floor -print ceil(3.7) #=> 4.0 -print floor(3.7) #=> 3.0 - -# Puedes importar todas las funciones de un módulo -# Precaución: Esto no es recomendable -from math import * - -# Puedes acortar los nombres de los módulos -import math as m -math.sqrt(16) == m.sqrt(16) #=> True - -# Los módulos de Python son sólo archivos ordinarios de Python. -# Puedes escribir tus propios módulos e importarlos. El nombre del módulo -# es el mismo del nombre del archivo. - -# Puedes encontrar que funciones y atributos definen un módulo. -import math -dir(math) - - -#################################################### -## 7. Avanzado -#################################################### - -# Los generadores permiten evaluación perezosa -def duplicar_numeros(iterable): - for i in iterable: - yield i + i - -# Un generador crea valores sobre la marcha -# En vez de generar y devolver todos los valores de una vez, crea un valor -# en cada iteración. En este ejemplo los valores mayores que 15 no serán -# procesados en duplicar_numeros. -# Nota: xrange es un generador que hace lo mismo que range. -# Crear una lista de 1 a 900000000 lleva mucho tiempo y ocupa mucho espacio. -# xrange crea un generador, mientras que range crea toda la lista. -# Añadimos un guión bajo a los nombres de variable que coinciden con palabras -# reservadas de python. -xrange_ = xrange(1, 900000000) - -# duplica todos los números hasta que encuentra un resultado >= 30 -for i in duplicar_numeros(xrange_): - print i - if i >= 30: - break - -# Decoradores -# en este ejemplo pedir rodea a hablar -# Si por_favor es True se cambiará el mensaje. -from functools import wraps - - -def pedir(target_function): - @wraps(target_function) - def wrapper(*args, **kwargs): - msg, por_favor = target_function(*args, **kwargs) - if por_favor: - return "{} {}".format(msg, "¡Por favor! Soy pobre :(") - return msg - - return wrapper - - -@pedir -def hablar(por_favor=False): - msg = "¿Me puedes comprar una cerveza?" - return msg, por_favor - -print hablar() # ¿Me puedes comprar una cerveza? -print hablar(por_favor=True) # ¿Me puedes comprar una cerveza? ¡Por favor! Soy pobre :( -``` - -## ¿Listo para más? - -### Gratis y en línea - -* [Learn Python The Hard Way](http://learnpythonthehardway.org/book/) -* [Dive Into Python](http://www.diveintopython.net/) -* [The Official Docs](http://docs.python.org/2.6/) -* [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/) -* [Python Module of the Week](http://pymotw.com/2/) -* [A Crash Course in Python for Scientists](http://nbviewer.ipython.org/5920182) - -### Encuadernados - -* [Programming Python](http://www.amazon.com/gp/product/0596158106/ref=as_li_qf_sp_asin_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596158106&linkCode=as2&tag=homebits04-20) -* [Dive Into Python](http://www.amazon.com/gp/product/1441413022/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1441413022&linkCode=as2&tag=homebits04-20) -* [Python Essential Reference](http://www.amazon.com/gp/product/0672329786/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0672329786&linkCode=as2&tag=homebits04-20) - diff --git a/es-es/pythonlegacy-es.html.markdown b/es-es/pythonlegacy-es.html.markdown new file mode 100644 index 00000000..2b8f498a --- /dev/null +++ b/es-es/pythonlegacy-es.html.markdown @@ -0,0 +1,562 @@ +--- +language: python +contributors: + - ["Louie Dinh", "http://ldinh.ca"] +translators: + - ["Camilo Garrido", "http://www.twitter.com/hirohope"] + - ["Fabio Souto", "http://fabiosouto.me"] +lang: es-es +filename: learnpython-es.py +--- + +Python fue creado por Guido Van Rossum en el principio de los 90. Ahora es uno +de los lenguajes más populares que existen. Me enamoré de Python por su claridad sintáctica. +Es básicamente pseudocódigo ejecutable. + +¡Comentarios serán muy apreciados! Pueden contactarme en [@louiedinh](http://twitter.com/louiedinh) o louiedinh [at] [servicio de email de google] + +Nota: Este artículo aplica a Python 2.7 específicamente, pero debería ser aplicable a Python 2.x. ¡Pronto un recorrido por Python 3! + +```python +# Comentarios de una línea comienzan con una almohadilla (o signo gato) +""" Strings multilínea pueden escribirse + usando tres "'s, y comúnmente son usados + como comentarios. +""" + +#################################################### +## 1. Tipos de datos primitivos y operadores. +#################################################### + +# Tienes números +3 #=> 3 + +# Evidentemente puedes realizar operaciones matemáticas +1 + 1 #=> 2 +8 - 1 #=> 7 +10 * 2 #=> 20 +35 / 5 #=> 7 + +# La división es un poco complicada. Es división entera y toma la parte entera +# de los resultados automáticamente. +5 / 2 #=> 2 + +# Para arreglar la división necesitamos aprender sobre 'floats' +# (números de coma flotante). +2.0 # Esto es un 'float' +11.0 / 4.0 #=> 2.75 ahhh...mucho mejor + +# Resultado de la división de enteros truncada para positivos y negativos +5 // 3 # => 1 +5.0 // 3.0 # => 1.0 # funciona con números de coma flotante +-5 // 3 # => -2 +-5.0 // 3.0 # => -2.0 + +# El operador módulo devuelve el resto de una división entre enteros +7 % 3 # => 1 + +# Exponenciación (x elevado a y) +2**4 # => 16 + +# Refuerza la precedencia con paréntesis +(1 + 3) * 2 #=> 8 + +# Operadores booleanos +# Nota: "and" y "or" son sensibles a mayúsculas +True and False #=> False +False or True #=> True + +# Podemos usar operadores booleanos con números enteros +0 and 2 #=> 0 +-5 or 0 #=> -5 +0 == False #=> True +2 == True #=> False +1 == True #=> True + +# Niega con 'not' +not True #=> False +not False #=> True + +# Igualdad es == +1 == 1 #=> True +2 == 1 #=> False + +# Desigualdad es != +1 != 1 #=> False +2 != 1 #=> True + +# Más comparaciones +1 < 10 #=> True +1 > 10 #=> False +2 <= 2 #=> True +2 >= 2 #=> True + +# ¡Las comparaciones pueden ser concatenadas! +1 < 2 < 3 #=> True +2 < 3 < 2 #=> False + +# Strings se crean con " o ' +"Esto es un string." +'Esto también es un string' + +# ¡Strings también pueden ser sumados! +"Hola " + "mundo!" #=> "Hola mundo!" + +# Un string puede ser tratado como una lista de caracteres +"Esto es un string"[0] #=> 'E' + +# % pueden ser usados para formatear strings, como esto: +"%s pueden ser %s" % ("strings", "interpolados") + +# Una forma más reciente de formatear strings es el método 'format'. +# Este método es la forma preferida +"{0} pueden ser {1}".format("strings", "formateados") +# Puedes usar palabras clave si no quieres contar. +"{nombre} quiere comer {comida}".format(nombre="Bob", comida="lasaña") + +# None es un objeto +None #=> None + +# No uses el símbolo de igualdad `==` para comparar objetos con None +# Usa `is` en lugar de +"etc" is None #=> False +None is None #=> True + +# El operador 'is' prueba la identidad del objeto. Esto no es +# muy útil cuando se trata de datos primitivos, pero es +# muy útil cuando se trata de objetos. + +# None, 0, y strings/listas vacíos(as) todas se evalúan como False. +# Todos los otros valores son True +bool(0) #=> False +bool("") #=> False + + +#################################################### +## 2. Variables y Colecciones +#################################################### + +# Imprimir es muy fácil +print "Soy Python. ¡Encantado de conocerte!" + + +# No hay necesidad de declarar las variables antes de asignarlas. +una_variable = 5 # La convención es usar guiones_bajos_con_minúsculas +una_variable #=> 5 + +# Acceder a variables no asignadas previamente es una excepción. +# Ve Control de Flujo para aprender más sobre el manejo de excepciones. +otra_variable # Levanta un error de nombre + +# 'if' puede ser usado como una expresión +"yahoo!" if 3 > 2 else 2 #=> "yahoo!" + +# Las listas almacenan secuencias +lista = [] +# Puedes empezar con una lista prellenada +otra_lista = [4, 5, 6] + +# Añadir cosas al final de una lista con 'append' +lista.append(1) # lista ahora es [1] +lista.append(2) # lista ahora es [1, 2] +lista.append(4) # lista ahora es [1, 2, 4] +lista.append(3) # lista ahora es [1, 2, 4, 3] +# Remueve del final de la lista con 'pop' +lista.pop() #=> 3 y lista ahora es [1, 2, 4] +# Pongámoslo de vuelta +lista.append(3) # Nuevamente lista ahora es [1, 2, 4, 3]. + +# Accede a una lista como lo harías con cualquier arreglo +lista[0] #=> 1 +# Mira el último elemento +lista[-1] #=> 3 + +# Mirar fuera de los límites es un error 'IndexError' +lista[4] # Levanta la excepción IndexError + +# Puedes mirar por rango con la sintáxis de trozo. +# (Es un rango cerrado/abierto para ustedes los matemáticos.) +lista[1:3] #=> [2, 4] +# Omite el inicio +lista[2:] #=> [4, 3] +# Omite el final +lista[:3] #=> [1, 2, 4] + +# Remueve elementos arbitrarios de una lista con 'del' +del lista[2] # lista ahora es [1, 2, 3] + +# Puedes sumar listas +lista + otra_lista #=> [1, 2, 3, 4, 5, 6] - Nota: lista y otra_lista no se tocan + +# Concatenar listas con 'extend' +lista.extend(otra_lista) # lista ahora es [1, 2, 3, 4, 5, 6] + +# Chequea la existencia en una lista con +1 in lista #=> True + +# Examina el tamaño de una lista con 'len' +len(lista) #=> 6 + + +# Las tuplas son como las listas, pero son inmutables. +tupla = (1, 2, 3) +tupla[0] #=> 1 +tupla[0] = 3 # Levanta un error TypeError + +# También puedes hacer todas esas cosas que haces con listas +len(tupla) #=> 3 +tupla + (4, 5, 6) #=> (1, 2, 3, 4, 5, 6) +tupla[:2] #=> (1, 2) +2 in tupla #=> True + +# Puedes desempacar tuplas (o listas) en variables +a, b, c = (1, 2, 3) # a ahora es 1, b ahora es 2 y c ahora es 3 +# Tuplas son creadas por defecto si omites los paréntesis +d, e, f = 4, 5, 6 +# Ahora mira que fácil es intercambiar dos valores +e, d = d, e # d ahora es 5 y e ahora es 4 + + +# Diccionarios almacenan mapeos +dicc_vacio = {} +# Aquí está un diccionario prellenado +dicc_lleno = {"uno": 1, "dos": 2, "tres": 3} + +# Busca valores con [] +dicc_lleno["uno"] #=> 1 + +# Obtén todas las llaves como una lista +dicc_lleno.keys() #=> ["tres", "dos", "uno"] +# Nota - El orden de las llaves del diccionario no está garantizada. +# Tus resultados podrían no ser los mismos del ejemplo. + +# Obtén todos los valores como una lista +dicc_lleno.values() #=> [3, 2, 1] +# Nota - Lo mismo que con las llaves, no se garantiza el orden. + +# Chequea la existencia de una llave en el diccionario con 'in' +"uno" in dicc_lleno #=> True +1 in dicc_lleno #=> False + +# Buscar una llave inexistente deriva en KeyError +dicc_lleno["cuatro"] # KeyError + +# Usa el método 'get' para evitar la excepción KeyError +dicc_lleno.get("uno") #=> 1 +dicc_lleno.get("cuatro") #=> None +# El método 'get' soporta un argumento por defecto cuando el valor no existe. +dicc_lleno.get("uno", 4) #=> 1 +dicc_lleno.get("cuatro", 4) #=> 4 + +# El método 'setdefault' es una manera segura de añadir nuevos pares +# llave-valor en un diccionario +dicc_lleno.setdefault("cinco", 5) #dicc_lleno["cinco"] es puesto con valor 5 +dicc_lleno.setdefault("cinco", 6) #dicc_lleno["cinco"] todavía es 5 + + +# Sets (conjuntos) almacenan ... bueno, conjuntos +conjunto_vacio = set() +# Inicializar un conjunto con montón de valores +un_conjunto = set([1,2,2,3,4]) # un_conjunto ahora es set([1, 2, 3, 4]) + +# Desde Python 2.7, {} puede ser usado para declarar un conjunto +conjunto_lleno = {1, 2, 2, 3, 4} # => {1 2 3 4} + +# Añade más valores a un conjunto +conjunto_lleno.add(5) # conjunto_lleno ahora es {1, 2, 3, 4, 5} + +# Haz intersección de conjuntos con & +otro_conjunto = {3, 4, 5, 6} +conjunto_lleno & otro_conjunto #=> {3, 4, 5} + +# Haz unión de conjuntos con | +conjunto_lleno | otro_conjunto #=> {1, 2, 3, 4, 5, 6} + +# Haz diferencia de conjuntos con - +{1,2,3,4} - {2,3,5} #=> {1, 4} + +# Chequea la existencia en un conjunto con 'in' +2 in conjunto_lleno #=> True +10 in conjunto_lleno #=> False + + +#################################################### +## 3. Control de Flujo +#################################################### + +# Hagamos sólo una variable +una_variable = 5 + +# Aquí está una declaración de un 'if'. ¡La indentación es importante en Python! +# imprime "una_variable es menor que 10" +if una_variable > 10: + print "una_variable es completamente mas grande que 10." +elif una_variable < 10: # Este condición 'elif' es opcional. + print "una_variable es mas chica que 10." +else: # Esto también es opcional. + print "una_variable es de hecho 10." + + +""" +For itera sobre listas +imprime: + perro es un mamifero + gato es un mamifero + raton es un mamifero +""" +for animal in ["perro", "gato", "raton"]: + # Puedes usar % para interpolar strings formateados + print "%s es un mamifero" % animal + +""" +`range(número)` retorna una lista de números +desde cero hasta el número dado +imprime: + 0 + 1 + 2 + 3 +""" +for i in range(4): + print i + +""" +While itera hasta que una condición no se cumple. +imprime: + 0 + 1 + 2 + 3 +""" +x = 0 +while x < 4: + print x + x += 1 # versión corta de x = x + 1 + +# Maneja excepciones con un bloque try/except + +# Funciona desde Python 2.6 en adelante: +try: + # Usa raise para levantar un error + raise IndexError("Este es un error de indice") +except IndexError as e: + pass # Pass no hace nada. Usualmente harias alguna recuperacion aqui. + + +#################################################### +## 4. Funciones +#################################################### + +# Usa 'def' para crear nuevas funciones +def add(x, y): + print "x es %s y y es %s" % (x, y) + return x + y # Retorna valores con una la declaración return + +# Llamando funciones con parámetros +add(5, 6) #=> imprime "x es 5 y y es 6" y retorna 11 + +# Otra forma de llamar funciones es con argumentos de palabras claves +add(y=6, x=5) # Argumentos de palabra clave pueden ir en cualquier orden. + +# Puedes definir funciones que tomen un número variable de argumentos +def varargs(*args): + return args + +varargs(1, 2, 3) #=> (1,2,3) + + +# Puedes definir funciones que toman un número variable de argumentos +# de palabras claves +def keyword_args(**kwargs): + return kwargs + +# Llamémosla para ver que sucede +keyword_args(pie="grande", lago="ness") #=> {"pie": "grande", "lago": "ness"} + +# Puedes hacer ambas a la vez si quieres +def todos_los_argumentos(*args, **kwargs): + print args + print kwargs +""" +todos_los_argumentos(1, 2, a=3, b=4) imprime: + (1, 2) + {"a": 3, "b": 4} +""" + +# ¡Cuando llames funciones, puedes hacer lo opuesto a varargs/kwargs! +# Usa * para expandir tuplas y usa ** para expandir argumentos de palabras claves. +args = (1, 2, 3, 4) +kwargs = {"a": 3, "b": 4} +todos_los_argumentos(*args) # es equivalente a foo(1, 2, 3, 4) +todos_los_argumentos(**kwargs) # es equivalente a foo(a=3, b=4) +todos_los_argumentos(*args, **kwargs) # es equivalente a foo(1, 2, 3, 4, a=3, b=4) + +# Python tiene funciones de primera clase +def crear_suma(x): + def suma(y): + return x + y + return suma + +sumar_10 = crear_suma(10) +sumar_10(3) #=> 13 + +# También hay funciones anónimas +(lambda x: x > 2)(3) #=> True + +# Hay funciones integradas de orden superior +map(sumar_10, [1,2,3]) #=> [11, 12, 13] +filter(lambda x: x > 5, [3, 4, 5, 6, 7]) #=> [6, 7] + +# Podemos usar listas por comprensión para mapeos y filtros agradables +[add_10(i) for i in [1, 2, 3]] #=> [11, 12, 13] +[x for x in [3, 4, 5, 6, 7] if x > 5] #=> [6, 7] + +#################################################### +## 5. Clases +#################################################### + +# Heredamos de object para obtener una clase. +class Humano(object): + + # Un atributo de clase es compartido por todas las instancias de esta clase + especie = "H. sapiens" + + # Constructor básico, se llama al instanciar la clase. + def __init__(self, nombre): + # Asigna el argumento al atributo nombre de la instancia + self.nombre = nombre + + # Un método de instancia. Todos los metodos toman self como primer argumento + def decir(self, msg): + return "%s: %s" % (self.nombre, msg) + + # Un metodo de clase es compartido a través de todas las instancias + # Son llamados con la clase como primer argumento + @classmethod + def get_especie(cls): + return cls.especie + + # Un metodo estático es llamado sin la clase o instancia como referencia + @staticmethod + def roncar(): + return "*roncar*" + + +# Instancia una clase +i = Humano(nombre="Ian") +print i.decir("hi") # imprime "Ian: hi" + +j = Humano("Joel") +print j.decir("hello") #imprime "Joel: hello" + +# Llama nuestro método de clase +i.get_especie() #=> "H. sapiens" + +# Cambia los atributos compartidos +Humano.especie = "H. neanderthalensis" +i.get_especie() #=> "H. neanderthalensis" +j.get_especie() #=> "H. neanderthalensis" + +# Llama al método estático +Humano.roncar() #=> "*roncar*" + + +#################################################### +## 6. Módulos +#################################################### + +# Puedes importar módulos +import math +print math.sqrt(16) #=> 4.0 + +# Puedes obtener funciones específicas desde un módulo +from math import ceil, floor +print ceil(3.7) #=> 4.0 +print floor(3.7) #=> 3.0 + +# Puedes importar todas las funciones de un módulo +# Precaución: Esto no es recomendable +from math import * + +# Puedes acortar los nombres de los módulos +import math as m +math.sqrt(16) == m.sqrt(16) #=> True + +# Los módulos de Python son sólo archivos ordinarios de Python. +# Puedes escribir tus propios módulos e importarlos. El nombre del módulo +# es el mismo del nombre del archivo. + +# Puedes encontrar que funciones y atributos definen un módulo. +import math +dir(math) + + +#################################################### +## 7. Avanzado +#################################################### + +# Los generadores permiten evaluación perezosa +def duplicar_numeros(iterable): + for i in iterable: + yield i + i + +# Un generador crea valores sobre la marcha +# En vez de generar y devolver todos los valores de una vez, crea un valor +# en cada iteración. En este ejemplo los valores mayores que 15 no serán +# procesados en duplicar_numeros. +# Nota: xrange es un generador que hace lo mismo que range. +# Crear una lista de 1 a 900000000 lleva mucho tiempo y ocupa mucho espacio. +# xrange crea un generador, mientras que range crea toda la lista. +# Añadimos un guión bajo a los nombres de variable que coinciden con palabras +# reservadas de python. +xrange_ = xrange(1, 900000000) + +# duplica todos los números hasta que encuentra un resultado >= 30 +for i in duplicar_numeros(xrange_): + print i + if i >= 30: + break + +# Decoradores +# en este ejemplo pedir rodea a hablar +# Si por_favor es True se cambiará el mensaje. +from functools import wraps + + +def pedir(target_function): + @wraps(target_function) + def wrapper(*args, **kwargs): + msg, por_favor = target_function(*args, **kwargs) + if por_favor: + return "{} {}".format(msg, "¡Por favor! Soy pobre :(") + return msg + + return wrapper + + +@pedir +def hablar(por_favor=False): + msg = "¿Me puedes comprar una cerveza?" + return msg, por_favor + +print hablar() # ¿Me puedes comprar una cerveza? +print hablar(por_favor=True) # ¿Me puedes comprar una cerveza? ¡Por favor! Soy pobre :( +``` + +## ¿Listo para más? + +### Gratis y en línea + +* [Learn Python The Hard Way](http://learnpythonthehardway.org/book/) +* [Dive Into Python](http://www.diveintopython.net/) +* [The Official Docs](http://docs.python.org/2.6/) +* [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/) +* [Python Module of the Week](http://pymotw.com/2/) +* [A Crash Course in Python for Scientists](http://nbviewer.ipython.org/5920182) + +### Encuadernados + +* [Programming Python](http://www.amazon.com/gp/product/0596158106/ref=as_li_qf_sp_asin_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596158106&linkCode=as2&tag=homebits04-20) +* [Dive Into Python](http://www.amazon.com/gp/product/1441413022/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1441413022&linkCode=as2&tag=homebits04-20) +* [Python Essential Reference](http://www.amazon.com/gp/product/0672329786/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0672329786&linkCode=as2&tag=homebits04-20) + -- cgit v1.2.3 From a3b0585374d69e392fdb724bde30bc4048358d31 Mon Sep 17 00:00:00 2001 From: Simon Shine Date: Wed, 12 Feb 2020 04:54:36 +0100 Subject: Rename Python 3 markdown files into 'python' ``` for f in $(find . -iname "*python3*" | grep -vE 'git'); do fnew=$(echo "$f" | sed 's/python3/python/') git mv "$f" "$fnew" done --- es-es/python-es.html.markdown | 577 +++++++++++++++++++++++++++++++++++++++++ es-es/python3-es.html.markdown | 577 ----------------------------------------- 2 files changed, 577 insertions(+), 577 deletions(-) create mode 100644 es-es/python-es.html.markdown delete mode 100644 es-es/python3-es.html.markdown (limited to 'es-es') diff --git a/es-es/python-es.html.markdown b/es-es/python-es.html.markdown new file mode 100644 index 00000000..3236e73a --- /dev/null +++ b/es-es/python-es.html.markdown @@ -0,0 +1,577 @@ +--- +language: python3 +contributors: + - ["Louie Dinh", "http://pythonpracticeprojects.com"] +translators: + - ["Camilo Garrido", "http://twitter.com/hirohope"] +lang: es-es +filename: learnpython3-es.py +--- + +Python fue creado por Guido Van Rossum en el principio de los 90'. Ahora es uno +de los lenguajes más populares en existencia. Me enamoré de Python por su claridad sintáctica. +Es básicamente pseudocódigo ejecutable. + +¡Comentarios serán muy apreciados! Pueden contactarme en [@louiedinh](http://twitter.com/louiedinh) o louiedinh [at] [servicio de email de google] + +```python + +# Comentarios de una línea comienzan con una almohadilla (o signo gato) + +""" Strings multilinea pueden escribirse + usando tres "'s, y comunmente son usados + como comentarios. +""" + +#################################################### +## 1. Tipos de datos primitivos y operadores. +#################################################### + +# Tienes números +3 #=> 3 + +# Matemática es lo que esperarías +1 + 1 #=> 2 +8 - 1 #=> 7 +10 * 2 #=> 20 + +# Excepto la división la cual por defecto retorna un número 'float' (número de coma flotante) +35 / 5 # => 7.0 +# Sin embargo también tienes disponible división entera +34 // 5 # => 6 + +# Cuando usas un float, los resultados son floats +3 * 2.0 # => 6.0 + +# Refuerza la precedencia con paréntesis +(1 + 3) * 2 # => 8 + + +# Valores 'boolean' (booleanos) son primitivos +True +False + +# Niega con 'not' +not True # => False +not False # => True + + +# Igualdad es == +1 == 1 # => True +2 == 1 # => False + +# Desigualdad es != +1 != 1 # => False +2 != 1 # => True + +# Más comparaciones +1 < 10 # => True +1 > 10 # => False +2 <= 2 # => True +2 >= 2 # => True + +# ¡Las comparaciones pueden ser concatenadas! +1 < 2 < 3 # => True +2 < 3 < 2 # => False + +# Strings se crean con " o ' +"Esto es un string." +'Esto también es un string' + +# ¡Strings también pueden ser sumados! +"Hola " + "mundo!" #=> "Hola mundo!" + +# Un string puede ser tratado como una lista de caracteres +"Esto es un string"[0] #=> 'E' + +# .format puede ser usaro para darle formato a los strings, así: +"{} pueden ser {}".format("strings", "interpolados") + +# Puedes reutilizar los argumentos de formato si estos se repiten. +"{0} sé ligero, {0} sé rápido, {0} brinca sobre la {1}".format("Jack", "vela") #=> "Jack sé ligero, Jack sé rápido, Jack brinca sobre la vela" +# Puedes usar palabras claves si no quieres contar. +"{nombre} quiere comer {comida}".format(nombre="Bob", comida="lasaña") #=> "Bob quiere comer lasaña" +# También puedes interpolar cadenas usando variables en el contexto +nombre = 'Bob' +comida = 'Lasaña' +f'{nombre} quiere comer {comida}' #=> "Bob quiere comer lasaña" + +# None es un objeto +None # => None + +# No uses el símbolo de igualdad `==` para comparar objetos con None +# Usa `is` en su lugar +"etc" is None #=> False +None is None #=> True + +# None, 0, y strings/listas/diccionarios/conjuntos vacíos(as) todos se evalúan como False. +# Todos los otros valores son True +bool(0) # => False +bool("") # => False +bool([]) #=> False +bool({}) #=> False +bool(set()) #=> False + + +#################################################### +## 2. Variables y Colecciones +#################################################### + +# Python tiene una función para imprimir +print("Soy Python. Encantado de conocerte") + +# No hay necesidad de declarar las variables antes de asignarlas. +una_variable = 5 # La convención es usar guiones_bajos_con_minúsculas +una_variable #=> 5 + +# Acceder a variables no asignadas previamente es una excepción. +# Ve Control de Flujo para aprender más sobre el manejo de excepciones. +otra_variable # Levanta un error de nombre + +# Listas almacena secuencias +lista = [] +# Puedes empezar con una lista prellenada +otra_lista = [4, 5, 6] + +# Añadir cosas al final de una lista con 'append' +lista.append(1) #lista ahora es [1] +lista.append(2) #lista ahora es [1, 2] +lista.append(4) #lista ahora es [1, 2, 4] +lista.append(3) #lista ahora es [1, 2, 4, 3] +# Remueve del final de la lista con 'pop' +lista.pop() #=> 3 y lista ahora es [1, 2, 4] +# Pongámoslo de vuelta +lista.append(3) # Nuevamente lista ahora es [1, 2, 4, 3]. + +# Accede a una lista como lo harías con cualquier arreglo +lista[0] #=> 1 +# Mira el último elemento +lista[-1] #=> 3 + +# Mirar fuera de los límites es un error 'IndexError' +lista[4] # Levanta la excepción IndexError + +# Puedes mirar por rango con la sintáxis de trozo. +# (Es un rango cerrado/abierto para ustedes los matemáticos.) +lista[1:3] #=> [2, 4] +# Omite el inicio +lista[2:] #=> [4, 3] +# Omite el final +lista[:3] #=> [1, 2, 4] +# Selecciona cada dos elementos +lista[::2] # =>[1, 4] +# Invierte la lista +lista[::-1] # => [3, 4, 2, 1] +# Usa cualquier combinación de estos para crear trozos avanzados +# lista[inicio:final:pasos] + +# Remueve elementos arbitrarios de una lista con 'del' +del lista[2] # lista ahora es [1, 2, 3] + +# Puedes sumar listas +lista + otra_lista #=> [1, 2, 3, 4, 5, 6] - Nota: lista y otra_lista no se tocan + +# Concatenar listas con 'extend' +lista.extend(otra_lista) # lista ahora es [1, 2, 3, 4, 5, 6] + +# Verifica la existencia en una lista con 'in' +1 in lista #=> True + +# Examina el largo de una lista con 'len' +len(lista) #=> 6 + + +# Tuplas son como listas pero son inmutables. +tupla = (1, 2, 3) +tupla[0] #=> 1 +tupla[0] = 3 # Levanta un error TypeError + +# También puedes hacer todas esas cosas que haces con listas +len(tupla) #=> 3 +tupla + (4, 5, 6) #=> (1, 2, 3, 4, 5, 6) +tupla[:2] #=> (1, 2) +2 in tupla #=> True + +# Puedes desempacar tuplas (o listas) en variables +a, b, c = (1, 2, 3) # a ahora es 1, b ahora es 2 y c ahora es 3 +# Tuplas son creadas por defecto si omites los paréntesis +d, e, f = 4, 5, 6 +# Ahora mira que fácil es intercambiar dos valores +e, d = d, e # d ahora es 5 y e ahora es 4 + + +# Diccionarios relacionan llaves y valores +dicc_vacio = {} +# Aquí está un diccionario prellenado +dicc_lleno = {"uno": 1, "dos": 2, "tres": 3} + +# Busca valores con [] +dicc_lleno["uno"] #=> 1 + +# Obtén todas las llaves como una lista con 'keys()'. Necesitamos envolver la llamada en 'list()' porque obtenemos un iterable. Hablaremos de eso luego. +list(dicc_lleno.keys()) #=> ["tres", "dos", "uno"] +# Nota - El orden de las llaves del diccionario no está garantizada. +# Tus resultados podrían no ser los mismos del ejemplo. + +# Obtén todos los valores como una lista. Nuevamente necesitamos envolverlas en una lista para sacarlas del iterable. +list(dicc_lleno.values()) #=> [3, 2, 1] +# Nota - Lo mismo que con las llaves, no se garantiza el orden. + +# Verifica la existencia de una llave en el diccionario con 'in' +"uno" in dicc_lleno #=> True +1 in dicc_lleno #=> False + +# Buscar una llave inexistente deriva en KeyError +dicc_lleno["cuatro"] # KeyError + +# Usa el método 'get' para evitar la excepción KeyError +dicc_lleno.get("uno") #=> 1 +dicc_lleno.get("cuatro") #=> None +# El método 'get' soporta un argumento por defecto cuando el valor no existe. +dicc_lleno.get("uno", 4) #=> 1 +dicc_lleno.get("cuatro", 4) #=> 4 + +# El método 'setdefault' inserta en un diccionario solo si la llave no está presente +dicc_lleno.setdefault("cinco", 5) #dicc_lleno["cinco"] es puesto con valor 5 +dicc_lleno.setdefault("cinco", 6) #dicc_lleno["cinco"] todavía es 5 + + +# Remueve llaves de un diccionario con 'del' +del dicc_lleno['uno'] # Remueve la llave 'uno' de dicc_lleno + +# Sets (conjuntos) almacenan ... bueno, conjuntos +conjunto_vacio = set() +# Inicializar un conjunto con montón de valores. Yeah, se ve un poco como un diccionario. Lo siento. +un_conjunto = {1,2,2,3,4} # un_conjunto ahora es {1, 2, 3, 4} + +# Añade más valores a un conjunto +conjunto_lleno.add(5) # conjunto_lleno ahora es {1, 2, 3, 4, 5} + +# Haz intersección de conjuntos con & +otro_conjunto = {3, 4, 5, 6} +conjunto_lleno & otro_conjunto #=> {3, 4, 5} + +# Haz unión de conjuntos con | +conjunto_lleno | otro_conjunto #=> {1, 2, 3, 4, 5, 6} + +# Haz diferencia de conjuntos con - +{1,2,3,4} - {2,3,5} #=> {1, 4} + +# Verifica la existencia en un conjunto con 'in' +2 in conjunto_lleno #=> True +10 in conjunto_lleno #=> False + + +#################################################### +## 3. Control de Flujo +#################################################### + +# Creemos una variable para experimentar +some_var = 5 + +# Aquí está una declaración de un 'if'. ¡La indentación es significativa en Python! +# imprime "una_variable es menor que 10" +if una_variable > 10: + print("una_variable es completamente mas grande que 10.") +elif una_variable < 10: # Este condición 'elif' es opcional. + print("una_variable es mas chica que 10.") +else: # Esto también es opcional. + print("una_variable es de hecho 10.") + +""" +For itera sobre iterables (listas, cadenas, diccionarios, tuplas, generadores...) +imprime: + perro es un mamifero + gato es un mamifero + raton es un mamifero +""" +for animal in ["perro", "gato", "raton"]: + print("{} es un mamifero".format(animal)) + +""" +`range(número)` retorna un generador de números +desde cero hasta el número dado +imprime: + 0 + 1 + 2 + 3 +""" +for i in range(4): + print(i) + +""" +While itera hasta que una condición no se cumple. +imprime: + 0 + 1 + 2 + 3 +""" +x = 0 +while x < 4: + print(x) + x += 1 # versión corta de x = x + 1 + +# Maneja excepciones con un bloque try/except +try: + # Usa raise para levantar un error + raise IndexError("Este es un error de indice") +except IndexError as e: + pass # Pass no hace nada. Usualmente harias alguna recuperacion aqui. + +# Python oferce una abstracción fundamental llamada Iterable. +# Un iterable es un objeto que puede ser tratado como una sequencia. +# El objeto es retornado por la función 'range' es un iterable. + +dicc_lleno = {"uno": 1, "dos": 2, "tres": 3} +nuestro_iterable = dicc_lleno.keys() +print(nuestro_iterable) #=> dict_keys(['uno', 'dos', 'tres']). Este es un objeto que implementa nuestra interfaz Iterable + +Podemos recorrerla. +for i in nuestro_iterable: + print(i) # Imprime uno, dos, tres + +# Aunque no podemos selecionar un elemento por su índice. +nuestro_iterable[1] # Genera un TypeError + +# Un iterable es un objeto que sabe como crear un iterador. +nuestro_iterator = iter(nuestro_iterable) + +# Nuestro iterador es un objeto que puede recordar el estado mientras lo recorremos. +# Obtenemos el siguiente objeto llamando la función __next__. +nuestro_iterator.__next__() #=> "uno" + +# Mantiene el estado mientras llamamos __next__. +nuestro_iterator.__next__() #=> "dos" +nuestro_iterator.__next__() #=> "tres" + +# Después que el iterador ha retornado todos sus datos, da una excepción StopIterator. +nuestro_iterator.__next__() # Genera StopIteration + +# Puedes obtener todos los elementos de un iterador llamando a list() en el. +list(dicc_lleno.keys()) #=> Retorna ["uno", "dos", "tres"] + + + +#################################################### +## 4. Funciones +#################################################### + +# Usa 'def' para crear nuevas funciones +def add(x, y): + print("x es {} y y es {}".format(x, y)) + return x + y # Retorna valores con una la declaración return + +# Llamando funciones con parámetros +add(5, 6) #=> imprime "x es 5 y y es 6" y retorna 11 + +# Otra forma de llamar funciones es con argumentos de palabras claves +add(y=6, x=5) # Argumentos de palabra clave pueden ir en cualquier orden. + + +# Puedes definir funciones que tomen un número variable de argumentos +def varargs(*args): + return args + +varargs(1, 2, 3) #=> (1,2,3) + + +# Puedes definir funciones que toman un número variable de argumentos +# de palabras claves +def keyword_args(**kwargs): + return kwargs + +# Llamémosla para ver que sucede +keyword_args(pie="grande", lago="ness") #=> {"pie": "grande", "lago": "ness"} + + +# Puedes hacer ambas a la vez si quieres +def todos_los_argumentos(*args, **kwargs): + print args + print kwargs +""" +todos_los_argumentos(1, 2, a=3, b=4) imprime: + (1, 2) + {"a": 3, "b": 4} +""" + +# ¡Cuando llames funciones, puedes hacer lo opuesto a varargs/kwargs! +# Usa * para expandir tuplas y usa ** para expandir argumentos de palabras claves. +args = (1, 2, 3, 4) +kwargs = {"a": 3, "b": 4} +todos_los_argumentos(*args) # es equivalente a foo(1, 2, 3, 4) +todos_los_argumentos(**kwargs) # es equivalente a foo(a=3, b=4) +todos_los_argumentos(*args, **kwargs) # es equivalente a foo(1, 2, 3, 4, a=3, b=4) + +# Python tiene funciones de primera clase +def crear_suma(x): + def suma(y): + return x + y + return suma + +sumar_10 = crear_suma(10) +sumar_10(3) #=> 13 + +# También hay funciones anónimas +(lambda x: x > 2)(3) #=> True + +# Hay funciones integradas de orden superior +map(sumar_10, [1,2,3]) #=> [11, 12, 13] +filter(lambda x: x > 5, [3, 4, 5, 6, 7]) #=> [6, 7] + +# Podemos usar listas por comprensión para mapeos y filtros agradables +[add_10(i) for i in [1, 2, 3]] #=> [11, 12, 13] +[x for x in [3, 4, 5, 6, 7] if x > 5] #=> [6, 7] +# también hay diccionarios +{k:k**2 for k in range(3)} #=> {0: 0, 1: 1, 2: 4} +# y conjuntos por comprensión +{c for c in "la cadena"} #=> {'d', 'l', 'a', 'n', ' ', 'c', 'e'} + +#################################################### +## 5. Classes +#################################################### + + +# Heredamos de object para obtener una clase. +class Humano(object): + + # Un atributo de clase es compartido por todas las instancias de esta clase + especie = "H. sapiens" + + # Constructor basico + def __init__(self, nombre): + # Asigna el argumento al atributo nombre de la instancia + self.nombre = nombre + + # Un metodo de instancia. Todos los metodos toman self como primer argumento + def decir(self, msg): + return "%s: %s" % (self.nombre, msg) + + # Un metodo de clase es compartido a través de todas las instancias + # Son llamados con la clase como primer argumento + @classmethod + def get_especie(cls): + return cls.especie + + # Un metodo estatico es llamado sin la clase o instancia como referencia + @staticmethod + def roncar(): + return "*roncar*" + + +# Instancia una clase +i = Humano(nombre="Ian") +print i.decir("hi") # imprime "Ian: hi" + +j = Humano("Joel") +print j.decir("hello") #imprime "Joel: hello" + +# Llama nuestro método de clase +i.get_especie() #=> "H. sapiens" + +# Cambia los atributos compartidos +Humano.especie = "H. neanderthalensis" +i.get_especie() #=> "H. neanderthalensis" +j.get_especie() #=> "H. neanderthalensis" + +# Llama al método estático +Humano.roncar() #=> "*roncar*" + + +#################################################### +## 6. Módulos +#################################################### + +# Puedes importar módulos +import math +print(math.sqrt(16)) #=> 4.0 + +# Puedes obtener funciones específicas desde un módulo +from math import ceil, floor +print(ceil(3.7)) #=> 4.0 +print(floor(3.7))#=> 3.0 + +# Puedes importar todas las funciones de un módulo +# Precaución: Esto no es recomendable +from math import * + +# Puedes acortar los nombres de los módulos +import math as m +math.sqrt(16) == m.sqrt(16) #=> True + +# Los módulos de Python son sólo archivos ordinarios de Python. +# Puedes escribir tus propios módulos e importarlos. El nombre del módulo +# es el mismo del nombre del archivo. + +# Puedes encontrar que funciones y atributos definen un módulo. +import math +dir(math) + + +#################################################### +## 7. Avanzado +#################################################### + +# Los generadores te ayudan a hacer un código perezoso (lazy) +def duplicar_numeros(iterable): + for i in iterable: + yield i + i + +# Un generador crea valores sobre la marcha. +# En vez de generar y retornar todos los valores de una vez, crea uno en cada iteración. +# Esto significa que valores más grandes que 15 no serán procesados en 'duplicar_numeros'. +# Fíjate que 'range' es un generador. Crear una lista 1-900000000 tomaría mucho tiempo en crearse. +_rango = range(1, 900000000) +# Duplicará todos los números hasta que un resultado >= se encuentre. +for i in duplicar_numeros(_rango): + print(i) + if i >= 30: + break + + +# Decoradores +# en este ejemplo 'pedir' envuelve a 'decir' +# Pedir llamará a 'decir'. Si decir_por_favor es True entonces cambiará el mensaje a retornar +from functools import wraps + + +def pedir(_decir): + @wraps(_decir) + def wrapper(*args, **kwargs): + mensaje, decir_por_favor = _decir(*args, **kwargs) + if decir_por_favor: + return "{} {}".format(mensaje, "¡Por favor! Soy pobre :(") + return mensaje + + return wrapper + + +@pedir +def say(decir_por_favor=False): + mensaje = "¿Puedes comprarme una cerveza?" + return mensaje, decir_por_favor + + +print(decir()) # ¿Puedes comprarme una cerveza? +print(decir(decir_por_favor=True)) # ¿Puedes comprarme una cerveza? ¡Por favor! Soy pobre :() +``` + +## ¿Listo para más? + +### Gratis y en línea + +* [Learn Python The Hard Way](http://learnpythonthehardway.org/book/) +* [Dive Into Python](http://www.diveintopython.net/) +* [Ideas for Python Projects](http://pythonpracticeprojects.com) +* [The Official Docs](http://docs.python.org/3/) +* [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/) +* [Python Module of the Week](http://pymotw.com/3/) +* [A Crash Course in Python for Scientists](http://nbviewer.ipython.org/5920182) + +### Encuadernados + +* [Programming Python](http://www.amazon.com/gp/product/0596158106/ref=as_li_qf_sp_asin_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596158106&linkCode=as2&tag=homebits04-20) +* [Dive Into Python](http://www.amazon.com/gp/product/1441413022/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1441413022&linkCode=as2&tag=homebits04-20) +* [Python Essential Reference](http://www.amazon.com/gp/product/0672329786/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0672329786&linkCode=as2&tag=homebits04-20) + diff --git a/es-es/python3-es.html.markdown b/es-es/python3-es.html.markdown deleted file mode 100644 index 3236e73a..00000000 --- a/es-es/python3-es.html.markdown +++ /dev/null @@ -1,577 +0,0 @@ ---- -language: python3 -contributors: - - ["Louie Dinh", "http://pythonpracticeprojects.com"] -translators: - - ["Camilo Garrido", "http://twitter.com/hirohope"] -lang: es-es -filename: learnpython3-es.py ---- - -Python fue creado por Guido Van Rossum en el principio de los 90'. Ahora es uno -de los lenguajes más populares en existencia. Me enamoré de Python por su claridad sintáctica. -Es básicamente pseudocódigo ejecutable. - -¡Comentarios serán muy apreciados! Pueden contactarme en [@louiedinh](http://twitter.com/louiedinh) o louiedinh [at] [servicio de email de google] - -```python - -# Comentarios de una línea comienzan con una almohadilla (o signo gato) - -""" Strings multilinea pueden escribirse - usando tres "'s, y comunmente son usados - como comentarios. -""" - -#################################################### -## 1. Tipos de datos primitivos y operadores. -#################################################### - -# Tienes números -3 #=> 3 - -# Matemática es lo que esperarías -1 + 1 #=> 2 -8 - 1 #=> 7 -10 * 2 #=> 20 - -# Excepto la división la cual por defecto retorna un número 'float' (número de coma flotante) -35 / 5 # => 7.0 -# Sin embargo también tienes disponible división entera -34 // 5 # => 6 - -# Cuando usas un float, los resultados son floats -3 * 2.0 # => 6.0 - -# Refuerza la precedencia con paréntesis -(1 + 3) * 2 # => 8 - - -# Valores 'boolean' (booleanos) son primitivos -True -False - -# Niega con 'not' -not True # => False -not False # => True - - -# Igualdad es == -1 == 1 # => True -2 == 1 # => False - -# Desigualdad es != -1 != 1 # => False -2 != 1 # => True - -# Más comparaciones -1 < 10 # => True -1 > 10 # => False -2 <= 2 # => True -2 >= 2 # => True - -# ¡Las comparaciones pueden ser concatenadas! -1 < 2 < 3 # => True -2 < 3 < 2 # => False - -# Strings se crean con " o ' -"Esto es un string." -'Esto también es un string' - -# ¡Strings también pueden ser sumados! -"Hola " + "mundo!" #=> "Hola mundo!" - -# Un string puede ser tratado como una lista de caracteres -"Esto es un string"[0] #=> 'E' - -# .format puede ser usaro para darle formato a los strings, así: -"{} pueden ser {}".format("strings", "interpolados") - -# Puedes reutilizar los argumentos de formato si estos se repiten. -"{0} sé ligero, {0} sé rápido, {0} brinca sobre la {1}".format("Jack", "vela") #=> "Jack sé ligero, Jack sé rápido, Jack brinca sobre la vela" -# Puedes usar palabras claves si no quieres contar. -"{nombre} quiere comer {comida}".format(nombre="Bob", comida="lasaña") #=> "Bob quiere comer lasaña" -# También puedes interpolar cadenas usando variables en el contexto -nombre = 'Bob' -comida = 'Lasaña' -f'{nombre} quiere comer {comida}' #=> "Bob quiere comer lasaña" - -# None es un objeto -None # => None - -# No uses el símbolo de igualdad `==` para comparar objetos con None -# Usa `is` en su lugar -"etc" is None #=> False -None is None #=> True - -# None, 0, y strings/listas/diccionarios/conjuntos vacíos(as) todos se evalúan como False. -# Todos los otros valores son True -bool(0) # => False -bool("") # => False -bool([]) #=> False -bool({}) #=> False -bool(set()) #=> False - - -#################################################### -## 2. Variables y Colecciones -#################################################### - -# Python tiene una función para imprimir -print("Soy Python. Encantado de conocerte") - -# No hay necesidad de declarar las variables antes de asignarlas. -una_variable = 5 # La convención es usar guiones_bajos_con_minúsculas -una_variable #=> 5 - -# Acceder a variables no asignadas previamente es una excepción. -# Ve Control de Flujo para aprender más sobre el manejo de excepciones. -otra_variable # Levanta un error de nombre - -# Listas almacena secuencias -lista = [] -# Puedes empezar con una lista prellenada -otra_lista = [4, 5, 6] - -# Añadir cosas al final de una lista con 'append' -lista.append(1) #lista ahora es [1] -lista.append(2) #lista ahora es [1, 2] -lista.append(4) #lista ahora es [1, 2, 4] -lista.append(3) #lista ahora es [1, 2, 4, 3] -# Remueve del final de la lista con 'pop' -lista.pop() #=> 3 y lista ahora es [1, 2, 4] -# Pongámoslo de vuelta -lista.append(3) # Nuevamente lista ahora es [1, 2, 4, 3]. - -# Accede a una lista como lo harías con cualquier arreglo -lista[0] #=> 1 -# Mira el último elemento -lista[-1] #=> 3 - -# Mirar fuera de los límites es un error 'IndexError' -lista[4] # Levanta la excepción IndexError - -# Puedes mirar por rango con la sintáxis de trozo. -# (Es un rango cerrado/abierto para ustedes los matemáticos.) -lista[1:3] #=> [2, 4] -# Omite el inicio -lista[2:] #=> [4, 3] -# Omite el final -lista[:3] #=> [1, 2, 4] -# Selecciona cada dos elementos -lista[::2] # =>[1, 4] -# Invierte la lista -lista[::-1] # => [3, 4, 2, 1] -# Usa cualquier combinación de estos para crear trozos avanzados -# lista[inicio:final:pasos] - -# Remueve elementos arbitrarios de una lista con 'del' -del lista[2] # lista ahora es [1, 2, 3] - -# Puedes sumar listas -lista + otra_lista #=> [1, 2, 3, 4, 5, 6] - Nota: lista y otra_lista no se tocan - -# Concatenar listas con 'extend' -lista.extend(otra_lista) # lista ahora es [1, 2, 3, 4, 5, 6] - -# Verifica la existencia en una lista con 'in' -1 in lista #=> True - -# Examina el largo de una lista con 'len' -len(lista) #=> 6 - - -# Tuplas son como listas pero son inmutables. -tupla = (1, 2, 3) -tupla[0] #=> 1 -tupla[0] = 3 # Levanta un error TypeError - -# También puedes hacer todas esas cosas que haces con listas -len(tupla) #=> 3 -tupla + (4, 5, 6) #=> (1, 2, 3, 4, 5, 6) -tupla[:2] #=> (1, 2) -2 in tupla #=> True - -# Puedes desempacar tuplas (o listas) en variables -a, b, c = (1, 2, 3) # a ahora es 1, b ahora es 2 y c ahora es 3 -# Tuplas son creadas por defecto si omites los paréntesis -d, e, f = 4, 5, 6 -# Ahora mira que fácil es intercambiar dos valores -e, d = d, e # d ahora es 5 y e ahora es 4 - - -# Diccionarios relacionan llaves y valores -dicc_vacio = {} -# Aquí está un diccionario prellenado -dicc_lleno = {"uno": 1, "dos": 2, "tres": 3} - -# Busca valores con [] -dicc_lleno["uno"] #=> 1 - -# Obtén todas las llaves como una lista con 'keys()'. Necesitamos envolver la llamada en 'list()' porque obtenemos un iterable. Hablaremos de eso luego. -list(dicc_lleno.keys()) #=> ["tres", "dos", "uno"] -# Nota - El orden de las llaves del diccionario no está garantizada. -# Tus resultados podrían no ser los mismos del ejemplo. - -# Obtén todos los valores como una lista. Nuevamente necesitamos envolverlas en una lista para sacarlas del iterable. -list(dicc_lleno.values()) #=> [3, 2, 1] -# Nota - Lo mismo que con las llaves, no se garantiza el orden. - -# Verifica la existencia de una llave en el diccionario con 'in' -"uno" in dicc_lleno #=> True -1 in dicc_lleno #=> False - -# Buscar una llave inexistente deriva en KeyError -dicc_lleno["cuatro"] # KeyError - -# Usa el método 'get' para evitar la excepción KeyError -dicc_lleno.get("uno") #=> 1 -dicc_lleno.get("cuatro") #=> None -# El método 'get' soporta un argumento por defecto cuando el valor no existe. -dicc_lleno.get("uno", 4) #=> 1 -dicc_lleno.get("cuatro", 4) #=> 4 - -# El método 'setdefault' inserta en un diccionario solo si la llave no está presente -dicc_lleno.setdefault("cinco", 5) #dicc_lleno["cinco"] es puesto con valor 5 -dicc_lleno.setdefault("cinco", 6) #dicc_lleno["cinco"] todavía es 5 - - -# Remueve llaves de un diccionario con 'del' -del dicc_lleno['uno'] # Remueve la llave 'uno' de dicc_lleno - -# Sets (conjuntos) almacenan ... bueno, conjuntos -conjunto_vacio = set() -# Inicializar un conjunto con montón de valores. Yeah, se ve un poco como un diccionario. Lo siento. -un_conjunto = {1,2,2,3,4} # un_conjunto ahora es {1, 2, 3, 4} - -# Añade más valores a un conjunto -conjunto_lleno.add(5) # conjunto_lleno ahora es {1, 2, 3, 4, 5} - -# Haz intersección de conjuntos con & -otro_conjunto = {3, 4, 5, 6} -conjunto_lleno & otro_conjunto #=> {3, 4, 5} - -# Haz unión de conjuntos con | -conjunto_lleno | otro_conjunto #=> {1, 2, 3, 4, 5, 6} - -# Haz diferencia de conjuntos con - -{1,2,3,4} - {2,3,5} #=> {1, 4} - -# Verifica la existencia en un conjunto con 'in' -2 in conjunto_lleno #=> True -10 in conjunto_lleno #=> False - - -#################################################### -## 3. Control de Flujo -#################################################### - -# Creemos una variable para experimentar -some_var = 5 - -# Aquí está una declaración de un 'if'. ¡La indentación es significativa en Python! -# imprime "una_variable es menor que 10" -if una_variable > 10: - print("una_variable es completamente mas grande que 10.") -elif una_variable < 10: # Este condición 'elif' es opcional. - print("una_variable es mas chica que 10.") -else: # Esto también es opcional. - print("una_variable es de hecho 10.") - -""" -For itera sobre iterables (listas, cadenas, diccionarios, tuplas, generadores...) -imprime: - perro es un mamifero - gato es un mamifero - raton es un mamifero -""" -for animal in ["perro", "gato", "raton"]: - print("{} es un mamifero".format(animal)) - -""" -`range(número)` retorna un generador de números -desde cero hasta el número dado -imprime: - 0 - 1 - 2 - 3 -""" -for i in range(4): - print(i) - -""" -While itera hasta que una condición no se cumple. -imprime: - 0 - 1 - 2 - 3 -""" -x = 0 -while x < 4: - print(x) - x += 1 # versión corta de x = x + 1 - -# Maneja excepciones con un bloque try/except -try: - # Usa raise para levantar un error - raise IndexError("Este es un error de indice") -except IndexError as e: - pass # Pass no hace nada. Usualmente harias alguna recuperacion aqui. - -# Python oferce una abstracción fundamental llamada Iterable. -# Un iterable es un objeto que puede ser tratado como una sequencia. -# El objeto es retornado por la función 'range' es un iterable. - -dicc_lleno = {"uno": 1, "dos": 2, "tres": 3} -nuestro_iterable = dicc_lleno.keys() -print(nuestro_iterable) #=> dict_keys(['uno', 'dos', 'tres']). Este es un objeto que implementa nuestra interfaz Iterable - -Podemos recorrerla. -for i in nuestro_iterable: - print(i) # Imprime uno, dos, tres - -# Aunque no podemos selecionar un elemento por su índice. -nuestro_iterable[1] # Genera un TypeError - -# Un iterable es un objeto que sabe como crear un iterador. -nuestro_iterator = iter(nuestro_iterable) - -# Nuestro iterador es un objeto que puede recordar el estado mientras lo recorremos. -# Obtenemos el siguiente objeto llamando la función __next__. -nuestro_iterator.__next__() #=> "uno" - -# Mantiene el estado mientras llamamos __next__. -nuestro_iterator.__next__() #=> "dos" -nuestro_iterator.__next__() #=> "tres" - -# Después que el iterador ha retornado todos sus datos, da una excepción StopIterator. -nuestro_iterator.__next__() # Genera StopIteration - -# Puedes obtener todos los elementos de un iterador llamando a list() en el. -list(dicc_lleno.keys()) #=> Retorna ["uno", "dos", "tres"] - - - -#################################################### -## 4. Funciones -#################################################### - -# Usa 'def' para crear nuevas funciones -def add(x, y): - print("x es {} y y es {}".format(x, y)) - return x + y # Retorna valores con una la declaración return - -# Llamando funciones con parámetros -add(5, 6) #=> imprime "x es 5 y y es 6" y retorna 11 - -# Otra forma de llamar funciones es con argumentos de palabras claves -add(y=6, x=5) # Argumentos de palabra clave pueden ir en cualquier orden. - - -# Puedes definir funciones que tomen un número variable de argumentos -def varargs(*args): - return args - -varargs(1, 2, 3) #=> (1,2,3) - - -# Puedes definir funciones que toman un número variable de argumentos -# de palabras claves -def keyword_args(**kwargs): - return kwargs - -# Llamémosla para ver que sucede -keyword_args(pie="grande", lago="ness") #=> {"pie": "grande", "lago": "ness"} - - -# Puedes hacer ambas a la vez si quieres -def todos_los_argumentos(*args, **kwargs): - print args - print kwargs -""" -todos_los_argumentos(1, 2, a=3, b=4) imprime: - (1, 2) - {"a": 3, "b": 4} -""" - -# ¡Cuando llames funciones, puedes hacer lo opuesto a varargs/kwargs! -# Usa * para expandir tuplas y usa ** para expandir argumentos de palabras claves. -args = (1, 2, 3, 4) -kwargs = {"a": 3, "b": 4} -todos_los_argumentos(*args) # es equivalente a foo(1, 2, 3, 4) -todos_los_argumentos(**kwargs) # es equivalente a foo(a=3, b=4) -todos_los_argumentos(*args, **kwargs) # es equivalente a foo(1, 2, 3, 4, a=3, b=4) - -# Python tiene funciones de primera clase -def crear_suma(x): - def suma(y): - return x + y - return suma - -sumar_10 = crear_suma(10) -sumar_10(3) #=> 13 - -# También hay funciones anónimas -(lambda x: x > 2)(3) #=> True - -# Hay funciones integradas de orden superior -map(sumar_10, [1,2,3]) #=> [11, 12, 13] -filter(lambda x: x > 5, [3, 4, 5, 6, 7]) #=> [6, 7] - -# Podemos usar listas por comprensión para mapeos y filtros agradables -[add_10(i) for i in [1, 2, 3]] #=> [11, 12, 13] -[x for x in [3, 4, 5, 6, 7] if x > 5] #=> [6, 7] -# también hay diccionarios -{k:k**2 for k in range(3)} #=> {0: 0, 1: 1, 2: 4} -# y conjuntos por comprensión -{c for c in "la cadena"} #=> {'d', 'l', 'a', 'n', ' ', 'c', 'e'} - -#################################################### -## 5. Classes -#################################################### - - -# Heredamos de object para obtener una clase. -class Humano(object): - - # Un atributo de clase es compartido por todas las instancias de esta clase - especie = "H. sapiens" - - # Constructor basico - def __init__(self, nombre): - # Asigna el argumento al atributo nombre de la instancia - self.nombre = nombre - - # Un metodo de instancia. Todos los metodos toman self como primer argumento - def decir(self, msg): - return "%s: %s" % (self.nombre, msg) - - # Un metodo de clase es compartido a través de todas las instancias - # Son llamados con la clase como primer argumento - @classmethod - def get_especie(cls): - return cls.especie - - # Un metodo estatico es llamado sin la clase o instancia como referencia - @staticmethod - def roncar(): - return "*roncar*" - - -# Instancia una clase -i = Humano(nombre="Ian") -print i.decir("hi") # imprime "Ian: hi" - -j = Humano("Joel") -print j.decir("hello") #imprime "Joel: hello" - -# Llama nuestro método de clase -i.get_especie() #=> "H. sapiens" - -# Cambia los atributos compartidos -Humano.especie = "H. neanderthalensis" -i.get_especie() #=> "H. neanderthalensis" -j.get_especie() #=> "H. neanderthalensis" - -# Llama al método estático -Humano.roncar() #=> "*roncar*" - - -#################################################### -## 6. Módulos -#################################################### - -# Puedes importar módulos -import math -print(math.sqrt(16)) #=> 4.0 - -# Puedes obtener funciones específicas desde un módulo -from math import ceil, floor -print(ceil(3.7)) #=> 4.0 -print(floor(3.7))#=> 3.0 - -# Puedes importar todas las funciones de un módulo -# Precaución: Esto no es recomendable -from math import * - -# Puedes acortar los nombres de los módulos -import math as m -math.sqrt(16) == m.sqrt(16) #=> True - -# Los módulos de Python son sólo archivos ordinarios de Python. -# Puedes escribir tus propios módulos e importarlos. El nombre del módulo -# es el mismo del nombre del archivo. - -# Puedes encontrar que funciones y atributos definen un módulo. -import math -dir(math) - - -#################################################### -## 7. Avanzado -#################################################### - -# Los generadores te ayudan a hacer un código perezoso (lazy) -def duplicar_numeros(iterable): - for i in iterable: - yield i + i - -# Un generador crea valores sobre la marcha. -# En vez de generar y retornar todos los valores de una vez, crea uno en cada iteración. -# Esto significa que valores más grandes que 15 no serán procesados en 'duplicar_numeros'. -# Fíjate que 'range' es un generador. Crear una lista 1-900000000 tomaría mucho tiempo en crearse. -_rango = range(1, 900000000) -# Duplicará todos los números hasta que un resultado >= se encuentre. -for i in duplicar_numeros(_rango): - print(i) - if i >= 30: - break - - -# Decoradores -# en este ejemplo 'pedir' envuelve a 'decir' -# Pedir llamará a 'decir'. Si decir_por_favor es True entonces cambiará el mensaje a retornar -from functools import wraps - - -def pedir(_decir): - @wraps(_decir) - def wrapper(*args, **kwargs): - mensaje, decir_por_favor = _decir(*args, **kwargs) - if decir_por_favor: - return "{} {}".format(mensaje, "¡Por favor! Soy pobre :(") - return mensaje - - return wrapper - - -@pedir -def say(decir_por_favor=False): - mensaje = "¿Puedes comprarme una cerveza?" - return mensaje, decir_por_favor - - -print(decir()) # ¿Puedes comprarme una cerveza? -print(decir(decir_por_favor=True)) # ¿Puedes comprarme una cerveza? ¡Por favor! Soy pobre :() -``` - -## ¿Listo para más? - -### Gratis y en línea - -* [Learn Python The Hard Way](http://learnpythonthehardway.org/book/) -* [Dive Into Python](http://www.diveintopython.net/) -* [Ideas for Python Projects](http://pythonpracticeprojects.com) -* [The Official Docs](http://docs.python.org/3/) -* [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/) -* [Python Module of the Week](http://pymotw.com/3/) -* [A Crash Course in Python for Scientists](http://nbviewer.ipython.org/5920182) - -### Encuadernados - -* [Programming Python](http://www.amazon.com/gp/product/0596158106/ref=as_li_qf_sp_asin_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596158106&linkCode=as2&tag=homebits04-20) -* [Dive Into Python](http://www.amazon.com/gp/product/1441413022/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1441413022&linkCode=as2&tag=homebits04-20) -* [Python Essential Reference](http://www.amazon.com/gp/product/0672329786/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0672329786&linkCode=as2&tag=homebits04-20) - -- cgit v1.2.3 From 95c8b24ebf8b8e0ed02923787a9f793bdf295200 Mon Sep 17 00:00:00 2001 From: Simon Shine Date: Wed, 12 Feb 2020 05:09:13 +0100 Subject: Python 2 'language': Python 2 (legacy) Instead of listing 'language: python' for Python 2, use language: Python 2 (legacy) ``` find . -iname "*pythonlegacy*" -exec \ sed -i 's/^language: .*/language: Python 2 (legacy)/' {} \; ``` --- es-es/pythonlegacy-es.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'es-es') diff --git a/es-es/pythonlegacy-es.html.markdown b/es-es/pythonlegacy-es.html.markdown index 2b8f498a..db16b9bd 100644 --- a/es-es/pythonlegacy-es.html.markdown +++ b/es-es/pythonlegacy-es.html.markdown @@ -1,5 +1,5 @@ --- -language: python +language: Python 2 (legacy) contributors: - ["Louie Dinh", "http://ldinh.ca"] translators: -- cgit v1.2.3 From 8f5fac98958098864b86e2a09d8131d6dafaaddd Mon Sep 17 00:00:00 2001 From: Simon Shine Date: Wed, 12 Feb 2020 05:15:29 +0100 Subject: Python 3: 'language: Python' Instead of listing 'language: python3' for Python 3, use language: Python as #3450 does. ``` find . -iname "python-*.markdown" -exec \ sed -i 's/language: python3/language: Python/' {} \; ``` --- es-es/python-es.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'es-es') diff --git a/es-es/python-es.html.markdown b/es-es/python-es.html.markdown index 3236e73a..aa74aaf8 100644 --- a/es-es/python-es.html.markdown +++ b/es-es/python-es.html.markdown @@ -1,5 +1,5 @@ --- -language: python3 +language: Python contributors: - ["Louie Dinh", "http://pythonpracticeprojects.com"] translators: -- cgit v1.2.3 From 887cbee8af080034177734b528819491e73a7a16 Mon Sep 17 00:00:00 2001 From: Simon Shine Date: Wed, 12 Feb 2020 05:50:44 +0100 Subject: Change 'filename:' for Python 2 (legacy) Before renaming, all Python 2 filenames were 'learnpython-*.py'. This commit renames them to 'learnpythonlegacy-*.py'. To verify that the filenames were named consistently across translations prior to this commit, and to change this: ``` find . -name "pythonlegacy*.markdown" -exec ack filename: {} \; find . -name "pythonlegacy*.markdown" -exec \ sed -i 's/^filename: learnpython/filename: learnpythonlegacy/' {} \; ``` --- es-es/pythonlegacy-es.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'es-es') diff --git a/es-es/pythonlegacy-es.html.markdown b/es-es/pythonlegacy-es.html.markdown index db16b9bd..0a7304e9 100644 --- a/es-es/pythonlegacy-es.html.markdown +++ b/es-es/pythonlegacy-es.html.markdown @@ -6,7 +6,7 @@ translators: - ["Camilo Garrido", "http://www.twitter.com/hirohope"] - ["Fabio Souto", "http://fabiosouto.me"] lang: es-es -filename: learnpython-es.py +filename: learnpythonlegacy-es.py --- Python fue creado por Guido Van Rossum en el principio de los 90. Ahora es uno -- cgit v1.2.3 From ae848c481fabaca935ffbe33293a43a43434d268 Mon Sep 17 00:00:00 2001 From: Simon Shine Date: Wed, 12 Feb 2020 06:23:31 +0100 Subject: Python 3: Use 'filename: learnpython*.py' (no '3') Before renaming, Python 3 filenames were 'learnpython3*.py'. This commit removes the '3' part from the filename. To verify that the filenames were named consistently across translations prior to this commit, and to change this: ``` ack -H 'filename:' python.html.markdown find . -name "python-*.markdown" -exec ack -H 'filename:' {} \; sed -i 's/^filename: learnpython3/filename: learnpython/' \ python.html.markdown find . -name "python-*.markdown" -exec \ sed -i 's/^filename: learnpython3/filename: learnpython/' {} \; ``` --- es-es/python-es.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'es-es') diff --git a/es-es/python-es.html.markdown b/es-es/python-es.html.markdown index aa74aaf8..7deec286 100644 --- a/es-es/python-es.html.markdown +++ b/es-es/python-es.html.markdown @@ -5,7 +5,7 @@ contributors: translators: - ["Camilo Garrido", "http://twitter.com/hirohope"] lang: es-es -filename: learnpython3-es.py +filename: learnpython-es.py --- Python fue creado por Guido Van Rossum en el principio de los 90'. Ahora es uno -- cgit v1.2.3 From 5864aba42d2cf57dfe96049568b3a9689ea6a813 Mon Sep 17 00:00:00 2001 From: Leigh Brenecki Date: Thu, 13 Feb 2020 10:38:29 +1030 Subject: Purge my deadname --- es-es/javascript-es.html.markdown | 6 +++--- es-es/yaml-es.html.markdown | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'es-es') diff --git a/es-es/javascript-es.html.markdown b/es-es/javascript-es.html.markdown index 31512dc4..050154c7 100644 --- a/es-es/javascript-es.html.markdown +++ b/es-es/javascript-es.html.markdown @@ -1,7 +1,7 @@ --- language: javascript contributors: - - ["Adam Brenecki", "http://adam.brenecki.id.au"] + - ["Leigh Brenecki", "https://leigh.net.au"] - ["Ariel Krakowski", "http://www.learneroo.com"] translators: - ["Daniel Zendejas","https://github.com/DanielZendejas"] @@ -19,8 +19,8 @@ para front-end que Java. Sin embargo, JavaScript no sólo se limita a los navegadores web: Node.js, un proyecto que proporciona un entorno de ejecución independiente para el motor V8 de Google Chrome, se está volviendo más y más popular. ¡La retroalimentación es bienvenida! Puedes encontrarme en: -[@adambrenecki](https://twitter.com/adambrenecki), o -[adam@brenecki.id.au](mailto:adam@brenecki.id.au). +[@ExcitedLeigh](https://twitter.com/ExcitedLeigh), o +[l@leigh.net.au](mailto:l@leigh.net.au). ```js // Los comentarios en JavaScript son los mismos como comentarios en C. diff --git a/es-es/yaml-es.html.markdown b/es-es/yaml-es.html.markdown index cd3143fb..582fa60e 100644 --- a/es-es/yaml-es.html.markdown +++ b/es-es/yaml-es.html.markdown @@ -3,7 +3,7 @@ language: yaml lang: es-es filename: learnyaml-es.yaml contributors: - - ["Adam Brenecki", "https://github.com/adambrenecki"] + - ["Leigh Brenecki", "https://github.com/adambrenecki"] - ["Everardo Medina","https://github.com/everblut"] translators: - ["Daniel Zendejas","https://github.com/DanielZendejas"] -- cgit v1.2.3 From c1e04d6868c07de97862f8484277748cc8a5ce92 Mon Sep 17 00:00:00 2001 From: brian Date: Fri, 28 Feb 2020 10:19:01 -0300 Subject: Fixed a spelling mistake --- es-es/ruby-es.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'es-es') diff --git a/es-es/ruby-es.html.markdown b/es-es/ruby-es.html.markdown index e3e43c18..63a47e89 100644 --- a/es-es/ruby-es.html.markdown +++ b/es-es/ruby-es.html.markdown @@ -139,7 +139,7 @@ status == :pendiente #=> true status == 'pendiente' #=> false -status == :aprovado #=> false +status == :aprobado #=> false # Arreglos -- cgit v1.2.3 From 0ecb8264293d852f2ef586279885848b621668d1 Mon Sep 17 00:00:00 2001 From: sumanstats Date: Wed, 10 Jun 2020 16:33:01 +0545 Subject: Perl6 to Raku and many more + As the Perl 6 is renamed to raku, it is good to reflect that https://github.com/Raku/problem-solving/blob/master/solutions/language/Path-to-Raku.md + perl6.org is now raku.org + change references of perl 6 to raku + rename file perl6-pod.html.markdown to raku-pod.html.markdown + Perl refers to Perl 5, there is no ambiguity after rename of Perl6 to Raku, use Perl only to refer to Perl 5 + fix links inside raku.html.markdown --- es-es/perl-es.html.markdown | 16 +- es-es/perl6-es.html.markdown | 420 +++++++++++++++++++++---------------------- 2 files changed, 218 insertions(+), 218 deletions(-) (limited to 'es-es') diff --git a/es-es/perl-es.html.markdown b/es-es/perl-es.html.markdown index 644182ff..76e9b6e6 100644 --- a/es-es/perl-es.html.markdown +++ b/es-es/perl-es.html.markdown @@ -11,9 +11,9 @@ translators: lang: es-es --- -Perl 5 es un lenguaje de programación altamente capaz, rico en características, con más de 25 años de desarrollo. +Perl es un lenguaje de programación altamente capaz, rico en características, con más de 25 años de desarrollo. -Perl 5 corre en más de 100 plataformas, desde portátiles hasta ordenadores centrales, y es adecuado para realizar desde prototipos rápidos hasta desarrollar proyectos a gran escala. +Perl corre en más de 100 plataformas, desde portátiles hasta ordenadores centrales, y es adecuado para realizar desde prototipos rápidos hasta desarrollar proyectos a gran escala. ```perl # Comentarios de una sola línea con un carácter hash @@ -31,7 +31,7 @@ Perl 5 corre en más de 100 plataformas, desde portátiles hasta ordenadores cen my $animal = "camello"; my $respuesta = 42; -# Los valores escalares pueden ser cadenas de caracteres, números enteros o +# Los valores escalares pueden ser cadenas de caracteres, números enteros o # de punto flotante; Perl automáticamente los convertirá como sea requerido ## Arreglos @@ -52,7 +52,7 @@ my %color_fruta = ( # Los escalares, arreglos y hashes están más documentados en perldata (perldoc perldata) -# Los tipos de datos más complejos se pueden construir utilizando +# Los tipos de datos más complejos se pueden construir utilizando # referencias, las cuales le permiten construir listas y hashes dentro # de listas y hashes @@ -61,7 +61,7 @@ my %color_fruta = ( # Perl tiene la mayoría de las estructuras condicionales y de ciclos más comunes if ( $var ) { ...; -} elsif ( $var eq 'bar' ) { +} elsif ( $var eq 'bar' ) { ...; } else { ...; @@ -98,7 +98,7 @@ foreach (@array) { #### Expresiones regulares -# El soporte de expresiones regulares en Perl es muy amplio y profundo, y +# El soporte de expresiones regulares en Perl es muy amplio y profundo, y # está sujeto a una extensa documentación en perlrequick, perlretut, entre otros. # Sin embargo, resumiendo: @@ -113,7 +113,7 @@ $a =~ s/foo/bar/g; # remplaza TODAS LAS INSTANCIAS de "foo" con "bar" en #### Archivos y E/S -# Puede abrir un archivo para obtener datos o escribirlos utilizando la +# Puede abrir un archivo para obtener datos o escribirlos utilizando la # función "open()" open(my $entrada, "<" "entrada.txt") or die "No es posible abrir entrada.txt: $!"; @@ -122,7 +122,7 @@ open(my $log, ">>", "mi.log") or die "No es posible abrir mi.log: $!"; # Es posible leer desde un gestor de archivo abierto utilizando el operador "<>". # En contexto escalar, leer una sola línea desde el gestor de archivo, y -# en contexto de lista, leer el archivo completo en donde asigna +# en contexto de lista, leer el archivo completo en donde asigna # cada línea a un elemento de la lista my $linea = <$entrada>; diff --git a/es-es/perl6-es.html.markdown b/es-es/perl6-es.html.markdown index bf3ae65e..b9f49e2d 100644 --- a/es-es/perl6-es.html.markdown +++ b/es-es/perl6-es.html.markdown @@ -11,10 +11,10 @@ translators: lang: es-es --- -Perl 6 es un lenguaje de programación altamente capaz y con características +Perl 6 es un lenguaje de programación altamente capaz y con características abundantes para hacerlo el lenguage ideal por los próximos 100 años. -El compilador primario de Perl 6 se llama [Rakudo](http://rakudo.org), el cual +El compilador primario de Perl 6 se llama [Rakudo](http://rakudo.org), el cual se ejecuta en JVM y en [MoarVM](http://moarvm.com). Meta-nota: dos signos de números (##) son usados para indicar párrafos, @@ -26,7 +26,7 @@ mientras que un solo signo de número (#) indica notas. # Un comentario de una sola línea comienza con un signo de número #`( - Comentarios multilíneas usan #` y signos de encerradura tales + Comentarios multilíneas usan #` y signos de encerradura tales como (), [], {}, 「」, etc. ) ``` @@ -42,16 +42,16 @@ my $variable; ### Escalares ```perl6 -# Un escalar representa un solo valor. Variables escalares comienzan +# Un escalar representa un solo valor. Variables escalares comienzan # con un `$` my $str = 'Cadena'; -# Las comillas inglesas ("") permiten la intepolación (lo cual veremos +# Las comillas inglesas ("") permiten la intepolación (lo cual veremos # luego): my $str2 = "Cadena"; ## Los nombres de variables pueden contener pero no terminar con comillas -## simples y guiones. Sin embargo, pueden contener +## simples y guiones. Sin embargo, pueden contener ## (y terminar con) guiones bajos (_): my $nombre'de-variable_ = 5; # Esto funciona! @@ -70,7 +70,7 @@ my $bool-forzado = so $str; # Y puedes usar el operador prefijo `so` que my @array = 'a', 'b', 'c'; # equivalente a: my @letras = ; # array de palabras, delimitado por espacios. - # Similar al qw de perl5, o el %w de Ruby. + # Similar al qw de perl, o el %w de Ruby. my @array = 1, 2, 3; say @array[2]; # Los índices de un array empiezan por el 0 -- Este es @@ -83,7 +83,7 @@ say "Interpola todos los elementos de un array usando [] : @array[]"; @array[0, 1] = 5, 6; # Asigna varios valores my @llaves = 0, 2; -@array[@llaves] = @letras; # Asignación usando un array que contiene valores +@array[@llaves] = @letras; # Asignación usando un array que contiene valores # índices say @array; #=> a 6 b ``` @@ -93,13 +93,13 @@ say @array; #=> a 6 b ```perl6 ## Un hash contiene parejas de llaves y valores. ## Puedes construir un objeto Pair usando la sintaxis `LLave => Valor`. -## Tablas de hashes son bien rápidas para búsqueda, y son almacenadas +## Tablas de hashes son bien rápidas para búsqueda, y son almacenadas ## sin ningún orden. ## Ten en cuenta que las llaves son "aplanadas" en contexto de hash, y ## cualquier llave duplicada es deduplicada. my %hash = 1 => 2, 3 => 4; -my %hash = foo => "bar", # las llaves reciben sus comillas +my %hash = foo => "bar", # las llaves reciben sus comillas # automáticamente. "some other" => "value", # las comas colgantes estań bien. ; @@ -133,7 +133,7 @@ say %hash; # Si es una cadena de texto, puedes actualmente usar <> ## creadas con la palabra clave `sub`. sub di-hola { say "¡Hola, mundo!" } -## Puedes proveer argumentos (tipados). Si especificado, +## Puedes proveer argumentos (tipados). Si especificado, ## el tipo será chequeado al tiempo de compilación si es posible. ## De lo contrario, al tiempo de ejecución. sub di-hola-a(Str $nombre) { @@ -165,7 +165,7 @@ say return-for; # imprime Nil ## Una subrutina puede tener argumentos opcionales: sub con-opcional($arg?) { # el signo "?" marca el argumento opcional - say "Podría returnar `(Any)` (valor de Perl parecido al 'null') si no me pasan + say "Podría returnar `(Any)` (valor de Perl parecido al 'null') si no me pasan un argumento, o returnaré mi argumento"; $arg; } @@ -173,7 +173,7 @@ con-opcional; # devuelve Any con-opcional(); # devuelve Any con-opcional(1); # devuelve 1 -## También puedes proveer un argumento por defecto para +## También puedes proveer un argumento por defecto para ## cuando los argumentos no son proveídos: sub hola-a($nombre = "Mundo") { say "¡Hola, $nombre!"; @@ -192,8 +192,8 @@ con-nombre(1, nombrado => 6); #=> 7 ## Sin embargo, debes tener algo en cuenta aquí: ## Si pones comillas alrededor de tu llave, Perl 6 no será capaz de verla ## al tiempo de compilación, y entonces tendrás un solo objeto Pair como -## un argumento posicional, lo que significa que el siguiente ejemplo -## falla: +## un argumento posicional, lo que significa que el siguiente ejemplo +## falla: con-nombre(1, 'nombrado' => 6); con-nombre(2, :nombrado(5)); #=> 7 @@ -205,7 +205,7 @@ sub con-nombre-mandatorio(:$str!) { } con-nombre-mandatorio(str => "Mi texto"); #=> Mi texto! con-nombre-mandatorio; # error al tiempo de ejecución: - # "Required named parameter not passed" + # "Required named parameter not passed" # ("Parámetro nombrado requerido no proveído") con-nombre-mandatorio(3);# error al tiempo de ejecución: # "Too many positional parameters passed" @@ -226,7 +226,7 @@ sub nombrado-definido(:$def = 5) { nombrado-definido; #=> 5 nombrado-definido(def => 15); #=> 15 -## Dado que puedes omitir los paréntesis para invocar una función sin +## Dado que puedes omitir los paréntesis para invocar una función sin ## argumentos, necesitas usar "&" en el nombre para almacenar la función ## `di-hola` en una variable. my &s = &di-hola; @@ -240,8 +240,8 @@ sub muchos($principal, *@resto) { #`*@` (slurpy) consumirá lo restante say @resto.join(' / ') ~ "!"; } say muchos('Feliz', 'Cumpleaño', 'Cumpleaño'); #=> Feliz / Cumpleaño! - # Nota que el asterisco (*) no - # consumió el parámetro frontal. + # Nota que el asterisco (*) no + # consumió el parámetro frontal. ## Puedes invocar un función con un array usando el ## operador "aplanador de lista de argumento" `|` @@ -257,11 +257,11 @@ concat3(|@array); #=> a, b, c ```perl6 ## En Perl 6, valores son actualmente almacenados en "contenedores". -## El operador de asignación le pregunta al contenedor en su izquierda +## El operador de asignación le pregunta al contenedor en su izquierda ## almacenar el valor a su derecha. Cuando se pasan alrededor, contenedores ## son marcados como inmutables. Esto significa que, en una función, tu ## tendrás un error si tratas de mutar uno de tus argumentos. -## Si realmente necesitas hacerlo, puedes preguntar por un contenedor +## Si realmente necesitas hacerlo, puedes preguntar por un contenedor ## mutable usando `is rw`: sub mutar($n is rw) { $n++; @@ -276,7 +276,7 @@ mutar $m; # ¡$n es ahora 43! ## dado que no contenedor ha sido pasado y números enteros son inmutables ## por naturaleza: -mutar 42; # Parámetro '$n' esperaba un contenedor mutable, +mutar 42; # Parámetro '$n' esperaba un contenedor mutable, # pero recibió un valor Int ## Si en cambio quieres una copia, debes usar `is copy`. @@ -297,9 +297,9 @@ say $x; #=> 52 ```perl6 ## - `if` ## Antes de hablar acerca de `if`, necesitamos saber cuales valores son -## "Truthy" (representa True (verdadero)), y cuales son "Falsey" -## (o "Falsy") -- representa False (falso). Solo estos valores son -## Falsey: 0, (), {}, "", Nil, un tipo (como `Str` o`Int`) y +## "Truthy" (representa True (verdadero)), y cuales son "Falsey" +## (o "Falsy") -- representa False (falso). Solo estos valores son +## Falsey: 0, (), {}, "", Nil, un tipo (como `Str` o`Int`) y ## por supuesto False. Todos los valores son Truthy. if True { say "¡Es verdadero!"; @@ -316,8 +316,8 @@ unless False { ## También puedes usar sus versiones sufijos seguidas por la palabra clave: say "Un poco verdadero" if True; -## - La condicional ternaria, "?? !!" (como `x ? y : z` en otros lenguajes) -## devuelve $valor-si-verdadera si la condición es verdadera y +## - La condicional ternaria, "?? !!" (como `x ? y : z` en otros lenguajes) +## devuelve $valor-si-verdadera si la condición es verdadera y ## $valor-si-falsa si es falsa. ## my $resultado = $valor condición ?? $valor-si-verdadera !! $valor-si-falsa; @@ -338,21 +338,21 @@ say $edad > 18 ?? "Eres un adulto" !! "Eres menor de 18"; ## ## `given` simplemente pone su argumento en `$_` (como un bloque lo haría), ## y `when` lo compara usando el operador de "coincidencia inteligente" (`~~`). -## +## ## Dado que otras construcciones de Perl 6 usan esta variable (por ejemplo, ## el bucle `for`, bloques, etc), esto se significa que el poderoso `when` no -## solo se aplica con un `given`, sino que se puede usar en cualquier +## solo se aplica con un `given`, sino que se puede usar en cualquier ## lugar donde exista una variable `$_`. given "foo bar" { say $_; #=> foo bar - when /foo/ { # No te preocupies acerca de la coincidencia inteligente – + when /foo/ { # No te preocupies acerca de la coincidencia inteligente – # solo ten presente que `when` la usa. # Esto es equivalente a `if $_ ~~ /foo/`. say "¡Yay!"; } when $_.chars > 50 { # coincidencia inteligente con cualquier cosa True es True, - # i.e. (`$a ~~ True`) + # i.e. (`$a ~~ True`) # por lo tanto puedes también poner condiciones "normales". # Este `when` es equivalente a este `if`: # if $_ ~~ ($_.chars > 50) {...} @@ -373,12 +373,12 @@ given "foo bar" { ## pero también puede ser un bucle for al estilo de C: loop { say "¡Este es un bucle infinito!"; - last; # last interrumpe el bucle, como la palabra clave `break` + last; # last interrumpe el bucle, como la palabra clave `break` # en otros lenguajes. } loop (my $i = 0; $i < 5; $i++) { - next if $i == 3; # `next` salta a la siguiente iteración, al igual + next if $i == 3; # `next` salta a la siguiente iteración, al igual # que `continue` en otros lenguajes. Ten en cuenta que # también puedes usar la condicionales postfix (sufijas) # bucles, etc. @@ -391,28 +391,28 @@ for @array -> $variable { } ## Como vimos con `given`, la variable de una "iteración actual" por defecto -## es `$_`. Esto significa que puedes usar `when` en un bucle `for` como +## es `$_`. Esto significa que puedes usar `when` en un bucle `for` como ## normalmente lo harías con `given`. for @array { say "he conseguido a $_"; .say; # Esto es también permitido. - # Una invocación con punto (dot call) sin "tópico" (recibidor) es - # enviada a `$_` por defecto. + # Una invocación con punto (dot call) sin "tópico" (recibidor) es + # enviada a `$_` por defecto. $_.say; # lo mismo de arriba, lo cual es equivalente. } for @array { # Puedes... - next if $_ == 3; # Saltar a la siguiente iteración (`continue` en + next if $_ == 3; # Saltar a la siguiente iteración (`continue` en # lenguages parecido a C) - redo if $_ == 4; # Re-hacer la iteración, manteniendo la + redo if $_ == 4; # Re-hacer la iteración, manteniendo la # misma variable tópica (`$_`) - last if $_ == 5; # Salir fuera del bucle (como `break` + last if $_ == 5; # Salir fuera del bucle (como `break` # en lenguages parecido a C) } -## La sintaxis de "bloque puntiagudo" no es específica al bucle for. +## La sintaxis de "bloque puntiagudo" no es específica al bucle for. ## Es solo una manera de expresar un bloque en Perl 6. if computación-larga() -> $resultado { say "El resultado es $resultado"; @@ -423,7 +423,7 @@ if computación-larga() -> $resultado { ```perl6 ## Dados que los lenguajes de la familia Perl son lenguages basados -## mayormente en operadores, los operadores de Perl 6 son actualmente +## mayormente en operadores, los operadores de Perl 6 son actualmente ## subrutinas un poco cómicas en las categorías sintácticas. Por ejemplo, ## infix:<+> (adición) o prefix: (bool not). @@ -455,7 +455,7 @@ if computación-larga() -> $resultado { (1, 2) eqv (1, 3); ## - Operador de coincidencia inteligente (smart matching): `~~` -## Asocia (aliasing en inglés) el lado izquierda a la variable $_ +## Asocia (aliasing en inglés) el lado izquierda a la variable $_ ## y después evalúa el lado derecho. ## Aquí algunas comparaciones semánticas comunes: @@ -464,8 +464,8 @@ if computación-larga() -> $resultado { 'Foo' ~~ 'Foo'; # True si las cadenas de texto son iguales. 12.5 ~~ 12.50; # True si los números son iguales. -## Regex - Para la comparación de una expresión regular en contra -## del lado izquierdo. Devuelve un objeto (Match), el cual evalúa +## Regex - Para la comparación de una expresión regular en contra +## del lado izquierdo. Devuelve un objeto (Match), el cual evalúa ## como True si el regex coincide con el patrón. my $obj = 'abc' ~~ /a/; @@ -475,12 +475,12 @@ say $obj.WHAT; # (Match) ## Hashes 'llave' ~~ %hash; # True si la llave existe en el hash -## Tipo - Chequea si el lado izquierdo "tiene un tipo" (puede chequear +## Tipo - Chequea si el lado izquierdo "tiene un tipo" (puede chequear ## superclases y roles) 1 ~~ Int; # True (1 es un número entero) -## Coincidencia inteligente contra un booleano siempre devuelve ese +## Coincidencia inteligente contra un booleano siempre devuelve ese ## booleano (y lanzará una advertencia). 1 ~~ True; # True @@ -502,7 +502,7 @@ False ~~ True; # True ## Esto también funciona como un atajo para `0..^N`: ^10; # significa 0..^10 -## Esto también nos permite demostrar que Perl 6 tiene arrays +## Esto también nos permite demostrar que Perl 6 tiene arrays ## ociosos/infinitos, usando la Whatever Star: my @array = 1..*; # 1 al Infinito! `1..Inf` es lo mismo. say @array[^10]; # puedes pasar arrays como subíndices y devolverá @@ -517,14 +517,14 @@ say @array[^10]; # puedes pasar arrays como subíndices y devolverá say join(' ', @array[15..*]); #=> 15 16 17 18 19 ## lo que es equivalente a: say join(' ', @array[-> $n { 15..$n }]); -## Nota: Si tratas de hacer cualquiera de esos con un array infinito, +## Nota: Si tratas de hacer cualquiera de esos con un array infinito, ## provocará un array infinito (tu programa nunca terminará) ## Puedes usar eso en los lugares que esperaría, como durante la asignación ## a un array my @números = ^20; -## Aquí los números son incrementados por "6"; más acerca del +## Aquí los números son incrementados por "6"; más acerca del ## operador `...` adelante. my @seq = 3, 9 ... * > 95; # 3 9 15 21 27 [...] 81 87 93 99; @números[5..*] = 3, 9 ... *; # aunque la secuencia es infinita, @@ -546,7 +546,7 @@ $a && $b && $c; # Devuelve 0, el primer valor que es False $b || $a; # 1 ## Y porque tu lo querrás, también tienes operadores de asignación -## compuestos: +## compuestos: $a *= 2; # multiplica y asigna. Equivalente a $a = $a * 2; $b %%= 5; # divisible por y asignación. Equivalente $b = $b %% 5; @array .= sort; # invoca el método `sort` y asigna el resultado devuelto. @@ -556,7 +556,7 @@ $b %%= 5; # divisible por y asignación. Equivalente $b = $b %% 5; ```perl6 ## Como dijimos anteriormente, Perl 6 tiene subrutinas realmente poderosas. -## Veremos unos conceptos claves que la hacen mejores que en cualquier otro +## Veremos unos conceptos claves que la hacen mejores que en cualquier otro ## lenguaje :-). ``` @@ -602,14 +602,14 @@ sub fst(*@ [$fst]) { # o simplemente: `sub fst($fst) { ... }` fst(1); #=> 1 fst(1, 2); # errores con "Too many positional parameters passed" -## También puedes desestructurar hashes (y clases, las cuales -## veremos adelante). La sintaxis es básicamente +## También puedes desestructurar hashes (y clases, las cuales +## veremos adelante). La sintaxis es básicamente ## `%nombre-del-hash (:llave($variable-para-almacenar))`. ## El hash puede permanecer anónimos si solo necesitas los valores extraídos. sub llave-de(% (:azul($val1), :red($val2))) { say "Valores: $val1, $val2."; } -## Después invócala con un hash: (necesitas mantener las llaves +## Después invócala con un hash: (necesitas mantener las llaves ## de los parejas de llave y valor para ser un hash) llave-de({azul => 'blue', rojo => "red"}); #llave-de(%hash); # lo mismo (para un `%hash` equivalente) @@ -621,11 +621,11 @@ sub siguiente-indice($n) { } my $nuevo-n= siguiente-indice(3); # $nuevo-n es ahora 4 -## Este es cierto para todo, excepto para las construcciones de bucles +## Este es cierto para todo, excepto para las construcciones de bucles ## (debido a razones de rendimiento): Hay una razón de construir una lista ## si la vamos a desechar todos los resultados. ## Si todavías quieres construir una, puedes usar la sentencia prefijo `do`: -## (o el prefijo `gather`, el cual veremos luego) +## (o el prefijo `gather`, el cual veremos luego) sub lista-de($n) { do for ^$n { # nota el uso del operador de rango `^` (`0..^N`) $_ # iteración de bucle actual @@ -639,19 +639,19 @@ my @list3 = lista-de(3); #=> (0, 1, 2) ```perl6 ## Puedes crear una lambda con `-> {}` ("bloque puntiagudo") o `{}` ("bloque") my &lambda = -> $argumento { "El argumento pasado a esta lambda es $argumento" } -## `-> {}` y `{}` son casi la misma cosa, excepto que la primerra puede +## `-> {}` y `{}` son casi la misma cosa, excepto que la primerra puede ## tomar argumentos, y la segunda puede ser malinterpretada como un hash ## por el parseador. ## Podemos, por ejemplo, agregar 3 a cada valor de un array usando map: my @arraymas3 = map({ $_ + 3 }, @array); # $_ es el argumento implícito -## Una subrutina (`sub {}`) tiene semánticas diferentes a un -## bloque (`{}` or `-> {}`): Un bloque no tiene "contexto funcional" +## Una subrutina (`sub {}`) tiene semánticas diferentes a un +## bloque (`{}` or `-> {}`): Un bloque no tiene "contexto funcional" ## (aunque puede tener argumentos), lo que significa que si quieres devolver ## algo desde un bloque, vas a returnar desde la función parental. Compara: sub is-in(@array, $elem) { - # esto `devolverá` desde la subrutina `is-in` + # esto `devolverá` desde la subrutina `is-in` # Una vez que la condición evalúa a True, el bucle terminará map({ return True if $_ == $elem }, @array); } @@ -685,7 +685,7 @@ map(sub ($a, $b) { $a + $b + 3 }, @array); # (aquí con `sub`) ### Acerca de tipos... ```perl6 -## Perl 6 es gradualmente tipado. Esto quiere decir que tu especifica el +## Perl 6 es gradualmente tipado. Esto quiere decir que tu especifica el ## tipo de tus variables/argumentos/devoluciones (return), o puedes omitirlos ## y serán "Any" por defecto. ## Obviamente tienes acceso a algunas tipos básicos, como Int y Str. @@ -703,7 +703,7 @@ subset EnteroGrande of Int where * > 500; ### Despacho Múltiple (Multiple Dispatch) ```perl6 -## Perl 6 puede decidir que variante de una subrutina invocar basado en el +## Perl 6 puede decidir que variante de una subrutina invocar basado en el ## tipo de los argumento, o precondiciones arbitrarias, como con un tipo o ## un `where`: @@ -740,9 +740,9 @@ multi sin_ti-o-contigo { } ## Esto es muy útil para muchos propósitos, como subrutinas `MAIN` (de las ## cuales hablaremos luego), y hasta el mismo lenguaje la está usando -## en muchos lugares. +## en muchos lugares. ## -## - `is`, por ejemplo, es actualmente un `multi sub` llamado +## - `is`, por ejemplo, es actualmente un `multi sub` llamado ## `trait_mod:`. ## - `is rw`, es simplemente un despacho a una función con esta signatura: ## sub trait_mod:(Routine $r, :$rw!) {} @@ -770,7 +770,7 @@ sub externo { } outer()(); #=> 'Foo Bar' -## Como puedes ver, `$archivo-en-ámbito` y `$ámbito-externo` +## Como puedes ver, `$archivo-en-ámbito` y `$ámbito-externo` ## fueron capturados. Pero si intentaramos usar `$bar` fuera de `foo`, ## la variable estaría indefinida (y obtendrías un error al tiempo de ## compilación). @@ -779,8 +779,8 @@ outer()(); #=> 'Foo Bar' ## Twigils ```perl6 -## Hay muchos `twigils` especiales (sigilos compuestos) en Perl 6. -## Los twigils definen el ámbito de las variables. +## Hay muchos `twigils` especiales (sigilos compuestos) en Perl 6. +## Los twigils definen el ámbito de las variables. ## Los twigils * y ? funcionan con variables regulares: ## * Variable dinámica ## ? Variable al tiempo de compilación @@ -820,20 +820,20 @@ di_ambito(); #=> 1 100 Cambiamos el valor de $*ambito_din_2 en invoca_a_di_ambit ```perl6 ## Para invocar a un método en un objeto, agrega un punto seguido por el -## nombre del objeto: +## nombre del objeto: ## => $object.method ## Las classes son declaradas usando la palabra clave `class`. Los atributos ## son declarados con la palabra clave `has`, y los métodos con `method`. ## Cada atributo que es privado usa el twigil `!`. Por ejemplo: `$!attr`. -## Atributos públicos inmutables usan el twigil `.` (los puedes hacer +## Atributos públicos inmutables usan el twigil `.` (los puedes hacer ## mutables con `is rw`). -## La manera más fácil de recordar el twigil `$.` is comparándolo +## La manera más fácil de recordar el twigil `$.` is comparándolo ## con como los métodos son llamados. ## El modelo de objeto de Perl 6 ("SixModel") es muy flexible, y te permite ## agregar métodos dinámicamente, cambiar la semántica, etc ... -## (no hablaremos de todo esto aquí. Por lo tanto, refiérete a: -## https://docs.perl6.org/language/objects.html). +## (no hablaremos de todo esto aquí. Por lo tanto, refiérete a: +## https://docs.raku.org/language/objects.html). class Clase-Atrib { has $.atrib; # `$.atrib` es inmutable. @@ -858,7 +858,7 @@ class Clase-Atrib { }; ## Crear una nueva instancia de Clase-Atrib con $.atrib asignado con 5: -## Nota: No puedes asignarle un valor a atrib-privado desde aquí (más de +## Nota: No puedes asignarle un valor a atrib-privado desde aquí (más de ## esto adelante). my $class-obj = Clase-Atrib.new(atrib => 5); say $class-obj.devolver-valor; #=> 5 @@ -875,7 +875,7 @@ $class-obj.otro-atrib = 10; # En cambio, esto funciona porque el atributo ## declarados con `submethod` no lo son. ## Submétodos son útiles para la construcción y destrucción de tareas, ## tales como BUILD, o métodos que deben ser anulados por subtipos. -## Aprenderemos acerca de BUILD más adelante. +## Aprenderemos acerca de BUILD más adelante. class Padre { has $.edad; @@ -890,7 +890,7 @@ class Padre { # Herencia usa la palabra clave `is` class Niño is Padre { method hablar { say "Goo goo ga ga" } - # Este método opaca el método `hablar` de Padre. + # Este método opaca el método `hablar` de Padre. # Este niño no ha aprendido a hablar todavía. } my Padre $Richard .= new(edad => 40, nombre => 'Richard'); @@ -899,19 +899,19 @@ $Richard.hablar; #=> "Hola, mi nombre es Richard" ## $Richard es capaz de acceder el submétodo; él sabe como decir su nombre. my Niño $Madison .= new(edad => 1, nombre => 'Madison'); -$Madison.hablar; # imprime "Goo goo ga ga" dado que el método fue cambiado +$Madison.hablar; # imprime "Goo goo ga ga" dado que el método fue cambiado # en la clase Niño. # $Madison.color-favorito # no funciona porque no es heredado ## Cuando se usa `my T $var` (donde `T` es el nombre de la clase), `$var` ## inicia con `T` en si misma, por lo tanto puedes invocar `new` en `$var`. -## (`.=` es sólo la invocación por punto y el operador de asignación: +## (`.=` es sólo la invocación por punto y el operador de asignación: ## `$a .= b` es lo mismo que `$a = $a.b`) ## Por ejemplo, la instancia $Richard pudo también haber sido declarada así: ## my $Richard = Padre.new(edad => 40, nombre => 'Richard'); -## También observa que `BUILD` (el método invocado dentro de `new`) -## asignará propiedades de la clase padre, por lo que puedes pasar +## También observa que `BUILD` (el método invocado dentro de `new`) +## asignará propiedades de la clase padre, por lo que puedes pasar ## `val => 5`. ``` @@ -932,7 +932,7 @@ class Item does PrintableVal { has $.val; ## Cuando se utiliza `does`, un `rol` se mezcla en al clase literalmente: - ## los métodos y atributos se ponen juntos, lo que significa que una clase + ## los métodos y atributos se ponen juntos, lo que significa que una clase ## puede acceder los métodos y atributos privados de su rol (pero no lo inverso!): method access { say $!counter++; @@ -945,15 +945,15 @@ class Item does PrintableVal { ## de su clase hijo/a, pero es un error sin un rol lo hace) ## NOTA: Puedes usar un rol como una clase (con `is ROLE`). En este caso, - ## métodos serán opacados, dado que el compilador considerará `ROLE` - ## como una clase. + ## métodos serán opacados, dado que el compilador considerará `ROLE` + ## como una clase. } ``` ## Excepciones ```perl6 -## Excepciones están construidas al tope de las clases, en el paquete +## Excepciones están construidas al tope de las clases, en el paquete ## `X` (como `X::IO`). ## En Perl 6, excepciones son lanzadas automáticamente. open 'foo'; #=> Failed to open file foo: no such file or directory @@ -969,13 +969,13 @@ die X::AdHoc.new(payload => 'Error!'); ## En Perl 6, `orelse` es similar al operador `or`, excepto que solamente ## coincide con variables indefinidas, en cambio de cualquier cosa ## que evalúa a falso. -## Valores indefinidos incluyen: `Nil`, `Mu` y `Failure`, también como +## Valores indefinidos incluyen: `Nil`, `Mu` y `Failure`, también como ## `Int`, `Str` y otros tipos que no han sido inicializados a ningún valor ## todavía. ## Puedes chequear si algo está definido o no usando el método defined: my $no-inicializada; say $no-inicializada.defined; #=> False -## Al usar `orelse`, se desarmará la excepción y creará un alias de dicho +## Al usar `orelse`, se desarmará la excepción y creará un alias de dicho ## fallo en $_ ## Esto evitará que sea automáticamente manejado e imprima una marejada de ## mensajes de errores en la pantalla. @@ -986,7 +986,7 @@ open 'foo' orelse say "Algo pasó {.exception}"; open 'foo' orelse say "Algo pasó $_"; #=> Algo pasó #=> Failed to open file foo: no such file or directory ## Ambos ejemplos anteriores funcionan pero en caso de que consigamos un -## objeto desde el lado izquierdo que no es un fallo, probablemente +## objeto desde el lado izquierdo que no es un fallo, probablemente ## obtendremos una advertencia. Más abajo vemos como usar `try` y `CATCH` ## para ser más expecíficos con las excepciones que capturamos. ``` @@ -994,8 +994,8 @@ open 'foo' orelse say "Algo pasó $_"; #=> Algo pasó ### Usando `try` y `CATCH` ```perl6 -## Al usar `try` y `CATCH`, puedes contener y manejar excepciones sin -## interrumpir el resto del programa. `try` asignará la última excepción +## Al usar `try` y `CATCH`, puedes contener y manejar excepciones sin +## interrumpir el resto del programa. `try` asignará la última excepción ## a la variable especial `$!`. ## Nota: Esto no tiene ninguna relación con las variables $!. @@ -1008,7 +1008,7 @@ say "Bueno, lo intenté! $!" if defined $!; #=> Bueno, lo intenté! Failed to op ## cuando 'disarmamos' la excepción con `orelse`, también usamos $_ en el ## bloque CATCH. ## Nota: ($! es solo asignada *después* del bloque `try`) -## Por defecto, un bloque `try` tiene un bloque `CATCH` que captura +## Por defecto, un bloque `try` tiene un bloque `CATCH` que captura ## cualquier excepción (`CATCH { default {} }`). try { my $a = (0 %% 0); CATCH { say "Algo pasó: $_" } } @@ -1022,9 +1022,9 @@ try { when X::AdHoc { say "Error: $_" } #=>Error: Failed to open file /dir/foo: no such file or directory - ## Cualquier otra excepción será levantada de nuevo, dado que no + ## Cualquier otra excepción será levantada de nuevo, dado que no ## tenemos un `default`. - ## Básicamente, si un `when` + ## Básicamente, si un `when` ## Basically, if a `when` matches (or there's a `default`) marks the ## exception as ## "handled" so that it doesn't get re-thrown from the `CATCH`. @@ -1032,14 +1032,14 @@ try { } } -## En Perl 6, excepciones poseen ciertas sutilezas. Algunas -## subrutinas en Perl 6 devuelven un `Failure`, el cual es un tipo de +## En Perl 6, excepciones poseen ciertas sutilezas. Algunas +## subrutinas en Perl 6 devuelven un `Failure`, el cual es un tipo de ## "excepción no levantada". Ellas no son levantadas hasta que tu intentas -## mirar a sus contenidos, a menos que invoques `.Bool`/`.defined` sobre +## mirar a sus contenidos, a menos que invoques `.Bool`/`.defined` sobre ## ellas - entonces, son manejadas. ## (el método `.handled` es `rw`, por lo que puedes marcarlo como `False` ## por ti mismo) -## Puedes levantar un `Failure` usando `fail`. Nota que si el pragma +## Puedes levantar un `Failure` usando `fail`. Nota que si el pragma ## `use fatal` estás siendo utilizado, `fail` levantará una excepión (como ## `die`). fail "foo"; # No estamos intentando acceder el valor, por lo tanto no problema. @@ -1053,27 +1053,27 @@ try { ## También hay otro tipo de excepción: Excepciones de control. ## Esas son excepciones "buenas", las cuales suceden cuando cambias el flujo ## de tu programa, usando operadores como `return`, `next` or `last`. -## Puedes capturarlas con `CONTROL` (no lista un 100% en Rakudo todavía). +## Puedes capturarlas con `CONTROL` (no lista un 100% en Rakudo todavía). ``` ## Paquetes ```perl6 -## Paquetes son una manera de reusar código. Paquetes son como -## "espacio de nombres" (namespaces en inglés), y cualquier elemento del +## Paquetes son una manera de reusar código. Paquetes son como +## "espacio de nombres" (namespaces en inglés), y cualquier elemento del ## modelo seis (`module`, `role`, `class`, `grammar`, `subset` y `enum`) -## son paquetes por ellos mismos. (Los paquetes son como el mínimo común +## son paquetes por ellos mismos. (Los paquetes son como el mínimo común ## denominador) -## Los paquetes son importantes - especialmente dado que Perl es bien +## Los paquetes son importantes - especialmente dado que Perl es bien ## reconocido por CPAN, the Comprehensive Perl Archive Nertwork. ## Puedes usar un módulo (traer sus declaraciones al ámbito) con `use` use JSON::Tiny; # si intalaste Rakudo* o Panda, tendrás este módulo say from-json('[1]').perl; #=> [1] -## A diferencia de Perl 5, no deberías declarar paquetes usando +## A diferencia de Perl, no deberías declarar paquetes usando ## la palabra clave `package`. En vez, usa `class Nombre::Paquete::Aquí;` -## para declarar una clase, o si solamente quieres exportar +## para declarar una clase, o si solamente quieres exportar ## variables/subrutinas, puedes usar `module`. module Hello::World { # forma de llaves @@ -1083,11 +1083,11 @@ module Hello::World { # forma de llaves } unit module Parse::Text; # forma de ámbito de archivo -grammar Parse::Text::Grammar { # Una gramática (grammar en inglés) es un paquete, +grammar Parse::Text::Grammar { # Una gramática (grammar en inglés) es un paquete, # en el cual puedes usar `use` } # Aprenderás más acerca de gramáticas en la sección de regex -## Como se dijo anteriormente, cualquier parte del modelo seis es también un +## Como se dijo anteriormente, cualquier parte del modelo seis es también un ## paquete. Dado que `JSON::Tiny` usa su propia clase `JSON::Tiny::Actions`, ## tu puedes usarla de la manera siguiente: my $acciones = JSON::Tiny::Actions.new; @@ -1104,7 +1104,7 @@ my $acciones = JSON::Tiny::Actions.new; ## * las declaraciones `our` ocurren al tiempo `INIT` (ve "Phasers" más abajo) ## Es como `my`, pero también crea una variable paquete. -## (Todas las cosas relacionadas con paquetes (`class`, `role`, etc) son +## (Todas las cosas relacionadas con paquetes (`class`, `role`, etc) son ## `our` por defecto) module Var::Incrementar { our $nuestra-var = 1; # Nota: No puedes colocar una restricción de tipo @@ -1132,7 +1132,7 @@ Var::Incrementar::Inc; #=> 3 # Nota como el valor de $nuestra-var fue Var::Incrementar::no-disponible; #=> Could not find symbol '&no-disponible' ## * `constant` (ocurre al tiempo `BEGIN`) -## Puedes usar la palabra clave `constant` para declarar una +## Puedes usar la palabra clave `constant` para declarar una ## variable/símbolo al tiempo de compilación: constant Pi = 3.14; constant $var = 1; @@ -1151,11 +1151,11 @@ sub aleatorio-fijo { aleatorio-fijo for ^10; # imprimirá el mismo número 10 veces ## Nota, sin embargo, que ellas existen separadamente en diferentes contextos. -## Si declaras una función con un `state` dentro de un bucle, recreará la +## Si declaras una función con un `state` dentro de un bucle, recreará la ## variable por cada iteración del bucle. Observa: for ^5 -> $a { sub foo { - state $valor = rand; # Esto imprimirá un valor diferente + state $valor = rand; # Esto imprimirá un valor diferente # por cada valor de `$a` } for ^5 -> $b { @@ -1165,11 +1165,11 @@ for ^5 -> $a { } ``` -## Phasers +## Phasers ```perl6 ## Un phaser en Perl 6 es un bloque que ocurre a determinados puntos de tiempo -## en tu programa. Se les llama phaser porque marca un cambio en la fase de +## en tu programa. Se les llama phaser porque marca un cambio en la fase de ## de tu programa. Por ejemplo, cuando el programa es compilado, un bucle ## for se ejecuta, dejas un bloque, o una excepción se levanta. ## (¡`CATCH` es actualmente un phaser!) @@ -1191,13 +1191,13 @@ END { say "Se ejecuta al tiempo de ejecución, " ~ "tan tarde como sea posible, una sola vez" } ## * Phasers de bloques -ENTER { say "[*] Se ejecuta cada vez que entra en un bloque, " ~ +ENTER { say "[*] Se ejecuta cada vez que entra en un bloque, " ~ "se repite en bloques de bucle" } -LEAVE { say "Se ejecuta cada vez que abandona un bloque, incluyendo " ~ +LEAVE { say "Se ejecuta cada vez que abandona un bloque, incluyendo " ~ "cuando una excepción ocurre. Se repite en bloques de bucle"} PRE { - say "Impone una precondición a cada entrada de un bloque, " ~ + say "Impone una precondición a cada entrada de un bloque, " ~ "antes que ENTER (especialmente útil para bucles)"; say "Si este bloque no returna un valor truthy, " ~ "una excepción del tipo X::Phaser::PrePost será levantada."; @@ -1209,7 +1209,7 @@ for 0..2 { } POST { - say "Impone una postcondAsserts a poscondición a la salida de un bloque, " ~ + say "Impone una postcondAsserts a poscondición a la salida de un bloque, " ~ "después de LEAVE (especialmente útil para bucles)"; say "Si este bloque no returna un valor truthy, " ~ "una excepción del tipo X::Phaser::PrePost será levantada, como con PRE."; @@ -1250,14 +1250,14 @@ sub do-db-stuff { ## Prefijos de sentencias ```perl6 -## Los prefijos de sentencias actúan como los phasers: Ellos afectan el +## Los prefijos de sentencias actúan como los phasers: Ellos afectan el ## comportamiento del siguiente código. ## Debido a que son ejecutados en línea con el código ejecutable, ellos ## se escriben en letras minúsculas. (`try` and `start` están teoréticamente ## en esa lista, pero serán explicados en otra parte) ## Nota: Ningunos de estos (excepto `start`) necesitan las llaves `{` y `}`. -## - `do` (el cual ya viste) - ejecuta un bloque o una sentencia como un +## - `do` (el cual ya viste) - ejecuta un bloque o una sentencia como un ## término. ## Normalmente no puedes usar una sentencia como un valor (o término): ## @@ -1289,7 +1289,7 @@ say join ',', gather if False { ## - `eager` - Evalúa una sentencia ávidamente (forza contexto ávido) ## No intentes esto en casa: ## -## eager 1..*; # esto probablemente se colgará por un momento +## eager 1..*; # esto probablemente se colgará por un momento ## # (y podría fallar...). ## ## Pero considera lo siguiente: @@ -1302,13 +1302,13 @@ constant tres-veces = eager gather for ^3 { say take $_ }; #=> 0 1 2 ## Iterables ```perl6 -## En Perl 6, los iterables son objetos que pueden ser iterados similar -## a la construcción `for`. +## En Perl 6, los iterables son objetos que pueden ser iterados similar +## a la construcción `for`. ## `flat`, aplana iterables: say (1, 10, (20, 10) ); #=> (1 10 (20 10)) Nota como la agrupación se mantiene say (1, 10, (20, 10) ).flat; #=> (1 10 20 10) Ahora el iterable es plano -## - `lazy` - Aplaza la evaluación actual hasta que el valor sea requirido +## - `lazy` - Aplaza la evaluación actual hasta que el valor sea requirido ## (forza contexto perezoso) my @lazy-array = (1..100).lazy; say @lazy-array.is-lazy; #=> True # Chequea por "pereza" con el método `is-lazy`. @@ -1333,7 +1333,7 @@ quietly { warn 'Esto es una advertencia!' }; #=> No salida ## ¡Todo el mundo ama los operadores! Tengamos más de ellos. ## La lista de precedencia puede ser encontrada aquí: -## https://docs.perl6.org/language/operators#Operator_Precedence +## https://docs.raku.org/language/operators#Operator_Precedence ## Pero primero, necesitamos un poco de explicación acerca ## de la asociatividad: @@ -1374,14 +1374,14 @@ sub postfix:(Int $n) { } say 5!; #=> 120 # Operadores sufijos (postfix) van *directamente* después del témino. - # No espacios en blanco. Puedes usar paréntesis para disambiguar, + # No espacios en blanco. Puedes usar paréntesis para disambiguar, # i.e. `(5!)!` sub infix:(Int $n, Block $r) { # infijo va en el medio for ^$n { $r(); # Necesitas los paréntesis explícitos para invocar la función - # almacenada en la variable `$r`. De lo contrario, te estaría + # almacenada en la variable `$r`. De lo contrario, te estaría # refiriendo a la variable (no a la función), como con `&r`. } } @@ -1399,7 +1399,7 @@ say [5]; #=> 3125 # un circunfijo va alrededor. De nuevo, no espacios en blanco. sub postcircumfix:<{ }>(Str $s, Int $idx) { - ## un pos-circunfijo es + ## un pos-circunfijo es ## "después de un término y alrededor de algo" $s.substr($idx, 1); } @@ -1411,21 +1411,21 @@ say "abc"{1}; #=> b ## `:delete` (un simple argumento con nombre debajo): %h{$llave}:delete; ## es equivalente a: -postcircumfix:<{ }>(%h, $llave, :delete); # (puedes invocar +postcircumfix:<{ }>(%h, $llave, :delete); # (puedes invocar # operadores de esta forma) -## ¡*Todos* usan los mismos bloques básicos! +## ¡*Todos* usan los mismos bloques básicos! ## Categorías sintácticas (prefix, infix, ...), argumentos nombrados ## (adverbios), ... - usados para construir el lenguaje - están al alcance ## de tus manos y disponibles para ti. -## (obviamente, no se te recomienda que hagas un operador de *cualquier +## (obviamente, no se te recomienda que hagas un operador de *cualquier ## cosa* -- Un gran poder conlleva una gran responsabilidad.) ``` ### Meta-operadores! ```perl6 -## ¡Prepárate! Prepárate porque nos estamos metiendo bien hondo -## en el agujero del conejo, y probablemente no querrás regresar a +## ¡Prepárate! Prepárate porque nos estamos metiendo bien hondo +## en el agujero del conejo, y probablemente no querrás regresar a ## otros lenguajes después de leer esto. ## (Me imagino que ya no quieres a este punto). ## Meta-operadores, como su nombre lo sugiere, son operadores *compuestos*. @@ -1434,14 +1434,14 @@ postcircumfix:<{ }>(%h, $llave, :delete); # (puedes invocar ## * El meta-operador reduce (reducir) ## Es un meta-operador prefijo que toman una función binaria y ## una o varias listas. Sino se pasa ningún argumento, -## returna un "valor por defecto" para este operador +## returna un "valor por defecto" para este operador ## (un valor sin significado) o `Any` si no hay ningún valor. ## -## De lo contrario, remueve un elemento de la(s) lista(s) uno a uno, y +## De lo contrario, remueve un elemento de la(s) lista(s) uno a uno, y ## aplica la función binaria al último resultado (o al primer elemento de ## la lista y el elemento que ha sido removido). ## -## Para sumar una lista, podrías usar el meta-operador "reduce" con `+`, +## Para sumar una lista, podrías usar el meta-operador "reduce" con `+`, ## i.e.: say [+] 1, 2, 3; #=> 6 ## es equivalente a `(1+2)+3` @@ -1461,20 +1461,20 @@ say [+] (); #=> 0 # valores sin significado, dado que N*1=N y N+0=N. say [//]; #=> (Any) # No hay valor por defecto para `//`. -## También puedes invocarlo con una función de tu creación usando +## También puedes invocarlo con una función de tu creación usando ## los dobles corchetes: sub add($a, $b) { $a + $b } say [[&add]] 1, 2, 3; #=> 6 ## * El meta-operador zip -## Este es un meta-operador infijo que también puede ser usado como un +## Este es un meta-operador infijo que también puede ser usado como un ## operador "normal". Toma una función binaria opcional (por defecto, solo -## crear un par), y remueve un valor de cada array e invoca su función +## crear un par), y remueve un valor de cada array e invoca su función ## binaria hasta que no tenga más elementos disponibles. Al final, returna ## un array con todos estos nuevos elementos. -(1, 2) Z (3, 4); # ((1, 3), (2, 4)), dado que por defecto, la función +(1, 2) Z (3, 4); # ((1, 3), (2, 4)), dado que por defecto, la función # crea un array. -1..3 Z+ 4..6; # (5, 7, 9), usando la función personalizada infix:<+> +1..3 Z+ 4..6; # (5, 7, 9), usando la función personalizada infix:<+> ## Dado que `Z` tiene asociatividad de lista (ve la lista más arriba), ## puedes usarlo en más de una lista @@ -1487,10 +1487,10 @@ say [[&add]] 1, 2, 3; #=> 6 ## Y para terminar la lista de operadores: ## * El operador secuencia -## El operador secuencia es uno de la más poderosas características de +## El operador secuencia es uno de la más poderosas características de ## Perl 6: Está compuesto, en la izquierda, de la lista que quieres que ## Perl 6 use para deducir (y podría incluir una clausura), y en la derecha, -## un valor o el predicado que dice cuando parar (o Whatever para una +## un valor o el predicado que dice cuando parar (o Whatever para una ## lista infinita perezosa). my @list = 1, 2, 3 ... 10; # deducción básica #my @list = 1, 3, 6 ... 10; # esto muere porque Perl 6 no puede deducir el final @@ -1505,8 +1505,8 @@ my @fib = 1, 1, *+* ... *; # lista infinita perezosa de la serie fibonacci, my @fib = 1, 1, -> $a, $b { $a + $b } ... *; # (equivalene a lo de arriba) my @fib = 1, 1, { $^a + $^b } ... *; #(... también equivalene a lo de arriba) ## $a and $b siempre tomarán el valor anterior, queriendo decir que -## ellos comenzarán con $a = 1 y $b = 1 (valores que hemos asignado -## de antemano). Por lo tanto, $a = 1 y $b = 2 (resultado del anterior $a+$b), +## ellos comenzarán con $a = 1 y $b = 1 (valores que hemos asignado +## de antemano). Por lo tanto, $a = 1 y $b = 2 (resultado del anterior $a+$b), ## etc. say @fib[^10]; #=> 1 1 2 3 5 8 13 21 34 55 @@ -1519,29 +1519,29 @@ say @fib[^10]; #=> 1 1 2 3 5 8 13 21 34 55 ## Expresiones Regulares ```perl6 -## Estoy seguro que has estado esperando por esta parte. Bien, ahora que -## sabes algo acerca de Perl 6, podemos comenzar. Primeramente, tendrás -## que olvidarte acerca de "PCRE regexps" (perl-compatible regexps) +## Estoy seguro que has estado esperando por esta parte. Bien, ahora que +## sabes algo acerca de Perl 6, podemos comenzar. Primeramente, tendrás +## que olvidarte acerca de "PCRE regexps" (perl-compatible regexps) ## (expresiones regulares compatible de perl). ## ## IMPORTANTE: No salte esto porque ya sabes acerca de PCRE. Son totalmente -## distintos. Algunas cosas son las mismas (como `?`, `+`, y `*`) pero +## distintos. Algunas cosas son las mismas (como `?`, `+`, y `*`) pero ## algunas veces la semántica cambia (`|`). Asegúrate de leer esto ## cuidadosamente porque podrías trospezarte sino lo haces. ## ## Perl 6 tiene muchas características relacionadas con RegExps. Después de ## todo, Rakudo se parsea a si mismo. Primero vamos a estudiar la sintaxis ## por si misma, después hablaremos acerca de gramáticas (parecido a PEG), -## las diferencias entre los declaradores `token`, `regex`, y `rule` y +## las diferencias entre los declaradores `token`, `regex`, y `rule` y ## mucho más. -## Nota aparte: Todavía tienes acceso a los regexes PCRE usando el +## Nota aparte: Todavía tienes acceso a los regexes PCRE usando el ## mofificador `:P5` (Sin embargo, no lo discutiremos en este tutorial). ## ## En esencia, Perl 6 implementa PEG ("Parsing Expression Grammars") ## ("Parseado de Expresiones de Gramáticas") nativamente. El orden jerárquico -## para los parseos ambiguos es determinado por un examen multi-nivel de +## para los parseos ambiguos es determinado por un examen multi-nivel de ## desempate: -## - La coincidencia de token más larga. `foo\s+` le gana a `foo` +## - La coincidencia de token más larga. `foo\s+` le gana a `foo` ## (por 2 o más posiciones) ## - El prefijo literal más largo. `food\w*` le gana a `foo\w*` (por 1) ## - Declaración desde la gramática más derivada a la menos derivada @@ -1550,36 +1550,36 @@ say @fib[^10]; #=> 1 1 2 3 5 8 13 21 34 55 say so 'a' ~~ /a/; #=> True say so 'a' ~~ / a /; #=> True # ¡Más legible con los espacios! -## Nota al lector (del traductor): +## Nota al lector (del traductor): ## Como pudiste haber notado, he decidido traducir "match" y sus diferentes -## formas verbales como "coincidir" y sus diferentes formas. Cuando digo que +## formas verbales como "coincidir" y sus diferentes formas. Cuando digo que ## un regex (o regexp) coincide con cierto texto, me refiero a que el regex ## describe cierto patrón dentro del texto. Por ejemplo, el regex "cencia" -## coincide con el texto "reminiscencia", lo que significa que dentro del +## coincide con el texto "reminiscencia", lo que significa que dentro del ## texto aparece ese patrón de caracteres (una `c`, seguida de una `e`, -## (seguida de una `n`, etc.) +## (seguida de una `n`, etc.) -## En todos nuestros ejemplos, vamos a usar el operador de -## "coincidencia inteligente" contra una expresión regular ("regexp" or +## En todos nuestros ejemplos, vamos a usar el operador de +## "coincidencia inteligente" contra una expresión regular ("regexp" or ## "regex" de aquí en adelante). Estamos convirtiendo el resultado usando `so`, ## pero en efecto, está devolviendo un objeto Match. Ellos saben como responder -## a la indexación de lista, indexación de hash, y devolver la cadena de +## a la indexación de lista, indexación de hash, y devolver la cadena de ## texto coincidente. -## Los resultados de la coincidencia están disponible como `$/` (en +## Los resultados de la coincidencia están disponible como `$/` (en ## ámbito implícito lexical). También puedes usar las variables de captura ## las cuales comienzan con 0: ## `$0`, `$1', `$2`... ## -## Nota que `~~` no hace un chequeo de inicio/final (es decir, +## Nota que `~~` no hace un chequeo de inicio/final (es decir, ## el regexp puede coincider con solo un carácter de la cadena de texto). ## Explicaremos luego como hacerlo. ## En Perl 6, puedes tener un carácter alfanumérico como un literal, ## todo lo demás debe escaparse usando una barra invertida o comillas. -say so 'a|b' ~~ / a '|' b /; # `True`. No sería lo mismo si no se escapara `|` +say so 'a|b' ~~ / a '|' b /; # `True`. No sería lo mismo si no se escapara `|` say so 'a|b' ~~ / a \| b /; # `True`. Otra forma de escaparlo -## El espacio en blanco actualmente no se significa nada en un regexp, +## El espacio en blanco actualmente no se significa nada en un regexp, ## a menos que uses el adverbio `:s` (`:sigspace`, espacio significante). say so 'a b c' ~~ / a b c /; #=> `False`. Espacio no significa nada aquí. say so 'a b c' ~~ /:s a b c /; #=> `True`. Agregamos el modificador `:s` aquí. @@ -1587,11 +1587,11 @@ say so 'a b c' ~~ /:s a b c /; #=> `True`. Agregamos el modificador `:s` aquí. ## nos advertirá: say so 'a b c' ~~ / a b c /; #=> 'False' # Espacio no significa nada aquí. ## Por favor usa comillas o el modificador :s (:sigspace) para suprimir -## esta advertencia, omitir el espacio, o cambiar el espaciamiento. Para -## arreglar esto y hacer los espacios menos ambiguos, usa por lo menos +## esta advertencia, omitir el espacio, o cambiar el espaciamiento. Para +## arreglar esto y hacer los espacios menos ambiguos, usa por lo menos ## dos espacios entre las cadenas de texto o usa el adverbio `:s`. -## Como vimos anteriormente, podemos incorporar `:s` dentro de los +## Como vimos anteriormente, podemos incorporar `:s` dentro de los ## delimitadores de barras. También podemos ponerlos fuera de ellos si ## especificamos `m` for `match` (coincidencia): say so 'a b c' ~~ m:s/a b c/; #=> `True` @@ -1603,7 +1603,7 @@ say so 'abc' ~~ m[a b c]; #=> `True` ## minúsculas y mayúsculas: say so 'ABC' ~~ m:i{a b c}; #=> `True` -## Sin embargo, es importante para como los modificadores son aplicados +## Sin embargo, es importante para como los modificadores son aplicados ## (lo cual verás más abajo)... ## Cuantificando - `?`, `+`, `*` y `**`. @@ -1612,7 +1612,7 @@ so 'ac' ~~ / a b c /; # `False` so 'ac' ~~ / a b? c /; # `True`, la "b" coincidió (apareció) 0 veces. so 'abc' ~~ / a b? c /; # `True`, la "b" coincidió 1 vez. -## ... Como debes saber, espacio en blancos son importante porque +## ... Como debes saber, espacio en blancos son importante porque ## determinan en que parte del regexp es el objetivo del modificador: so 'def' ~~ / a b c? /; # `False`. Solamente la `c` es opcional so 'def' ~~ / a b? c /; # `False`. Espacio en blanco no es significante @@ -1663,7 +1663,7 @@ so 'foo' ~~ / <-[ f o ]> + /; # False ## ... y componerlos: so 'foo' ~~ / <[ a..z ] - [ f o ]> + /; # False (cualquier letra excepto f y o) so 'foo' ~~ / <-[ a..z ] + [ f o ]> + /; # True (no letra excepto f and o) -so 'foo!' ~~ / <-[ a..z ] + [ f o ]> + /; # True (el signo + no reemplaza la +so 'foo!' ~~ / <-[ a..z ] + [ f o ]> + /; # True (el signo + no reemplaza la # parte de la izquierda) ``` @@ -1671,7 +1671,7 @@ so 'foo!' ~~ / <-[ a..z ] + [ f o ]> + /; # True (el signo + no reemplaza la ```perl6 ## Grupo: Puedes agrupar partes de tu regexp con `[]`. -## Estos grupos *no son* capturados (como con `(?:)` en PCRE). +## Estos grupos *no son* capturados (como con `(?:)` en PCRE). so 'abc' ~~ / a [ b ] c /; # `True`. El agrupamiento no hace casi nada so 'foo012012bar' ~~ / foo [ '01' <[0..9]> ] + bar /; ## La línea anterior returna `True`. @@ -1680,15 +1680,15 @@ so 'foo012012bar' ~~ / foo [ '01' <[0..9]> ] + bar /; ## Pero esto no va demasiado lejos, porque no podemos actualmente obtener ## devuelta el patrón que coincidió. -## Captura: Podemos actualmente *capturar* los resultados del regexp, +## Captura: Podemos actualmente *capturar* los resultados del regexp, ## usando paréntesis. so 'fooABCABCbar' ~~ / foo ( 'A' <[A..Z]> 'C' ) + bar /; # `True`. (usando `so` # aquí, `$/` más abajo) -## Ok. Comenzando con las explicaciones de grupos. Como dijimos, +## Ok. Comenzando con las explicaciones de grupos. Como dijimos, ### nuestra objeto `Match` está disponible en la variable `$/`: -say $/; # Imprimirá algo extraño (explicaremos luego) o - # "Nil" si nada coincidió +say $/; # Imprimirá algo extraño (explicaremos luego) o + # "Nil" si nada coincidió ## Como dijimos anteriormente, un objeto Match tiene indexación de array: say $/[0]; #=> 「ABC」 「ABC」 @@ -1696,15 +1696,15 @@ say $/[0]; #=> 「ABC」 「ABC」 # Aquí, tenemos un array de ellos. say $0; # Lo mismo que lo anterior. -## Nuestra captura es `$0` porque es la primera y única captura en el -## regexp. Podrías estarte preguntando porque un array y la respuesta es +## Nuestra captura es `$0` porque es la primera y única captura en el +## regexp. Podrías estarte preguntando porque un array y la respuesta es ## simple: Algunas capturas (indezadas usando `$0`, `$/[0]` o una nombrada) ## será un array si y solo si puedes tener más de un elemento. ## (Así que, con `*`, `+` y `**` (cualquiera los operandos), pero no con `?`). ## Usemos algunos ejemplos para ver como funciona: ## Nota: Pusimos A B C entre comillas para demostrar que el espacio en blanco -## entre ellos no es significante. Si queremos que el espacio en blanco +## entre ellos no es significante. Si queremos que el espacio en blanco ## *sea* significante, podemos utilizar el modificador `:sigspace`. so 'fooABCbar' ~~ / foo ( "A" "B" "C" )? bar /; # `True` say $/[0]; #=> 「ABC」 @@ -1718,22 +1718,22 @@ say $0.WHAT; #=> (Array) # Un cuantificador específico siempre capturará un Array, # puede ser un rango o un valor específico (hasta 1). -## Las capturas son indezadas por anidación. Esto quiere decir que un grupo -## dentro de un grup estará anidado dentro de su grupo padre: `$/[0][0]`, +## Las capturas son indezadas por anidación. Esto quiere decir que un grupo +## dentro de un grup estará anidado dentro de su grupo padre: `$/[0][0]`, ## para este código: 'hello-~-world' ~~ / ( 'hello' ( <[ \- \~ ]> + ) ) 'world' /; say $/[0].Str; #=> hello~ say $/[0][0].Str; #=> ~ -## Esto se origina de un hecho bien simple: `$/` no contiene cadenas de -## texto, números enteros o arrays sino que solo contiene objetos Match. -## Estos objetos contienen los métodos `.list`, `.hash` y `.Str`. (Pero -## también puedes usar `match` para accesar un hash y `match[indice]` +## Esto se origina de un hecho bien simple: `$/` no contiene cadenas de +## texto, números enteros o arrays sino que solo contiene objetos Match. +## Estos objetos contienen los métodos `.list`, `.hash` y `.Str`. (Pero +## también puedes usar `match` para accesar un hash y `match[indice]` ## para accesar un array. say $/[0].list.perl; #=> (Match.new(...),).list # Podemos ver que es una lista de objetos Match. - # Estos contienen un montón de información: dónde la - # coincidencia comenzó o terminó, el "ast" + # Estos contienen un montón de información: dónde la + # coincidencia comenzó o terminó, el "ast" # (chequea las acciones más abajo), etc. # Verás capturas nombradas más abajo con las gramáticas. @@ -1743,9 +1743,9 @@ so 'abc' ~~ / a [ b | y ] c /; # `True`. o "b" o "y". so 'ayc' ~~ / a [ b | y ] c /; # `True`. Obviamente suficiente... ## La diferencia entre este `|` y el otro al que estás acustombrado es LTM. -## LTM significa "Longest Token Matching", traducido libremente como +## LTM significa "Longest Token Matching", traducido libremente como ## "Coincidencia de Token Más Larga". Esto significa que el motor ("engine") -## siempre intentará coindidir tanto como sea posible en la cadena de texto. +## siempre intentará coindidir tanto como sea posible en la cadena de texto. ## Básicamente, intentará el patrón más largo que concuerde con el regexp. 'foo' ~~ / fo | foo /; # `foo` porque es más largo. ## Para decidir cual parte es la "más larga", primero separa el regex en @@ -1759,19 +1759,19 @@ so 'ayc' ~~ / a [ b | y ] c /; # `True`. Obviamente suficiente... ## anteriores, aserciones de código, y otras cosas que tradicionalmente no pueden ## ser representadas por regexes normales. ## -## Entonces, todas las alternativas se intentan al mismo tiempo, y la +## Entonces, todas las alternativas se intentan al mismo tiempo, y la ## más larga gana. ## Ejemplos: ## DECLARATIVO | PROCEDIMENTAL / 'foo' \d+ [ || ] /; ## DECLARATIVO (grupos anidados no son un problema) / \s* [ \w & b ] [ c | d ] /; -## Sin embargo, las clausuras y la recursión (de regexes nombrados) +## Sin embargo, las clausuras y la recursión (de regexes nombrados) ## son procedimentales. ## ... Hay más reglas complicadas, como la especifidad (los literales ganan ## son las clases de caracteres) + -## Nota: la primera coincidencia `or` todavía existen, pero ahora se +## Nota: la primera coincidencia `or` todavía existen, pero ahora se ## deletrea `||` 'foo' ~~ / fo || foo /; # `fo` ahora. ``` @@ -1779,9 +1779,9 @@ so 'ayc' ~~ / a [ b | y ] c /; # `True`. Obviamente suficiente... ## Extra: la subrutina MAIN ```perl6 -## La subrutina `MAIN` se invoca cuando tu ejecuta un archivo de Perl 6 -## directamente. Es realmente poderosa porque Perl 6 actualmente parsea -## los argumentos y los pasas a la subrutina. También maneja argumentos +## La subrutina `MAIN` se invoca cuando tu ejecuta un archivo de Perl 6 +## directamente. Es realmente poderosa porque Perl 6 actualmente parsea +## los argumentos y los pasas a la subrutina. También maneja argumentos ## nombrados (`--foo`) y hasta autogenerará un `--help`. sub MAIN($nombre) { say "¡Hola, $nombre!" } ## Esto produce: @@ -1789,9 +1789,9 @@ sub MAIN($nombre) { say "¡Hola, $nombre!" } ## Uso: ## t.pl -## Y dado que una subrutina regular en Perl 6, puedes tener múltiples +## Y dado que una subrutina regular en Perl 6, puedes tener múltiples ## despachos: -## (usando un "Bool" por un argumento nombrado para que podamos hacer +## (usando un "Bool" por un argumento nombrado para que podamos hacer ## `--replace` a cambio de `--replace=1`) subset File of Str where *.IO.d; # convierte a un objeto IO para chequear si # un archivo existe @@ -1825,13 +1825,13 @@ multi MAIN('import', File, Str :$as) { ... } # omitiendo parámetros nombrados ## (los cuales representan los números -1, 0 o +1). 1 <=> 4; # comparación de orden para caracteres numéricos 'a' leg 'b'; # comparación de orden para cadenas de texto -$obj eqv $obj2; # comparación de orden usando la semántica eqv +$obj eqv $obj2; # comparación de orden usando la semántica eqv ## * Ordenación genérica 3 before 4; # True 'b' after 'a'; # True -## * Operador (por defecto) de circuito corto +## * Operador (por defecto) de circuito corto ## Al igual que `or` y `||`, pero devuelve el primer valor *defined* ## (definido): say Any // Nil // 0 // 5; #=> 0 @@ -1843,9 +1843,9 @@ say True ^^ False; #=> True ## * Flip Flop ## Los operadores flip flop (`ff` y `fff`, equivalente a `..`/`...` en P5) ## son operadores que toman dos predicados para evalualarlos: -## Ellos son `False` hasta que su lado izquierdo devuelve `True`, entonces +## Ellos son `False` hasta que su lado izquierdo devuelve `True`, entonces ## son `True` hasta que su lado derecho devuelve `True`. -## Como los rangos, tu puedes excluir la iteración cuando se convierte en +## Como los rangos, tu puedes excluir la iteración cuando se convierte en ## `True`/`False` usando `^` en cualquier lado. ## Comencemos con un ejemplo: for { @@ -1861,25 +1861,25 @@ for { } ## Esto imprimirá "young hero we shall meet" (exluyendo "met"): ## el flip-flop comenzará devolviendo `True` cuando primero encuentra "met" -## (pero no returnará `False` por "met" dabido al `^` al frente de `ff`), +## (pero no returnará `False` por "met" dabido al `^` al frente de `ff`), ## hasta que ve "meet", lo cual es cuando comenzará devolviendo `False`. ## La diferencia entre `ff` (al estilo de awk) y `fff` (al estilo de sed) -## es que `ff` probará su lado derecho cuando su lado izquierdo cambia +## es que `ff` probará su lado derecho cuando su lado izquierdo cambia ## a `True`, y puede returnar a `False` inmediamente (*excepto* que será -## `True` por la iteración con la cual coincidió). Por lo contrario, -## `fff` esperará por la próxima iteración para intentar su lado +## `True` por la iteración con la cual coincidió). Por lo contrario, +## `fff` esperará por la próxima iteración para intentar su lado ## derecho, una vez que su lado izquierdo ha cambiado: .say if 'B' ff 'B' for ; #=> B B # porque el lado derecho se puso a prueba # directamente (y returnó `True`). # Las "B"s se imprimen dadó que coincidió - # en ese momento (returnó a `False` + # en ese momento (returnó a `False` # inmediatamente). .say if 'B' fff 'B' for ; #=> B C B # El lado derecho no se puso a prueba # hasta que `$_` se convirtió en "C" - # (y por lo tanto no coincidió + # (y por lo tanto no coincidió # inmediamente). ## Un flip-flop puede cambiar estado cuantas veces se necesite: @@ -1901,35 +1901,35 @@ for (1, 3, 60, 3, 40, 60) { # Nota: los paréntesis son superfluos aquí ## que no pasará la primera vez: for { .say if * ^ff *; # el flip-flop es `True` y nunca returna a `False`, - # pero el `^` lo hace *que no se ejecute* en la + # pero el `^` lo hace *que no se ejecute* en la # primera iteración #=> b c } -## - `===` es la identidad de valor y usa `.WHICH` +## - `===` es la identidad de valor y usa `.WHICH` ## en los objetos para compararlos. -## - `=:=` es la identidad de contenedor y usa `VAR()` +## - `=:=` es la identidad de contenedor y usa `VAR()` ## en los objetos para compararlos. ``` Si quieres ir más allá de lo que se muestra aquí, puedes: - - Leer la [documentación de Perl 6](https://docs.perl6.org/). Esto es un recurso + - Leer la [documentación de Perl 6](https://docs.raku.org/). Esto es un recurso grandioso acerca de Perl 6. Si estás buscando por algo en particular, usa la barra de búsquedas. Esto te dará un menú de todas las páginas concernientes a tu término de búsqueda (¡Es mucho mejor que usar Google para encontrar documentos acerca de Perl 6!) - - Leer el [Perl 6 Advent Calendar](http://perl6advent.wordpress.com/). Este es + - Leer el [Perl 6 Advent Calendar](http://perl6advent.wordpress.com/). Este es un gran recurso de fragmentos de código de Perl 6 y explicaciones. Si la documentación no describe algo lo suficientemente bien, puedes encontrar información más detallada aquí. Esta información puede ser un poquito más antigua pero hay muchos ejemplos y - explicaciones. Las publicaciones fueron suspendidas al final del 2015 cuando + explicaciones. Las publicaciones fueron suspendidas al final del 2015 cuando el lenguaje fue declarado estable y Perl 6.c fue lanzado. - Unirte a `#perl6` en `irc.freenode.net`. Las personas aquí son siempre serviciales. - Chequear la [fuente de las funciones y clases de Perl 6 - ](https://github.com/rakudo/rakudo/tree/nom/src/core). Rakudo está principalmente + ](https://github.com/rakudo/rakudo/tree/nom/src/core). Rakudo está principalmente escrito en Perl 6 (con mucho de NQP, "Not Quite Perl" ("No Perl Todavía"), un subconjunto de Perl 6 que es más fácil de implementar y optimizar). - - Leer [documentos acerca del diseño del lenguaje](http://design.perl6.org). + - Leer [documentos acerca del diseño del lenguaje](http://design.raku.org). Estos explican P6 desde la perspectiva de un implementador, lo cual es bastante interesante. -- cgit v1.2.3 From d78605e0d7839c6c9e7ccf9d07a041800e6d340b Mon Sep 17 00:00:00 2001 From: sumanstats Date: Mon, 15 Jun 2020 20:42:57 +0545 Subject: Reflect perl6 to raku rename + As mentioned here: https://github.com/Raku/problem-solving/blob/master/solutions/language/Path-to-Raku.md perl6 is renamed to raku + change references of perl6 to raku + change extension from .p6 to .raku + fix the link of raku advent calendar --- es-es/perl6-es.html.markdown | 1935 ------------------------------------------ es-es/raku-es.html.markdown | 1935 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1935 insertions(+), 1935 deletions(-) delete mode 100644 es-es/perl6-es.html.markdown create mode 100644 es-es/raku-es.html.markdown (limited to 'es-es') diff --git a/es-es/perl6-es.html.markdown b/es-es/perl6-es.html.markdown deleted file mode 100644 index b9f49e2d..00000000 --- a/es-es/perl6-es.html.markdown +++ /dev/null @@ -1,1935 +0,0 @@ ---- -name: perl6 -category: language -language: perl6 -filename: perl6-es.p6 -contributors: - - ["vendethiel", "http://github.com/vendethiel"] - - ["Samantha McVey", "https://cry.nu"] -translators: - - ["Luis F. Uceta", "https://github.com/uzluisf"] -lang: es-es ---- - -Perl 6 es un lenguaje de programación altamente capaz y con características -abundantes para hacerlo el lenguage ideal por los próximos 100 años. - -El compilador primario de Perl 6 se llama [Rakudo](http://rakudo.org), el cual -se ejecuta en JVM y en [MoarVM](http://moarvm.com). - -Meta-nota: dos signos de números (##) son usados para indicar párrafos, -mientras que un solo signo de número (#) indica notas. - -`#=>` representa la salida de un comando. - -```perl6 -# Un comentario de una sola línea comienza con un signo de número - -#`( - Comentarios multilíneas usan #` y signos de encerradura tales - como (), [], {}, 「」, etc. -) -``` - -## Variables - -```perl6 -## En Perl 6, se declara una variable lexical usando `my` -my $variable; -## Perl 6 tiene 3 tipos básicos de variables: escalares, arrays, y hashes. -``` - -### Escalares - -```perl6 -# Un escalar representa un solo valor. Variables escalares comienzan -# con un `$` - -my $str = 'Cadena'; -# Las comillas inglesas ("") permiten la intepolación (lo cual veremos -# luego): -my $str2 = "Cadena"; - -## Los nombres de variables pueden contener pero no terminar con comillas -## simples y guiones. Sin embargo, pueden contener -## (y terminar con) guiones bajos (_): -my $nombre'de-variable_ = 5; # Esto funciona! - -my $booleano = True; # `True` y `False` son valores booleanos en Perl 6. -my $inverso = !$booleano; # Puedes invertir un booleano con el operador prefijo `!` -my $bool-forzado = so $str; # Y puedes usar el operador prefijo `so` que - # convierte su operador en un Bool -``` - -### Arrays y Listas - -```perl6 -## Un array representa varios valores. Variables arrays comienzan con `@`. -## Las listas son similares pero son un tipo inmutable. - -my @array = 'a', 'b', 'c'; -# equivalente a: -my @letras = ; # array de palabras, delimitado por espacios. - # Similar al qw de perl, o el %w de Ruby. -my @array = 1, 2, 3; - -say @array[2]; # Los índices de un array empiezan por el 0 -- Este es - # el tercer elemento. - -say "Interpola todos los elementos de un array usando [] : @array[]"; -#=> Interpola todos los elementos de un array usando [] : 1 2 3 - -@array[0] = -1; # Asigna un nuevo valor a un índice del array -@array[0, 1] = 5, 6; # Asigna varios valores - -my @llaves = 0, 2; -@array[@llaves] = @letras; # Asignación usando un array que contiene valores - # índices -say @array; #=> a 6 b -``` - -### Hashes, o Pairs (pares) de llaves-valores. - -```perl6 -## Un hash contiene parejas de llaves y valores. -## Puedes construir un objeto Pair usando la sintaxis `LLave => Valor`. -## Tablas de hashes son bien rápidas para búsqueda, y son almacenadas -## sin ningún orden. -## Ten en cuenta que las llaves son "aplanadas" en contexto de hash, y -## cualquier llave duplicada es deduplicada. -my %hash = 1 => 2, - 3 => 4; -my %hash = foo => "bar", # las llaves reciben sus comillas - # automáticamente. - "some other" => "value", # las comas colgantes estań bien. - ; - -## Aunque los hashes son almacenados internamente de forma diferente a los -## arrays, Perl 6 te permite crear un hash usando un array -## con un número par de elementos fácilmente. -my %hash = ; - -my %hash = llave1 => 'valor1', llave2 => 'valor2'; # ¡el mismo resultado! - -## También puedes usar la sintaxis "pareja con dos puntos": -## (especialmente útil para parámetros nombrados que verás más adelante) -my %hash = :w(1), # equivalente a `w => 1` - # esto es útil para el atajo `True`: - :truey, # equivalente a `:truey(True)`, o `truey => True` - # y para el `False`: - :!falsey, # equivalente a `:falsey(False)`, o `falsey => False` - ; - -say %hash{'llave1'}; # Puedes usar {} para obtener el valor de una llave -say %hash; # Si es una cadena de texto, puedes actualmente usar <> - # (`{llave1}` no funciona, debido a que Perl 6 no tiene - # palabras desnudas (barewords en inglés)) -``` - -## Subrutinas - -```perl6 -## Subrutinas, o funciones como otros lenguajes las llaman, son -## creadas con la palabra clave `sub`. -sub di-hola { say "¡Hola, mundo!" } - -## Puedes proveer argumentos (tipados). Si especificado, -## el tipo será chequeado al tiempo de compilación si es posible. -## De lo contrario, al tiempo de ejecución. -sub di-hola-a(Str $nombre) { - say "¡Hola, $nombre!"; -} - -## Una subrutina devuelve el último valor evaluado del bloque. -sub devolver-valor { - 5; -} -say devolver-valor; # imprime 5 -sub devolver-vacio { -} -say devolver-vacio; # imprime Nil - -## Algunas estructuras de control producen un valor. Por ejemplo if: -sub devuelva-si { - if True { - "Truthy"; - } -} -say devuelva-si; # imprime Truthy - -## Otras no, como un bucle for: -sub return-for { - for 1, 2, 3 { } -} -say return-for; # imprime Nil - -## Una subrutina puede tener argumentos opcionales: -sub con-opcional($arg?) { # el signo "?" marca el argumento opcional - say "Podría returnar `(Any)` (valor de Perl parecido al 'null') si no me pasan - un argumento, o returnaré mi argumento"; - $arg; -} -con-opcional; # devuelve Any -con-opcional(); # devuelve Any -con-opcional(1); # devuelve 1 - -## También puedes proveer un argumento por defecto para -## cuando los argumentos no son proveídos: -sub hola-a($nombre = "Mundo") { - say "¡Hola, $nombre!"; -} -hola-a; #=> ¡Hola, Mundo! -hola-a(); #=> ¡Hola, Mundo! -hola-a('Tú'); #=> ¡Hola, Tú! - -## De igual manera, al usar la sintaxis parecida a la de los hashes -## (¡Hurra, sintaxis unificada!), puedes pasar argumentos *nombrados* -## a una subrutina. Ellos son opcionales, y por defecto son del tipo "Any". -sub con-nombre($arg-normal, :$nombrado) { - say $arg-normal + $nombrado; -} -con-nombre(1, nombrado => 6); #=> 7 -## Sin embargo, debes tener algo en cuenta aquí: -## Si pones comillas alrededor de tu llave, Perl 6 no será capaz de verla -## al tiempo de compilación, y entonces tendrás un solo objeto Pair como -## un argumento posicional, lo que significa que el siguiente ejemplo -## falla: -con-nombre(1, 'nombrado' => 6); - -con-nombre(2, :nombrado(5)); #=> 7 - -## Para hacer un argumento nombrado mandatorio, puedes utilizar el -## inverso de `?`, `!`: -sub con-nombre-mandatorio(:$str!) { - say "$str!"; -} -con-nombre-mandatorio(str => "Mi texto"); #=> Mi texto! -con-nombre-mandatorio; # error al tiempo de ejecución: - # "Required named parameter not passed" - # ("Parámetro nombrado requerido no proveído") -con-nombre-mandatorio(3);# error al tiempo de ejecución: - # "Too many positional parameters passed" - # ("Demasiados argumentos posicionales proveídos") - -## Si una subrutina toma un argumento booleano nombrado ... -sub toma-un-bool($nombre, :$bool) { - say "$nombre toma $bool"; -} -## ... puedes usar la misma sintaxis de hash de un "booleano corto": -takes-a-bool('config', :bool); # config toma True -takes-a-bool('config', :!bool); # config toma False - -## También puedes proveer tus argumentos nombrados con valores por defecto: -sub nombrado-definido(:$def = 5) { - say $def; -} -nombrado-definido; #=> 5 -nombrado-definido(def => 15); #=> 15 - -## Dado que puedes omitir los paréntesis para invocar una función sin -## argumentos, necesitas usar "&" en el nombre para almacenar la función -## `di-hola` en una variable. -my &s = &di-hola; -my &otra-s = sub { say "¡Función anónima!" } - -## Una subrutina puede tener un parámetro "slurpy", o "no importa cuantos", -## indicando que la función puede recibir cualquier número de parámetros. -sub muchos($principal, *@resto) { #`*@` (slurpy) consumirá lo restante -## Nota: Puedes tener parámetros *antes que* un parámetro "slurpy" (como -## aquí) pero no *después* de uno. - say @resto.join(' / ') ~ "!"; -} -say muchos('Feliz', 'Cumpleaño', 'Cumpleaño'); #=> Feliz / Cumpleaño! - # Nota que el asterisco (*) no - # consumió el parámetro frontal. - -## Puedes invocar un función con un array usando el -## operador "aplanador de lista de argumento" `|` -## (actualmente no es el único rol de este operador pero es uno de ellos) -sub concat3($a, $b, $c) { - say "$a, $b, $c"; -} -concat3(|@array); #=> a, b, c - # `@array` fue "aplanado" como parte de la lista de argumento -``` - -## Contenedores - -```perl6 -## En Perl 6, valores son actualmente almacenados en "contenedores". -## El operador de asignación le pregunta al contenedor en su izquierda -## almacenar el valor a su derecha. Cuando se pasan alrededor, contenedores -## son marcados como inmutables. Esto significa que, en una función, tu -## tendrás un error si tratas de mutar uno de tus argumentos. -## Si realmente necesitas hacerlo, puedes preguntar por un contenedor -## mutable usando `is rw`: -sub mutar($n is rw) { - $n++; - say "¡\$n es ahora $n!"; -} - -my $m = 42; -mutar $m; # ¡$n es ahora 43! - -## Esto funciona porque estamos pasando el contenedor $m para mutarlo. Si -## intentamos pasar un número en vez de pasar una variable, no funcionará -## dado que no contenedor ha sido pasado y números enteros son inmutables -## por naturaleza: - -mutar 42; # Parámetro '$n' esperaba un contenedor mutable, - # pero recibió un valor Int - -## Si en cambio quieres una copia, debes usar `is copy`. - -## Por si misma, una subrutina devuelve un contenedor, lo que significa -## que puede ser marcada con rw: -my $x = 42; -sub x-almacena() is rw { $x } -x-almacena() = 52; # En este caso, los paréntesis son mandatorios - # (porque de otra forma, Perl 6 piensa que la función - # `x-almacena` es un identificador). -say $x; #=> 52 -``` - -## Estructuras de control -### Condicionales - -```perl6 -## - `if` -## Antes de hablar acerca de `if`, necesitamos saber cuales valores son -## "Truthy" (representa True (verdadero)), y cuales son "Falsey" -## (o "Falsy") -- representa False (falso). Solo estos valores son -## Falsey: 0, (), {}, "", Nil, un tipo (como `Str` o`Int`) y -## por supuesto False. Todos los valores son Truthy. -if True { - say "¡Es verdadero!"; -} - -unless False { - say "¡No es falso!"; -} - -## Como puedes observar, no necesitas paréntesis alrededor de condiciones. -## Sin embargo, necesitas las llaves `{}` alrededor del cuerpo de un bloque: -# if (true) say; # !Esto no funciona! - -## También puedes usar sus versiones sufijos seguidas por la palabra clave: -say "Un poco verdadero" if True; - -## - La condicional ternaria, "?? !!" (como `x ? y : z` en otros lenguajes) -## devuelve $valor-si-verdadera si la condición es verdadera y -## $valor-si-falsa si es falsa. -## my $resultado = $valor condición ?? $valor-si-verdadera !! $valor-si-falsa; - -my $edad = 30; -say $edad > 18 ?? "Eres un adulto" !! "Eres menor de 18"; -``` - -### given/when, ó switch - -```perl6 -## - `given`-`when` se parece al `switch` de otros lenguajes, pero es más -## poderoso gracias a la coincidencia inteligente ("smart matching" en inglés) -## y la "variable tópica" $_ de Perl. -## -## Esta variable ($_) contiene los argumentos por defecto de un bloque, -## la iteración actual de un loop (a menos que sea explícitamente -## nombrado), etc. -## -## `given` simplemente pone su argumento en `$_` (como un bloque lo haría), -## y `when` lo compara usando el operador de "coincidencia inteligente" (`~~`). -## -## Dado que otras construcciones de Perl 6 usan esta variable (por ejemplo, -## el bucle `for`, bloques, etc), esto se significa que el poderoso `when` no -## solo se aplica con un `given`, sino que se puede usar en cualquier -## lugar donde exista una variable `$_`. - -given "foo bar" { - say $_; #=> foo bar - when /foo/ { # No te preocupies acerca de la coincidencia inteligente – - # solo ten presente que `when` la usa. - # Esto es equivalente a `if $_ ~~ /foo/`. - say "¡Yay!"; - } - when $_.chars > 50 { # coincidencia inteligente con cualquier cosa True es True, - # i.e. (`$a ~~ True`) - # por lo tanto puedes también poner condiciones "normales". - # Este `when` es equivalente a este `if`: - # if $_ ~~ ($_.chars > 50) {...} - # que significa: - # if $_.chars > 50 {...} - say "¡Una cadena de texto bien larga!"; - } - default { # lo mismo que `when *` (usando la Whatever Star) - say "Algo más"; - } -} -``` - -### Construcciones de bucle - -```perl6 -## - `loop` es un bucle infinito si no le pasas sus argumentos, -## pero también puede ser un bucle for al estilo de C: -loop { - say "¡Este es un bucle infinito!"; - last; # last interrumpe el bucle, como la palabra clave `break` - # en otros lenguajes. -} - -loop (my $i = 0; $i < 5; $i++) { - next if $i == 3; # `next` salta a la siguiente iteración, al igual - # que `continue` en otros lenguajes. Ten en cuenta que - # también puedes usar la condicionales postfix (sufijas) - # bucles, etc. - say "¡Este es un bucle al estilo de C!"; -} - -## - `for` - Hace iteraciones en un array -for @array -> $variable { - say "¡He conseguido una $variable!"; -} - -## Como vimos con `given`, la variable de una "iteración actual" por defecto -## es `$_`. Esto significa que puedes usar `when` en un bucle `for` como -## normalmente lo harías con `given`. -for @array { - say "he conseguido a $_"; - - .say; # Esto es también permitido. - # Una invocación con punto (dot call) sin "tópico" (recibidor) es - # enviada a `$_` por defecto. - $_.say; # lo mismo de arriba, lo cual es equivalente. -} - -for @array { - # Puedes... - next if $_ == 3; # Saltar a la siguiente iteración (`continue` en - # lenguages parecido a C) - redo if $_ == 4; # Re-hacer la iteración, manteniendo la - # misma variable tópica (`$_`) - last if $_ == 5; # Salir fuera del bucle (como `break` - # en lenguages parecido a C) -} - -## La sintaxis de "bloque puntiagudo" no es específica al bucle for. -## Es solo una manera de expresar un bloque en Perl 6. -if computación-larga() -> $resultado { - say "El resultado es $resultado"; -} -``` - -## Operadores - -```perl6 -## Dados que los lenguajes de la familia Perl son lenguages basados -## mayormente en operadores, los operadores de Perl 6 son actualmente -## subrutinas un poco cómicas en las categorías sintácticas. Por ejemplo, -## infix:<+> (adición) o prefix: (bool not). - -## Las categorías son: -## - "prefix" (prefijo): anterior a (como `!` en `!True`). -## - "postfix" (sufijo): posterior a (como `++` en `$a++`). -## - "infix" (infijo): en medio de (como `*` en `4 * 3`). -## - "circumfix" (circunfijo): alrededor de (como `[`-`]` en `[1, 2]`). -## - "post-circumfix" (pos-circunfijo): alrededor de un término, -## posterior a otro término. -## (como `{`-`}` en `%hash{'key'}`) - -## La lista de asociatividad y precedencia se explica más abajo. - -## ¡Bueno, ya estás listo(a)! - -## * Chequeando igualdad - -## - `==` se usa en comparaciones numéricas. -3 == 4; # Falso -3 != 4; # Verdadero - -## - `eq` se usa en comparaciones de cadenas de texto. -'a' eq 'b'; -'a' ne 'b'; # no igual -'a' !eq 'b'; # lo mismo que lo anterior - -## - `eqv` es equivalencia canónica (or "igualdad profunda") -(1, 2) eqv (1, 3); - -## - Operador de coincidencia inteligente (smart matching): `~~` -## Asocia (aliasing en inglés) el lado izquierda a la variable $_ -## y después evalúa el lado derecho. -## Aquí algunas comparaciones semánticas comunes: - -## Igualdad de cadena de texto o numérica - -'Foo' ~~ 'Foo'; # True si las cadenas de texto son iguales. -12.5 ~~ 12.50; # True si los números son iguales. - -## Regex - Para la comparación de una expresión regular en contra -## del lado izquierdo. Devuelve un objeto (Match), el cual evalúa -## como True si el regex coincide con el patrón. - -my $obj = 'abc' ~~ /a/; -say $obj; # 「a」 -say $obj.WHAT; # (Match) - -## Hashes -'llave' ~~ %hash; # True si la llave existe en el hash - -## Tipo - Chequea si el lado izquierdo "tiene un tipo" (puede chequear -## superclases y roles) - -1 ~~ Int; # True (1 es un número entero) - -## Coincidencia inteligente contra un booleano siempre devuelve ese -## booleano (y lanzará una advertencia). - -1 ~~ True; # True -False ~~ True; # True - -## La sintaxis general es $arg ~~ &función-returnando-bool; -## Para una lista completa de combinaciones, usa esta tabla: -## http://perlcabal.org/syn/S03.html#Smart_matching - -## También, por supuesto, tienes `<`, `<=`, `>`, `>=`. -## Sus equivalentes para cadenas de texto están disponibles: -## `lt`, `le`, `gt`, `ge`. -3 > 4; - -## * Constructores de rango -3 .. 7; # 3 a 7, ambos incluidos -## `^` en cualquier lado excluye a ese lado: -3 ^..^ 7; # 3 a 7, no incluidos (básicamente `4 .. 6`) -## Esto también funciona como un atajo para `0..^N`: -^10; # significa 0..^10 - -## Esto también nos permite demostrar que Perl 6 tiene arrays -## ociosos/infinitos, usando la Whatever Star: -my @array = 1..*; # 1 al Infinito! `1..Inf` es lo mismo. -say @array[^10]; # puedes pasar arrays como subíndices y devolverá - # un array de resultados. Esto imprimirá - # "1 2 3 4 5 6 7 8 9 10" (y no se quedaré sin memoria!) -## Nota: Al leer una lista infinita, Perl 6 "cosificará" los elementos que -## necesita y los mantendrá en la memoria. Ellos no serán calculados más de -## una vez. Tampoco calculará más elementos de los que necesita. - -## Un índice de array también puede ser una clausura ("closure" en inglés). -## Será llamada con la longitud como el argumento -say join(' ', @array[15..*]); #=> 15 16 17 18 19 -## lo que es equivalente a: -say join(' ', @array[-> $n { 15..$n }]); -## Nota: Si tratas de hacer cualquiera de esos con un array infinito, -## provocará un array infinito (tu programa nunca terminará) - -## Puedes usar eso en los lugares que esperaría, como durante la asignación -## a un array -my @números = ^20; - -## Aquí los números son incrementados por "6"; más acerca del -## operador `...` adelante. -my @seq = 3, 9 ... * > 95; # 3 9 15 21 27 [...] 81 87 93 99; -@números[5..*] = 3, 9 ... *; # aunque la secuencia es infinita, - # solo los 15 números necesarios será calculados. -say @números; #=> 0 1 2 3 4 3 9 15 21 [...] 81 87 - # (solamente 20 valores) - -## * And &&, Or || -3 && 4; # 4, el cual es Truthy. Invoca `.Bool` en `4` y obtiene `True`. -0 || False; # False. Invoca `.Bool` en `0` - -## * Versiones circuito corto de lo de arriba -## && Devuelve el primer argumento que evalúa a False, o el último. - -my ( $a, $b, $c ) = 1, 0, 2; -$a && $b && $c; # Devuelve 0, el primer valor que es False - -## || Devuelve el primer argumento que evalúa a True. -$b || $a; # 1 - -## Y porque tu lo querrás, también tienes operadores de asignación -## compuestos: -$a *= 2; # multiplica y asigna. Equivalente a $a = $a * 2; -$b %%= 5; # divisible por y asignación. Equivalente $b = $b %% 5; -@array .= sort; # invoca el método `sort` y asigna el resultado devuelto. -``` - -## ¡Más sobre subrutinas! - -```perl6 -## Como dijimos anteriormente, Perl 6 tiene subrutinas realmente poderosas. -## Veremos unos conceptos claves que la hacen mejores que en cualquier otro -## lenguaje :-). -``` - -### !Desempacado! - -```perl6 -## Es la abilidad de extraer arrays y llaves (También conocido como -## "destructuring"). También funcionará en `my` y en las listas de parámetros. -my ($f, $g) = 1, 2; -say $f; #=> 1 -my ($, $, $h) = 1, 2, 3; # mantiene los anónimos no interesante -say $h; #=> 3 - -my ($cabeza, *@cola) = 1, 2, 3; # Sí, es lo mismo que con subrutinas "slurpy" -my (*@small) = 1; - -sub desempacar_array(@array [$fst, $snd]) { - say "Mi primero es $fst, mi segundo es $snd! De todo en todo, soy un @array[]."; - # (^ recuerda que `[]` interpola el array) -} -desempacar_array(@cola); #=> My first is 2, my second is 3 ! All in all, I'm 2 3 - - -## Si no está usando el array, puedes también mantenerlo anónimo, como un -## escalar: -sub primero-de-array(@ [$fst]) { $fst } -primero-de-array(@small); #=> 1 -primero-de-array(@tail); # Lanza un error "Demasiados argumentos posicionales - # proveídos" - # (lo que significa que el array es muy grande). - -## También puedes usar un slurp ... -sub slurp-en-array(@ [$fst, *@rest]) { # Podrías mantener `*@rest` anónimos - say $fst + @rest.elems; # `.elems` returna la longitud de una lista. - # Aquí, `@rest` es `(3,)`, since `$fst` holds the `2`. -} -slurp-en-array(@tail); #=> 3 - -## Hasta podrías hacer un extracción usando una slurpy (pero no sería útil ;-).) -sub fst(*@ [$fst]) { # o simplemente: `sub fst($fst) { ... }` - say $fst; -} -fst(1); #=> 1 -fst(1, 2); # errores con "Too many positional parameters passed" - -## También puedes desestructurar hashes (y clases, las cuales -## veremos adelante). La sintaxis es básicamente -## `%nombre-del-hash (:llave($variable-para-almacenar))`. -## El hash puede permanecer anónimos si solo necesitas los valores extraídos. -sub llave-de(% (:azul($val1), :red($val2))) { - say "Valores: $val1, $val2."; -} -## Después invócala con un hash: (necesitas mantener las llaves -## de los parejas de llave y valor para ser un hash) -llave-de({azul => 'blue', rojo => "red"}); -#llave-de(%hash); # lo mismo (para un `%hash` equivalente) - -## La última expresión de una subrutina es devuelta inmediatamente -## (aunque puedes usar la palabra clave `return`): -sub siguiente-indice($n) { - $n + 1; -} -my $nuevo-n= siguiente-indice(3); # $nuevo-n es ahora 4 - -## Este es cierto para todo, excepto para las construcciones de bucles -## (debido a razones de rendimiento): Hay una razón de construir una lista -## si la vamos a desechar todos los resultados. -## Si todavías quieres construir una, puedes usar la sentencia prefijo `do`: -## (o el prefijo `gather`, el cual veremos luego) -sub lista-de($n) { - do for ^$n { # nota el uso del operador de rango `^` (`0..^N`) - $_ # iteración de bucle actual - } -} -my @list3 = lista-de(3); #=> (0, 1, 2) -``` - -### lambdas - -```perl6 -## Puedes crear una lambda con `-> {}` ("bloque puntiagudo") o `{}` ("bloque") -my &lambda = -> $argumento { "El argumento pasado a esta lambda es $argumento" } -## `-> {}` y `{}` son casi la misma cosa, excepto que la primerra puede -## tomar argumentos, y la segunda puede ser malinterpretada como un hash -## por el parseador. - -## Podemos, por ejemplo, agregar 3 a cada valor de un array usando map: -my @arraymas3 = map({ $_ + 3 }, @array); # $_ es el argumento implícito - -## Una subrutina (`sub {}`) tiene semánticas diferentes a un -## bloque (`{}` or `-> {}`): Un bloque no tiene "contexto funcional" -## (aunque puede tener argumentos), lo que significa que si quieres devolver -## algo desde un bloque, vas a returnar desde la función parental. Compara: -sub is-in(@array, $elem) { - # esto `devolverá` desde la subrutina `is-in` - # Una vez que la condición evalúa a True, el bucle terminará - map({ return True if $_ == $elem }, @array); -} -sub truthy-array(@array) { - # esto producirá un array de `True` Y `False`: - # (también puedes decir `anon sub` para "subrutina anónima") - map(sub ($i) { if $i { return True } else { return False } }, @array); - # ^ el `return` solo devuelve desde la `sub` -} - -## También puedes usar la "whatever star" para crear una función anónima -## (terminará con el último operador en la expresión actual) -my @arraymas3 = map(*+3, @array); # `*+3` es lo mismo que `{ $_ + 3 }` -my @arraymas3 = map(*+*+3, @array); # lo mismo que `-> $a, $b { $a + $b + 3 }` - # también `sub ($a, $b) { $a + $b + 3 }` -say (*/2)(4); #=> 2 - # Inmediatamente ejecuta la función que Whatever creó. -say ((*+3)/5)(5); #=> 1.6 - # ¡funciona hasta con los paréntesis! - -## Pero si necesitas más que un argumento (`$_`) en un bloque -## (sin depender en `-> {}`), también puedes usar la sintaxis implícita -## de argumento, `$` : -map({ $^a + $^b + 3 }, @array); # equivalente a lo siguiente: -map(sub ($a, $b) { $a + $b + 3 }, @array); # (aquí con `sub`) - -## Nota : Esos son ordernados lexicográficamente. -# `{ $^b / $^a }` es como `-> $a, $b { $b / $a }` -``` - -### Acerca de tipos... - -```perl6 -## Perl 6 es gradualmente tipado. Esto quiere decir que tu especifica el -## tipo de tus variables/argumentos/devoluciones (return), o puedes omitirlos -## y serán "Any" por defecto. -## Obviamente tienes acceso a algunas tipos básicos, como Int y Str. -## Las construcciones para declarar tipos son "class", "role", lo cual -## verás más adelante. - -## Por ahora, examinemos "subset" (subconjunto). -## Un "subset" es un "sub-tipo" con chequeos adicionales. -## Por ejemplo: "un número entero bien grande es un Int que es mayor que 500" -## Puedes especificar el tipo del que creas el subconjunto (por defecto, Any), -## y añadir chequeos adicionales con la palabra clave "where" (donde): -subset EnteroGrande of Int where * > 500; -``` - -### Despacho Múltiple (Multiple Dispatch) - -```perl6 -## Perl 6 puede decidir que variante de una subrutina invocar basado en el -## tipo de los argumento, o precondiciones arbitrarias, como con un tipo o -## un `where`: - -## con tipos -multi sub dilo(Int $n) { # nota la palabra clave `multi` aquí - say "Número: $n"; -} -multi dilo(Str $s) { # un multi es una subrutina por defecto - say "Cadena de texto: $s"; -} -dilo("azul"); # prints "Cadena de texto: azul" -dilo(True); # falla al *tiempo de compilación* con - # "calling 'dilo' will never work with arguments of types ..." - # (invocar 'dilo' nunca funcionará con argumentos de tipos ...") -## con precondición arbitraria (¿recuerdas los subconjuntos?): -multi es-grande(Int $n where * > 50) { "¡Sí!" } # usando una clausura -multi es-grande(Int $ where 10..50) { "Tal vez." } # Usando coincidencia inteligente - # (podrías usar un regexp, etc) -multi es-grande(Int $) { "No" } - -subset Par of Int where * %% 2; - -multi inpar-o-par(Par) { "Par" } # El caso principal usando el tipo. - # No nombramos los argumentos, -multi inpar-o-par($) { "Inpar" } # "else" - -## ¡Podrías despachar basado en la presencia de argumentos posicionales! -multi sin_ti-o-contigo(:$with!) { # Necesitas hacerlo mandatorio - # para despachar en contra del argumento. - say "¡Puedo vivir! Actualmente, no puedo."; -} -multi sin_ti-o-contigo { - say "Definitivamente no puedo vivir."; -} -## Esto es muy útil para muchos propósitos, como subrutinas `MAIN` (de las -## cuales hablaremos luego), y hasta el mismo lenguaje la está usando -## en muchos lugares. -## -## - `is`, por ejemplo, es actualmente un `multi sub` llamado -## `trait_mod:`. -## - `is rw`, es simplemente un despacho a una función con esta signatura: -## sub trait_mod:(Routine $r, :$rw!) {} -## -## (¡lo pusimos en un comentario dado que ejecutando esto sería una terrible -## idea!) -``` - -## Ámbito (Scoping) - -```perl6 -## En Perl 6, a diferencia de otros lenguajes de scripting, (tales como -## (Python, Ruby, PHP), debes declarar tus variables antes de usarlas. El -## declarador `my`, del cual aprendiste anteriormente, usa "ámbito léxical". -## Hay otros declaradores (`our`, `state`, ..., ) los cuales veremos luego. -## Esto se llama "ámbito léxico", donde en los bloques internos, -## puedes acceder variables de los bloques externos. -my $archivo-en-ámbito = 'Foo'; -sub externo { - my $ámbito-externo = 'Bar'; - sub interno { - say "$archivo-en-ámbito $ámbito-externo"; - } - &interno; # devuelve la función -} -outer()(); #=> 'Foo Bar' - -## Como puedes ver, `$archivo-en-ámbito` y `$ámbito-externo` -## fueron capturados. Pero si intentaramos usar `$bar` fuera de `foo`, -## la variable estaría indefinida (y obtendrías un error al tiempo de -## compilación). -``` - -## Twigils - -```perl6 -## Hay muchos `twigils` especiales (sigilos compuestos) en Perl 6. -## Los twigils definen el ámbito de las variables. -## Los twigils * y ? funcionan con variables regulares: -## * Variable dinámica -## ? Variable al tiempo de compilación -## Los twigils ! y . son usados con los objetos de Perl 6: -## ! Atributo (miembro de la clase) -## . Método (no una variable realmente) - -## El twigil `*`: Ámbito dinámico -## Estas variables usan el twigil `*` para marcar variables con ámbito -## dinámico. Variables con ámbito dinámico son buscadas a través del -## invocador, no a través del ámbito externo. - -my $*ambito_din_1 = 1; -my $*ambito_din_2 = 10; - -sub di_ambito { - say "$*ambito_din_1 $*ambito_din_2"; -} - -sub invoca_a_di_ambito { - my $*ambito_din_1 = 25; # Define a $*ambito_din_1 solo en esta subrutina. - $*ambito_din_2 = 100; # Cambiará el valor de la variable en ámbito. - di_ambito(); #=> 25 100 $*ambito_din_1 y 2 serán buscadas en la invocación. - # Se usa el valor de $*ambito_din_1 desde el ámbito léxico de esta - # subrutina aunque los bloques no están anidados (están anidados por - # invocación). -} -di_ambito(); #=> 1 10 -invoca_a_di_ambito(); #=> 25 100 - # Se usa a $*ambito_din_1 como fue definida en invoca_a_di_ambito - # aunque la estamos invocando desde afuera. -di_ambito(); #=> 1 100 Cambiamos el valor de $*ambito_din_2 en invoca_a_di_ambito - # por lo tanto su valor a cambiado. -``` - -## Modelo de Objeto - -```perl6 -## Para invocar a un método en un objeto, agrega un punto seguido por el -## nombre del objeto: -## => $object.method -## Las classes son declaradas usando la palabra clave `class`. Los atributos -## son declarados con la palabra clave `has`, y los métodos con `method`. -## Cada atributo que es privado usa el twigil `!`. Por ejemplo: `$!attr`. -## Atributos públicos inmutables usan el twigil `.` (los puedes hacer -## mutables con `is rw`). -## La manera más fácil de recordar el twigil `$.` is comparándolo -## con como los métodos son llamados. - -## El modelo de objeto de Perl 6 ("SixModel") es muy flexible, y te permite -## agregar métodos dinámicamente, cambiar la semántica, etc ... -## (no hablaremos de todo esto aquí. Por lo tanto, refiérete a: -## https://docs.raku.org/language/objects.html). - -class Clase-Atrib { - has $.atrib; # `$.atrib` es inmutable. - # Desde dentro de la clase, usa `$!atrib` para modificarlo. - has $.otro-atrib is rw; # Puedes marcar un atributo como público con `rw`. - has Int $!atrib-privado = 10; - - method devolver-valor { - $.atrib + $!atrib-privado; - } - - method asignar-valor($param) { # Métodos pueden tomar parámetros. - $!attrib = $param; # Esto funciona porque `$!` es siempre mutable. - # $.attrib = $param; # Incorrecto: No puedes usar la versión inmutable `$.`. - - $.otro-atrib = 5; # Esto funciona porque `$.otro-atrib` es `rw`. - } - - method !metodo-privado { - say "Este método es privado para la clase !"; - } -}; - -## Crear una nueva instancia de Clase-Atrib con $.atrib asignado con 5: -## Nota: No puedes asignarle un valor a atrib-privado desde aquí (más de -## esto adelante). -my $class-obj = Clase-Atrib.new(atrib => 5); -say $class-obj.devolver-valor; #=> 5 -# $class-obj.atrib = 5; # Esto falla porque `has $.atrib` es inmutable -$class-obj.otro-atrib = 10; # En cambio, esto funciona porque el atributo - # público es mutable (`rw`). -``` - -### Herencia de Objeto - -```perl6 -## Perl 6 también tiene herencia (junto a herencia múltiple) -## Mientras los métodos declarados con `method` son heredados, aquellos -## declarados con `submethod` no lo son. -## Submétodos son útiles para la construcción y destrucción de tareas, -## tales como BUILD, o métodos que deben ser anulados por subtipos. -## Aprenderemos acerca de BUILD más adelante. - -class Padre { - has $.edad; - has $.nombre; - # Este submétodo no será heredado por la clase Niño. - submethod color-favorito { - say "Mi color favorito es Azul"; - } - # Este método será heredado - method hablar { say "Hola, mi nombre es $!nombre" } -} -# Herencia usa la palabra clave `is` -class Niño is Padre { - method hablar { say "Goo goo ga ga" } - # Este método opaca el método `hablar` de Padre. - # Este niño no ha aprendido a hablar todavía. -} -my Padre $Richard .= new(edad => 40, nombre => 'Richard'); -$Richard.color-favorito; #=> "Mi color favorito es Azul" -$Richard.hablar; #=> "Hola, mi nombre es Richard" -## $Richard es capaz de acceder el submétodo; él sabe como decir su nombre. - -my Niño $Madison .= new(edad => 1, nombre => 'Madison'); -$Madison.hablar; # imprime "Goo goo ga ga" dado que el método fue cambiado - # en la clase Niño. -# $Madison.color-favorito # no funciona porque no es heredado - -## Cuando se usa `my T $var` (donde `T` es el nombre de la clase), `$var` -## inicia con `T` en si misma, por lo tanto puedes invocar `new` en `$var`. -## (`.=` es sólo la invocación por punto y el operador de asignación: -## `$a .= b` es lo mismo que `$a = $a.b`) -## Por ejemplo, la instancia $Richard pudo también haber sido declarada así: -## my $Richard = Padre.new(edad => 40, nombre => 'Richard'); - -## También observa que `BUILD` (el método invocado dentro de `new`) -## asignará propiedades de la clase padre, por lo que puedes pasar -## `val => 5`. -``` - -### Roles, o Mixins - -```perl6 -## Roles son suportados también (comúnmente llamados Mixins en otros -## lenguajes) -role PrintableVal { - has $!counter = 0; - method print { - say $.val; - } -} - -## Se "importa" un mixin (un "role") con "does": -class Item does PrintableVal { - has $.val; - - ## Cuando se utiliza `does`, un `rol` se mezcla en al clase literalmente: - ## los métodos y atributos se ponen juntos, lo que significa que una clase - ## puede acceder los métodos y atributos privados de su rol (pero no lo inverso!): - method access { - say $!counter++; - } - - ## Sin embargo, esto: - ## method print {} - ## es SÓLO válido cuando `print` no es una `multi` con el mismo dispacho. - ## (esto significa que una clase padre puede opacar una `multi print() {}` - ## de su clase hijo/a, pero es un error sin un rol lo hace) - - ## NOTA: Puedes usar un rol como una clase (con `is ROLE`). En este caso, - ## métodos serán opacados, dado que el compilador considerará `ROLE` - ## como una clase. -} -``` - -## Excepciones - -```perl6 -## Excepciones están construidas al tope de las clases, en el paquete -## `X` (como `X::IO`). -## En Perl 6, excepciones son lanzadas automáticamente. -open 'foo'; #=> Failed to open file foo: no such file or directory -## También imprimirá la línea donde el error fue lanzado y otra información -## concerniente al error. - -## Puedes lanzar una excepción usando `die`: -die 'Error!'; #=> Error! - -## O más explícitamente: -die X::AdHoc.new(payload => 'Error!'); - -## En Perl 6, `orelse` es similar al operador `or`, excepto que solamente -## coincide con variables indefinidas, en cambio de cualquier cosa -## que evalúa a falso. -## Valores indefinidos incluyen: `Nil`, `Mu` y `Failure`, también como -## `Int`, `Str` y otros tipos que no han sido inicializados a ningún valor -## todavía. -## Puedes chequear si algo está definido o no usando el método defined: -my $no-inicializada; -say $no-inicializada.defined; #=> False -## Al usar `orelse`, se desarmará la excepción y creará un alias de dicho -## fallo en $_ -## Esto evitará que sea automáticamente manejado e imprima una marejada de -## mensajes de errores en la pantalla. -## Podemos usar el método de excepción en $_ para acceder la excepción: -open 'foo' orelse say "Algo pasó {.exception}"; - -## Esto también funciona: -open 'foo' orelse say "Algo pasó $_"; #=> Algo pasó - #=> Failed to open file foo: no such file or directory -## Ambos ejemplos anteriores funcionan pero en caso de que consigamos un -## objeto desde el lado izquierdo que no es un fallo, probablemente -## obtendremos una advertencia. Más abajo vemos como usar `try` y `CATCH` -## para ser más expecíficos con las excepciones que capturamos. -``` - -### Usando `try` y `CATCH` - -```perl6 -## Al usar `try` y `CATCH`, puedes contener y manejar excepciones sin -## interrumpir el resto del programa. `try` asignará la última excepción -## a la variable especial `$!`. -## Nota: Esto no tiene ninguna relación con las variables $!. - -try open 'foo'; -say "Bueno, lo intenté! $!" if defined $!; #=> Bueno, lo intenté! Failed to open file - #foo: no such file or directory -## Ahora, ¿qué debemos hacer si queremos más control sobre la excepción? -## A diferencia de otros lenguajes, en Perl 6 se pone el bloque `CATCH` -## *dentro* del bloque a intentar (`try`). Similarmente como $_ fue asignada -## cuando 'disarmamos' la excepción con `orelse`, también usamos $_ en el -## bloque CATCH. -## Nota: ($! es solo asignada *después* del bloque `try`) -## Por defecto, un bloque `try` tiene un bloque `CATCH` que captura -## cualquier excepción (`CATCH { default {} }`). - -try { my $a = (0 %% 0); CATCH { say "Algo pasó: $_" } } - #=> Algo pasó: Attempt to divide by zero using infix:<%%> - -## Puedes redefinir lo anterior usando `when` y (`default`) -## para manejar las excepciones que desees: -try { - open 'foo'; - CATCH { # En el bloque `CATCH`, la excepción es asignada a $_ - when X::AdHoc { say "Error: $_" } - #=>Error: Failed to open file /dir/foo: no such file or directory - - ## Cualquier otra excepción será levantada de nuevo, dado que no - ## tenemos un `default`. - ## Básicamente, si un `when` - ## Basically, if a `when` matches (or there's a `default`) marks the - ## exception as - ## "handled" so that it doesn't get re-thrown from the `CATCH`. - ## You still can re-throw the exception (see below) by hand. - } -} - -## En Perl 6, excepciones poseen ciertas sutilezas. Algunas -## subrutinas en Perl 6 devuelven un `Failure`, el cual es un tipo de -## "excepción no levantada". Ellas no son levantadas hasta que tu intentas -## mirar a sus contenidos, a menos que invoques `.Bool`/`.defined` sobre -## ellas - entonces, son manejadas. -## (el método `.handled` es `rw`, por lo que puedes marcarlo como `False` -## por ti mismo) -## Puedes levantar un `Failure` usando `fail`. Nota que si el pragma -## `use fatal` estás siendo utilizado, `fail` levantará una excepión (como -## `die`). -fail "foo"; # No estamos intentando acceder el valor, por lo tanto no problema. -try { - fail "foo"; - CATCH { - default { say "Levantó un error porque intentamos acceder el valor del fallo!" } - } -} - -## También hay otro tipo de excepción: Excepciones de control. -## Esas son excepciones "buenas", las cuales suceden cuando cambias el flujo -## de tu programa, usando operadores como `return`, `next` or `last`. -## Puedes capturarlas con `CONTROL` (no lista un 100% en Rakudo todavía). -``` - -## Paquetes - -```perl6 -## Paquetes son una manera de reusar código. Paquetes son como -## "espacio de nombres" (namespaces en inglés), y cualquier elemento del -## modelo seis (`module`, `role`, `class`, `grammar`, `subset` y `enum`) -## son paquetes por ellos mismos. (Los paquetes son como el mínimo común -## denominador) -## Los paquetes son importantes - especialmente dado que Perl es bien -## reconocido por CPAN, the Comprehensive Perl Archive Nertwork. - -## Puedes usar un módulo (traer sus declaraciones al ámbito) con `use` -use JSON::Tiny; # si intalaste Rakudo* o Panda, tendrás este módulo -say from-json('[1]').perl; #=> [1] - -## A diferencia de Perl, no deberías declarar paquetes usando -## la palabra clave `package`. En vez, usa `class Nombre::Paquete::Aquí;` -## para declarar una clase, o si solamente quieres exportar -## variables/subrutinas, puedes usar `module`. - -module Hello::World { # forma de llaves - # Si `Hello` no existe todavía, solamente será una cola ("stub"), - # que puede ser redeclarada más tarde. - # ... declaraciones aquí ... -} -unit module Parse::Text; # forma de ámbito de archivo - -grammar Parse::Text::Grammar { # Una gramática (grammar en inglés) es un paquete, - # en el cual puedes usar `use` -} # Aprenderás más acerca de gramáticas en la sección de regex - -## Como se dijo anteriormente, cualquier parte del modelo seis es también un -## paquete. Dado que `JSON::Tiny` usa su propia clase `JSON::Tiny::Actions`, -## tu puedes usarla de la manera siguiente: -my $acciones = JSON::Tiny::Actions.new; - -## Veremos como exportar variables y subrutinas en la siguiente parte: -``` - -## Declaradores - -```perl6 -## En Perl 6, tu obtienes diferentes comportamientos basado en como declaras -## una variable. -## Ya has visto `my` y `has`, ahora exploraremos el resto. - -## * las declaraciones `our` ocurren al tiempo `INIT` (ve "Phasers" más abajo) -## Es como `my`, pero también crea una variable paquete. -## (Todas las cosas relacionadas con paquetes (`class`, `role`, etc) son -## `our` por defecto) -module Var::Incrementar { - our $nuestra-var = 1; # Nota: No puedes colocar una restricción de tipo - my $mi-var = 22; # como Int (por ejemplo) en una variable `our`. - our sub Inc { - - our sub disponible { # Si tratas de hacer subrutinas internas `our`... - # Mejor que sepas lo que haces (No lo haga!). - say "No hagas eso. En serio. Estás jugando con fuego y te quemarás."; - } - - my sub no-disponible { # `my sub` es por defecto - say "No puedes acceder aquí desde fuera. Soy 'my'!"; - } - say ++$nuestra-var; # Incrementa la variable paquete y muestra su valor - } - -} -say $Var::Incrementar::nuestra-var; #=> 1 Esto funciona -say $Var::Incrementar::mi-var; #=> (Any) Esto no funcionará. - -Var::Incrementar::Inc; #=> 2 -Var::Incrementar::Inc; #=> 3 # Nota como el valor de $nuestra-var fue - # retenido -Var::Incrementar::no-disponible; #=> Could not find symbol '&no-disponible' - -## * `constant` (ocurre al tiempo `BEGIN`) -## Puedes usar la palabra clave `constant` para declarar una -## variable/símbolo al tiempo de compilación: -constant Pi = 3.14; -constant $var = 1; - -## Y por si te estás preguntando, sí, también puede contener listas infinitas. -constant porque-no = 5, 15 ... *; -say porque-no[^5]; #=> 5 15 25 35 45 - -## * `state` (ocurre al tiempo de ejecución, pero una sola vez) -## Variables "states" son solo inicializadas una vez. -## (ellas existen en otros lenguaje como `static` en C) -sub aleatorio-fijo { - state $valor = rand; - say $valor; -} -aleatorio-fijo for ^10; # imprimirá el mismo número 10 veces - -## Nota, sin embargo, que ellas existen separadamente en diferentes contextos. -## Si declaras una función con un `state` dentro de un bucle, recreará la -## variable por cada iteración del bucle. Observa: -for ^5 -> $a { - sub foo { - state $valor = rand; # Esto imprimirá un valor diferente - # por cada valor de `$a` - } - for ^5 -> $b { - say foo; # Esto imprimirá el mismo valor 5 veces, pero sólo 5. - # La siguiente iteración ejecutará `rand` nuevamente. - } -} -``` - -## Phasers - -```perl6 -## Un phaser en Perl 6 es un bloque que ocurre a determinados puntos de tiempo -## en tu programa. Se les llama phaser porque marca un cambio en la fase de -## de tu programa. Por ejemplo, cuando el programa es compilado, un bucle -## for se ejecuta, dejas un bloque, o una excepción se levanta. -## (¡`CATCH` es actualmente un phaser!) -## Algunos de ellos pueden ser utilizados por sus valores devueltos, otros -## no pueden (aquellos que tiene un "[*]" al inicio de su texto de -## explicación). -## ¡Tomemos una mirada! - -## * Phasers al tiempo de compilación -BEGIN { say "[*] Se ejecuta al tiempo de compilación, " ~ - "tan pronto como sea posible, una sola vez" } -CHECK { say "[*] Se ejecuta al tiempo de compilación, " ~ - "tan tarde como sea posible, una sola vez" } - -## * Phasers al tiempo de ejecución -INIT { say "[*] Se ejecuta al tiempo de ejecución, " ~ - "tan pronto como sea posible, una sola vez" } -END { say "Se ejecuta al tiempo de ejecución, " ~ - "tan tarde como sea posible, una sola vez" } - -## * Phasers de bloques -ENTER { say "[*] Se ejecuta cada vez que entra en un bloque, " ~ - "se repite en bloques de bucle" } -LEAVE { say "Se ejecuta cada vez que abandona un bloque, incluyendo " ~ - "cuando una excepción ocurre. Se repite en bloques de bucle"} - -PRE { - say "Impone una precondición a cada entrada de un bloque, " ~ - "antes que ENTER (especialmente útil para bucles)"; - say "Si este bloque no returna un valor truthy, " ~ - "una excepción del tipo X::Phaser::PrePost será levantada."; -} - -## Ejemplos: -for 0..2 { - PRE { $_ > 1 } # Esto fallará con un "Precondition failed" -} - -POST { - say "Impone una postcondAsserts a poscondición a la salida de un bloque, " ~ - "después de LEAVE (especialmente útil para bucles)"; - say "Si este bloque no returna un valor truthy, " ~ - "una excepción del tipo X::Phaser::PrePost será levantada, como con PRE."; -} -for 0..2 { - POST { $_ < 2 } # Esto fallará con un "Postcondition failed" -} - -## * Phasers de bloques/excepciones -sub { - KEEP { say "Se ejecuta cuando sales de un bloque exitosamente - (sin lanzar un excepción)" } - UNDO { say "Se ejecuta cuando sale de bloque sin éxito - (al lanzar una excepción)" } -} - -## * Phasers de bucle -for ^5 { - FIRST { say "[*] La primera vez que un bucle se ejecuta, antes que ENTER" } - NEXT { say "Al tiempo de la continuación del bucle, antes que LEAVE" } - LAST { say "Al tiempo de la terminación del bucle, después de LEAVE" } -} - -## * Phasers de rol/clase -COMPOSE { "Cuando un rol es compuesto en una clase. /!\ NO IMPLEMENTADO TODAVÍA" } - -## Ellos permite pequeños trucos o código brillante...: -say "Este código tomó " ~ (time - CHECK time) ~ "s para compilar"; - -## ... o brillante organización: -sub do-db-stuff { - $db.start-transaction; # comienza una transacción nueva - KEEP $db.commit; # commit (procede con) la transacción si todo estuvo bien - UNDO $db.rollback; # o retrocede si todo falló -} -``` - -## Prefijos de sentencias - -```perl6 -## Los prefijos de sentencias actúan como los phasers: Ellos afectan el -## comportamiento del siguiente código. -## Debido a que son ejecutados en línea con el código ejecutable, ellos -## se escriben en letras minúsculas. (`try` and `start` están teoréticamente -## en esa lista, pero serán explicados en otra parte) -## Nota: Ningunos de estos (excepto `start`) necesitan las llaves `{` y `}`. - -## - `do` (el cual ya viste) - ejecuta un bloque o una sentencia como un -## término. -## Normalmente no puedes usar una sentencia como un valor (o término): -## -## my $valor = if True { 1 } # `if` es una sentencia - error del parseador -## -## Esto funciona: -my $a = do if True { 5 } # con `do`, `if` ahora se comporta como un término. - -## - `once` - se asegura que una porción de código se ejecute una sola vez. -for ^5 { once say 1 }; #=> 1 - # solo imprime ... una sola vez. -## Al igual que `state`, ellos son clonados por ámbito -for ^5 { sub { once say 1 }() } #=> 1 1 1 1 1 - # Imprime una sola vez por ámbito léxico - -## - `gather` - Hilo de co-rutina -## `gather` te permite tomar (`take`) varios valores en un array, -## al igual que `do`. Encima de esto, te permite tomar cualquier expresión. -say gather for ^5 { - take $_ * 3 - 1; - take $_ * 3 + 1; -} #=> -1 1 2 4 5 7 8 10 11 13 -say join ',', gather if False { - take 1; - take 2; - take 3; -} # no imprime nada. - -## - `eager` - Evalúa una sentencia ávidamente (forza contexto ávido) -## No intentes esto en casa: -## -## eager 1..*; # esto probablemente se colgará por un momento -## # (y podría fallar...). -## -## Pero considera lo siguiente: -constant tres-veces = gather for ^3 { say take $_ }; # No imprime nada - -## frente a esto: -constant tres-veces = eager gather for ^3 { say take $_ }; #=> 0 1 2 -``` - -## Iterables - -```perl6 -## En Perl 6, los iterables son objetos que pueden ser iterados similar -## a la construcción `for`. -## `flat`, aplana iterables: -say (1, 10, (20, 10) ); #=> (1 10 (20 10)) Nota como la agrupación se mantiene -say (1, 10, (20, 10) ).flat; #=> (1 10 20 10) Ahora el iterable es plano - -## - `lazy` - Aplaza la evaluación actual hasta que el valor sea requirido -## (forza contexto perezoso) -my @lazy-array = (1..100).lazy; -say @lazy-array.is-lazy; #=> True # Chequea por "pereza" con el método `is-lazy`. -say @lazy-array; #=> [...] No se ha iterado sobre la lista -for @lazy-array { .print }; # Esto funciona y hará tanto trabajo como sea necesario. - -[//]: # ( TODO explica que gather/take y map son todos perezosos) -## - `sink` - Un `eager` que desecha los resultados (forza el contexto sink) -constant nilthingie = sink for ^3 { .say } #=> 0 1 2 -say nilthingie.perl; #=> Nil - -## - `quietly` - Un bloque `quietly` reprime las advertencias: -quietly { warn 'Esto es una advertencia!' }; #=> No salida - -## - `contend` - Intenta efectos secundarios debajo de STM -## ¡No implementado todavía! -``` - -## ¡Más operadores! - -```perl6 -## ¡Todo el mundo ama los operadores! Tengamos más de ellos. - -## La lista de precedencia puede ser encontrada aquí: -## https://docs.raku.org/language/operators#Operator_Precedence -## Pero primero, necesitamos un poco de explicación acerca -## de la asociatividad: - -## * Operadores binarios: -$a ! $b ! $c; # con asociatividad izquierda `!`, esto es `($a ! $b) ! $c` -$a ! $b ! $c; # con asociatividad derecha `!`, esto es `$a ! ($b ! $c)` -$a ! $b ! $c; # sin asociatividad `!`, esto es ilegal -$a ! $b ! $c; # con una cadena de asociatividad `!`, esto es `($a ! $b) and ($b ! $c)` -$a ! $b ! $c; # con asociatividad de lista `!`, esto es `infix:<>` - -## * Operadores unarios: -!$a! # con asociatividad izquierda `!`, esto es `(!$a)!` -!$a! # con asociatividad derecha `!`, esto es `!($a!)` -!$a! # sin asociatividad `!`, esto es ilegal -``` - -### ¡Crea tus propios operadores! - -```perl6 -## Okay, has leído todo esto y me imagino que debería mostrarte -## algo interesante. -## Te mostraré un pequeño secreto (o algo no tan secreto): -## En Perl 6, todos los operadores son actualmente solo subrutinas. - -## Puedes declarar un operador como declaras una subrutina: -sub prefix:($ganador) { # se refiere a las categorías de los operadores - # (exacto, es el "operador de palabras" `<>`) - say "¡$ganador ganó!"; -} -ganar "El Rey"; #=> ¡El Rey Ganó! - # (prefijo se pone delante) - -## todavías puedes invocar la subrutina con su "nombre completo": -say prefix:(True); #=> False - -sub postfix:(Int $n) { - [*] 2..$n; # usando el meta-operador reduce ... Ve más abajo! -} -say 5!; #=> 120 - # Operadores sufijos (postfix) van *directamente* después del témino. - # No espacios en blanco. Puedes usar paréntesis para disambiguar, - # i.e. `(5!)!` - - -sub infix:(Int $n, Block $r) { # infijo va en el medio - for ^$n { - $r(); # Necesitas los paréntesis explícitos para invocar la función - # almacenada en la variable `$r`. De lo contrario, te estaría - # refiriendo a la variable (no a la función), como con `&r`. - } -} -3 veces -> { say "hola" }; #=> hola - #=> hola - #=> hola - # Se te recomienda que ponga espacios - # alrededor de la invocación de operador infijo. - -## Para los circunfijos y pos-circunfijos -sub circumfix:<[ ]>(Int $n) { - $n ** $n -} -say [5]; #=> 3125 - # un circunfijo va alrededor. De nuevo, no espacios en blanco. - -sub postcircumfix:<{ }>(Str $s, Int $idx) { - ## un pos-circunfijo es - ## "después de un término y alrededor de algo" - $s.substr($idx, 1); -} -say "abc"{1}; #=> b - # depués del término `"abc"`, y alrededor del índice (1) - -## Esto es de gran valor -- porque todo en Perl 6 usa esto. -## Por ejemplo, para eliminar una llave de un hash, tu usas el adverbio -## `:delete` (un simple argumento con nombre debajo): -%h{$llave}:delete; -## es equivalente a: -postcircumfix:<{ }>(%h, $llave, :delete); # (puedes invocar - # operadores de esta forma) -## ¡*Todos* usan los mismos bloques básicos! -## Categorías sintácticas (prefix, infix, ...), argumentos nombrados -## (adverbios), ... - usados para construir el lenguaje - están al alcance -## de tus manos y disponibles para ti. -## (obviamente, no se te recomienda que hagas un operador de *cualquier -## cosa* -- Un gran poder conlleva una gran responsabilidad.) -``` - -### Meta-operadores! - -```perl6 -## ¡Prepárate! Prepárate porque nos estamos metiendo bien hondo -## en el agujero del conejo, y probablemente no querrás regresar a -## otros lenguajes después de leer esto. -## (Me imagino que ya no quieres a este punto). -## Meta-operadores, como su nombre lo sugiere, son operadores *compuestos*. -## Básicamente, ellos son operadores que se aplican a otros operadores. - -## * El meta-operador reduce (reducir) -## Es un meta-operador prefijo que toman una función binaria y -## una o varias listas. Sino se pasa ningún argumento, -## returna un "valor por defecto" para este operador -## (un valor sin significado) o `Any` si no hay ningún valor. -## -## De lo contrario, remueve un elemento de la(s) lista(s) uno a uno, y -## aplica la función binaria al último resultado (o al primer elemento de -## la lista y el elemento que ha sido removido). -## -## Para sumar una lista, podrías usar el meta-operador "reduce" con `+`, -## i.e.: -say [+] 1, 2, 3; #=> 6 -## es equivalente a `(1+2)+3` - -say [*] 1..5; #=> 120 -## es equivalente a `((((1*2)*3)*4)*5)`. - -## Puedes reducir con cualquier operador, no solo con operadores matemáticos. -## Por ejemplo, podrías reducir con `//` para conseguir -## el primer elemento definido de una lista: -say [//] Nil, Any, False, 1, 5; #=> False - # (Falsey, pero definido) - -## Ejemplos con valores por defecto: -say [*] (); #=> 1 -say [+] (); #=> 0 - # valores sin significado, dado que N*1=N y N+0=N. -say [//]; #=> (Any) - # No hay valor por defecto para `//`. -## También puedes invocarlo con una función de tu creación usando -## los dobles corchetes: -sub add($a, $b) { $a + $b } -say [[&add]] 1, 2, 3; #=> 6 - -## * El meta-operador zip -## Este es un meta-operador infijo que también puede ser usado como un -## operador "normal". Toma una función binaria opcional (por defecto, solo -## crear un par), y remueve un valor de cada array e invoca su función -## binaria hasta que no tenga más elementos disponibles. Al final, returna -## un array con todos estos nuevos elementos. -(1, 2) Z (3, 4); # ((1, 3), (2, 4)), dado que por defecto, la función - # crea un array. -1..3 Z+ 4..6; # (5, 7, 9), usando la función personalizada infix:<+> - -## Dado que `Z` tiene asociatividad de lista (ve la lista más arriba), -## puedes usarlo en más de una lista -(True, False) Z|| (False, False) Z|| (False, False); # (True, False) - -## Y pasa que también puedes usarlo con el meta-operador reduce: -[Z||] (True, False), (False, False), (False, False); # (True, False) - - -## Y para terminar la lista de operadores: - -## * El operador secuencia -## El operador secuencia es uno de la más poderosas características de -## Perl 6: Está compuesto, en la izquierda, de la lista que quieres que -## Perl 6 use para deducir (y podría incluir una clausura), y en la derecha, -## un valor o el predicado que dice cuando parar (o Whatever para una -## lista infinita perezosa). -my @list = 1, 2, 3 ... 10; # deducción básica -#my @list = 1, 3, 6 ... 10; # esto muere porque Perl 6 no puede deducir el final -my @list = 1, 2, 3 ...^ 10; # como con rangos, puedes excluir el último elemento - # (la iteración cuando el predicado iguala). -my @list = 1, 3, 9 ... * > 30; # puedes usar un predicado - # (con la Whatever Star, aquí). -my @list = 1, 3, 9 ... { $_ > 30 }; # (equivalente a lo de arriba) - -my @fib = 1, 1, *+* ... *; # lista infinita perezosa de la serie fibonacci, - # computada usando una clausura! -my @fib = 1, 1, -> $a, $b { $a + $b } ... *; # (equivalene a lo de arriba) -my @fib = 1, 1, { $^a + $^b } ... *; #(... también equivalene a lo de arriba) -## $a and $b siempre tomarán el valor anterior, queriendo decir que -## ellos comenzarán con $a = 1 y $b = 1 (valores que hemos asignado -## de antemano). Por lo tanto, $a = 1 y $b = 2 (resultado del anterior $a+$b), -## etc. - -say @fib[^10]; #=> 1 1 2 3 5 8 13 21 34 55 - # (usandi un rango como el índice) -## Nota: Los elementos de un rango, una vez cosificados, no son re-calculados. -## Esta es la razón por la cual `@primes[^100]` tomará más tiempo la primera -## vez que se imprime. Después de esto, será hará en un instante. -``` - -## Expresiones Regulares - -```perl6 -## Estoy seguro que has estado esperando por esta parte. Bien, ahora que -## sabes algo acerca de Perl 6, podemos comenzar. Primeramente, tendrás -## que olvidarte acerca de "PCRE regexps" (perl-compatible regexps) -## (expresiones regulares compatible de perl). -## -## IMPORTANTE: No salte esto porque ya sabes acerca de PCRE. Son totalmente -## distintos. Algunas cosas son las mismas (como `?`, `+`, y `*`) pero -## algunas veces la semántica cambia (`|`). Asegúrate de leer esto -## cuidadosamente porque podrías trospezarte sino lo haces. -## -## Perl 6 tiene muchas características relacionadas con RegExps. Después de -## todo, Rakudo se parsea a si mismo. Primero vamos a estudiar la sintaxis -## por si misma, después hablaremos acerca de gramáticas (parecido a PEG), -## las diferencias entre los declaradores `token`, `regex`, y `rule` y -## mucho más. -## Nota aparte: Todavía tienes acceso a los regexes PCRE usando el -## mofificador `:P5` (Sin embargo, no lo discutiremos en este tutorial). -## -## En esencia, Perl 6 implementa PEG ("Parsing Expression Grammars") -## ("Parseado de Expresiones de Gramáticas") nativamente. El orden jerárquico -## para los parseos ambiguos es determinado por un examen multi-nivel de -## desempate: -## - La coincidencia de token más larga. `foo\s+` le gana a `foo` -## (por 2 o más posiciones) -## - El prefijo literal más largo. `food\w*` le gana a `foo\w*` (por 1) -## - Declaración desde la gramática más derivada a la menos derivada -## (las gramáticas son actualmente clases) -## - La declaración más temprana gana -say so 'a' ~~ /a/; #=> True -say so 'a' ~~ / a /; #=> True # ¡Más legible con los espacios! - -## Nota al lector (del traductor): -## Como pudiste haber notado, he decidido traducir "match" y sus diferentes -## formas verbales como "coincidir" y sus diferentes formas. Cuando digo que -## un regex (o regexp) coincide con cierto texto, me refiero a que el regex -## describe cierto patrón dentro del texto. Por ejemplo, el regex "cencia" -## coincide con el texto "reminiscencia", lo que significa que dentro del -## texto aparece ese patrón de caracteres (una `c`, seguida de una `e`, -## (seguida de una `n`, etc.) - -## En todos nuestros ejemplos, vamos a usar el operador de -## "coincidencia inteligente" contra una expresión regular ("regexp" or -## "regex" de aquí en adelante). Estamos convirtiendo el resultado usando `so`, -## pero en efecto, está devolviendo un objeto Match. Ellos saben como responder -## a la indexación de lista, indexación de hash, y devolver la cadena de -## texto coincidente. -## Los resultados de la coincidencia están disponible como `$/` (en -## ámbito implícito lexical). También puedes usar las variables de captura -## las cuales comienzan con 0: -## `$0`, `$1', `$2`... -## -## Nota que `~~` no hace un chequeo de inicio/final (es decir, -## el regexp puede coincider con solo un carácter de la cadena de texto). -## Explicaremos luego como hacerlo. - -## En Perl 6, puedes tener un carácter alfanumérico como un literal, -## todo lo demás debe escaparse usando una barra invertida o comillas. -say so 'a|b' ~~ / a '|' b /; # `True`. No sería lo mismo si no se escapara `|` -say so 'a|b' ~~ / a \| b /; # `True`. Otra forma de escaparlo - -## El espacio en blanco actualmente no se significa nada en un regexp, -## a menos que uses el adverbio `:s` (`:sigspace`, espacio significante). -say so 'a b c' ~~ / a b c /; #=> `False`. Espacio no significa nada aquí. -say so 'a b c' ~~ /:s a b c /; #=> `True`. Agregamos el modificador `:s` aquí. -## Si usamos solo un espacio entre cadenas de texto en un regexp, Perl 6 -## nos advertirá: -say so 'a b c' ~~ / a b c /; #=> 'False' # Espacio no significa nada aquí. -## Por favor usa comillas o el modificador :s (:sigspace) para suprimir -## esta advertencia, omitir el espacio, o cambiar el espaciamiento. Para -## arreglar esto y hacer los espacios menos ambiguos, usa por lo menos -## dos espacios entre las cadenas de texto o usa el adverbio `:s`. - -## Como vimos anteriormente, podemos incorporar `:s` dentro de los -## delimitadores de barras. También podemos ponerlos fuera de ellos si -## especificamos `m` for `match` (coincidencia): -say so 'a b c' ~~ m:s/a b c/; #=> `True` -## Al usar `m` para especificar 'match', podemos también otros delimitadore: -say so 'abc' ~~ m{a b c}; #=> `True` -say so 'abc' ~~ m[a b c]; #=> `True` - -## Usa el adverbio :i para especificar que no debería haber distinción entre -## minúsculas y mayúsculas: -say so 'ABC' ~~ m:i{a b c}; #=> `True` - -## Sin embargo, es importante para como los modificadores son aplicados -## (lo cual verás más abajo)... - -## Cuantificando - `?`, `+`, `*` y `**`. -## - `?` - 0 o 1 -so 'ac' ~~ / a b c /; # `False` -so 'ac' ~~ / a b? c /; # `True`, la "b" coincidió (apareció) 0 veces. -so 'abc' ~~ / a b? c /; # `True`, la "b" coincidió 1 vez. - -## ... Como debes saber, espacio en blancos son importante porque -## determinan en que parte del regexp es el objetivo del modificador: -so 'def' ~~ / a b c? /; # `False`. Solamente la `c` es opcional -so 'def' ~~ / a b? c /; # `False`. Espacio en blanco no es significante -so 'def' ~~ / 'abc'? /; # `True`. El grupo "abc"completo es opcional. - -## Aquí (y más abajo) el cuantificador aplica solamente a la `b` - -## - `+` - 1 o más -so 'ac' ~~ / a b+ c /; # `False`; `+` quiere por lo menos una coincidencia -so 'abc' ~~ / a b+ c /; # `True`; una es suficiente -so 'abbbbc' ~~ / a b+ c /; # `True`, coincidió con 4 "b"s - -## - `*` - 0 o más -so 'ac' ~~ / a b* c /; # `True`, todos son opcionales. -so 'abc' ~~ / a b* c /; # `True` -so 'abbbbc' ~~ / a b* c /; # `True` -so 'aec' ~~ / a b* c /; # `False`. "b"(s) son opcionales, no reemplazables. - -## - `**` - Cuantificador (sin límites) -## Si entrecierras los ojos lo suficiente, pueder ser que entiendas -## por qué la exponenciación es usada para la cantidad. -so 'abc' ~~ / a b**1 c /; # `True` (exactamente una vez) -so 'abc' ~~ / a b**1..3 c /; # `True` (entre una y tres veces) -so 'abbbc' ~~ / a b**1..3 c /; # `True` -so 'abbbbbbc' ~~ / a b**1..3 c /; # `False` (demasiado) -so 'abbbbbbc' ~~ / a b**3..* c /; # `True` (rangos infinitos no son un problema) - -## - `<[]>` - Clases de carácteres -## Las clases de carácteres son equivalentes a las clases `[]` de PCRE, -## pero usan una sintaxis de Perl 6: -say 'fooa' ~~ / f <[ o a ]>+ /; #=> 'fooa' - -## Puedes usar rangos: -say 'aeiou' ~~ / a <[ e..w ]> /; #=> 'ae' - -## Al igual que regexes normales, si quieres usar un carácter especial, -## escápalo (el último está escapando un espacio) -say 'he-he !' ~~ / 'he-' <[ a..z \! \ ]> + /; #=> 'he-he !' - -## Obtendrás una advertencia si pones nombres duplicados -## (lo cual tiene el efecto de capturar la frase escrita) -'he he' ~~ / <[ h e ' ' ]> /; # Advierte "Repeated characters found in characters - # class" - -## También puedes negarlos... (equivalenta a `[^]` en PCRE) -so 'foo' ~~ / <-[ f o ]> + /; # False - -## ... y componerlos: -so 'foo' ~~ / <[ a..z ] - [ f o ]> + /; # False (cualquier letra excepto f y o) -so 'foo' ~~ / <-[ a..z ] + [ f o ]> + /; # True (no letra excepto f and o) -so 'foo!' ~~ / <-[ a..z ] + [ f o ]> + /; # True (el signo + no reemplaza la - # parte de la izquierda) -``` - -### Grupos y Capturas - -```perl6 -## Grupo: Puedes agrupar partes de tu regexp con `[]`. -## Estos grupos *no son* capturados (como con `(?:)` en PCRE). -so 'abc' ~~ / a [ b ] c /; # `True`. El agrupamiento no hace casi nada -so 'foo012012bar' ~~ / foo [ '01' <[0..9]> ] + bar /; -## La línea anterior returna `True`. -## Coincidimos (o encotramos el patrón) "012" una o más de una vez ( -## (el signo `+` fue aplicado al grupo). -## Pero esto no va demasiado lejos, porque no podemos actualmente obtener -## devuelta el patrón que coincidió. - -## Captura: Podemos actualmente *capturar* los resultados del regexp, -## usando paréntesis. -so 'fooABCABCbar' ~~ / foo ( 'A' <[A..Z]> 'C' ) + bar /; # `True`. (usando `so` - # aquí, `$/` más abajo) - -## Ok. Comenzando con las explicaciones de grupos. Como dijimos, -### nuestra objeto `Match` está disponible en la variable `$/`: -say $/; # Imprimirá algo extraño (explicaremos luego) o - # "Nil" si nada coincidió - -## Como dijimos anteriormente, un objeto Match tiene indexación de array: -say $/[0]; #=> 「ABC」 「ABC」 - # Estos corchetes extranos son los objetos `Match`. - # Aquí, tenemos un array de ellos. -say $0; # Lo mismo que lo anterior. - -## Nuestra captura es `$0` porque es la primera y única captura en el -## regexp. Podrías estarte preguntando porque un array y la respuesta es -## simple: Algunas capturas (indezadas usando `$0`, `$/[0]` o una nombrada) -## será un array si y solo si puedes tener más de un elemento. -## (Así que, con `*`, `+` y `**` (cualquiera los operandos), pero no con `?`). -## Usemos algunos ejemplos para ver como funciona: - -## Nota: Pusimos A B C entre comillas para demostrar que el espacio en blanco -## entre ellos no es significante. Si queremos que el espacio en blanco -## *sea* significante, podemos utilizar el modificador `:sigspace`. -so 'fooABCbar' ~~ / foo ( "A" "B" "C" )? bar /; # `True` -say $/[0]; #=> 「ABC」 -say $0.WHAT; #=> (Match) - # Puede haber más de uno, por lo tanto es solo un solo objeto match. -so 'foobar' ~~ / foo ( "A" "B" "C" )? bar /; #=> True -say $0.WHAT; #=> (Any) - # Esta captura no coincidió, por lo tanto está vacía -so 'foobar' ~~ / foo ( "A" "B" "C" ) ** 0..1 bar /; # `True` -say $0.WHAT; #=> (Array) - # Un cuantificador específico siempre capturará un Array, - # puede ser un rango o un valor específico (hasta 1). - -## Las capturas son indezadas por anidación. Esto quiere decir que un grupo -## dentro de un grup estará anidado dentro de su grupo padre: `$/[0][0]`, -## para este código: -'hello-~-world' ~~ / ( 'hello' ( <[ \- \~ ]> + ) ) 'world' /; -say $/[0].Str; #=> hello~ -say $/[0][0].Str; #=> ~ - -## Esto se origina de un hecho bien simple: `$/` no contiene cadenas de -## texto, números enteros o arrays sino que solo contiene objetos Match. -## Estos objetos contienen los métodos `.list`, `.hash` y `.Str`. (Pero -## también puedes usar `match` para accesar un hash y `match[indice]` -## para accesar un array. -say $/[0].list.perl; #=> (Match.new(...),).list - # Podemos ver que es una lista de objetos Match. - # Estos contienen un montón de información: dónde la - # coincidencia comenzó o terminó, el "ast" - # (chequea las acciones más abajo), etc. - # Verás capturas nombradas más abajo con las gramáticas. - -## Alternativas - el `or` de regexes -## Advertencia: Es diferente a los regexes de PCRE. -so 'abc' ~~ / a [ b | y ] c /; # `True`. o "b" o "y". -so 'ayc' ~~ / a [ b | y ] c /; # `True`. Obviamente suficiente... - -## La diferencia entre este `|` y el otro al que estás acustombrado es LTM. -## LTM significa "Longest Token Matching", traducido libremente como -## "Coincidencia de Token Más Larga". Esto significa que el motor ("engine") -## siempre intentará coindidir tanto como sea posible en la cadena de texto. -## Básicamente, intentará el patrón más largo que concuerde con el regexp. -'foo' ~~ / fo | foo /; # `foo` porque es más largo. -## Para decidir cual parte es la "más larga", primero separa el regex en -## dos partes: -## El "prefijo declarativo" (la parte que puede ser analizada estáticamente) -## y las partes procedimentales. -## Los prefijos declarativos incluyen alternaciones (`|`), conjunciones (`&`), -## invocaciones de sub-reglas (no han sido introducidos todavía), clases de -## caracteres y cuantificadores. -## Las partes procidimentales incluyen todo lo demás: referencias a elementos -## anteriores, aserciones de código, y otras cosas que tradicionalmente no pueden -## ser representadas por regexes normales. -## -## Entonces, todas las alternativas se intentan al mismo tiempo, y la -## más larga gana. -## Ejemplos: -## DECLARATIVO | PROCEDIMENTAL -/ 'foo' \d+ [ || ] /; -## DECLARATIVO (grupos anidados no son un problema) -/ \s* [ \w & b ] [ c | d ] /; -## Sin embargo, las clausuras y la recursión (de regexes nombrados) -## son procedimentales. -## ... Hay más reglas complicadas, como la especifidad (los literales ganan -## son las clases de caracteres) -+ -## Nota: la primera coincidencia `or` todavía existen, pero ahora se -## deletrea `||` -'foo' ~~ / fo || foo /; # `fo` ahora. -``` - -## Extra: la subrutina MAIN - -```perl6 -## La subrutina `MAIN` se invoca cuando tu ejecuta un archivo de Perl 6 -## directamente. Es realmente poderosa porque Perl 6 actualmente parsea -## los argumentos y los pasas a la subrutina. También maneja argumentos -## nombrados (`--foo`) y hasta autogenerará un `--help`. -sub MAIN($nombre) { say "¡Hola, $nombre!" } -## Esto produce: -## $ perl6 cli.pl -## Uso: -## t.pl - -## Y dado que una subrutina regular en Perl 6, puedes tener múltiples -## despachos: -## (usando un "Bool" por un argumento nombrado para que podamos hacer -## `--replace` a cambio de `--replace=1`) -subset File of Str where *.IO.d; # convierte a un objeto IO para chequear si - # un archivo existe - -multi MAIN('add', $key, $value, Bool :$replace) { ... } -multi MAIN('remove', $key) { ... } -multi MAIN('import', File, Str :$as) { ... } # omitiendo parámetros nombrados -## Esto produce: -## $ perl6 cli.pl -## Uso: -## t.pl [--replace] add -## t.pl remove -## t.pl [--as=] import (File) -## Como puedes ver, esto es *realmente* poderoso. -## Fue tan lejos como para mostrar las constantes en líneas. -## (el tipo solo se muestra cuando el argumento `$`/ es nombrado) -``` - -## APÉNDICE A: -### Lista de cosas - -```perl6 -## Consideramos que por ahora ya sabes lo básico de Perl 6. -## Esta sección es solo para listar algunas operaciones comunes -## las cuales no están en la "parte principal" del tutorial. - -## Operadores - -## * Comparación para ordenar -## Ellos returnan un valor de los enum `Order`: `Less`, `Same` y `More` -## (los cuales representan los números -1, 0 o +1). -1 <=> 4; # comparación de orden para caracteres numéricos -'a' leg 'b'; # comparación de orden para cadenas de texto -$obj eqv $obj2; # comparación de orden usando la semántica eqv - -## * Ordenación genérica -3 before 4; # True -'b' after 'a'; # True - -## * Operador (por defecto) de circuito corto -## Al igual que `or` y `||`, pero devuelve el primer valor *defined* -## (definido): -say Any // Nil // 0 // 5; #=> 0 - -## * Circuito corto exclusivo or (XOR) -## Devuelve `True` si uno (y solo uno) de sus argumentos es verdadero: -say True ^^ False; #=> True - -## * Flip Flop -## Los operadores flip flop (`ff` y `fff`, equivalente a `..`/`...` en P5) -## son operadores que toman dos predicados para evalualarlos: -## Ellos son `False` hasta que su lado izquierdo devuelve `True`, entonces -## son `True` hasta que su lado derecho devuelve `True`. -## Como los rangos, tu puedes excluir la iteración cuando se convierte en -## `True`/`False` usando `^` en cualquier lado. -## Comencemos con un ejemplo: -for { - # por defecto, `ff`/`fff` hace coincidencia inteligente (`~~`) contra `$_`: - if 'met' ^ff 'meet' { # no entrará el bucle if por "met" - # (se explica más abajo). - .say - } - - if rand == 0 ff rand == 1 { # compara variables más que `$_` - say "Esto ... probablemente nunca se ejecutará ..."; - } -} -## Esto imprimirá "young hero we shall meet" (exluyendo "met"): -## el flip-flop comenzará devolviendo `True` cuando primero encuentra "met" -## (pero no returnará `False` por "met" dabido al `^` al frente de `ff`), -## hasta que ve "meet", lo cual es cuando comenzará devolviendo `False`. - -## La diferencia entre `ff` (al estilo de awk) y `fff` (al estilo de sed) -## es que `ff` probará su lado derecho cuando su lado izquierdo cambia -## a `True`, y puede returnar a `False` inmediamente (*excepto* que será -## `True` por la iteración con la cual coincidió). Por lo contrario, -## `fff` esperará por la próxima iteración para intentar su lado -## derecho, una vez que su lado izquierdo ha cambiado: -.say if 'B' ff 'B' for ; #=> B B - # porque el lado derecho se puso a prueba - # directamente (y returnó `True`). - # Las "B"s se imprimen dadó que coincidió - # en ese momento (returnó a `False` - # inmediatamente). -.say if 'B' fff 'B' for ; #=> B C B - # El lado derecho no se puso a prueba - # hasta que `$_` se convirtió en "C" - # (y por lo tanto no coincidió - # inmediamente). - -## Un flip-flop puede cambiar estado cuantas veces se necesite: -for { - .say if $_ eq 'start' ^ff^ $_ eq 'stop'; # excluye a "start" y "stop", - #=> "print it print again" -} - -## También podrías usar una Whatever Star, lo cual es equivalente -## a `True` para el lado izquierdo o `False` para el lado derecho: -for (1, 3, 60, 3, 40, 60) { # Nota: los paréntesis son superfluos aquí - # (algunas veces se les llaman "paréntesis superticiosos") - .say if $_ > 50 ff *; # Una vez el flip-flop alcanza un número mayor que 50, - # no returnará jamás a `False` - #=> 60 3 40 60 -} - -## También puedes usar esta propiedad para crear un `If` -## que no pasará la primera vez: -for { - .say if * ^ff *; # el flip-flop es `True` y nunca returna a `False`, - # pero el `^` lo hace *que no se ejecute* en la - # primera iteración - #=> b c -} - -## - `===` es la identidad de valor y usa `.WHICH` -## en los objetos para compararlos. -## - `=:=` es la identidad de contenedor y usa `VAR()` -## en los objetos para compararlos. - -``` -Si quieres ir más allá de lo que se muestra aquí, puedes: - - - Leer la [documentación de Perl 6](https://docs.raku.org/). Esto es un recurso - grandioso acerca de Perl 6. Si estás buscando por algo en particular, usa la - barra de búsquedas. Esto te dará un menú de todas las páginas concernientes - a tu término de búsqueda (¡Es mucho mejor que usar Google para encontrar - documentos acerca de Perl 6!) - - Leer el [Perl 6 Advent Calendar](http://perl6advent.wordpress.com/). Este es - un gran recurso de fragmentos de código de Perl 6 y explicaciones. Si la documentación - no describe algo lo suficientemente bien, puedes encontrar información más detallada - aquí. Esta información puede ser un poquito más antigua pero hay muchos ejemplos y - explicaciones. Las publicaciones fueron suspendidas al final del 2015 cuando - el lenguaje fue declarado estable y Perl 6.c fue lanzado. - - Unirte a `#perl6` en `irc.freenode.net`. Las personas aquí son siempre serviciales. - - Chequear la [fuente de las funciones y clases de Perl 6 - ](https://github.com/rakudo/rakudo/tree/nom/src/core). Rakudo está principalmente - escrito en Perl 6 (con mucho de NQP, "Not Quite Perl" ("No Perl Todavía"), un - subconjunto de Perl 6 que es más fácil de implementar y optimizar). - - Leer [documentos acerca del diseño del lenguaje](http://design.raku.org). - Estos explican P6 desde la perspectiva de un implementador, lo cual es bastante - interesante. diff --git a/es-es/raku-es.html.markdown b/es-es/raku-es.html.markdown new file mode 100644 index 00000000..e916d0fd --- /dev/null +++ b/es-es/raku-es.html.markdown @@ -0,0 +1,1935 @@ +--- +name: perl6 +category: language +language: Raku +filename: learnraku-es.raku +contributors: + - ["vendethiel", "http://github.com/vendethiel"] + - ["Samantha McVey", "https://cry.nu"] +translators: + - ["Luis F. Uceta", "https://github.com/uzluisf"] +lang: es-es +--- + +Raku es un lenguaje de programación altamente capaz y con características +abundantes para hacerlo el lenguage ideal por los próximos 100 años. + +El compilador primario de Raku se llama [Rakudo](http://rakudo.org), el cual +se ejecuta en JVM y en [MoarVM](http://moarvm.com). + +Meta-nota: dos signos de números (##) son usados para indicar párrafos, +mientras que un solo signo de número (#) indica notas. + +`#=>` representa la salida de un comando. + +```perl6 +# Un comentario de una sola línea comienza con un signo de número + +#`( + Comentarios multilíneas usan #` y signos de encerradura tales + como (), [], {}, 「」, etc. +) +``` + +## Variables + +```perl6 +## En Raku, se declara una variable lexical usando `my` +my $variable; +## Raku tiene 3 tipos básicos de variables: escalares, arrays, y hashes. +``` + +### Escalares + +```perl6 +# Un escalar representa un solo valor. Variables escalares comienzan +# con un `$` + +my $str = 'Cadena'; +# Las comillas inglesas ("") permiten la intepolación (lo cual veremos +# luego): +my $str2 = "Cadena"; + +## Los nombres de variables pueden contener pero no terminar con comillas +## simples y guiones. Sin embargo, pueden contener +## (y terminar con) guiones bajos (_): +my $nombre'de-variable_ = 5; # Esto funciona! + +my $booleano = True; # `True` y `False` son valores booleanos en Raku. +my $inverso = !$booleano; # Puedes invertir un booleano con el operador prefijo `!` +my $bool-forzado = so $str; # Y puedes usar el operador prefijo `so` que + # convierte su operador en un Bool +``` + +### Arrays y Listas + +```perl6 +## Un array representa varios valores. Variables arrays comienzan con `@`. +## Las listas son similares pero son un tipo inmutable. + +my @array = 'a', 'b', 'c'; +# equivalente a: +my @letras = ; # array de palabras, delimitado por espacios. + # Similar al qw de perl, o el %w de Ruby. +my @array = 1, 2, 3; + +say @array[2]; # Los índices de un array empiezan por el 0 -- Este es + # el tercer elemento. + +say "Interpola todos los elementos de un array usando [] : @array[]"; +#=> Interpola todos los elementos de un array usando [] : 1 2 3 + +@array[0] = -1; # Asigna un nuevo valor a un índice del array +@array[0, 1] = 5, 6; # Asigna varios valores + +my @llaves = 0, 2; +@array[@llaves] = @letras; # Asignación usando un array que contiene valores + # índices +say @array; #=> a 6 b +``` + +### Hashes, o Pairs (pares) de llaves-valores. + +```perl6 +## Un hash contiene parejas de llaves y valores. +## Puedes construir un objeto Pair usando la sintaxis `LLave => Valor`. +## Tablas de hashes son bien rápidas para búsqueda, y son almacenadas +## sin ningún orden. +## Ten en cuenta que las llaves son "aplanadas" en contexto de hash, y +## cualquier llave duplicada es deduplicada. +my %hash = 1 => 2, + 3 => 4; +my %hash = foo => "bar", # las llaves reciben sus comillas + # automáticamente. + "some other" => "value", # las comas colgantes estań bien. + ; + +## Aunque los hashes son almacenados internamente de forma diferente a los +## arrays, Raku te permite crear un hash usando un array +## con un número par de elementos fácilmente. +my %hash = ; + +my %hash = llave1 => 'valor1', llave2 => 'valor2'; # ¡el mismo resultado! + +## También puedes usar la sintaxis "pareja con dos puntos": +## (especialmente útil para parámetros nombrados que verás más adelante) +my %hash = :w(1), # equivalente a `w => 1` + # esto es útil para el atajo `True`: + :truey, # equivalente a `:truey(True)`, o `truey => True` + # y para el `False`: + :!falsey, # equivalente a `:falsey(False)`, o `falsey => False` + ; + +say %hash{'llave1'}; # Puedes usar {} para obtener el valor de una llave +say %hash; # Si es una cadena de texto, puedes actualmente usar <> + # (`{llave1}` no funciona, debido a que Raku no tiene + # palabras desnudas (barewords en inglés)) +``` + +## Subrutinas + +```perl6 +## Subrutinas, o funciones como otros lenguajes las llaman, son +## creadas con la palabra clave `sub`. +sub di-hola { say "¡Hola, mundo!" } + +## Puedes proveer argumentos (tipados). Si especificado, +## el tipo será chequeado al tiempo de compilación si es posible. +## De lo contrario, al tiempo de ejecución. +sub di-hola-a(Str $nombre) { + say "¡Hola, $nombre!"; +} + +## Una subrutina devuelve el último valor evaluado del bloque. +sub devolver-valor { + 5; +} +say devolver-valor; # imprime 5 +sub devolver-vacio { +} +say devolver-vacio; # imprime Nil + +## Algunas estructuras de control producen un valor. Por ejemplo if: +sub devuelva-si { + if True { + "Truthy"; + } +} +say devuelva-si; # imprime Truthy + +## Otras no, como un bucle for: +sub return-for { + for 1, 2, 3 { } +} +say return-for; # imprime Nil + +## Una subrutina puede tener argumentos opcionales: +sub con-opcional($arg?) { # el signo "?" marca el argumento opcional + say "Podría returnar `(Any)` (valor de Perl parecido al 'null') si no me pasan + un argumento, o returnaré mi argumento"; + $arg; +} +con-opcional; # devuelve Any +con-opcional(); # devuelve Any +con-opcional(1); # devuelve 1 + +## También puedes proveer un argumento por defecto para +## cuando los argumentos no son proveídos: +sub hola-a($nombre = "Mundo") { + say "¡Hola, $nombre!"; +} +hola-a; #=> ¡Hola, Mundo! +hola-a(); #=> ¡Hola, Mundo! +hola-a('Tú'); #=> ¡Hola, Tú! + +## De igual manera, al usar la sintaxis parecida a la de los hashes +## (¡Hurra, sintaxis unificada!), puedes pasar argumentos *nombrados* +## a una subrutina. Ellos son opcionales, y por defecto son del tipo "Any". +sub con-nombre($arg-normal, :$nombrado) { + say $arg-normal + $nombrado; +} +con-nombre(1, nombrado => 6); #=> 7 +## Sin embargo, debes tener algo en cuenta aquí: +## Si pones comillas alrededor de tu llave, Raku no será capaz de verla +## al tiempo de compilación, y entonces tendrás un solo objeto Pair como +## un argumento posicional, lo que significa que el siguiente ejemplo +## falla: +con-nombre(1, 'nombrado' => 6); + +con-nombre(2, :nombrado(5)); #=> 7 + +## Para hacer un argumento nombrado mandatorio, puedes utilizar el +## inverso de `?`, `!`: +sub con-nombre-mandatorio(:$str!) { + say "$str!"; +} +con-nombre-mandatorio(str => "Mi texto"); #=> Mi texto! +con-nombre-mandatorio; # error al tiempo de ejecución: + # "Required named parameter not passed" + # ("Parámetro nombrado requerido no proveído") +con-nombre-mandatorio(3);# error al tiempo de ejecución: + # "Too many positional parameters passed" + # ("Demasiados argumentos posicionales proveídos") + +## Si una subrutina toma un argumento booleano nombrado ... +sub toma-un-bool($nombre, :$bool) { + say "$nombre toma $bool"; +} +## ... puedes usar la misma sintaxis de hash de un "booleano corto": +takes-a-bool('config', :bool); # config toma True +takes-a-bool('config', :!bool); # config toma False + +## También puedes proveer tus argumentos nombrados con valores por defecto: +sub nombrado-definido(:$def = 5) { + say $def; +} +nombrado-definido; #=> 5 +nombrado-definido(def => 15); #=> 15 + +## Dado que puedes omitir los paréntesis para invocar una función sin +## argumentos, necesitas usar "&" en el nombre para almacenar la función +## `di-hola` en una variable. +my &s = &di-hola; +my &otra-s = sub { say "¡Función anónima!" } + +## Una subrutina puede tener un parámetro "slurpy", o "no importa cuantos", +## indicando que la función puede recibir cualquier número de parámetros. +sub muchos($principal, *@resto) { #`*@` (slurpy) consumirá lo restante +## Nota: Puedes tener parámetros *antes que* un parámetro "slurpy" (como +## aquí) pero no *después* de uno. + say @resto.join(' / ') ~ "!"; +} +say muchos('Feliz', 'Cumpleaño', 'Cumpleaño'); #=> Feliz / Cumpleaño! + # Nota que el asterisco (*) no + # consumió el parámetro frontal. + +## Puedes invocar un función con un array usando el +## operador "aplanador de lista de argumento" `|` +## (actualmente no es el único rol de este operador pero es uno de ellos) +sub concat3($a, $b, $c) { + say "$a, $b, $c"; +} +concat3(|@array); #=> a, b, c + # `@array` fue "aplanado" como parte de la lista de argumento +``` + +## Contenedores + +```perl6 +## En Raku, valores son actualmente almacenados en "contenedores". +## El operador de asignación le pregunta al contenedor en su izquierda +## almacenar el valor a su derecha. Cuando se pasan alrededor, contenedores +## son marcados como inmutables. Esto significa que, en una función, tu +## tendrás un error si tratas de mutar uno de tus argumentos. +## Si realmente necesitas hacerlo, puedes preguntar por un contenedor +## mutable usando `is rw`: +sub mutar($n is rw) { + $n++; + say "¡\$n es ahora $n!"; +} + +my $m = 42; +mutar $m; # ¡$n es ahora 43! + +## Esto funciona porque estamos pasando el contenedor $m para mutarlo. Si +## intentamos pasar un número en vez de pasar una variable, no funcionará +## dado que no contenedor ha sido pasado y números enteros son inmutables +## por naturaleza: + +mutar 42; # Parámetro '$n' esperaba un contenedor mutable, + # pero recibió un valor Int + +## Si en cambio quieres una copia, debes usar `is copy`. + +## Por si misma, una subrutina devuelve un contenedor, lo que significa +## que puede ser marcada con rw: +my $x = 42; +sub x-almacena() is rw { $x } +x-almacena() = 52; # En este caso, los paréntesis son mandatorios + # (porque de otra forma, Raku piensa que la función + # `x-almacena` es un identificador). +say $x; #=> 52 +``` + +## Estructuras de control +### Condicionales + +```perl6 +## - `if` +## Antes de hablar acerca de `if`, necesitamos saber cuales valores son +## "Truthy" (representa True (verdadero)), y cuales son "Falsey" +## (o "Falsy") -- representa False (falso). Solo estos valores son +## Falsey: 0, (), {}, "", Nil, un tipo (como `Str` o`Int`) y +## por supuesto False. Todos los valores son Truthy. +if True { + say "¡Es verdadero!"; +} + +unless False { + say "¡No es falso!"; +} + +## Como puedes observar, no necesitas paréntesis alrededor de condiciones. +## Sin embargo, necesitas las llaves `{}` alrededor del cuerpo de un bloque: +# if (true) say; # !Esto no funciona! + +## También puedes usar sus versiones sufijos seguidas por la palabra clave: +say "Un poco verdadero" if True; + +## - La condicional ternaria, "?? !!" (como `x ? y : z` en otros lenguajes) +## devuelve $valor-si-verdadera si la condición es verdadera y +## $valor-si-falsa si es falsa. +## my $resultado = $valor condición ?? $valor-si-verdadera !! $valor-si-falsa; + +my $edad = 30; +say $edad > 18 ?? "Eres un adulto" !! "Eres menor de 18"; +``` + +### given/when, ó switch + +```perl6 +## - `given`-`when` se parece al `switch` de otros lenguajes, pero es más +## poderoso gracias a la coincidencia inteligente ("smart matching" en inglés) +## y la "variable tópica" $_ de Perl. +## +## Esta variable ($_) contiene los argumentos por defecto de un bloque, +## la iteración actual de un loop (a menos que sea explícitamente +## nombrado), etc. +## +## `given` simplemente pone su argumento en `$_` (como un bloque lo haría), +## y `when` lo compara usando el operador de "coincidencia inteligente" (`~~`). +## +## Dado que otras construcciones de Raku usan esta variable (por ejemplo, +## el bucle `for`, bloques, etc), esto se significa que el poderoso `when` no +## solo se aplica con un `given`, sino que se puede usar en cualquier +## lugar donde exista una variable `$_`. + +given "foo bar" { + say $_; #=> foo bar + when /foo/ { # No te preocupies acerca de la coincidencia inteligente – + # solo ten presente que `when` la usa. + # Esto es equivalente a `if $_ ~~ /foo/`. + say "¡Yay!"; + } + when $_.chars > 50 { # coincidencia inteligente con cualquier cosa True es True, + # i.e. (`$a ~~ True`) + # por lo tanto puedes también poner condiciones "normales". + # Este `when` es equivalente a este `if`: + # if $_ ~~ ($_.chars > 50) {...} + # que significa: + # if $_.chars > 50 {...} + say "¡Una cadena de texto bien larga!"; + } + default { # lo mismo que `when *` (usando la Whatever Star) + say "Algo más"; + } +} +``` + +### Construcciones de bucle + +```perl6 +## - `loop` es un bucle infinito si no le pasas sus argumentos, +## pero también puede ser un bucle for al estilo de C: +loop { + say "¡Este es un bucle infinito!"; + last; # last interrumpe el bucle, como la palabra clave `break` + # en otros lenguajes. +} + +loop (my $i = 0; $i < 5; $i++) { + next if $i == 3; # `next` salta a la siguiente iteración, al igual + # que `continue` en otros lenguajes. Ten en cuenta que + # también puedes usar la condicionales postfix (sufijas) + # bucles, etc. + say "¡Este es un bucle al estilo de C!"; +} + +## - `for` - Hace iteraciones en un array +for @array -> $variable { + say "¡He conseguido una $variable!"; +} + +## Como vimos con `given`, la variable de una "iteración actual" por defecto +## es `$_`. Esto significa que puedes usar `when` en un bucle `for` como +## normalmente lo harías con `given`. +for @array { + say "he conseguido a $_"; + + .say; # Esto es también permitido. + # Una invocación con punto (dot call) sin "tópico" (recibidor) es + # enviada a `$_` por defecto. + $_.say; # lo mismo de arriba, lo cual es equivalente. +} + +for @array { + # Puedes... + next if $_ == 3; # Saltar a la siguiente iteración (`continue` en + # lenguages parecido a C) + redo if $_ == 4; # Re-hacer la iteración, manteniendo la + # misma variable tópica (`$_`) + last if $_ == 5; # Salir fuera del bucle (como `break` + # en lenguages parecido a C) +} + +## La sintaxis de "bloque puntiagudo" no es específica al bucle for. +## Es solo una manera de expresar un bloque en Raku. +if computación-larga() -> $resultado { + say "El resultado es $resultado"; +} +``` + +## Operadores + +```perl6 +## Dados que los lenguajes de la familia Perl son lenguages basados +## mayormente en operadores, los operadores de Raku son actualmente +## subrutinas un poco cómicas en las categorías sintácticas. Por ejemplo, +## infix:<+> (adición) o prefix: (bool not). + +## Las categorías son: +## - "prefix" (prefijo): anterior a (como `!` en `!True`). +## - "postfix" (sufijo): posterior a (como `++` en `$a++`). +## - "infix" (infijo): en medio de (como `*` en `4 * 3`). +## - "circumfix" (circunfijo): alrededor de (como `[`-`]` en `[1, 2]`). +## - "post-circumfix" (pos-circunfijo): alrededor de un término, +## posterior a otro término. +## (como `{`-`}` en `%hash{'key'}`) + +## La lista de asociatividad y precedencia se explica más abajo. + +## ¡Bueno, ya estás listo(a)! + +## * Chequeando igualdad + +## - `==` se usa en comparaciones numéricas. +3 == 4; # Falso +3 != 4; # Verdadero + +## - `eq` se usa en comparaciones de cadenas de texto. +'a' eq 'b'; +'a' ne 'b'; # no igual +'a' !eq 'b'; # lo mismo que lo anterior + +## - `eqv` es equivalencia canónica (or "igualdad profunda") +(1, 2) eqv (1, 3); + +## - Operador de coincidencia inteligente (smart matching): `~~` +## Asocia (aliasing en inglés) el lado izquierda a la variable $_ +## y después evalúa el lado derecho. +## Aquí algunas comparaciones semánticas comunes: + +## Igualdad de cadena de texto o numérica + +'Foo' ~~ 'Foo'; # True si las cadenas de texto son iguales. +12.5 ~~ 12.50; # True si los números son iguales. + +## Regex - Para la comparación de una expresión regular en contra +## del lado izquierdo. Devuelve un objeto (Match), el cual evalúa +## como True si el regex coincide con el patrón. + +my $obj = 'abc' ~~ /a/; +say $obj; # 「a」 +say $obj.WHAT; # (Match) + +## Hashes +'llave' ~~ %hash; # True si la llave existe en el hash + +## Tipo - Chequea si el lado izquierdo "tiene un tipo" (puede chequear +## superclases y roles) + +1 ~~ Int; # True (1 es un número entero) + +## Coincidencia inteligente contra un booleano siempre devuelve ese +## booleano (y lanzará una advertencia). + +1 ~~ True; # True +False ~~ True; # True + +## La sintaxis general es $arg ~~ &función-returnando-bool; +## Para una lista completa de combinaciones, usa esta tabla: +## http://perlcabal.org/syn/S03.html#Smart_matching + +## También, por supuesto, tienes `<`, `<=`, `>`, `>=`. +## Sus equivalentes para cadenas de texto están disponibles: +## `lt`, `le`, `gt`, `ge`. +3 > 4; + +## * Constructores de rango +3 .. 7; # 3 a 7, ambos incluidos +## `^` en cualquier lado excluye a ese lado: +3 ^..^ 7; # 3 a 7, no incluidos (básicamente `4 .. 6`) +## Esto también funciona como un atajo para `0..^N`: +^10; # significa 0..^10 + +## Esto también nos permite demostrar que Raku tiene arrays +## ociosos/infinitos, usando la Whatever Star: +my @array = 1..*; # 1 al Infinito! `1..Inf` es lo mismo. +say @array[^10]; # puedes pasar arrays como subíndices y devolverá + # un array de resultados. Esto imprimirá + # "1 2 3 4 5 6 7 8 9 10" (y no se quedaré sin memoria!) +## Nota: Al leer una lista infinita, Raku "cosificará" los elementos que +## necesita y los mantendrá en la memoria. Ellos no serán calculados más de +## una vez. Tampoco calculará más elementos de los que necesita. + +## Un índice de array también puede ser una clausura ("closure" en inglés). +## Será llamada con la longitud como el argumento +say join(' ', @array[15..*]); #=> 15 16 17 18 19 +## lo que es equivalente a: +say join(' ', @array[-> $n { 15..$n }]); +## Nota: Si tratas de hacer cualquiera de esos con un array infinito, +## provocará un array infinito (tu programa nunca terminará) + +## Puedes usar eso en los lugares que esperaría, como durante la asignación +## a un array +my @números = ^20; + +## Aquí los números son incrementados por "6"; más acerca del +## operador `...` adelante. +my @seq = 3, 9 ... * > 95; # 3 9 15 21 27 [...] 81 87 93 99; +@números[5..*] = 3, 9 ... *; # aunque la secuencia es infinita, + # solo los 15 números necesarios será calculados. +say @números; #=> 0 1 2 3 4 3 9 15 21 [...] 81 87 + # (solamente 20 valores) + +## * And &&, Or || +3 && 4; # 4, el cual es Truthy. Invoca `.Bool` en `4` y obtiene `True`. +0 || False; # False. Invoca `.Bool` en `0` + +## * Versiones circuito corto de lo de arriba +## && Devuelve el primer argumento que evalúa a False, o el último. + +my ( $a, $b, $c ) = 1, 0, 2; +$a && $b && $c; # Devuelve 0, el primer valor que es False + +## || Devuelve el primer argumento que evalúa a True. +$b || $a; # 1 + +## Y porque tu lo querrás, también tienes operadores de asignación +## compuestos: +$a *= 2; # multiplica y asigna. Equivalente a $a = $a * 2; +$b %%= 5; # divisible por y asignación. Equivalente $b = $b %% 5; +@array .= sort; # invoca el método `sort` y asigna el resultado devuelto. +``` + +## ¡Más sobre subrutinas! + +```perl6 +## Como dijimos anteriormente, Raku tiene subrutinas realmente poderosas. +## Veremos unos conceptos claves que la hacen mejores que en cualquier otro +## lenguaje :-). +``` + +### !Desempacado! + +```perl6 +## Es la abilidad de extraer arrays y llaves (También conocido como +## "destructuring"). También funcionará en `my` y en las listas de parámetros. +my ($f, $g) = 1, 2; +say $f; #=> 1 +my ($, $, $h) = 1, 2, 3; # mantiene los anónimos no interesante +say $h; #=> 3 + +my ($cabeza, *@cola) = 1, 2, 3; # Sí, es lo mismo que con subrutinas "slurpy" +my (*@small) = 1; + +sub desempacar_array(@array [$fst, $snd]) { + say "Mi primero es $fst, mi segundo es $snd! De todo en todo, soy un @array[]."; + # (^ recuerda que `[]` interpola el array) +} +desempacar_array(@cola); #=> My first is 2, my second is 3 ! All in all, I'm 2 3 + + +## Si no está usando el array, puedes también mantenerlo anónimo, como un +## escalar: +sub primero-de-array(@ [$fst]) { $fst } +primero-de-array(@small); #=> 1 +primero-de-array(@tail); # Lanza un error "Demasiados argumentos posicionales + # proveídos" + # (lo que significa que el array es muy grande). + +## También puedes usar un slurp ... +sub slurp-en-array(@ [$fst, *@rest]) { # Podrías mantener `*@rest` anónimos + say $fst + @rest.elems; # `.elems` returna la longitud de una lista. + # Aquí, `@rest` es `(3,)`, since `$fst` holds the `2`. +} +slurp-en-array(@tail); #=> 3 + +## Hasta podrías hacer un extracción usando una slurpy (pero no sería útil ;-).) +sub fst(*@ [$fst]) { # o simplemente: `sub fst($fst) { ... }` + say $fst; +} +fst(1); #=> 1 +fst(1, 2); # errores con "Too many positional parameters passed" + +## También puedes desestructurar hashes (y clases, las cuales +## veremos adelante). La sintaxis es básicamente +## `%nombre-del-hash (:llave($variable-para-almacenar))`. +## El hash puede permanecer anónimos si solo necesitas los valores extraídos. +sub llave-de(% (:azul($val1), :red($val2))) { + say "Valores: $val1, $val2."; +} +## Después invócala con un hash: (necesitas mantener las llaves +## de los parejas de llave y valor para ser un hash) +llave-de({azul => 'blue', rojo => "red"}); +#llave-de(%hash); # lo mismo (para un `%hash` equivalente) + +## La última expresión de una subrutina es devuelta inmediatamente +## (aunque puedes usar la palabra clave `return`): +sub siguiente-indice($n) { + $n + 1; +} +my $nuevo-n= siguiente-indice(3); # $nuevo-n es ahora 4 + +## Este es cierto para todo, excepto para las construcciones de bucles +## (debido a razones de rendimiento): Hay una razón de construir una lista +## si la vamos a desechar todos los resultados. +## Si todavías quieres construir una, puedes usar la sentencia prefijo `do`: +## (o el prefijo `gather`, el cual veremos luego) +sub lista-de($n) { + do for ^$n { # nota el uso del operador de rango `^` (`0..^N`) + $_ # iteración de bucle actual + } +} +my @list3 = lista-de(3); #=> (0, 1, 2) +``` + +### lambdas + +```perl6 +## Puedes crear una lambda con `-> {}` ("bloque puntiagudo") o `{}` ("bloque") +my &lambda = -> $argumento { "El argumento pasado a esta lambda es $argumento" } +## `-> {}` y `{}` son casi la misma cosa, excepto que la primerra puede +## tomar argumentos, y la segunda puede ser malinterpretada como un hash +## por el parseador. + +## Podemos, por ejemplo, agregar 3 a cada valor de un array usando map: +my @arraymas3 = map({ $_ + 3 }, @array); # $_ es el argumento implícito + +## Una subrutina (`sub {}`) tiene semánticas diferentes a un +## bloque (`{}` or `-> {}`): Un bloque no tiene "contexto funcional" +## (aunque puede tener argumentos), lo que significa que si quieres devolver +## algo desde un bloque, vas a returnar desde la función parental. Compara: +sub is-in(@array, $elem) { + # esto `devolverá` desde la subrutina `is-in` + # Una vez que la condición evalúa a True, el bucle terminará + map({ return True if $_ == $elem }, @array); +} +sub truthy-array(@array) { + # esto producirá un array de `True` Y `False`: + # (también puedes decir `anon sub` para "subrutina anónima") + map(sub ($i) { if $i { return True } else { return False } }, @array); + # ^ el `return` solo devuelve desde la `sub` +} + +## También puedes usar la "whatever star" para crear una función anónima +## (terminará con el último operador en la expresión actual) +my @arraymas3 = map(*+3, @array); # `*+3` es lo mismo que `{ $_ + 3 }` +my @arraymas3 = map(*+*+3, @array); # lo mismo que `-> $a, $b { $a + $b + 3 }` + # también `sub ($a, $b) { $a + $b + 3 }` +say (*/2)(4); #=> 2 + # Inmediatamente ejecuta la función que Whatever creó. +say ((*+3)/5)(5); #=> 1.6 + # ¡funciona hasta con los paréntesis! + +## Pero si necesitas más que un argumento (`$_`) en un bloque +## (sin depender en `-> {}`), también puedes usar la sintaxis implícita +## de argumento, `$` : +map({ $^a + $^b + 3 }, @array); # equivalente a lo siguiente: +map(sub ($a, $b) { $a + $b + 3 }, @array); # (aquí con `sub`) + +## Nota : Esos son ordernados lexicográficamente. +# `{ $^b / $^a }` es como `-> $a, $b { $b / $a }` +``` + +### Acerca de tipos... + +```perl6 +## Raku es gradualmente tipado. Esto quiere decir que tu especifica el +## tipo de tus variables/argumentos/devoluciones (return), o puedes omitirlos +## y serán "Any" por defecto. +## Obviamente tienes acceso a algunas tipos básicos, como Int y Str. +## Las construcciones para declarar tipos son "class", "role", lo cual +## verás más adelante. + +## Por ahora, examinemos "subset" (subconjunto). +## Un "subset" es un "sub-tipo" con chequeos adicionales. +## Por ejemplo: "un número entero bien grande es un Int que es mayor que 500" +## Puedes especificar el tipo del que creas el subconjunto (por defecto, Any), +## y añadir chequeos adicionales con la palabra clave "where" (donde): +subset EnteroGrande of Int where * > 500; +``` + +### Despacho Múltiple (Multiple Dispatch) + +```perl6 +## Raku puede decidir que variante de una subrutina invocar basado en el +## tipo de los argumento, o precondiciones arbitrarias, como con un tipo o +## un `where`: + +## con tipos +multi sub dilo(Int $n) { # nota la palabra clave `multi` aquí + say "Número: $n"; +} +multi dilo(Str $s) { # un multi es una subrutina por defecto + say "Cadena de texto: $s"; +} +dilo("azul"); # prints "Cadena de texto: azul" +dilo(True); # falla al *tiempo de compilación* con + # "calling 'dilo' will never work with arguments of types ..." + # (invocar 'dilo' nunca funcionará con argumentos de tipos ...") +## con precondición arbitraria (¿recuerdas los subconjuntos?): +multi es-grande(Int $n where * > 50) { "¡Sí!" } # usando una clausura +multi es-grande(Int $ where 10..50) { "Tal vez." } # Usando coincidencia inteligente + # (podrías usar un regexp, etc) +multi es-grande(Int $) { "No" } + +subset Par of Int where * %% 2; + +multi inpar-o-par(Par) { "Par" } # El caso principal usando el tipo. + # No nombramos los argumentos, +multi inpar-o-par($) { "Inpar" } # "else" + +## ¡Podrías despachar basado en la presencia de argumentos posicionales! +multi sin_ti-o-contigo(:$with!) { # Necesitas hacerlo mandatorio + # para despachar en contra del argumento. + say "¡Puedo vivir! Actualmente, no puedo."; +} +multi sin_ti-o-contigo { + say "Definitivamente no puedo vivir."; +} +## Esto es muy útil para muchos propósitos, como subrutinas `MAIN` (de las +## cuales hablaremos luego), y hasta el mismo lenguaje la está usando +## en muchos lugares. +## +## - `is`, por ejemplo, es actualmente un `multi sub` llamado +## `trait_mod:`. +## - `is rw`, es simplemente un despacho a una función con esta signatura: +## sub trait_mod:(Routine $r, :$rw!) {} +## +## (¡lo pusimos en un comentario dado que ejecutando esto sería una terrible +## idea!) +``` + +## Ámbito (Scoping) + +```perl6 +## En Raku, a diferencia de otros lenguajes de scripting, (tales como +## (Python, Ruby, PHP), debes declarar tus variables antes de usarlas. El +## declarador `my`, del cual aprendiste anteriormente, usa "ámbito léxical". +## Hay otros declaradores (`our`, `state`, ..., ) los cuales veremos luego. +## Esto se llama "ámbito léxico", donde en los bloques internos, +## puedes acceder variables de los bloques externos. +my $archivo-en-ámbito = 'Foo'; +sub externo { + my $ámbito-externo = 'Bar'; + sub interno { + say "$archivo-en-ámbito $ámbito-externo"; + } + &interno; # devuelve la función +} +outer()(); #=> 'Foo Bar' + +## Como puedes ver, `$archivo-en-ámbito` y `$ámbito-externo` +## fueron capturados. Pero si intentaramos usar `$bar` fuera de `foo`, +## la variable estaría indefinida (y obtendrías un error al tiempo de +## compilación). +``` + +## Twigils + +```perl6 +## Hay muchos `twigils` especiales (sigilos compuestos) en Raku. +## Los twigils definen el ámbito de las variables. +## Los twigils * y ? funcionan con variables regulares: +## * Variable dinámica +## ? Variable al tiempo de compilación +## Los twigils ! y . son usados con los objetos de Raku: +## ! Atributo (miembro de la clase) +## . Método (no una variable realmente) + +## El twigil `*`: Ámbito dinámico +## Estas variables usan el twigil `*` para marcar variables con ámbito +## dinámico. Variables con ámbito dinámico son buscadas a través del +## invocador, no a través del ámbito externo. + +my $*ambito_din_1 = 1; +my $*ambito_din_2 = 10; + +sub di_ambito { + say "$*ambito_din_1 $*ambito_din_2"; +} + +sub invoca_a_di_ambito { + my $*ambito_din_1 = 25; # Define a $*ambito_din_1 solo en esta subrutina. + $*ambito_din_2 = 100; # Cambiará el valor de la variable en ámbito. + di_ambito(); #=> 25 100 $*ambito_din_1 y 2 serán buscadas en la invocación. + # Se usa el valor de $*ambito_din_1 desde el ámbito léxico de esta + # subrutina aunque los bloques no están anidados (están anidados por + # invocación). +} +di_ambito(); #=> 1 10 +invoca_a_di_ambito(); #=> 25 100 + # Se usa a $*ambito_din_1 como fue definida en invoca_a_di_ambito + # aunque la estamos invocando desde afuera. +di_ambito(); #=> 1 100 Cambiamos el valor de $*ambito_din_2 en invoca_a_di_ambito + # por lo tanto su valor a cambiado. +``` + +## Modelo de Objeto + +```perl6 +## Para invocar a un método en un objeto, agrega un punto seguido por el +## nombre del objeto: +## => $object.method +## Las classes son declaradas usando la palabra clave `class`. Los atributos +## son declarados con la palabra clave `has`, y los métodos con `method`. +## Cada atributo que es privado usa el twigil `!`. Por ejemplo: `$!attr`. +## Atributos públicos inmutables usan el twigil `.` (los puedes hacer +## mutables con `is rw`). +## La manera más fácil de recordar el twigil `$.` is comparándolo +## con como los métodos son llamados. + +## El modelo de objeto de Raku ("SixModel") es muy flexible, y te permite +## agregar métodos dinámicamente, cambiar la semántica, etc ... +## (no hablaremos de todo esto aquí. Por lo tanto, refiérete a: +## https://docs.raku.org/language/objects.html). + +class Clase-Atrib { + has $.atrib; # `$.atrib` es inmutable. + # Desde dentro de la clase, usa `$!atrib` para modificarlo. + has $.otro-atrib is rw; # Puedes marcar un atributo como público con `rw`. + has Int $!atrib-privado = 10; + + method devolver-valor { + $.atrib + $!atrib-privado; + } + + method asignar-valor($param) { # Métodos pueden tomar parámetros. + $!attrib = $param; # Esto funciona porque `$!` es siempre mutable. + # $.attrib = $param; # Incorrecto: No puedes usar la versión inmutable `$.`. + + $.otro-atrib = 5; # Esto funciona porque `$.otro-atrib` es `rw`. + } + + method !metodo-privado { + say "Este método es privado para la clase !"; + } +}; + +## Crear una nueva instancia de Clase-Atrib con $.atrib asignado con 5: +## Nota: No puedes asignarle un valor a atrib-privado desde aquí (más de +## esto adelante). +my $class-obj = Clase-Atrib.new(atrib => 5); +say $class-obj.devolver-valor; #=> 5 +# $class-obj.atrib = 5; # Esto falla porque `has $.atrib` es inmutable +$class-obj.otro-atrib = 10; # En cambio, esto funciona porque el atributo + # público es mutable (`rw`). +``` + +### Herencia de Objeto + +```perl6 +## Raku también tiene herencia (junto a herencia múltiple) +## Mientras los métodos declarados con `method` son heredados, aquellos +## declarados con `submethod` no lo son. +## Submétodos son útiles para la construcción y destrucción de tareas, +## tales como BUILD, o métodos que deben ser anulados por subtipos. +## Aprenderemos acerca de BUILD más adelante. + +class Padre { + has $.edad; + has $.nombre; + # Este submétodo no será heredado por la clase Niño. + submethod color-favorito { + say "Mi color favorito es Azul"; + } + # Este método será heredado + method hablar { say "Hola, mi nombre es $!nombre" } +} +# Herencia usa la palabra clave `is` +class Niño is Padre { + method hablar { say "Goo goo ga ga" } + # Este método opaca el método `hablar` de Padre. + # Este niño no ha aprendido a hablar todavía. +} +my Padre $Richard .= new(edad => 40, nombre => 'Richard'); +$Richard.color-favorito; #=> "Mi color favorito es Azul" +$Richard.hablar; #=> "Hola, mi nombre es Richard" +## $Richard es capaz de acceder el submétodo; él sabe como decir su nombre. + +my Niño $Madison .= new(edad => 1, nombre => 'Madison'); +$Madison.hablar; # imprime "Goo goo ga ga" dado que el método fue cambiado + # en la clase Niño. +# $Madison.color-favorito # no funciona porque no es heredado + +## Cuando se usa `my T $var` (donde `T` es el nombre de la clase), `$var` +## inicia con `T` en si misma, por lo tanto puedes invocar `new` en `$var`. +## (`.=` es sólo la invocación por punto y el operador de asignación: +## `$a .= b` es lo mismo que `$a = $a.b`) +## Por ejemplo, la instancia $Richard pudo también haber sido declarada así: +## my $Richard = Padre.new(edad => 40, nombre => 'Richard'); + +## También observa que `BUILD` (el método invocado dentro de `new`) +## asignará propiedades de la clase padre, por lo que puedes pasar +## `val => 5`. +``` + +### Roles, o Mixins + +```perl6 +## Roles son suportados también (comúnmente llamados Mixins en otros +## lenguajes) +role PrintableVal { + has $!counter = 0; + method print { + say $.val; + } +} + +## Se "importa" un mixin (un "role") con "does": +class Item does PrintableVal { + has $.val; + + ## Cuando se utiliza `does`, un `rol` se mezcla en al clase literalmente: + ## los métodos y atributos se ponen juntos, lo que significa que una clase + ## puede acceder los métodos y atributos privados de su rol (pero no lo inverso!): + method access { + say $!counter++; + } + + ## Sin embargo, esto: + ## method print {} + ## es SÓLO válido cuando `print` no es una `multi` con el mismo dispacho. + ## (esto significa que una clase padre puede opacar una `multi print() {}` + ## de su clase hijo/a, pero es un error sin un rol lo hace) + + ## NOTA: Puedes usar un rol como una clase (con `is ROLE`). En este caso, + ## métodos serán opacados, dado que el compilador considerará `ROLE` + ## como una clase. +} +``` + +## Excepciones + +```perl6 +## Excepciones están construidas al tope de las clases, en el paquete +## `X` (como `X::IO`). +## En Raku, excepciones son lanzadas automáticamente. +open 'foo'; #=> Failed to open file foo: no such file or directory +## También imprimirá la línea donde el error fue lanzado y otra información +## concerniente al error. + +## Puedes lanzar una excepción usando `die`: +die 'Error!'; #=> Error! + +## O más explícitamente: +die X::AdHoc.new(payload => 'Error!'); + +## En Raku, `orelse` es similar al operador `or`, excepto que solamente +## coincide con variables indefinidas, en cambio de cualquier cosa +## que evalúa a falso. +## Valores indefinidos incluyen: `Nil`, `Mu` y `Failure`, también como +## `Int`, `Str` y otros tipos que no han sido inicializados a ningún valor +## todavía. +## Puedes chequear si algo está definido o no usando el método defined: +my $no-inicializada; +say $no-inicializada.defined; #=> False +## Al usar `orelse`, se desarmará la excepción y creará un alias de dicho +## fallo en $_ +## Esto evitará que sea automáticamente manejado e imprima una marejada de +## mensajes de errores en la pantalla. +## Podemos usar el método de excepción en $_ para acceder la excepción: +open 'foo' orelse say "Algo pasó {.exception}"; + +## Esto también funciona: +open 'foo' orelse say "Algo pasó $_"; #=> Algo pasó + #=> Failed to open file foo: no such file or directory +## Ambos ejemplos anteriores funcionan pero en caso de que consigamos un +## objeto desde el lado izquierdo que no es un fallo, probablemente +## obtendremos una advertencia. Más abajo vemos como usar `try` y `CATCH` +## para ser más expecíficos con las excepciones que capturamos. +``` + +### Usando `try` y `CATCH` + +```perl6 +## Al usar `try` y `CATCH`, puedes contener y manejar excepciones sin +## interrumpir el resto del programa. `try` asignará la última excepción +## a la variable especial `$!`. +## Nota: Esto no tiene ninguna relación con las variables $!. + +try open 'foo'; +say "Bueno, lo intenté! $!" if defined $!; #=> Bueno, lo intenté! Failed to open file + #foo: no such file or directory +## Ahora, ¿qué debemos hacer si queremos más control sobre la excepción? +## A diferencia de otros lenguajes, en Raku se pone el bloque `CATCH` +## *dentro* del bloque a intentar (`try`). Similarmente como $_ fue asignada +## cuando 'disarmamos' la excepción con `orelse`, también usamos $_ en el +## bloque CATCH. +## Nota: ($! es solo asignada *después* del bloque `try`) +## Por defecto, un bloque `try` tiene un bloque `CATCH` que captura +## cualquier excepción (`CATCH { default {} }`). + +try { my $a = (0 %% 0); CATCH { say "Algo pasó: $_" } } + #=> Algo pasó: Attempt to divide by zero using infix:<%%> + +## Puedes redefinir lo anterior usando `when` y (`default`) +## para manejar las excepciones que desees: +try { + open 'foo'; + CATCH { # En el bloque `CATCH`, la excepción es asignada a $_ + when X::AdHoc { say "Error: $_" } + #=>Error: Failed to open file /dir/foo: no such file or directory + + ## Cualquier otra excepción será levantada de nuevo, dado que no + ## tenemos un `default`. + ## Básicamente, si un `when` + ## Basically, if a `when` matches (or there's a `default`) marks the + ## exception as + ## "handled" so that it doesn't get re-thrown from the `CATCH`. + ## You still can re-throw the exception (see below) by hand. + } +} + +## En Raku, excepciones poseen ciertas sutilezas. Algunas +## subrutinas en Raku devuelven un `Failure`, el cual es un tipo de +## "excepción no levantada". Ellas no son levantadas hasta que tu intentas +## mirar a sus contenidos, a menos que invoques `.Bool`/`.defined` sobre +## ellas - entonces, son manejadas. +## (el método `.handled` es `rw`, por lo que puedes marcarlo como `False` +## por ti mismo) +## Puedes levantar un `Failure` usando `fail`. Nota que si el pragma +## `use fatal` estás siendo utilizado, `fail` levantará una excepión (como +## `die`). +fail "foo"; # No estamos intentando acceder el valor, por lo tanto no problema. +try { + fail "foo"; + CATCH { + default { say "Levantó un error porque intentamos acceder el valor del fallo!" } + } +} + +## También hay otro tipo de excepción: Excepciones de control. +## Esas son excepciones "buenas", las cuales suceden cuando cambias el flujo +## de tu programa, usando operadores como `return`, `next` or `last`. +## Puedes capturarlas con `CONTROL` (no lista un 100% en Rakudo todavía). +``` + +## Paquetes + +```perl6 +## Paquetes son una manera de reusar código. Paquetes son como +## "espacio de nombres" (namespaces en inglés), y cualquier elemento del +## modelo seis (`module`, `role`, `class`, `grammar`, `subset` y `enum`) +## son paquetes por ellos mismos. (Los paquetes son como el mínimo común +## denominador) +## Los paquetes son importantes - especialmente dado que Perl es bien +## reconocido por CPAN, the Comprehensive Perl Archive Nertwork. + +## Puedes usar un módulo (traer sus declaraciones al ámbito) con `use` +use JSON::Tiny; # si intalaste Rakudo* o Panda, tendrás este módulo +say from-json('[1]').perl; #=> [1] + +## A diferencia de Perl, no deberías declarar paquetes usando +## la palabra clave `package`. En vez, usa `class Nombre::Paquete::Aquí;` +## para declarar una clase, o si solamente quieres exportar +## variables/subrutinas, puedes usar `module`. + +module Hello::World { # forma de llaves + # Si `Hello` no existe todavía, solamente será una cola ("stub"), + # que puede ser redeclarada más tarde. + # ... declaraciones aquí ... +} +unit module Parse::Text; # forma de ámbito de archivo + +grammar Parse::Text::Grammar { # Una gramática (grammar en inglés) es un paquete, + # en el cual puedes usar `use` +} # Aprenderás más acerca de gramáticas en la sección de regex + +## Como se dijo anteriormente, cualquier parte del modelo seis es también un +## paquete. Dado que `JSON::Tiny` usa su propia clase `JSON::Tiny::Actions`, +## tu puedes usarla de la manera siguiente: +my $acciones = JSON::Tiny::Actions.new; + +## Veremos como exportar variables y subrutinas en la siguiente parte: +``` + +## Declaradores + +```perl6 +## En Raku, tu obtienes diferentes comportamientos basado en como declaras +## una variable. +## Ya has visto `my` y `has`, ahora exploraremos el resto. + +## * las declaraciones `our` ocurren al tiempo `INIT` (ve "Phasers" más abajo) +## Es como `my`, pero también crea una variable paquete. +## (Todas las cosas relacionadas con paquetes (`class`, `role`, etc) son +## `our` por defecto) +module Var::Incrementar { + our $nuestra-var = 1; # Nota: No puedes colocar una restricción de tipo + my $mi-var = 22; # como Int (por ejemplo) en una variable `our`. + our sub Inc { + + our sub disponible { # Si tratas de hacer subrutinas internas `our`... + # Mejor que sepas lo que haces (No lo haga!). + say "No hagas eso. En serio. Estás jugando con fuego y te quemarás."; + } + + my sub no-disponible { # `my sub` es por defecto + say "No puedes acceder aquí desde fuera. Soy 'my'!"; + } + say ++$nuestra-var; # Incrementa la variable paquete y muestra su valor + } + +} +say $Var::Incrementar::nuestra-var; #=> 1 Esto funciona +say $Var::Incrementar::mi-var; #=> (Any) Esto no funcionará. + +Var::Incrementar::Inc; #=> 2 +Var::Incrementar::Inc; #=> 3 # Nota como el valor de $nuestra-var fue + # retenido +Var::Incrementar::no-disponible; #=> Could not find symbol '&no-disponible' + +## * `constant` (ocurre al tiempo `BEGIN`) +## Puedes usar la palabra clave `constant` para declarar una +## variable/símbolo al tiempo de compilación: +constant Pi = 3.14; +constant $var = 1; + +## Y por si te estás preguntando, sí, también puede contener listas infinitas. +constant porque-no = 5, 15 ... *; +say porque-no[^5]; #=> 5 15 25 35 45 + +## * `state` (ocurre al tiempo de ejecución, pero una sola vez) +## Variables "states" son solo inicializadas una vez. +## (ellas existen en otros lenguaje como `static` en C) +sub aleatorio-fijo { + state $valor = rand; + say $valor; +} +aleatorio-fijo for ^10; # imprimirá el mismo número 10 veces + +## Nota, sin embargo, que ellas existen separadamente en diferentes contextos. +## Si declaras una función con un `state` dentro de un bucle, recreará la +## variable por cada iteración del bucle. Observa: +for ^5 -> $a { + sub foo { + state $valor = rand; # Esto imprimirá un valor diferente + # por cada valor de `$a` + } + for ^5 -> $b { + say foo; # Esto imprimirá el mismo valor 5 veces, pero sólo 5. + # La siguiente iteración ejecutará `rand` nuevamente. + } +} +``` + +## Phasers + +```perl6 +## Un phaser en Raku es un bloque que ocurre a determinados puntos de tiempo +## en tu programa. Se les llama phaser porque marca un cambio en la fase de +## de tu programa. Por ejemplo, cuando el programa es compilado, un bucle +## for se ejecuta, dejas un bloque, o una excepción se levanta. +## (¡`CATCH` es actualmente un phaser!) +## Algunos de ellos pueden ser utilizados por sus valores devueltos, otros +## no pueden (aquellos que tiene un "[*]" al inicio de su texto de +## explicación). +## ¡Tomemos una mirada! + +## * Phasers al tiempo de compilación +BEGIN { say "[*] Se ejecuta al tiempo de compilación, " ~ + "tan pronto como sea posible, una sola vez" } +CHECK { say "[*] Se ejecuta al tiempo de compilación, " ~ + "tan tarde como sea posible, una sola vez" } + +## * Phasers al tiempo de ejecución +INIT { say "[*] Se ejecuta al tiempo de ejecución, " ~ + "tan pronto como sea posible, una sola vez" } +END { say "Se ejecuta al tiempo de ejecución, " ~ + "tan tarde como sea posible, una sola vez" } + +## * Phasers de bloques +ENTER { say "[*] Se ejecuta cada vez que entra en un bloque, " ~ + "se repite en bloques de bucle" } +LEAVE { say "Se ejecuta cada vez que abandona un bloque, incluyendo " ~ + "cuando una excepción ocurre. Se repite en bloques de bucle"} + +PRE { + say "Impone una precondición a cada entrada de un bloque, " ~ + "antes que ENTER (especialmente útil para bucles)"; + say "Si este bloque no returna un valor truthy, " ~ + "una excepción del tipo X::Phaser::PrePost será levantada."; +} + +## Ejemplos: +for 0..2 { + PRE { $_ > 1 } # Esto fallará con un "Precondition failed" +} + +POST { + say "Impone una postcondAsserts a poscondición a la salida de un bloque, " ~ + "después de LEAVE (especialmente útil para bucles)"; + say "Si este bloque no returna un valor truthy, " ~ + "una excepción del tipo X::Phaser::PrePost será levantada, como con PRE."; +} +for 0..2 { + POST { $_ < 2 } # Esto fallará con un "Postcondition failed" +} + +## * Phasers de bloques/excepciones +sub { + KEEP { say "Se ejecuta cuando sales de un bloque exitosamente + (sin lanzar un excepción)" } + UNDO { say "Se ejecuta cuando sale de bloque sin éxito + (al lanzar una excepción)" } +} + +## * Phasers de bucle +for ^5 { + FIRST { say "[*] La primera vez que un bucle se ejecuta, antes que ENTER" } + NEXT { say "Al tiempo de la continuación del bucle, antes que LEAVE" } + LAST { say "Al tiempo de la terminación del bucle, después de LEAVE" } +} + +## * Phasers de rol/clase +COMPOSE { "Cuando un rol es compuesto en una clase. /!\ NO IMPLEMENTADO TODAVÍA" } + +## Ellos permite pequeños trucos o código brillante...: +say "Este código tomó " ~ (time - CHECK time) ~ "s para compilar"; + +## ... o brillante organización: +sub do-db-stuff { + $db.start-transaction; # comienza una transacción nueva + KEEP $db.commit; # commit (procede con) la transacción si todo estuvo bien + UNDO $db.rollback; # o retrocede si todo falló +} +``` + +## Prefijos de sentencias + +```perl6 +## Los prefijos de sentencias actúan como los phasers: Ellos afectan el +## comportamiento del siguiente código. +## Debido a que son ejecutados en línea con el código ejecutable, ellos +## se escriben en letras minúsculas. (`try` and `start` están teoréticamente +## en esa lista, pero serán explicados en otra parte) +## Nota: Ningunos de estos (excepto `start`) necesitan las llaves `{` y `}`. + +## - `do` (el cual ya viste) - ejecuta un bloque o una sentencia como un +## término. +## Normalmente no puedes usar una sentencia como un valor (o término): +## +## my $valor = if True { 1 } # `if` es una sentencia - error del parseador +## +## Esto funciona: +my $a = do if True { 5 } # con `do`, `if` ahora se comporta como un término. + +## - `once` - se asegura que una porción de código se ejecute una sola vez. +for ^5 { once say 1 }; #=> 1 + # solo imprime ... una sola vez. +## Al igual que `state`, ellos son clonados por ámbito +for ^5 { sub { once say 1 }() } #=> 1 1 1 1 1 + # Imprime una sola vez por ámbito léxico + +## - `gather` - Hilo de co-rutina +## `gather` te permite tomar (`take`) varios valores en un array, +## al igual que `do`. Encima de esto, te permite tomar cualquier expresión. +say gather for ^5 { + take $_ * 3 - 1; + take $_ * 3 + 1; +} #=> -1 1 2 4 5 7 8 10 11 13 +say join ',', gather if False { + take 1; + take 2; + take 3; +} # no imprime nada. + +## - `eager` - Evalúa una sentencia ávidamente (forza contexto ávido) +## No intentes esto en casa: +## +## eager 1..*; # esto probablemente se colgará por un momento +## # (y podría fallar...). +## +## Pero considera lo siguiente: +constant tres-veces = gather for ^3 { say take $_ }; # No imprime nada + +## frente a esto: +constant tres-veces = eager gather for ^3 { say take $_ }; #=> 0 1 2 +``` + +## Iterables + +```perl6 +## En Raku, los iterables son objetos que pueden ser iterados similar +## a la construcción `for`. +## `flat`, aplana iterables: +say (1, 10, (20, 10) ); #=> (1 10 (20 10)) Nota como la agrupación se mantiene +say (1, 10, (20, 10) ).flat; #=> (1 10 20 10) Ahora el iterable es plano + +## - `lazy` - Aplaza la evaluación actual hasta que el valor sea requirido +## (forza contexto perezoso) +my @lazy-array = (1..100).lazy; +say @lazy-array.is-lazy; #=> True # Chequea por "pereza" con el método `is-lazy`. +say @lazy-array; #=> [...] No se ha iterado sobre la lista +for @lazy-array { .print }; # Esto funciona y hará tanto trabajo como sea necesario. + +[//]: # ( TODO explica que gather/take y map son todos perezosos) +## - `sink` - Un `eager` que desecha los resultados (forza el contexto sink) +constant nilthingie = sink for ^3 { .say } #=> 0 1 2 +say nilthingie.perl; #=> Nil + +## - `quietly` - Un bloque `quietly` reprime las advertencias: +quietly { warn 'Esto es una advertencia!' }; #=> No salida + +## - `contend` - Intenta efectos secundarios debajo de STM +## ¡No implementado todavía! +``` + +## ¡Más operadores! + +```perl6 +## ¡Todo el mundo ama los operadores! Tengamos más de ellos. + +## La lista de precedencia puede ser encontrada aquí: +## https://docs.raku.org/language/operators#Operator_Precedence +## Pero primero, necesitamos un poco de explicación acerca +## de la asociatividad: + +## * Operadores binarios: +$a ! $b ! $c; # con asociatividad izquierda `!`, esto es `($a ! $b) ! $c` +$a ! $b ! $c; # con asociatividad derecha `!`, esto es `$a ! ($b ! $c)` +$a ! $b ! $c; # sin asociatividad `!`, esto es ilegal +$a ! $b ! $c; # con una cadena de asociatividad `!`, esto es `($a ! $b) and ($b ! $c)` +$a ! $b ! $c; # con asociatividad de lista `!`, esto es `infix:<>` + +## * Operadores unarios: +!$a! # con asociatividad izquierda `!`, esto es `(!$a)!` +!$a! # con asociatividad derecha `!`, esto es `!($a!)` +!$a! # sin asociatividad `!`, esto es ilegal +``` + +### ¡Crea tus propios operadores! + +```perl6 +## Okay, has leído todo esto y me imagino que debería mostrarte +## algo interesante. +## Te mostraré un pequeño secreto (o algo no tan secreto): +## En Raku, todos los operadores son actualmente solo subrutinas. + +## Puedes declarar un operador como declaras una subrutina: +sub prefix:($ganador) { # se refiere a las categorías de los operadores + # (exacto, es el "operador de palabras" `<>`) + say "¡$ganador ganó!"; +} +ganar "El Rey"; #=> ¡El Rey Ganó! + # (prefijo se pone delante) + +## todavías puedes invocar la subrutina con su "nombre completo": +say prefix:(True); #=> False + +sub postfix:(Int $n) { + [*] 2..$n; # usando el meta-operador reduce ... Ve más abajo! +} +say 5!; #=> 120 + # Operadores sufijos (postfix) van *directamente* después del témino. + # No espacios en blanco. Puedes usar paréntesis para disambiguar, + # i.e. `(5!)!` + + +sub infix:(Int $n, Block $r) { # infijo va en el medio + for ^$n { + $r(); # Necesitas los paréntesis explícitos para invocar la función + # almacenada en la variable `$r`. De lo contrario, te estaría + # refiriendo a la variable (no a la función), como con `&r`. + } +} +3 veces -> { say "hola" }; #=> hola + #=> hola + #=> hola + # Se te recomienda que ponga espacios + # alrededor de la invocación de operador infijo. + +## Para los circunfijos y pos-circunfijos +sub circumfix:<[ ]>(Int $n) { + $n ** $n +} +say [5]; #=> 3125 + # un circunfijo va alrededor. De nuevo, no espacios en blanco. + +sub postcircumfix:<{ }>(Str $s, Int $idx) { + ## un pos-circunfijo es + ## "después de un término y alrededor de algo" + $s.substr($idx, 1); +} +say "abc"{1}; #=> b + # depués del término `"abc"`, y alrededor del índice (1) + +## Esto es de gran valor -- porque todo en Raku usa esto. +## Por ejemplo, para eliminar una llave de un hash, tu usas el adverbio +## `:delete` (un simple argumento con nombre debajo): +%h{$llave}:delete; +## es equivalente a: +postcircumfix:<{ }>(%h, $llave, :delete); # (puedes invocar + # operadores de esta forma) +## ¡*Todos* usan los mismos bloques básicos! +## Categorías sintácticas (prefix, infix, ...), argumentos nombrados +## (adverbios), ... - usados para construir el lenguaje - están al alcance +## de tus manos y disponibles para ti. +## (obviamente, no se te recomienda que hagas un operador de *cualquier +## cosa* -- Un gran poder conlleva una gran responsabilidad.) +``` + +### Meta-operadores! + +```perl6 +## ¡Prepárate! Prepárate porque nos estamos metiendo bien hondo +## en el agujero del conejo, y probablemente no querrás regresar a +## otros lenguajes después de leer esto. +## (Me imagino que ya no quieres a este punto). +## Meta-operadores, como su nombre lo sugiere, son operadores *compuestos*. +## Básicamente, ellos son operadores que se aplican a otros operadores. + +## * El meta-operador reduce (reducir) +## Es un meta-operador prefijo que toman una función binaria y +## una o varias listas. Sino se pasa ningún argumento, +## returna un "valor por defecto" para este operador +## (un valor sin significado) o `Any` si no hay ningún valor. +## +## De lo contrario, remueve un elemento de la(s) lista(s) uno a uno, y +## aplica la función binaria al último resultado (o al primer elemento de +## la lista y el elemento que ha sido removido). +## +## Para sumar una lista, podrías usar el meta-operador "reduce" con `+`, +## i.e.: +say [+] 1, 2, 3; #=> 6 +## es equivalente a `(1+2)+3` + +say [*] 1..5; #=> 120 +## es equivalente a `((((1*2)*3)*4)*5)`. + +## Puedes reducir con cualquier operador, no solo con operadores matemáticos. +## Por ejemplo, podrías reducir con `//` para conseguir +## el primer elemento definido de una lista: +say [//] Nil, Any, False, 1, 5; #=> False + # (Falsey, pero definido) + +## Ejemplos con valores por defecto: +say [*] (); #=> 1 +say [+] (); #=> 0 + # valores sin significado, dado que N*1=N y N+0=N. +say [//]; #=> (Any) + # No hay valor por defecto para `//`. +## También puedes invocarlo con una función de tu creación usando +## los dobles corchetes: +sub add($a, $b) { $a + $b } +say [[&add]] 1, 2, 3; #=> 6 + +## * El meta-operador zip +## Este es un meta-operador infijo que también puede ser usado como un +## operador "normal". Toma una función binaria opcional (por defecto, solo +## crear un par), y remueve un valor de cada array e invoca su función +## binaria hasta que no tenga más elementos disponibles. Al final, returna +## un array con todos estos nuevos elementos. +(1, 2) Z (3, 4); # ((1, 3), (2, 4)), dado que por defecto, la función + # crea un array. +1..3 Z+ 4..6; # (5, 7, 9), usando la función personalizada infix:<+> + +## Dado que `Z` tiene asociatividad de lista (ve la lista más arriba), +## puedes usarlo en más de una lista +(True, False) Z|| (False, False) Z|| (False, False); # (True, False) + +## Y pasa que también puedes usarlo con el meta-operador reduce: +[Z||] (True, False), (False, False), (False, False); # (True, False) + + +## Y para terminar la lista de operadores: + +## * El operador secuencia +## El operador secuencia es uno de la más poderosas características de +## Raku: Está compuesto, en la izquierda, de la lista que quieres que +## Raku use para deducir (y podría incluir una clausura), y en la derecha, +## un valor o el predicado que dice cuando parar (o Whatever para una +## lista infinita perezosa). +my @list = 1, 2, 3 ... 10; # deducción básica +#my @list = 1, 3, 6 ... 10; # esto muere porque Raku no puede deducir el final +my @list = 1, 2, 3 ...^ 10; # como con rangos, puedes excluir el último elemento + # (la iteración cuando el predicado iguala). +my @list = 1, 3, 9 ... * > 30; # puedes usar un predicado + # (con la Whatever Star, aquí). +my @list = 1, 3, 9 ... { $_ > 30 }; # (equivalente a lo de arriba) + +my @fib = 1, 1, *+* ... *; # lista infinita perezosa de la serie fibonacci, + # computada usando una clausura! +my @fib = 1, 1, -> $a, $b { $a + $b } ... *; # (equivalene a lo de arriba) +my @fib = 1, 1, { $^a + $^b } ... *; #(... también equivalene a lo de arriba) +## $a and $b siempre tomarán el valor anterior, queriendo decir que +## ellos comenzarán con $a = 1 y $b = 1 (valores que hemos asignado +## de antemano). Por lo tanto, $a = 1 y $b = 2 (resultado del anterior $a+$b), +## etc. + +say @fib[^10]; #=> 1 1 2 3 5 8 13 21 34 55 + # (usandi un rango como el índice) +## Nota: Los elementos de un rango, una vez cosificados, no son re-calculados. +## Esta es la razón por la cual `@primes[^100]` tomará más tiempo la primera +## vez que se imprime. Después de esto, será hará en un instante. +``` + +## Expresiones Regulares + +```perl6 +## Estoy seguro que has estado esperando por esta parte. Bien, ahora que +## sabes algo acerca de Raku, podemos comenzar. Primeramente, tendrás +## que olvidarte acerca de "PCRE regexps" (perl-compatible regexps) +## (expresiones regulares compatible de perl). +## +## IMPORTANTE: No salte esto porque ya sabes acerca de PCRE. Son totalmente +## distintos. Algunas cosas son las mismas (como `?`, `+`, y `*`) pero +## algunas veces la semántica cambia (`|`). Asegúrate de leer esto +## cuidadosamente porque podrías trospezarte sino lo haces. +## +## Raku tiene muchas características relacionadas con RegExps. Después de +## todo, Rakudo se parsea a si mismo. Primero vamos a estudiar la sintaxis +## por si misma, después hablaremos acerca de gramáticas (parecido a PEG), +## las diferencias entre los declaradores `token`, `regex`, y `rule` y +## mucho más. +## Nota aparte: Todavía tienes acceso a los regexes PCRE usando el +## mofificador `:P5` (Sin embargo, no lo discutiremos en este tutorial). +## +## En esencia, Raku implementa PEG ("Parsing Expression Grammars") +## ("Parseado de Expresiones de Gramáticas") nativamente. El orden jerárquico +## para los parseos ambiguos es determinado por un examen multi-nivel de +## desempate: +## - La coincidencia de token más larga. `foo\s+` le gana a `foo` +## (por 2 o más posiciones) +## - El prefijo literal más largo. `food\w*` le gana a `foo\w*` (por 1) +## - Declaración desde la gramática más derivada a la menos derivada +## (las gramáticas son actualmente clases) +## - La declaración más temprana gana +say so 'a' ~~ /a/; #=> True +say so 'a' ~~ / a /; #=> True # ¡Más legible con los espacios! + +## Nota al lector (del traductor): +## Como pudiste haber notado, he decidido traducir "match" y sus diferentes +## formas verbales como "coincidir" y sus diferentes formas. Cuando digo que +## un regex (o regexp) coincide con cierto texto, me refiero a que el regex +## describe cierto patrón dentro del texto. Por ejemplo, el regex "cencia" +## coincide con el texto "reminiscencia", lo que significa que dentro del +## texto aparece ese patrón de caracteres (una `c`, seguida de una `e`, +## (seguida de una `n`, etc.) + +## En todos nuestros ejemplos, vamos a usar el operador de +## "coincidencia inteligente" contra una expresión regular ("regexp" or +## "regex" de aquí en adelante). Estamos convirtiendo el resultado usando `so`, +## pero en efecto, está devolviendo un objeto Match. Ellos saben como responder +## a la indexación de lista, indexación de hash, y devolver la cadena de +## texto coincidente. +## Los resultados de la coincidencia están disponible como `$/` (en +## ámbito implícito lexical). También puedes usar las variables de captura +## las cuales comienzan con 0: +## `$0`, `$1', `$2`... +## +## Nota que `~~` no hace un chequeo de inicio/final (es decir, +## el regexp puede coincider con solo un carácter de la cadena de texto). +## Explicaremos luego como hacerlo. + +## En Raku, puedes tener un carácter alfanumérico como un literal, +## todo lo demás debe escaparse usando una barra invertida o comillas. +say so 'a|b' ~~ / a '|' b /; # `True`. No sería lo mismo si no se escapara `|` +say so 'a|b' ~~ / a \| b /; # `True`. Otra forma de escaparlo + +## El espacio en blanco actualmente no se significa nada en un regexp, +## a menos que uses el adverbio `:s` (`:sigspace`, espacio significante). +say so 'a b c' ~~ / a b c /; #=> `False`. Espacio no significa nada aquí. +say so 'a b c' ~~ /:s a b c /; #=> `True`. Agregamos el modificador `:s` aquí. +## Si usamos solo un espacio entre cadenas de texto en un regexp, Raku +## nos advertirá: +say so 'a b c' ~~ / a b c /; #=> 'False' # Espacio no significa nada aquí. +## Por favor usa comillas o el modificador :s (:sigspace) para suprimir +## esta advertencia, omitir el espacio, o cambiar el espaciamiento. Para +## arreglar esto y hacer los espacios menos ambiguos, usa por lo menos +## dos espacios entre las cadenas de texto o usa el adverbio `:s`. + +## Como vimos anteriormente, podemos incorporar `:s` dentro de los +## delimitadores de barras. También podemos ponerlos fuera de ellos si +## especificamos `m` for `match` (coincidencia): +say so 'a b c' ~~ m:s/a b c/; #=> `True` +## Al usar `m` para especificar 'match', podemos también otros delimitadore: +say so 'abc' ~~ m{a b c}; #=> `True` +say so 'abc' ~~ m[a b c]; #=> `True` + +## Usa el adverbio :i para especificar que no debería haber distinción entre +## minúsculas y mayúsculas: +say so 'ABC' ~~ m:i{a b c}; #=> `True` + +## Sin embargo, es importante para como los modificadores son aplicados +## (lo cual verás más abajo)... + +## Cuantificando - `?`, `+`, `*` y `**`. +## - `?` - 0 o 1 +so 'ac' ~~ / a b c /; # `False` +so 'ac' ~~ / a b? c /; # `True`, la "b" coincidió (apareció) 0 veces. +so 'abc' ~~ / a b? c /; # `True`, la "b" coincidió 1 vez. + +## ... Como debes saber, espacio en blancos son importante porque +## determinan en que parte del regexp es el objetivo del modificador: +so 'def' ~~ / a b c? /; # `False`. Solamente la `c` es opcional +so 'def' ~~ / a b? c /; # `False`. Espacio en blanco no es significante +so 'def' ~~ / 'abc'? /; # `True`. El grupo "abc"completo es opcional. + +## Aquí (y más abajo) el cuantificador aplica solamente a la `b` + +## - `+` - 1 o más +so 'ac' ~~ / a b+ c /; # `False`; `+` quiere por lo menos una coincidencia +so 'abc' ~~ / a b+ c /; # `True`; una es suficiente +so 'abbbbc' ~~ / a b+ c /; # `True`, coincidió con 4 "b"s + +## - `*` - 0 o más +so 'ac' ~~ / a b* c /; # `True`, todos son opcionales. +so 'abc' ~~ / a b* c /; # `True` +so 'abbbbc' ~~ / a b* c /; # `True` +so 'aec' ~~ / a b* c /; # `False`. "b"(s) son opcionales, no reemplazables. + +## - `**` - Cuantificador (sin límites) +## Si entrecierras los ojos lo suficiente, pueder ser que entiendas +## por qué la exponenciación es usada para la cantidad. +so 'abc' ~~ / a b**1 c /; # `True` (exactamente una vez) +so 'abc' ~~ / a b**1..3 c /; # `True` (entre una y tres veces) +so 'abbbc' ~~ / a b**1..3 c /; # `True` +so 'abbbbbbc' ~~ / a b**1..3 c /; # `False` (demasiado) +so 'abbbbbbc' ~~ / a b**3..* c /; # `True` (rangos infinitos no son un problema) + +## - `<[]>` - Clases de carácteres +## Las clases de carácteres son equivalentes a las clases `[]` de PCRE, +## pero usan una sintaxis de Raku: +say 'fooa' ~~ / f <[ o a ]>+ /; #=> 'fooa' + +## Puedes usar rangos: +say 'aeiou' ~~ / a <[ e..w ]> /; #=> 'ae' + +## Al igual que regexes normales, si quieres usar un carácter especial, +## escápalo (el último está escapando un espacio) +say 'he-he !' ~~ / 'he-' <[ a..z \! \ ]> + /; #=> 'he-he !' + +## Obtendrás una advertencia si pones nombres duplicados +## (lo cual tiene el efecto de capturar la frase escrita) +'he he' ~~ / <[ h e ' ' ]> /; # Advierte "Repeated characters found in characters + # class" + +## También puedes negarlos... (equivalenta a `[^]` en PCRE) +so 'foo' ~~ / <-[ f o ]> + /; # False + +## ... y componerlos: +so 'foo' ~~ / <[ a..z ] - [ f o ]> + /; # False (cualquier letra excepto f y o) +so 'foo' ~~ / <-[ a..z ] + [ f o ]> + /; # True (no letra excepto f and o) +so 'foo!' ~~ / <-[ a..z ] + [ f o ]> + /; # True (el signo + no reemplaza la + # parte de la izquierda) +``` + +### Grupos y Capturas + +```perl6 +## Grupo: Puedes agrupar partes de tu regexp con `[]`. +## Estos grupos *no son* capturados (como con `(?:)` en PCRE). +so 'abc' ~~ / a [ b ] c /; # `True`. El agrupamiento no hace casi nada +so 'foo012012bar' ~~ / foo [ '01' <[0..9]> ] + bar /; +## La línea anterior returna `True`. +## Coincidimos (o encotramos el patrón) "012" una o más de una vez ( +## (el signo `+` fue aplicado al grupo). +## Pero esto no va demasiado lejos, porque no podemos actualmente obtener +## devuelta el patrón que coincidió. + +## Captura: Podemos actualmente *capturar* los resultados del regexp, +## usando paréntesis. +so 'fooABCABCbar' ~~ / foo ( 'A' <[A..Z]> 'C' ) + bar /; # `True`. (usando `so` + # aquí, `$/` más abajo) + +## Ok. Comenzando con las explicaciones de grupos. Como dijimos, +### nuestra objeto `Match` está disponible en la variable `$/`: +say $/; # Imprimirá algo extraño (explicaremos luego) o + # "Nil" si nada coincidió + +## Como dijimos anteriormente, un objeto Match tiene indexación de array: +say $/[0]; #=> 「ABC」 「ABC」 + # Estos corchetes extranos son los objetos `Match`. + # Aquí, tenemos un array de ellos. +say $0; # Lo mismo que lo anterior. + +## Nuestra captura es `$0` porque es la primera y única captura en el +## regexp. Podrías estarte preguntando porque un array y la respuesta es +## simple: Algunas capturas (indezadas usando `$0`, `$/[0]` o una nombrada) +## será un array si y solo si puedes tener más de un elemento. +## (Así que, con `*`, `+` y `**` (cualquiera los operandos), pero no con `?`). +## Usemos algunos ejemplos para ver como funciona: + +## Nota: Pusimos A B C entre comillas para demostrar que el espacio en blanco +## entre ellos no es significante. Si queremos que el espacio en blanco +## *sea* significante, podemos utilizar el modificador `:sigspace`. +so 'fooABCbar' ~~ / foo ( "A" "B" "C" )? bar /; # `True` +say $/[0]; #=> 「ABC」 +say $0.WHAT; #=> (Match) + # Puede haber más de uno, por lo tanto es solo un solo objeto match. +so 'foobar' ~~ / foo ( "A" "B" "C" )? bar /; #=> True +say $0.WHAT; #=> (Any) + # Esta captura no coincidió, por lo tanto está vacía +so 'foobar' ~~ / foo ( "A" "B" "C" ) ** 0..1 bar /; # `True` +say $0.WHAT; #=> (Array) + # Un cuantificador específico siempre capturará un Array, + # puede ser un rango o un valor específico (hasta 1). + +## Las capturas son indezadas por anidación. Esto quiere decir que un grupo +## dentro de un grup estará anidado dentro de su grupo padre: `$/[0][0]`, +## para este código: +'hello-~-world' ~~ / ( 'hello' ( <[ \- \~ ]> + ) ) 'world' /; +say $/[0].Str; #=> hello~ +say $/[0][0].Str; #=> ~ + +## Esto se origina de un hecho bien simple: `$/` no contiene cadenas de +## texto, números enteros o arrays sino que solo contiene objetos Match. +## Estos objetos contienen los métodos `.list`, `.hash` y `.Str`. (Pero +## también puedes usar `match` para accesar un hash y `match[indice]` +## para accesar un array. +say $/[0].list.perl; #=> (Match.new(...),).list + # Podemos ver que es una lista de objetos Match. + # Estos contienen un montón de información: dónde la + # coincidencia comenzó o terminó, el "ast" + # (chequea las acciones más abajo), etc. + # Verás capturas nombradas más abajo con las gramáticas. + +## Alternativas - el `or` de regexes +## Advertencia: Es diferente a los regexes de PCRE. +so 'abc' ~~ / a [ b | y ] c /; # `True`. o "b" o "y". +so 'ayc' ~~ / a [ b | y ] c /; # `True`. Obviamente suficiente... + +## La diferencia entre este `|` y el otro al que estás acustombrado es LTM. +## LTM significa "Longest Token Matching", traducido libremente como +## "Coincidencia de Token Más Larga". Esto significa que el motor ("engine") +## siempre intentará coindidir tanto como sea posible en la cadena de texto. +## Básicamente, intentará el patrón más largo que concuerde con el regexp. +'foo' ~~ / fo | foo /; # `foo` porque es más largo. +## Para decidir cual parte es la "más larga", primero separa el regex en +## dos partes: +## El "prefijo declarativo" (la parte que puede ser analizada estáticamente) +## y las partes procedimentales. +## Los prefijos declarativos incluyen alternaciones (`|`), conjunciones (`&`), +## invocaciones de sub-reglas (no han sido introducidos todavía), clases de +## caracteres y cuantificadores. +## Las partes procidimentales incluyen todo lo demás: referencias a elementos +## anteriores, aserciones de código, y otras cosas que tradicionalmente no pueden +## ser representadas por regexes normales. +## +## Entonces, todas las alternativas se intentan al mismo tiempo, y la +## más larga gana. +## Ejemplos: +## DECLARATIVO | PROCEDIMENTAL +/ 'foo' \d+ [ || ] /; +## DECLARATIVO (grupos anidados no son un problema) +/ \s* [ \w & b ] [ c | d ] /; +## Sin embargo, las clausuras y la recursión (de regexes nombrados) +## son procedimentales. +## ... Hay más reglas complicadas, como la especifidad (los literales ganan +## son las clases de caracteres) ++ +## Nota: la primera coincidencia `or` todavía existen, pero ahora se +## deletrea `||` +'foo' ~~ / fo || foo /; # `fo` ahora. +``` + +## Extra: la subrutina MAIN + +```perl6 +## La subrutina `MAIN` se invoca cuando tu ejecuta un archivo de Raku +## directamente. Es realmente poderosa porque Raku actualmente parsea +## los argumentos y los pasas a la subrutina. También maneja argumentos +## nombrados (`--foo`) y hasta autogenerará un `--help`. +sub MAIN($nombre) { say "¡Hola, $nombre!" } +## Esto produce: +## $ raku cli.pl +## Uso: +## t.pl + +## Y dado que una subrutina regular en Raku, puedes tener múltiples +## despachos: +## (usando un "Bool" por un argumento nombrado para que podamos hacer +## `--replace` a cambio de `--replace=1`) +subset File of Str where *.IO.d; # convierte a un objeto IO para chequear si + # un archivo existe + +multi MAIN('add', $key, $value, Bool :$replace) { ... } +multi MAIN('remove', $key) { ... } +multi MAIN('import', File, Str :$as) { ... } # omitiendo parámetros nombrados +## Esto produce: +## $ raku cli.pl +## Uso: +## t.pl [--replace] add +## t.pl remove +## t.pl [--as=] import (File) +## Como puedes ver, esto es *realmente* poderoso. +## Fue tan lejos como para mostrar las constantes en líneas. +## (el tipo solo se muestra cuando el argumento `$`/ es nombrado) +``` + +## APÉNDICE A: +### Lista de cosas + +```perl6 +## Consideramos que por ahora ya sabes lo básico de Raku. +## Esta sección es solo para listar algunas operaciones comunes +## las cuales no están en la "parte principal" del tutorial. + +## Operadores + +## * Comparación para ordenar +## Ellos returnan un valor de los enum `Order`: `Less`, `Same` y `More` +## (los cuales representan los números -1, 0 o +1). +1 <=> 4; # comparación de orden para caracteres numéricos +'a' leg 'b'; # comparación de orden para cadenas de texto +$obj eqv $obj2; # comparación de orden usando la semántica eqv + +## * Ordenación genérica +3 before 4; # True +'b' after 'a'; # True + +## * Operador (por defecto) de circuito corto +## Al igual que `or` y `||`, pero devuelve el primer valor *defined* +## (definido): +say Any // Nil // 0 // 5; #=> 0 + +## * Circuito corto exclusivo or (XOR) +## Devuelve `True` si uno (y solo uno) de sus argumentos es verdadero: +say True ^^ False; #=> True + +## * Flip Flop +## Los operadores flip flop (`ff` y `fff`, equivalente a `..`/`...` en P5) +## son operadores que toman dos predicados para evalualarlos: +## Ellos son `False` hasta que su lado izquierdo devuelve `True`, entonces +## son `True` hasta que su lado derecho devuelve `True`. +## Como los rangos, tu puedes excluir la iteración cuando se convierte en +## `True`/`False` usando `^` en cualquier lado. +## Comencemos con un ejemplo: +for { + # por defecto, `ff`/`fff` hace coincidencia inteligente (`~~`) contra `$_`: + if 'met' ^ff 'meet' { # no entrará el bucle if por "met" + # (se explica más abajo). + .say + } + + if rand == 0 ff rand == 1 { # compara variables más que `$_` + say "Esto ... probablemente nunca se ejecutará ..."; + } +} +## Esto imprimirá "young hero we shall meet" (exluyendo "met"): +## el flip-flop comenzará devolviendo `True` cuando primero encuentra "met" +## (pero no returnará `False` por "met" dabido al `^` al frente de `ff`), +## hasta que ve "meet", lo cual es cuando comenzará devolviendo `False`. + +## La diferencia entre `ff` (al estilo de awk) y `fff` (al estilo de sed) +## es que `ff` probará su lado derecho cuando su lado izquierdo cambia +## a `True`, y puede returnar a `False` inmediamente (*excepto* que será +## `True` por la iteración con la cual coincidió). Por lo contrario, +## `fff` esperará por la próxima iteración para intentar su lado +## derecho, una vez que su lado izquierdo ha cambiado: +.say if 'B' ff 'B' for ; #=> B B + # porque el lado derecho se puso a prueba + # directamente (y returnó `True`). + # Las "B"s se imprimen dadó que coincidió + # en ese momento (returnó a `False` + # inmediatamente). +.say if 'B' fff 'B' for ; #=> B C B + # El lado derecho no se puso a prueba + # hasta que `$_` se convirtió en "C" + # (y por lo tanto no coincidió + # inmediamente). + +## Un flip-flop puede cambiar estado cuantas veces se necesite: +for { + .say if $_ eq 'start' ^ff^ $_ eq 'stop'; # excluye a "start" y "stop", + #=> "print it print again" +} + +## También podrías usar una Whatever Star, lo cual es equivalente +## a `True` para el lado izquierdo o `False` para el lado derecho: +for (1, 3, 60, 3, 40, 60) { # Nota: los paréntesis son superfluos aquí + # (algunas veces se les llaman "paréntesis superticiosos") + .say if $_ > 50 ff *; # Una vez el flip-flop alcanza un número mayor que 50, + # no returnará jamás a `False` + #=> 60 3 40 60 +} + +## También puedes usar esta propiedad para crear un `If` +## que no pasará la primera vez: +for { + .say if * ^ff *; # el flip-flop es `True` y nunca returna a `False`, + # pero el `^` lo hace *que no se ejecute* en la + # primera iteración + #=> b c +} + +## - `===` es la identidad de valor y usa `.WHICH` +## en los objetos para compararlos. +## - `=:=` es la identidad de contenedor y usa `VAR()` +## en los objetos para compararlos. + +``` +Si quieres ir más allá de lo que se muestra aquí, puedes: + + - Leer la [documentación de Raku](https://docs.raku.org/). Esto es un recurso + grandioso acerca de Raku. Si estás buscando por algo en particular, usa la + barra de búsquedas. Esto te dará un menú de todas las páginas concernientes + a tu término de búsqueda (¡Es mucho mejor que usar Google para encontrar + documentos acerca de Raku!) + - Leer el [Raku Advent Calendar](https://rakuadventcalendar.wordpress.com/). Este es + un gran recurso de fragmentos de código de Raku y explicaciones. Si la documentación + no describe algo lo suficientemente bien, puedes encontrar información más detallada + aquí. Esta información puede ser un poquito más antigua pero hay muchos ejemplos y + explicaciones. Las publicaciones fueron suspendidas al final del 2015 cuando + el lenguaje fue declarado estable y Raku.c fue lanzado. + - Unirte a `#raku` en `irc.freenode.net`. Las personas aquí son siempre serviciales. + - Chequear la [fuente de las funciones y clases de Raku + ](https://github.com/rakudo/rakudo/tree/master/src/core.c). Rakudo está principalmente + escrito en Raku (con mucho de NQP, "Not Quite Perl" ("No Perl Todavía"), un + subconjunto de Raku que es más fácil de implementar y optimizar). + - Leer [documentos acerca del diseño del lenguaje](http://design.raku.org). + Estos explican P6 desde la perspectiva de un implementador, lo cual es bastante + interesante. -- cgit v1.2.3