diff options
-rw-r--r-- | ISSUE_TEMPLATE.md | 9 | ||||
-rw-r--r-- | c.html.markdown | 2 | ||||
-rw-r--r-- | es-es/perl6-es.html.markdown | 1935 | ||||
-rw-r--r-- | it-it/python3-it.html.markdown | 1016 | ||||
-rw-r--r-- | matlab.html.markdown | 6 | ||||
-rw-r--r-- | objective-c.html.markdown | 5 | ||||
-rw-r--r-- | pt-br/c-pt.html.markdown | 7 | ||||
-rw-r--r-- | ruby.html.markdown | 145 | ||||
-rw-r--r-- | solidity.html.markdown | 14 | ||||
-rwxr-xr-x | toml.html.markdown | 7 | ||||
-rw-r--r-- | tr-tr/c++-tr.html.markdown | 1077 | ||||
-rw-r--r-- | tr-tr/git-tr.html.markdown | 595 | ||||
-rw-r--r-- | zh-cn/python3-cn.html.markdown | 3 |
13 files changed, 4740 insertions, 81 deletions
diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md index 022dedab..96278da9 100644 --- a/ISSUE_TEMPLATE.md +++ b/ISSUE_TEMPLATE.md @@ -1,3 +1,12 @@ +## Is this a major issue that you cannot fix? + +**Being a community driven documents of languages and tools,"YOUR" contributions +are also important. +If the issue you're reporting is trivial to report to maintainers why not contribute +to fix it. In that way, you will have contributed to an awesome open-source project. +The changes can be typo fix, fixing of data in examples or grammar fix. If you found it, +why not do it and take full credit for it?** + Make sure the issue title is prepended with '[language/lang-code]' if the language is already on the site. If it's a request for a new language, use: '[Request] [language/lang-code]' diff --git a/c.html.markdown b/c.html.markdown index 0c6df413..684d330a 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -101,7 +101,7 @@ int main (int argc, char** argv) char y_char = 'y'; // Char literals are quoted with '' // longs are often 4 to 8 bytes; long longs are guaranteed to be at least - // 64 bits + // 8 bytes long x_long = 0; long long x_long_long = 0; diff --git a/es-es/perl6-es.html.markdown b/es-es/perl6-es.html.markdown new file mode 100644 index 00000000..bf3ae65e --- /dev/null +++ b/es-es/perl6-es.html.markdown @@ -0,0 +1,1935 @@ +--- +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 = <a b c>; # array de palabras, delimitado por espacios. + # Similar al qw de perl5, 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 = <llave1 valor1 llave2 valor2>; + +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<llave2>; # 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>`. +## - `is rw`, es simplemente un despacho a una función con esta signatura: +## sub trait_mod:<is>(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.perl6.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 5, 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.perl6.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:<ganar>($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:<veces>(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<llave>` 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+ [ <subrule1> || <subrule2> ] /; +## 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 <nombre> + +## 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 <key> <value> +## t.pl remove <key> +## t.pl [--as=<Str>] 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 <well met young hero we shall meet later> { + # 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 <A B C B A>; #=> 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 <A B C B A>; #=> 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 <test start print it stop not printing start print again stop not anymore> { + .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 <a b c> { + .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.perl6.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.perl6.org). + Estos explican P6 desde la perspectiva de un implementador, lo cual es bastante + interesante. diff --git a/it-it/python3-it.html.markdown b/it-it/python3-it.html.markdown new file mode 100644 index 00000000..06ef9a5e --- /dev/null +++ b/it-it/python3-it.html.markdown @@ -0,0 +1,1016 @@ +--- +language: python3 +filename: learnpython3-it.py +contributors: + - ["Louie Dinh", "http://pythonpracticeprojects.com"] + - ["Steven Basart", "http://github.com/xksteven"] + - ["Andre Polykanine", "https://github.com/Oire"] + - ["Zachary Ferguson", "http://github.com/zfergus2"] + - ["evuez", "http://github.com/evuez"] + - ["Rommel Martinez", "https://ebzzry.io"] +translators: + - ["Draio", "http://github.com/Draio/"] + - ["Ale46", "http://github.com/Ale46/"] + - ["Tommaso Pifferi", "http://github.com/neslinesli93/"] +lang: it-it +--- + +Python è stato creato da Guido Van Rossum agli inizi degli anni 90. Oggi è uno dei più popolari linguaggi esistenti. Mi sono innamorato di Python per la sua chiarezza sintattica. E' sostanzialmente pseudocodice eseguibile. + +Feedback sono altamente apprezzati! Potete contattarmi su [@louiedinh](http://twitter.com/louiedinh) oppure [at] [google's email service] + +Nota: Questo articolo è riferito a Python 3 in modo specifico. Se volete avete la necessità di utilizzare Python 2.7 potete consultarla [qui](https://learnxinyminutes.com/docs/it-it/python-it/) + +```python + +# I commenti su una sola linea iniziano con un cancelletto + + +""" Più stringhe possono essere scritte + usando tre ", e sono spesso usate + come documentazione +""" + +#################################################### +## 1. Tipi di dati primitivi ed Operatori +#################################################### + +# Ci sono i numeri +3 # => 3 + +# La matematica è quello che vi aspettereste +1 + 1 # => 2 +8 - 1 # => 7 +10 * 2 # => 20 +35 / 5 # => 7.0 + +# Risultato della divisione intera troncata sia in positivo che in negativo +5 // 3 # => 1 +5.0 // 3.0 # => 1.0 # works on floats too +-5 // 3 # => -2 +-5.0 // 3.0 # => -2.0 + +# Il risultato di una divisione è sempre un numero decimale (float) +10.0 / 3 # => 3.3333333333333335 + +# Operazione Modulo +7 % 3 # => 1 + +# Elevamento a potenza (x alla y-esima potenza) +2**3 # => 8 + +# Forzare le precedenze con le parentesi +(1 + 3) * 2 # => 8 + +# I valori booleani sono primitive del linguaggio (nota la maiuscola) +True +False + +# nega con not +not True # => False +not False # => True + +# Operatori Booleani +# Nota "and" e "or" sono case-sensitive +True and False # => False +False or True # => True + +# Note sull'uso di operatori Bool con interi +# False è 0 e True è 1 +# Non confonderti tra bool(ints) e le operazioni bitwise and/or (&,|) +0 and 2 # => 0 +-5 or 0 # => -5 +0 == False # => True +2 == True # => False +1 == True # => True +-5 != False != True #=> True + +# Uguaglianza è == +1 == 1 # => True +2 == 1 # => False + +# Disuguaglianza è != +1 != 1 # => False +2 != 1 # => True + +# Altri confronti +1 < 10 # => True +1 > 10 # => False +2 <= 2 # => True +2 >= 2 # => True + +# I confronti possono essere concatenati! +1 < 2 < 3 # => True +2 < 3 < 2 # => False + +# ('is' vs. '==') +# 'is' controlla se due variabili si riferiscono allo stesso oggetto +# '==' controlla se gli oggetti puntati hanno lo stesso valore. +a = [1, 2, 3, 4] # a punta ad una nuova lista [1, 2, 3, 4] +b = a # b punta a ciò a cui punta a +b is a # => True, a e b puntano allo stesso oggeto +b == a # => True, gli oggetti di a e b sono uguali +b = [1, 2, 3, 4] # b punta ad una nuova lista [1, 2, 3, 4] +b is a # => False, a e b non puntano allo stesso oggetto +b == a # => True, gli oggetti di a e b sono uguali + +# Le stringhe sono create con " o ' +"Questa è una stringa." +'Anche questa è una stringa.' + +# Anche le stringhe possono essere sommate! Ma cerca di non farlo. +"Hello " + "world!" # => "Hello world!" +# Le stringhe (ma non le variabili contenenti stringhe) possono essere +# sommate anche senza '+' +"Hello " "world!" # => "Hello world!" + +# Una stringa può essere considerata come una lista di caratteri +"Questa è una stringa"[0] # => 'Q' + +# Puoi conoscere la lunghezza di una stringa +len("Questa è una stringa") # => 20 + +# .format può essere usato per formattare le stringhe, in questo modo: +"{} possono essere {}".format("Le stringhe", "interpolate") # => "Le stringhe possono essere interpolate" + +# Puoi ripetere gli argomenti di formattazione per risparmiare un po' di codice +"{0} be nimble, {0} be quick, {0} jump over the {1}".format("Jack", "candle stick") +# => "Jack be nimble, Jack be quick, Jack jump over the candle stick" + +# Puoi usare dei nomi se non vuoi contare gli argomenti +"{nome} vuole mangiare {cibo}".format(nome="Bob", cibo="le lasagne") # => "Bob vuole mangiare le lasagne" + +# Se il tuo codice Python 3 necessita di eseguire codice Python 2.x puoi ancora +# utilizzare il vecchio stile di formattazione: +"%s possono essere %s nel %s modo" % ("Le stringhe", "interpolate", "vecchio") # => "Le stringhe possono essere interpolate nel vecchio modo" + +# None è un oggetto +None # => None + +# Non usare il simbolo di uguaglianza "==" per comparare oggetti a None +# Usa "is" invece +"etc" is None # => False +None is None # => True + +# None, 0, e stringhe/liste/dizionari/tuple vuoti vengono considerati +# falsi (False). Tutti gli altri valori sono considerati veri (True). +bool(0) # => False +bool("") # => False +bool([]) # => False +bool({}) # => False +bool(()) # => False + +#################################################### +## 2. Variabili e Collections +#################################################### + +# Python ha una funzione per scrivere (sul tuo schermo) +print("Sono Python. Piacere di conoscerti!") # => Sono Python. Piacere di conoscerti! + +# Di default la funzione print() scrive e va a capo aggiungendo un carattere +# newline alla fine della stringa. È possibile utilizzare l'argomento opzionale +# end per cambiare quest'ultimo carattere aggiunto. +print("Hello, World", end="!") # => Hello, World! + +# Un modo semplice per ricevere dati in input dalla riga di comando +variabile_stringa_input = input("Inserisci del testo: ") # Restituisce i dati letti come stringa +# Nota: Nelle precedenti vesioni di Python, il metodo input() +# era chiamato raw_input() + +# Non c'è bisogno di dichiarare una variabile per assegnarle un valore +# Come convenzione, per i nomi delle variabili, si utilizzano i caratteri +# minuscoli separati, se necessario, da underscore +some_var = 5 +some_var # => 5 + +# Accedendo ad una variabile non precedentemente assegnata genera un'eccezione. +# Dai un'occhiata al Control Flow per imparare di più su come gestire +# le eccezioni. +some_unknown_var # Genera un errore di nome + +# if può essere usato come un'espressione +# È l'equivalente dell'operatore ternario in C +"yahoo!" if 3 > 2 else 2 # => "yahoo!" + +# Le liste immagazzinano sequenze +li = [] +# Puoi partire con una lista pre-riempita +other_li = [4, 5, 6] + +# Aggiungere alla fine di una lista con append +li.append(1) # li ora è [1] +li.append(2) # li ora è [1, 2] +li.append(4) # li ora è [1, 2, 4] +li.append(3) # li ora è [1, 2, 4, 3] +# Rimuovi dalla fine della lista con pop +li.pop() # => 3 e li ora è [1, 2, 4] +# Rimettiamolo a posto +li.append(3) # li ora è [1, 2, 4, 3] di nuovo. + +# Accedi ad una lista come faresti con un array +li[0] # => 1 +# Guarda l'ultimo elemento +li[-1] # => 3 + +# Guardare al di fuori dei limiti genera un IndexError +li[4] # Genera IndexError + +# Puoi guardare gli intervalli con la sintassi slice (a fetta). +# (E' un intervallo chiuso/aperto per voi tipi matematici.) +li[1:3] # => [2, 4] +# Ometti l'inizio +li[2:] # => [4, 3] +# Ometti la fine +li[:3] # => [1, 2, 4] +# Seleziona ogni seconda voce +li[::2] # =>[1, 4] +# Copia al contrario della lista +li[::-1] # => [3, 4, 2, 1] +# Usa combinazioni per fare slices avanzate +# li[inizio:fine:passo] + +# Crea una copia (one layer deep copy) usando la sintassi slices +li2 = li[:] # => li2 = [1, 2, 4, 3] ma (li2 is li) risulterà falso. + +# Rimuovi arbitrariamente elementi da una lista con "del" +del li[2] # li è ora [1, 2, 3] + +# Rimuove la prima occorrenza di un elemento +li.remove(2) # Ora li è [1, 3, 4, 5, 6] +li.remove(2) # Emette un ValueError, poichè 2 non è contenuto nella lista + +# Inserisce un elemento all'indice specificato +li.insert(1, 2) # li è di nuovo [1, 2, 3, 4, 5, 6] + + Ritorna l'indice della prima occorrenza dell'elemento fornito +li.index(2) # => 1 +li.index(7) # Emette un ValueError, poichè 7 non è contenuto nella lista + +# Puoi sommare le liste +# Nota: i valori per li e per other_li non vengono modificati. +li + other_li # => [1, 2, 3, 4, 5, 6] + +# Concatena le liste con "extend()" +li.extend(other_li) # Adesso li è [1, 2, 3, 4, 5, 6] + +# Controlla l'esistenza di un valore in una lista con "in" +1 in li # => True + +# Esamina la lunghezza con "len()" +len(li) # => 6 + + +# Le tuple sono come le liste ma immutabili. +tup = (1, 2, 3) +tup[0] # => 1 +tup[0] = 3 # Genera un TypeError + +# Note that a tuple of length one has to have a comma after the last element but +# tuples of other lengths, even zero, do not. +type((1)) # => <class 'int'> +type((1,)) # => <class 'tuple'> +type(()) # => <class 'tuple'> + +# Puoi fare tutte queste cose da lista anche sulle tuple +len(tup) # => 3 +tup + (4, 5, 6) # => (1, 2, 3, 4, 5, 6) +tup[:2] # => (1, 2) +2 in tup # => True + +# Puoi scompattare le tuple (o liste) in variabili +a, b, c = (1, 2, 3) # a è ora 1, b è ora 2 e c è ora 3 +d, e, f = 4, 5, 6 # puoi anche omettere le parentesi +# Le tuple sono create di default se non usi le parentesi +g = 4, 5, 6 # => (4, 5, 6) +# Guarda come è facile scambiare due valori +e, d = d, e # d è ora 5 ed e è ora 4 + +# I dizionari memorizzano insiemi di dati indicizzati da nomi arbitrari (chiavi) +empty_dict= {} +# Questo è un dizionario pre-caricato +filled_dict = {"uno": 1, "due": 2, "tre": 3} + +# Nota: le chiavi dei dizionari devono essere di tipo immutabile. Questo per +# assicurare che le chiavi possano essere convertite in calori hash costanti +# per un risposta più veloce. +invalid_dict = {[1,2,3]: "123"} # => Emette un TypeError: unhashable type: 'list' +valid_dict = {(1,2,3):[1,2,3]} # I valori, invece, possono essere di qualunque tipo + +# Accedi ai valori indicando la chiave tra [] +filled_dict["uno"] # => 1 + +# Puoi ottenere tutte le chiavi di un dizionario con "keys()" +# (come oggetto iterabile). Per averle in formato lista è necessario +# utilizzare list(). +# Nota - Nei dizionari l'ordine delle chiavi non è garantito. +# Il tuo risultato potrebbe non essere uguale a questo. +list(filled_dict.keys()) # => ["tre", "due", "uno"] + + +# Puoi ottenere tutti i valori di un dizionario con "values()" +# (come oggetto iterabile). +# Anche in questo caso, er averle in formato lista, è necessario utilizzare list() +# Anche in questo caso, come per le chiavi, l'ordine non è garantito +list(filled_dict.values()) # => [3, 2, 1] + +# Controlla l'esistenza delle chiavi in un dizionario con "in" +"uno" in filled_dict # => True +1 in filled_dict # => False + +# Cercando una chiave non esistente genera un KeyError +filled_dict["quattro"] # KeyError + +# Usa il metodo "get()" per evitare KeyError +filled_dict.get("uno") # => 1 +filled_dict.get("quattro") # => None +# Il metodo get supporta un argomento di default quando il valore è mancante +filled_dict.get("uno", 4) # => 1 +filled_dict.get("quattro", 4) # => 4 + + +# "setdefault()" inserisce un valore per una chiave in un dizionario +# solo se la chiave data non è già presente +filled_dict.setdefault("cinque", 5) # filled_dict["cinque"] viene impostato a 5 +filled_dict.setdefault("cinque", 6) # filled_dict["cinque"] rimane 5 + +# Aggiungere una coppia chiave->valore a un dizionario +filled_dict.update({"quattro":4}) # => {"uno": 1, "due": 2, "tre": 3, "quattro": 4} +filled_dict["quattro"] = 4 # un altro modo pe aggiungere a un dizionario + +# Rimuovi una chiave da un dizionario con del +del filled_dict["uno"] # Rimuove la chiave "uno" dal dizionario + +# Da Python 3.5 puoi anche usare ulteriori opzioni di spacchettamento +{'a': 1, **{'b': 2}} # => {'a': 1, 'b': 2} +{'a': 1, **{'a': 2}} # => {'a': 2} + +# I set sono come le liste ma non possono contenere doppioni +empty_set = set() +# Inizializza un "set()" con un dei valori. Sì, sembra un dizionario. +some_set = {1, 1, 2, 2, 3, 4} # set_nuovo è {1, 2, 3, 4} + +# Come le chiavi di un dizionario, gli elementi di un set devono essere +# di tipo immutabile +invalid_set = {[1], 1} # => Genera un "TypeError: unhashable type: 'list'"" +valid_set = {(1,), 1} + +# Aggiungere uno o più elementi ad un set +some_set.add(5) # some_set ora è {1, 2, 3, 4, 5} + +# Fai intersezioni su un set con & +other_set = {3, 4, 5, 6} +some_set & other_set # => {3, 4, 5} + +# Fai unioni su set con | +some_set | other_set # => {1, 2, 3, 4, 5, 6} + +# Fai differenze su set con - +{1, 2, 3, 4} - {2, 3, 5} # => {1, 4} + +# Effettua la differenza simmetrica con ^ +{1, 2, 3, 4} ^ {2, 3, 5} # => {1, 4, 5} + +# Controlla se il set a sinistra contiene quello a destra +{1, 2} >= {1, 2, 3} # => False + +# Controlla se il set a sinistra è un sottoinsieme di quello a destra +{1, 2} <= {1, 2, 3} # => True + +# Controlla l'esistenza in un set con in +2 in some_set # => True +10 in some_set # => False + + + +#################################################### +## 3. Control Flow e oggetti Iterabili +#################################################### + +# Dichiariamo una variabile +some_var = 5 + +# Questo è un controllo if. L'indentazione è molto importante in python! +# Come convenzione si utilizzano quattro spazi, non la tabulazione. +# Il seguente codice stampa "some_var è minore di 10" +if some_var > 10: + print("some_var è maggiore di 10") +elif some_var < 10: # La clausolo elif è opzionale + print("some_var è minore di 10") +else: # Anche else è opzionale + print("some_var è 10.") + +""" +I cicli for iterano sulle liste, cioé ripetono un codice per ogni elemento +# di una lista. +Il seguente codice scriverà: + cane è un mammifero + gatto è un mammifero + topo è un mammifero +""" +for animale in ["cane", "gatto", "topo"]: + # Puoi usare format() per interpolare le stringhe formattate. + print("{} is a mammal".format(animal)) + +""" +"range(numero)" restituisce una lista di numeri da zero al numero dato +Il seguente codice scriverà: + 0 + 1 + 2 + 3 +""" +for i in range(4): + print(i) + +""" +"range(lower, upper)" restituisce una lista di numeri dal più piccolo (lower) +al più grande (upper). +Il seguente codice scriverà: + 4 + 5 + 6 + 7 +""" +for i in range(4, 8): + print(i) + +""" +"range(lower, upper, step)" rrestituisce una lista di numeri dal più piccolo +(lower) al più grande (upper), incrementando del valore step. +Se step non è indicato, avrà come valore di default 1. +Il seguente codice scriverà: + 4 + 6 +""" +for i in range(4, 8, 2): + print(i) +""" + +I cicli while vengono eseguiti finchè una condizione viene a mancare +Il seguente codice scriverà: + 0 + 1 + 2 + 3 +""" +x = 0 +while x < 4: + print(x) + x += 1 # Forma compatta per x = x + 1 + +# Gestione delle eccezioni con un blocco try/except +try: + # Usa "raise" per generare un errore + raise IndexError("Questo è un IndexError") +except IndexError as e: + pass # Pass è solo una non-operazione. Solitamente vorrai rimediare all'errore. +except (TypeError, NameError): + pass # Eccezioni multiple possono essere gestite tutte insieme, se necessario. +else: # Clausola opzionale al blocco try/except. Deve essere dopo tutti i blocchi except + print("Tutto ok!") # Viene eseguita solo se il codice dentro try non genera eccezioni +finally: # Eseguito sempre + print("Possiamo liberare risorse qui") + +# Se ti serve solo un try/finally, per liberare risorse, puoi usare il metodo with +with open("myfile.txt") as f: + for line in f: + print(line) + +# In Python qualunque oggetto in grado di essere trattato come una +# sequenza è definito un oggetto Iterable (itarabile). +# L'oggetto restituito da una funzione range è un iterabile. + +filled_dict = {"uno": 1, "due": 2, "tre": 3} +our_iterable = filled_dict.keys() +print(our_iterable) # => dict_keys(['uno', 'due', 'tre']). +# Questo è un oggetto che implementa la nostra interfaccia Iterable. + +# È possibile utilizzarlo con i loop: +for i in our_iterable: + print(i) # Scrive uno, due, tre + +# Tuttavia non possiamo recuperarne i valori tramite indice. +our_iterable[1] # Genera un TypeError + +# Un oggetto iterabile è in grado di generare un iteratore +our_iterator = iter(our_iterable) + +# L'iteratore è un oggetto che ricorda il suo stato mentro lo si "attraversa" +# Possiamo accedere al successivo elemento con "next()". +next(our_iterator) # => "uno" + +# Mantiene il suo stato mentro eseguiamo l'iterazione +next(our_iterator) # => "due" +next(our_iterator) # => "tre" + +# Dopo che un iteratore ha restituito tutti i suoi dati, genera +# un'eccezione StopIteration +next(our_iterator) # Raises StopIteration + +# Puoi prendere tutti gli elementi di un iteratore utilizzando list(). +list(filled_dict.keys()) # => Returns ["one", "two", "three"] + + + +#################################################### +## 4. Funzioni +#################################################### + +# Usa "def" per creare nuove funzioni +def aggiungi(x, y): + print("x è {} e y è {}".format(x, y)) // Scrive i valori formattati in una stringa + return x + y # Restituisce la somma dei valori con il metodo return + +# Chiamare funzioni con parametri +aggiungi(5, 6) # => scrive "x è 5 e y è 6" e restituisce 11 + +# Un altro modo per chiamare funzioni è con parole chiave come argomenti +aggiungi(y=6, x=5) # In questo modo non è necessario rispettare l'ordine degli argomenti + +# Puoi definire funzioni che accettano un numero non definito di argomenti +def varargs(*args): + return args + +varargs(1, 2, 3) # => (1, 2, 3) + +# Puoi definire funzioni che accettano un numero variabile di parole chiave +# come argomento, che saranno interpretati come un dizionario usando ** +def keyword_args(**kwargs): + return kwargs + +# Chiamiamola per vedere cosa succede +keyword_args(big="foot", loch="ness") # => {"big": "foot", "loch": "ness"} + + +# Puoi farle entrambi in una volta, se ti va +def all_the_args(*args, **kwargs): + print(args) + print(kwargs) +""" +all_the_args(1, 2, a=3, b=4) stampa: + (1, 2) + {"a": 3, "b": 4} +""" + +# Quando chiami funzioni, puoi fare l'opposto di args/kwargs! +# Usa * per sviluppare gli argomenti posizionale ed usa ** per +# espandere gli argomenti parola chiave +args = (1, 2, 3, 4) +kwargs = {"a": 3, "b": 4} +all_the_args(*args) # equivalente a foo(1, 2, 3, 4) +all_the_args(**kwargs) # equivalente a foo(a=3, b=4) +all_the_args(*args, **kwargs) # equivalente a foo(1, 2, 3, 4, a=3, b=4) + + +# Restituire valori multipli (with tuple assignments) +def swap(x, y): + return y, x # Restituisce valori multipli come tupla senza parentesi + # (Nota: le parentesi sono state escluse ma possono essere messe) + +x = 1 +y = 2 +x, y = swap(x, y) # => x = 2, y = 1 +# (x, y) = swap(x,y) # Le parentesi sono state escluse ma possono essere incluse. + +# Funzioni - Visibilità delle variabili (variable scope) +x = 5 + +def set_x(num): + # La variabile locale x non è la variabile globale x + x = num # => 43 + print(x) # => 43 + +def set_global_x(num): + global x + print(x) # => 5 + x = num # la variabile globable x è ora 6 + print(x) # => 6 + +set_x(43) +set_global_x(6) + + +# Python ha "first class functions" +def create_adder(x): + def adder(y): + return x + y + return adder + +add_10 = create_adder(10) +add_10(3) # => 13 + +# Ci sono anche funzioni anonime +(lambda x: x > 2)(3) # => True +(lambda x, y: x ** 2 + y ** 2)(2, 1) # => 5 + +# È possibile creare "mappe" e "filtri" +list(map(add_10, [1, 2, 3])) # => [11, 12, 13] +list(map(max, [1, 2, 3], [4, 2, 1])) # => [4, 2, 3] + +list(filter(lambda x: x > 5, [3, 4, 5, 6, 7])) # => [6, 7] + +# Possiamo usare le "list comprehensions" per mappe e filtri +# Le "list comprehensions" memorizzano l'output come una lista che può essere +# di per sé una lista annidata +[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] + +# Puoi fare anche la comprensione di set e dizionari +{x for x in 'abcddeef' if x not in 'abc'} # => {'d', 'e', 'f'} +{x: x**2 for x in range(5)} # => {0: 0, 1: 1, 2: 4, 3: 9, 4: 16} + + +#################################################### +## 5. Modules +#################################################### + +# Puoi importare moduli +import math +print(math.sqrt(16)) # => 4.0 + +# Puoi ottenere specifiche funzione da un modulo +from math import ceil, floor +print(ceil(3.7)) # => 4.0 +print(floor(3.7)) # => 3.0 + +# Puoi importare tutte le funzioni da un modulo +# Attenzione: questo non è raccomandato +from math import * + +# Puoi abbreviare i nomi dei moduli +import math as m +math.sqrt(16) == m.sqrt(16) # => True + + +# I moduli di Python sono normali file python. Ne puoi +# scrivere di tuoi ed importarli. Il nome del modulo +# è lo stesso del nome del file. + +# Potete scoprire quali funzioni e attributi +# sono definiti in un modulo +import math +dir(math) + +# Se nella cartella corrente hai uno script chiamato math.py, +# Python caricherà quello invece del modulo math. +# Questo succede perchè la cartella corrente ha priorità +# sulle librerie standard di Python + +# Se hai uno script Python chiamato math.py nella stessa +# cartella del tua script, Python caricherà quello al posto del +# comune modulo math. +# Questo accade perché la cartella locale ha la priorità +# sulle librerie built-in di Python. + + +#################################################### +## 6. Classes +#################################################### + +# Usiamo l'istruzione "class" per creare una classe +class Human: + + # Un attributo della classe. E' condiviso tra tutte le istanze delle classe + species = "H. sapiens" + + # Si noti che i doppi underscore iniziali e finali denotano gli oggetti o + # attributi utilizzati da Python ma che vivono nel namespace controllato + # dall'utente + # Metodi, oggetti o attributi come: __init__, __str__, __repr__, etc. sono + # chiamati metodi speciali (o talvolta chiamati "dunder methods"). + # Non dovresti inventare tali nomi da solo. + + def __init__(self, name): + # Assegna l'argomento all'attributo name dell'istanza + self.name = name + + # Inizializza una proprietà + self._age = 0 + + # Un metodo dell'istanza. Tutti i metodi prendo "self" come primo argomento + def say(self, msg): + print("{name}: {message}".format(name=self.name, message=msg)) + + # Un altro metodo dell'istanza + def sing(self): + return 'yo... yo... microphone check... one two... one two...' + + # Un metodo della classe è condiviso fra tutte le istanze + # Sono chiamati con la classe chiamante come primo argomento + @classmethod + def get_species(cls): + return cls.species + + # Un metodo statico è chiamato senza classe o istanza di riferimento + @staticmethod + def grunt(): + return "*grunt*" + + # Una property è come un metodo getter. + # Trasforma il metodo age() in un attributo in sola lettura, che ha + # lo stesso nome + # In Python non c'è bisogno di scrivere futili getter e setter. + @property + def age(self): + return self._age + + # Questo metodo permette di modificare una property + @age.setter + def age(self, age): + self._age = age + + # Questo metodo permette di cancellare una property + @age.deleter + def age(self): + del self._age + +# Quando l'interprete Python legge un sorgente esegue tutto il suo codice. +# Questo controllo su __name__ assicura che questo blocco di codice venga +# eseguito solo quando questo modulo è il programma principale. + +if __name__ == '__main__': + # Crea un'istanza della classe + i = Human(name="Ian") + i.say("hi") # "Ian: hi" + j = Human("Joel") + j.say("hello") # "Joel: hello" + # i e j sono istanze del tipo Human, o in altre parole sono oggetti Human + + # Chiama un metodo della classe + i.say(i.get_species()) # "Ian: H. sapiens" + # Cambia l'attributo condiviso + Human.species = "H. neanderthalensis" + i.say(i.get_species()) # => "Ian: H. neanderthalensis" + j.say(j.get_species()) # => "Joel: H. neanderthalensis" + + # Chiama un metodo statico + print(Human.grunt()) # => "*grunt*" + + # Non è possibile chiamare il metodo statico con l'istanza dell'oggetto + # poiché i.grunt() metterà automaticamente "self" (l'oggetto i) + # come argomento + print(i.grunt()) # => TypeError: grunt() takes 0 positional arguments but 1 was given + + # Aggiorna la property (age) di questa istanza + i.age = 42 + # Leggi la property + i.say(i.age) # => "Ian: 42" + j.say(j.age) # => "Joel: 0" + # Cancella la property + del i.age + i.age # => questo genererà un AttributeError + + +#################################################### +## 6.1 Ereditarietà (Inheritance) +#################################################### + +# L'ereditarietà consente di definire nuove classi figlio che ereditano metodi e +# variabili dalla loro classe genitore. + +# Usando la classe Human definita sopra come classe base o genitore, possiamo +# definire una classe figlia, Superhero, che erediterà le variabili di classe +# come "species", "name" e "age", così come i metodi, come "sing" e "grunt", +# dalla classe Human, ma potrà anche avere le sue proprietà uniche. + +# Per importare le funzioni da altri file usa il seguente formato +# from "nomefile-senza-estensione" import "funzione-o-classe" + +from human import Human + +# Specificare le classi genitore come parametri della definizione della classe +class Superhero(Human): + + # Se la classe figlio deve ereditare tutte le definizioni del genitore + # senza alcuna modifica, puoi semplicemente usare la parola chiave "pass" + # (e nient'altro) + + #Le classi figlio possono sovrascrivere gli attributi dei loro genitori + species = 'Superhuman' + + # Le classi figlie ereditano automaticamente il costruttore della classe + # genitore, inclusi i suoi argomenti, ma possono anche definire ulteriori + # argomenti o definizioni e sovrascrivere i suoi metodi (compreso il + # costruttore della classe). + # Questo costruttore eredita l'argomento "nome" dalla classe "Human" e + # aggiunge gli argomenti "superpowers" e "movie": + + def __init__(self, name, movie=False, + superpowers=["super strength", "bulletproofing"]): + + # aggiungi ulteriori attributi della classe + self.fictional = True + self.movie = movie + self.superpowers = superpowers + + # La funzione "super" ti consente di accedere ai metodi della classe + # genitore che sono stati sovrascritti dalla classe figlia, + # in questo caso il metodo __init__. + # Il seguente codice esegue il costruttore della classe genitore: + super().__init__(name) + + # Sovrascrivere il metodo "sing" + def sing(self): + return 'Dun, dun, DUN!' + + # Aggiungi un ulteriore metodo dell'istanza + def boast(self): + for power in self.superpowers: + print("I wield the power of {pow}!".format(pow=power)) + + +if __name__ == '__main__': + sup = Superhero(name="Tick") + + # Controllo del tipo di istanza + if isinstance(sup, Human): + print('I am human') + if type(sup) is Superhero: + print('I am a superhero') + + # Ottieni il "Method Resolution search Order" usato sia da getattr () + # che da super (). Questo attributo è dinamico e può essere aggiornato + print(Superhero.__mro__) # => (<class '__main__.Superhero'>, + # => <class 'human.Human'>, <class 'object'>) + + # Esegui il metodo principale ma utilizza il proprio attributo di classe + print(sup.get_species()) # => Superhuman + + # Esegui un metodo che è stato sovrascritto + print(sup.sing()) # => Dun, dun, DUN! + + # Esegui un metodo di Human + sup.say('Spoon') # => Tick: Spoon + + # Esegui un metodo che esiste solo in Superhero + sup.boast() # => I wield the power of super strength! + # => I wield the power of bulletproofing! + + # Attributo di classe ereditato + sup.age = 31 + print(sup.age) # => 31 + + # Attributo che esiste solo in Superhero + print('Am I Oscar eligible? ' + str(sup.movie)) + +#################################################### +## 6.2 Ereditarietà multipla +#################################################### + +# Un'altra definizione di classe +# bat.py +class Bat: + + species = 'Baty' + + def __init__(self, can_fly=True): + self.fly = can_fly + + # Questa classe ha anche un metodo "say" + def say(self, msg): + msg = '... ... ...' + return msg + + # E anche un suo metodo personale + def sonar(self): + return '))) ... (((' + +if __name__ == '__main__': + b = Bat() + print(b.say('hello')) + print(b.fly) + +# Definizione di classe che eredita da Superhero e Bat +# superhero.py +from superhero import Superhero +from bat import Bat + +# Definisci Batman come classe figlia che eredita sia da Superhero che da Bat +class Batman(Superhero, Bat): + + def __init__(self, *args, **kwargs): + # In genere per ereditare gli attributi devi chiamare super: + # super(Batman, self).__init__(*args, **kwargs) + # Ma qui abbiamo a che fare con l'ereditarietà multipla, e super() + # funziona solo con la successiva classe nell'elenco MRO. + # Quindi, invece, chiamiamo esplicitamente __init__ per tutti gli + # antenati. L'uso di *args e **kwargs consente di passare in modo + # pulito gli argomenti, con ciascun genitore che "sbuccia un + # livello della cipolla". + Superhero.__init__(self, 'anonymous', movie=True, + superpowers=['Wealthy'], *args, **kwargs) + Bat.__init__(self, *args, can_fly=False, **kwargs) + # sovrascrivere il valore per l'attributo name + self.name = 'Sad Affleck' + + def sing(self): + return 'nan nan nan nan nan batman!' + + +if __name__ == '__main__': + sup = Batman() + + # Ottieni il "Method Resolution search Order" utilizzato da getattr() e super(). + # Questo attributo è dinamico e può essere aggiornato + print(Batman.__mro__) # => (<class '__main__.Batman'>, + # => <class 'superhero.Superhero'>, + # => <class 'human.Human'>, + # => <class 'bat.Bat'>, <class 'object'>) + + # Esegui il metodo del genitore ma utilizza il proprio attributo di classe + print(sup.get_species()) # => Superhuman + + # Esegui un metodo che è stato sovrascritto + print(sup.sing()) # => nan nan nan nan nan batman! + + # Esegui un metodo da Human, perché l'ordine di ereditarietà è importante + sup.say('I agree') # => Sad Affleck: I agree + + # Esegui un metodo che esiste solo nel 2o antenato + print(sup.sonar()) # => ))) ... ((( + + # Attributo di classe ereditato + sup.age = 100 + print(sup.age) # => 100 + + # Attributo ereditato dal secondo antenato il cui valore predefinito + # è stato ignorato. + print('Can I fly? ' + str(sup.fly)) # => Can I fly? False + + + +#################################################### +## 7. Advanced +#################################################### + +# I generatori ti aiutano a creare codice pigro (lazy code). +# Codice che darà un risultato solo quando sarà "valutato" +def double_numbers(iterable): + for i in iterable: + yield i + i + +# I generatori sono efficienti in termini di memoria perché caricano +# solo i dati necessari per elaborare il valore successivo nell'iterabile. +# Ciò consente loro di eseguire operazioni su intervalli di valori +# altrimenti proibitivi. +# NOTA: `range` sostituisce` xrange` in Python 3. +for i in double_numbers(range(1, 900000000)): # `range` is a generator. + print(i) + if i >= 30: + break + +# Proprio come è possibile creare una "list comprehension", è possibile +# creare anche delle "generator comprehensions". +values = (-x for x in [1,2,3,4,5]) +for x in values: + print(x) # prints -1 -2 -3 -4 -5 to console/terminal + +# Puoi anche trasmettere una "generator comprehensions" direttamente +# ad un elenco. +values = (-x for x in [1,2,3,4,5]) +gen_to_list = list(values) +print(gen_to_list) # => [-1, -2, -3, -4, -5] + + +# Decoratori +# In questo esempio "beg" avvolge/wrappa "say". +# Se say_please è True, cambierà il messaggio restituito. +from functools import wraps + +def beg(target_function): + @wraps(target_function) + def wrapper(*args, **kwargs): + msg, say_please = target_function(*args, **kwargs) + if say_please: + return "{} {}".format(msg, "Per favore! Sono povero :(") + return msg + + return wrapper + + +@beg +def say(say_please=False): + msg = "Puoi comprarmi una birra?" + return msg, say_please + + +print(say()) # Puoi comprarmi una birra? +print(say(say_please=True)) # Puoi comprarmi una birra? Per favore! Sono povero :( +``` + +## Pronto per qualcosa di più? + +### Gratis Online + +* [Automate the Boring Stuff with Python](https://automatetheboringstuff.com) +* [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 Course](http://www.python-course.eu/index.php) +* [First Steps With Python](https://realpython.com/learn/python-first-steps/) +* [A curated list of awesome Python frameworks, libraries and software](https://github.com/vinta/awesome-python) +* [30 Python Language Features and Tricks You May Not Know About](http://sahandsaba.com/thirty-python-language-features-and-tricks-you-may-not-know.html) +* [Official Style Guide for Python](https://www.python.org/dev/peps/pep-0008/) +* [Python 3 Computer Science Circles](http://cscircles.cemc.uwaterloo.ca/) +* [Dive Into Python 3](http://www.diveintopython3.net/index.html) +* [A Crash Course in Python for Scientists](http://nbviewer.jupyter.org/gist/anonymous/5924718) diff --git a/matlab.html.markdown b/matlab.html.markdown index 6dc9f697..b88b1c03 100644 --- a/matlab.html.markdown +++ b/matlab.html.markdown @@ -374,8 +374,8 @@ disp('Hello World') % Print out a string fprintf % Print to Command Window with more control % Conditional statements (the parentheses are optional, but good style) -if (a > 15) - disp('Greater than 15') +if (a > 23) + disp('Greater than 23') elseif (a == 23) disp('a is 23') else @@ -545,7 +545,7 @@ ans = multiplyLatBy(a,3) % The method can also be called using dot notation. In this case, the object % does not need to be passed to the method. -ans = a.multiplyLatBy(a,1/3) +ans = a.multiplyLatBy(1/3) % Matlab functions can be overloaded to handle objects. % In the method above, we have overloaded how Matlab handles diff --git a/objective-c.html.markdown b/objective-c.html.markdown index 04c4e529..de3884af 100644 --- a/objective-c.html.markdown +++ b/objective-c.html.markdown @@ -731,7 +731,10 @@ if ([myClass conformsToProtocol:@protocol(CarUtilities)]) { /////////////////////////////////////// // Blocks are statements of code, just like a function, that are able to be used as data. // Below is a simple block with an integer argument that returns the argument plus 4. -int (^addUp)(int n); // Declare a variable to store the block. +^(int n) { + return n + 4; +} +int (^addUp)(int n); // Declare a variable to store a block. void (^noParameterBlockVar)(void); // Example variable declaration of block with no arguments. // Blocks have access to variables in the same scope. But the variables are readonly and the // value passed to the block is the value of the variable when the block is created. diff --git a/pt-br/c-pt.html.markdown b/pt-br/c-pt.html.markdown index 0dca7ab0..d594b7b9 100644 --- a/pt-br/c-pt.html.markdown +++ b/pt-br/c-pt.html.markdown @@ -638,16 +638,17 @@ typedef void (*minha_função_type)(char *); ## Leitura adicional É recomendado ter uma cópia de [K&R, aka "The C Programming Language"](https://en.wikipedia.org/wiki/The_C_Programming_Language). -Este é *o* livro sobre C, escrito pelos criadores da linguage. Mas cuidado - ele é antigo e contém alguns erros (bem, -ideias que não são consideradas boas hoje) ou práticas mudadas. +Este é *o* livro sobre C, escrito pelos criadores da linguagem. Mas cuidado - ele é antigo e contém alguns erros (bem, +ideias que não são mais consideradas boas) ou práticas ultrapassadas. Outra boa referência é [Learn C the hard way](http://c.learncodethehardway.org/book/). Se você tem uma pergunta, leia [compl.lang.c Frequently Asked Questions](http://c-faq.com). É importante usar espaços e indentação adequadamente e ser consistente com seu estilo de código em geral. -Código legível é melhor que código 'esperto' e rápido. Para adotar um estilo de código bom e são, veja +Código legível é melhor que código 'esperto' e rápido. Para adotar um estilo de código bom e sensato, veja [Linux kernel coding style](https://www.kernel.org/doc/Documentation/CodingStyle). Além disso, Google é teu amigo. + [1] http://stackoverflow.com/questions/119123/why-isnt-sizeof-for-a-struct-equal-to-the-sum-of-sizeof-of-each-member diff --git a/ruby.html.markdown b/ruby.html.markdown index e0a6bb6e..bbc8c558 100644 --- a/ruby.html.markdown +++ b/ruby.html.markdown @@ -15,32 +15,28 @@ contributors: - ["Gabriel Halley", "https://github.com/ghalley"] - ["Persa Zula", "http://persazula.com"] - ["Jake Faris", "https://github.com/farisj"] + - ["Corey Ward", "https://github.com/coreyward"] --- ```ruby # This is a comment -=begin -This is a multiline comment -No-one uses them -You shouldn't either -=end +# In Ruby, (almost) everything is an object. +# This includes numbers… +3.class #=> Integer -# First and foremost: Everything is an object. - -# Numbers are objects - -3.class #=> Fixnum - -3.to_s #=> "3" +# …strings… +"Hello".class #=> String +# …even methods! +"Hello".method(:class).class #=> Method # Some basic arithmetic 1 + 1 #=> 2 8 - 1 #=> 7 10 * 2 #=> 20 35 / 5 #=> 7 -2**5 #=> 32 +2 ** 5 #=> 32 5 % 3 #=> 2 # Bitwise operators @@ -52,6 +48,7 @@ You shouldn't either # for calling a method on an object 1.+(3) #=> 4 10.* 5 #=> 50 +100.methods.include?(:/) #=> true # Special values are objects nil # equivalent to null in other languages @@ -72,9 +69,10 @@ false.class #=> FalseClass # apart from false itself, nil is the only other 'falsey' value -!nil #=> true -!false #=> true -!0 #=> false +!!nil #=> false +!!false #=> false +!!0 #=> true +!!"" #=> true # More comparisons 1 < 10 #=> true @@ -82,7 +80,8 @@ false.class #=> FalseClass 2 <= 2 #=> true 2 >= 2 #=> true -# Combined comparison operator +# Combined comparison operator (returns `1` when the first argument is greater, +# `-1` when the second argument is greater, and `0` otherwise) 1 <=> 10 #=> -1 10 <=> 1 #=> 1 1 <=> 1 #=> 0 @@ -90,7 +89,6 @@ false.class #=> FalseClass # Logical operators true && false #=> false true || false #=> true -!true #=> false # There are alternate versions of the logical operators with much lower # precedence. These are meant to be used as flow-control constructs to chain @@ -101,23 +99,17 @@ do_something() and do_something_else() # `log_error` only called if `do_something` fails. do_something() or log_error() - -# Strings are objects - -'I am a string'.class #=> String -"I am a string too".class #=> String +# String interpolation placeholder = 'use string interpolation' "I can #{placeholder} when using double quoted strings" #=> "I can use string interpolation when using double quoted strings" -# Prefer single quoted strings to double quoted ones where possible -# Double quoted strings perform additional inner calculations - -# Combine strings, but not with numbers +# You can combine strings using `+`, but not with other types 'hello ' + 'world' #=> "hello world" 'hello ' + 3 #=> TypeError: can't convert Fixnum into String 'hello ' + 3.to_s #=> "hello 3" +"hello #{3}" #=> "hello 3" # Combine strings and operators 'hello ' * 3 #=> "hello hello hello " @@ -150,9 +142,8 @@ snake_case = true # Use descriptive variable names path_to_project_root = '/good/name/' -path = '/bad/name/' +m = '/bad/name/' -# Symbols (are objects) # Symbols are immutable, reusable constants represented internally by an # integer value. They're often used instead of strings to efficiently convey # specific, meaningful values @@ -167,6 +158,11 @@ status == 'pending' #=> false status == :approved #=> false +Strings can be converted into symbols and vice versa: + +status.to_s #=> "pending" +"argon".to_sym #=> :argon + # Arrays # This is an array @@ -196,7 +192,7 @@ array.last #=> 5 array[2, 3] #=> [3, 4, 5] # Reverse an Array -a=[1,2,3] +a = [1,2,3] a.reverse! #=> [3,2,1] # Or with a range @@ -223,7 +219,7 @@ hash['number'] #=> 5 # Asking a hash for a key that doesn't exist returns nil: hash['nothing here'] #=> nil -# Since Ruby 1.9, there's a special syntax when using symbols as keys: +# When using symbols for keys in a hash, you can use this alternate syntax: new_hash = { defcon: 3, action: true } @@ -246,33 +242,26 @@ else 'else, also optional' end + +# In Ruby, traditional `for` loops aren't very common. Instead, these +# basic loops are implemented using enumerable, which hinges on `each`: + +(1..5).each do |counter| + puts "iteration #{counter}" +end + +# Which is roughly equivalent to this, which is unusual to see in Ruby: + for counter in 1..5 puts "iteration #{counter}" end -#=> iteration 1 -#=> iteration 2 -#=> iteration 3 -#=> iteration 4 -#=> iteration 5 -# HOWEVER, No-one uses for loops. -# Instead you should use the "each" method and pass it a block. -# A block is a bunch of code that you can pass to a method like "each". -# It is analogous to lambdas, anonymous functions or closures in other -# programming languages. +# The `do |variable| ... end` construct above is called a “block”. Blocks are similar +# to lambdas, anonymous functions or closures in other programming languages. They can +# be passed around as objects, called, or attached as methods. # # The "each" method of a range runs the block once for each element of the range. # The block is passed a counter as a parameter. -# Calling the "each" method with a block looks like this: - -(1..5).each do |counter| - puts "iteration #{counter}" -end -#=> iteration 1 -#=> iteration 2 -#=> iteration 3 -#=> iteration 4 -#=> iteration 5 # You can also surround blocks in curly brackets: (1..5).each { |counter| puts "iteration #{counter}" } @@ -365,10 +354,10 @@ def double(x) x * 2 end -# Methods (and all blocks) implicitly return the value of the last statement +# Methods (and blocks) implicitly return the value of the last statement double(2) #=> 4 -# Parentheses are optional where the result is unambiguous +# Parentheses are optional where the interpretation is unambiguous double 3 #=> 6 double double 3 #=> 12 @@ -399,25 +388,57 @@ surround { puts 'hello world' } # } -# You can pass a block to a method -# "&" marks a reference to a passed block +# Blocks can be converted into a `proc` object, which wraps the block +# and allows it to be passed to another method, bound to a different scope, +# or manipulated otherwise. This is most common in method parameter lists, +# where you frequently see a trailing `&block` parameter that will accept +# the block, if one is given, and convert it to a `Proc`. The naming here is +# convention; it would work just as well with `&pineapple`: def guests(&block) - block.call 'some_argument' + block.class #=> Proc + block.call(4) end +# The `call` method on the Proc is similar to calling `yield` when a block is +# present. The arguments passed to `call` will be forwarded to the block as arugments: + +guests { |n| "You have #{n} guests." } +# => "You have 4 guests." + # You can pass a list of arguments, which will be converted into an array # That's what splat operator ("*") is for def guests(*array) array.each { |guest| puts guest } end -# If a method returns an array, you can use destructuring assignment -def foods - ['pancake', 'sandwich', 'quesadilla'] +# Destructuring + +# Ruby will automatically destrucure arrays on assignment to multiple variables: +a, b, c = [1, 2, 3] +a #=> 1 +b #=> 2 +c #=> 3 + +# In some cases, you will want to use the splat operator: `*` to prompt destructuring +# of an array into a list: + +ranked_competitors = ["John", "Sally", "Dingus", "Moe", "Marcy"] + +def best(first, second, third) + puts "Winners are #{first}, #{second}, and #{third}." end -breakfast, lunch, dinner = foods -breakfast #=> 'pancake' -dinner #=> 'quesadilla' + +best *ranked_competitors.first(3) #=> Winners are John, Sally, and Dingus. + +# The splat operator can also be used in parameters: +def best(first, second, third, *others) + puts "Winners are #{first}, #{second}, and #{third}." + puts "There were #{others.count} other participants." +end + +best *ranked_competitors +#=> Winners are John, Sally, and Dingus. +#=> There were 2 other participants. # By convention, all methods that return booleans end with a question mark 5.even? # false diff --git a/solidity.html.markdown b/solidity.html.markdown index a0f8cd40..b657b6a1 100644 --- a/solidity.html.markdown +++ b/solidity.html.markdown @@ -134,7 +134,7 @@ uint constant VERSION_ID = 0x123A1; // A hex constant // All state variables (those outside a function) // are by default 'internal' and accessible inside contract // and in all contracts that inherit ONLY -// Need to explicitly set to 'public' to allow external contracts to access +// Need to explicitly set to 'public' to allow external contracts to access int256 public a = 8; // For int and uint, can explicitly set space in steps of 8 up to 256 @@ -352,7 +352,7 @@ function increment(uint x) constant returns (uint x) { // y is a state variable, and can't be changed in a constant function } -// 'pure' is more strict than 'constant', and does not +// 'pure' is more strict than 'constant', and does not // even allow reading of state vars // The exact rules are more complicated, so see more about // constant/pure: @@ -384,7 +384,7 @@ function depositEther() public payable { // Prefer loops to recursion (max call stack depth is 1024) -// Also, don't setup loops that you haven't bounded, +// Also, don't setup loops that you haven't bounded, // as this can hit the gas limit // B. Events @@ -399,11 +399,11 @@ function depositEther() public payable { event LogSent(address indexed from, address indexed to, uint amount); // note capital first letter // Call -Sent(from, to, amount); +LogSent(from, to, amount); -// For an external party (a contract or external entity), to watch using +// For an external party (a contract or external entity), to watch using // the Web3 Javascript library: -Coin.Sent().watch({}, '', function(error, result) { +Coin.LogSent().watch({}, '', function(error, result) { if (!error) { console.log("Coin transfer: " + result.args.amount + " coins were sent from " + result.args.from + @@ -709,7 +709,7 @@ contract CrowdFunder { return contributions.length - 1; // return id } - function checkIfFundingCompleteOrExpired() + function checkIfFundingCompleteOrExpired() public { if (totalRaised > minimumToRaise) { diff --git a/toml.html.markdown b/toml.html.markdown index 980563f9..39caaa23 100755 --- a/toml.html.markdown +++ b/toml.html.markdown @@ -102,9 +102,10 @@ boolMustBeLowercase = true # Datetime # ############ -date1 = 1979-05-27T07:32:00Z # follows the RFC 3339 spec -date2 = 1979-05-27T07:32:00 # without offset -date3 = 1979-05-27 # without offset nor time +date1 = 1979-05-27T07:32:00Z # UTC time, following RFC 3339/ISO 8601 spec +date2 = 1979-05-26T15:32:00+08:00 # with RFC 3339/ISO 8601 offset +date3 = 1979-05-27T07:32:00 # without offset +date4 = 1979-05-27 # without offset or time #################### # COLLECTION TYPES # diff --git a/tr-tr/c++-tr.html.markdown b/tr-tr/c++-tr.html.markdown new file mode 100644 index 00000000..a1318876 --- /dev/null +++ b/tr-tr/c++-tr.html.markdown @@ -0,0 +1,1077 @@ +--- +language: c++ +filename: learncpp.cpp +contributors: + - ["Steven Basart", "http://github.com/xksteven"] + - ["Matt Kline", "https://github.com/mrkline"] + - ["Geoff Liu", "http://geoffliu.me"] + - ["Connor Waters", "http://github.com/connorwaters"] + - ["Ankush Goyal", "http://github.com/ankushg07"] + - ["Jatin Dhankhar", "https://github.com/jatindhankhar"] + - ["Adem Budak", "https://github.com/p1v0t"] +--- + +C++ +[yaratıcısı Bjarne Stroustrup'a göre](http://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2014/Keynote), + +- "daha iyi bir C" yapmak +- veri soyutlamayı desteklemek +- nesneye yönelik programlamayı deskteklemek +- tipten bağımsız programlamayı desteklemek + +için tasarlanmış bir sistem programlama dilir. + +Sözdizimi daha yeni dillerden daha zor veya karmaşık olsa da işlemcinin doğrudan çalıştırabileceği +native komutlara derlenerek, donanım üzerinde (C gibi) sıkı bir kontrol sağlar, bunu yaparken +tipten bağımsızlık, exception'lar ve sınıflar gibi yüksek-seviyeli özellikleri destekler. +Bu hız ve kullanışlılık C++'ı en çok kullanılan dillerden biri yapar. + +```c++ +////////////////// +// C ile karşılaştırma +////////////////// + +// C++ _neredeyse_ C'nin bir üstkümesidir, değişken tanımı, basit tipleri +ve fonksiyonları için temelde aynı sözdizimini paylaşır. + +// Aynı C gibi, programın başlangıç noktası bir integer döndüren +// main fonksiyonudur. +// Bu değer programın bitiş statüsünü belli eder. +// Daha fazla bilgi için bknz http://en.wikipedia.org/wiki/Exit_status . + +int main(int argc, char** argv) +{ + // Komut satırı argümanları C'de olduğu gibi argv ve argc ile geçilir + // argc, argüman sayısını belli eder, + // argv, argümanları belli eden, C-stili string'lerin (char*) dizisidir. + // İlk argüman çağrılan programın adıdır. + // Eğer argümanları umursamıyorsan, argv ve argc kullanılmayabilir + // int main() gibi + + // 0 çıkış durumu başarıyı belirtir. + return 0; +} + +// Bunlara rağmen C++ aşağıdaki noktalarda farklılaşır: + +// C++'ta, karakterler char türündendir +sizeof('c') == sizeof(char) == 1 + +// C'de, karakterler int türündendir +sizeof('c') == sizeof(int) + + +// C++ katı bir prototip kuralına sahiptir +void func(); // fonksiyon argüman kabul etmez + +// C'de +void func(); // fonksiyon herhangi bir sayıda argüman kabul edebilir + +// C++'da NULL yerine nullptr kullanılır +int* ip = nullptr; + +// C standard başlıkları başına "c" eklenip, sondaki .h +// kullanılmadan C++'ta kullanılabilir +#include <cstdio> + +int main() +{ + printf("Hello, world!\n"); + return 0; +} + +////////////////////////////////// +// Fonksiyonun fazladan yüklenmesi +////////////////////////////////// + +// C++ herbir fonksiyonun farklı parametereler +// aldığı fonksiyon fazladan yüklenmesini desktekler + +void print(char const* myString) +{ + printf("String %s\n", myString); +} + +void print(int myInt) +{ + printf("My int is %d", myInt); +} + +int main() +{ + print("Hello"); // void print(const char*) fonksiyonunu çağırır. + print(15); // void print(int) fonksiyonunu çağırır. +} + +//////////////////////////////// +// Default fonksiyon argümanları +/////////////////////////////i// + +// Eğer çağırıcı tarafından fonksiyona argüman sağlanmamışsa, +// fonksiyona default argüman verebilirsin + +void doSomethingWithInts(int a = 1, int b = 4) +{ + // Burada int'lerle birşeyler yap +} + +int main() +{ + doSomethingWithInts(); // a = 1, b = 4 + doSomethingWithInts(20); // a = 20, b = 4 + doSomethingWithInts(20, 5); // a = 20, b = 5 +} + +// Default argümanlar, argüman listesinin sonunda yer almalı. + +void invalidDeclaration(int a = 1, int b) // Hata! +{ +} + + +///////////////////////// +// Namespace(İsim uzayı) +///////////////////////// + +// Namespace'ler değişken, fonksiyon ve diğer bildirimlerin +// kapsama alanını ayırır. +// Namespace'ler içiçe geçebilir. + +namespace First { + namespace Nested { + void foo() + { + printf("This is First::Nested::foo\n"); + } + } // Nested namespace'inin sonu +} // First namespace'inin sonu + +namespace Second { + void foo() + { + printf("This is Second::foo\n"); + } +} + +void foo() +{ + printf("This is global foo\n"); +} + +int main() +{ + // Second namespace'i içinideki tüm sembolleri mevcut kapsama alanına dahil eder. + // Dikkat edersen artık yalnızca foo() çağrısı çalışmayacaktır çünkü hangi + // namespace'ten çağrıldığı açık değildir. + using namespace Second; + + Second::foo(); // "This is Second::foo" yazdırıır + First::Nested::foo(); // "This is First::Nested::foo" yazdırır + ::foo(); // "This is global foo" yazdırır. +} + +/////////////// +// Input/Output +/////////////// + +// C++'ta input ve output stream'leri kullanır. +// cin, cout ve cerr,sırasıyla, stdin, stdout, ve stderr'i temsil eder. +// << araya ekleme ve >> aradan çıkarma operatörüdür. + +#include <iostream> // I/O stream'lerini dahil etmek için + +using namespace std; // Streamler std namespace'i içindedir(standard kütüphane) + +int main() +{ + int myInt; + + // stdout (veya terminal/screen)'ta çıktı verir + cout << "Enter your favorite number:\n"; + // Girdiyi alır + cin >> myInt; + + // cout ayrıca formatlanabilir + cout << "Your favorite number is " << myInt << "\n"; + // prints "Your favorite number is <myInt>" + + cerr << "Used for error messages"; +} + +////////////// +// String'ler +///////////// + +// String'ler C++'ta nesnedir ve pek çok üye fonksiyonu vardır +#include <string> + +using namespace std; // String'ler de std namespace'i içindedir. (standard kütüphane) + +string myString = "Hello"; +string myOtherString = " World"; + +// + eklemek için kullanıldır +cout << myString + myOtherString; // "Hello World" + +cout << myString + " You"; // "Hello You" + +// C++'ta stringler are mutable'dır (değişebilir). +myString.append(" Dog"); +cout << myString; // "Hello Dog" + + +/////////////////////// +// Reference (Referans) +/////////////////////// + +// C'deki pointer'lara ek olarak +// C++ _reference_'lara sahiptir. +// Bunlar bir kere atandınğında tekrardan atanamayan pointer'dır +// ve null olamaz. +// Değişkenin kendisiyle aynı sözdizimine sahiptir: +// Değerine ulaşmak için * ihtiyaç yoktur ve +// atama için & (address of) kullanılmaz. + +using namespace std; + +string foo = "I am foo"; +string bar = "I am bar"; + + +string& fooRef = foo; // Bu foo'nun reference'ını oluşturur. +fooRef += ". Hi!"; // foo'yu reference'ı üzerinden değiştirir. +cout << fooRef; // "I am foo. Hi!" yazdırır. + +// "fooRef"e yeniden atama yapmaz. Bu "foo = bar" denktir ve bu satırdan sonra +// foo == "I am bar" olur +cout << &fooRef << endl; // foo'un adresini yazdırır +fooRef = bar; +cout << &fooRef << endl; //Hala foo'nun adresini yazdırır +cout << fooRef; //"I am bar" yazdırır + +// fooRef'in adresi aynı kalır yani hala foo'nun adresidir. + +const string& barRef = bar; // bar'a const reference oluşturur +// C'de olduğu gibi, const değerler (pointer'lar ve reference'ler) değiştirilemez. +barRef += ". Hi!"; // Hata, const reference'ler değiştirilemez. + +// Kısa bir ekleme: reference'lere devam etmeden önce, geçici nesne konseptinden +// bahsetmeliyiz. Mesela aşadaki gibi bir kod var: +string tempObjectFun() { ... } +string retVal = tempObjectFun(); + +// Bu iki satırda aslında ne oluyor: +// - tempObjectFun fonksiyonundan bir string nesnesi dönüyor +// - dönmüş olan nesneyle yeni bir string oluşturuyor +/ - dönmüş olan nesne yok ediliyor +// İşte bu dönen nesneye geçici nesne denir. Geçici nesneler fonksiyon nesne +// döndürdüğünde oluşturulur ve ifade işini bitirdiğinde yok edilir (Aslında, +// standard'ın söylediği şey bu ama derleyiciler bu davranışı değiştirmemize +// izin veriyor. Daha fazla detay için "return value optimization" diye +// aratabilirsin. Sonuç olarak aşağıdaki kodda: +foo(bar(tempObjectFun())) + +// foo ve bar'ın varolduğunu kabul ediyoruz, tempObjectFun'dan dönen nesne +// bar'a geçti ve foo çağrılmadan önce yokedildir. + +// Şimdi reference'lara dönelim. "ifadenin sonunda" kuralının bir istisnası +// eğer geçici nesne const reference'a geçildiyse oratya çıkar, bu durumda +// nesnenin ömrü mevcut kapsama alanına kadar uzar: + +void constReferenceTempObjectFun() { + // constRef geçici nesneyi alır ve bu durum fonksiyonun sonuna kadar geçerlidir. + const string& constRef = tempObjectFun(); + ... +} + +// C++11 ile gelen diğer bir reference geçici nesnelere özeldir. Bu türden birden +// bir tip tanımlayamazsın ama aşırı yüklenme sırasında bu tipler öncelik alır: +void someFun(string& s) { ... } // Regular reference +void someFun(string&& s) { ... } // Geçici nesneye reference + +string foo; +someFun(foo); // regular reference'ı çağırır +someFun(tempObjectFun()); // geçici reference'ı çağırır + +///////////////////// +// Enum +///////////////////// + +// Enum'lar sabit değerler yapmak için kullanılır ve çoğunlukla kodun daha okunaklı +// olması için kullanılır + +enum ECarTypes +{ + Sedan, + Hatchback, + SUV, + Wagon +}; + +ECarTypes GetPreferredCarType() +{ + return ECarTypes::Hatchback; +} + +// C++11 ile beraber bir tipi enum'a atamanın kolay bir yolu var, bu enum'un istenen +// tipe dönüştürmek için kullanışlı bir yöntem +enum ECarTypes : uint8_t +{ + Sedan, // 0 + Hatchback, // 1 + SUV = 254, // 254 + Hybrid // 255 +}; + +void WriteByteToFile(uint8_t InputValue) +{ + // Serialize the InputValue to a file +} + +void WritePreferredCarTypeToFile(ECarTypes InputCarType) +{ + // enum uint8_t tipine dönüştürüldü + WriteByteToFile(InputCarType); +} + +// Diğer yandan enum'ların yanlışlıkla integer tipini veya diğer enumlara dönüşmesini +// istemiyorsan enum class olarak tanımlayabilirsin +enum class ECarTypes : uint8_t +{ + Sedan, // 0 + Hatchback, // 1 + SUV = 254, // 254 + Hybrid // 255 +}; + +void WriteByteToFile(uint8_t InputValue) +{ + // Serialize the InputValue to a file +} + +void WritePreferredCarTypeToFile(ECarTypes InputCarType) +{ + // ECarTypes, uint8_t tipinde olmasına rağmen, "enum class" olarak + // tanımlandığından derlenmeyecektir! + WriteByteToFile(InputCarType); +} + +/////////////////////////////////////////// +// Sınıflar ve nesneye yönelik proglamalama +/////////////////////////////////////////// + +// Sınıflara(class) ilk örnek +#include <iostream> + +// Sınıfı tanımla. +// Sınıflar genelde header (.h veya .hpp) dosyalarında tanımlanır. +class Dog { + // Member variables and functions are private by default. + // Üye değişkenler ve fonksiyonlar default olarak private'dir. + std::string name; + int weight; + +// Aşağıda, "private:" veya "protected:" bulunana kadar +// bütün üyeler public'tir. +public: + + // Default constructor + Dog(); + + // Üye fonksiyon bildirimi (gerçeklenimi aşağıda) + // Dikkat ederseniz using namespace std; yerine + // std::string kullandık. + // Hiçbir zaman header dosyasında "using namespace std;" kullanma. + void setName(const std::string& dogsName); + + void setWeight(int dogsWeight); + + // Nesnenin durumunu değiştirmeyen fonksiyonlar const ile işaretlenmelidir + + // Türetilen sınıflarda fonksiyonu override edebilmek için başına + // _virtual_ eklenmelidir. + // Fonksiyonlar, performanslar ilgili nedenlerden ötürü default olarak virtual değildir + virtual void print() const; + + // Fonksiyonlar class içinde de tanımlanabilir. + // Bu şekille tanımlanan fonksiyonlar otomatik olarak inline olur. + void bark() const { std::cout << name << " barks!\n"; } + + // C++ constructor'ların yanında destructor'da sağlar. + // Bunlar nesne silindiğinde veya scope'un dışına çıktığında çağrılır. + // Bu RAII gibi güçlü paradigmaları etkin kılar. + // (aşağıda açıklandı) + // Eğer sınıf kendisinden türetiliyorsa, destructor virtual olmalıdır, + // eğer virtual değilse, türetilmiş sınıfın destructor'ı nesne, ana sınıf + // referans'ı veya pointer'ı üzerinden yok edildiğinde, çağrılmayacaktır. + virtual ~Dog(); + +}; // class tanımının sonuda noktalı virgül(;) olmalıdır. + +// Sınıfın üye fonksiyonları genelde .cpp dosyaları içinde gerçeklenir. +Dog::Dog() +{ + std::cout << "A dog has been constructed\n"; +} + +// Objects (such as strings) should be passed by reference +// Nesneler (string gibi) reference ile fonksiyonlara geçilmelidir +// Eğer nesneleri değiştirilecekse reference ile fonksiyonlara geçilmelidir, +// değiştirilmeyecekse const reference ile geçilmelidir. +void Dog::setName(const std::string& dogsName) +{ + name = dogsName; +} + +void Dog::setWeight(int dogsWeight) +{ + weight = dogsWeight; +} + +// Dikkat edersen "virtual" yalnızca bildirimde gerekli, tanımlamada değil. +void Dog::print() const +{ + std::cout << "Dog is " << name << " and weighs " << weight << "kg\n"; +} + +Dog::~Dog() +{ + std::cout << "Goodbye " << name << "\n"; +} + +int main() { + Dog myDog; // "A dog has been constructed" yazdırır + myDog.setName("Barkley"); + myDog.setWeight(10); + myDog.print(); // "Dog is Barkley and weighs 10 kg" yazdırır. + return 0; +} // "Goodbye Barkley" yazdırır. + +// Inheritance(Miras) + +// Bu sınıf, Dog sınıfında public ve protected olan herşeyi miras alır, +// private olanları da miras alır ama, public ve protected sınıflar aracılıyla +// yapılmıyorsa, doğrudan erişemez. +class OwnedDog : public Dog { + +public: + void setOwner(const std::string& dogsOwner); + + // print fonksiyonunun davranışını bütün OwnedDogs sınıfı için override eder + // (üstünden geçer, kendine uyarlar). + // bknz http://en.wikipedia.org/wiki/Polymorphism_(computer_science) + // override anahtar sözcüpü kullanılma da olur ama kullanılması aslında bir temel + // temel sınıf fonksiyonunun üzerinden geçtiğimizi gösterir. + void print() const override; + +private: + std::string owner; +}; + +// Bu arada takip eden .cpp dosyasında: + +void OwnedDog::setOwner(const std::string& dogsOwner) +{ + owner = dogsOwner; +} + +void OwnedDog::print() const +{ + Dog::print(); // Ana dog sınıfındaki print fonksiyonunu çağırır + std::cout << "Dog is owned by " << owner << "\n"; + // "Dog is <name> and weights <weight>" + // "Dog is owned by <owner>" + // yazdırır +} + +///////////////////////////////////////////////////// +// ilk değer atama ve Operatörün fazladan yüklenmesi +///////////////////////////////////////////////////// + +// C++ dilinde +, -, *, /, gibi operatörlerin davranışını fazladan yükleyebilirsiniz. +// Bu, operator her kullandınıldığında çağrılan bir fonksiyon tanımlamasıyla yapılır. + +#include <iostream> +using namespace std; + +class Point { +public: + // Üye değişkenkenlere default değer atanabilir. + double x = 0; + double y = 0; + + // Default constructor + Point() { }; + + Point (double a, double b) : + x(a), + y(b) + { /* İlk değer atama dışında birşey yapma */ } + + // + operatorünün fazladan yükle. + Point operator+(const Point& rhs) const; + + // += operatorünü fazladan yükle + Point& operator+=(const Point& rhs); + + // - ve -= operatorleri fazladan yüklemek de mantıklı olurdu + // ama kısa tutmak için burda değinmedik. +}; + +Point Point::operator+(const Point& rhs) const +{ + // yeni bir nokta oluştur ve bunu rhs ile topla + return Point(x + rhs.x, y + rhs.y); +} + +Point& Point::operator+=(const Point& rhs) +{ + x += rhs.x; + y += rhs.y; + return *this; +} + +int main () { + Point up (0,1); + Point right (1,0); + // Bu Point + operatorünü çağırır + Point result = up + right; + // "Result is upright (1,1)" yazdırır. + cout << "Result is upright (" << result.x << ',' << result.y << ")\n"; + return 0; +} + +//////////////////////// +// Şablonlar (Templates) +//////////////////////// + +// Şablonlar C++ dilinde tipten bağımsız programlama için kullanılır. + +// Zaten aşina olduğun tipten bağımsız programlamayla başladık. Bir tip parametresi +alan fonksiyon veya sınıf tanımlamaık için: +template<class T> +class Box { +public: + // Bu sınıfta T, herhangi bir tip için kullanılabilir. + void insert(const T&) { ... } +}; + +// Derleme esnasında derleyici aslında, parametreleri yerine konmuş şekilde herbir şablonu üretir, +// bu yüzden sınıfın tam tanımı her çağrılma sırasında var olmak zorundadır. Bu nedenle şablon sınıflarını +// tamamen header dosyalarında görürsün. + +// Stack'ta şablon sınıfın bir örneğini oluşturmak için: +Box<int> intBox; + +// ve, anladığın gibi, kullanabilirsin: +intBox.insert(123); + +// Tabi, şablonları içiçe geçirebilirsin: +Box<Box<int> > boxOfBox; +boxOfBox.insert(intBox); + +// C++11'den önce iki '>' arasına boşluk koymak zorundaydık yoksa sağa kaydırma +// operatörü olarak algılanabilirdi. + +// Bazen şunu da görebilirsin +// template<typename T> +// 'class' ve 'typename' anahtar sözcükleri çoğunlukla +// birbirlerinin yerine kullanılabilir. Tam açıklama için, bknz. +// http://en.wikipedia.org/wiki/Typename +// (evet, bu anahtar sözcüğün kendi Wikipedia sayfası var). + +// Benzer şekilde, bir şablon fonksiyon: +template<class T> +void barkThreeTimes(const T& input) +{ + input.bark(); + input.bark(); + input.bark(); +} + +// Dikkat edersen tip parametresi hakkında birşey belirtilmedi. Derleyici bunları üretecek +// ve her parametre geçişinde tip-kontrolü yapacaktır, bu nedenle de fonksiyon herhangi bir T +// tipi için çalışacaktır! + +Dog fluffy; +fluffy.setName("Fluffy") +barkThreeTimes(fluffy); // Üç kere "Fluffy barks" yazdırır. + +// Şablonun parametresi sınıf olmak zorunda değildir: +template<int Y> +void printMessage() { + cout << "Learn C++ in " << Y << " minutes!" << endl; +} + +// Ve template'i daha etkili kod için dışarıdan özelleştirebilirsin. +// Tabiki gerçek-dünya kullanımlarında özelleştirme bunun kadar kolay değildir. +// Dikkat edersen, bütün parametreleri dıştan özelleştirmiş olsak bile +// hala fonksiyonu (veya sınıfı( template olarak tanımlamamız gerekli. +template<> +void printMessage<10>() { + cout << "Learn C++ faster in only 10 minutes!" << endl; +} + +printMessage<20>(); // "Learn C++ in 20 minutes!" yazdırır +printMessage<10>(); // "Learn C++ faster in only 10 minutes!" yazdırır + + +/////////////////////////////////////////////// +// İstisnai Durum Yönetimi (Exception Handling) +/////////////////////////////////////////////// + +// Standard kütüphane bazı istisnai tipler sağlar +// (bknz http://en.cppreference.com/w/cpp/error/exception) +// ama herhangi bir tip de istisnai durum fırlatabilir + +#include <exception> +#include <stdexcept> + +// _try_ bloğu içinde fırlatılan bütün istisnai durumlar, takip eden, _catch_ ile +// yakalanabilir. +try { + // _new_ kullanarak heap'ten istisnai durumlar için yer ayırma + throw std::runtime_error("A problem occurred"); +} + +// istisnai durumlar nesne ise const reference ile yakala +catch (const std::exception& ex) +{ + std::cout << ex.what(); +} + +// Bir önceki _catch_ bloğundan kaçan istisnai durum burda yakala +catch (...) +{ + std::cout << "Unknown exception caught"; + throw; // Tekrardan istisnai durum fırlatır +} + +/////// +// RAII +/////// + +// RAII, "Resource Acquisition Is Initialization" kelimelerinin kısaltmasıdır. +// Bu Türkçe, "Kaynak alımı aynı zamanda ilk değer atamasıdır." olarak çevrilebilir. +// Bunu basitçe constructor ile ayrılan hafızanın destructor ile iade edilmesi olarak +// düşünebiliriz. + +// Bunun ne şekilde kullanışlı olduğunu görmek için +// bir C dosyasının, dosya işleme biçimine bakabiliriz: +void doSomethingWithAFile(const char* filename) +{ + // Başlangıçta herşeyin yolunda gittiğini düşünelim + + FILE* fh = fopen(filename, "r"); // Dosyayı okuma modunda aç + + doSomethingWithTheFile(fh); + doSomethingElseWithIt(fh); + + fclose(fh); // Dosyayı kapat +} + +// Malesef hatalarla başa çıkmaya çalışırken işler hızlıca karmaşıklaşır. +// Mesela fopen'ın başarısız olduğunu varsayalım, ve doSoomethingWithTheFile ve +// doSomethingWithIt hata kodları gönderdi. +// (İstisnai durumlar yonetimi, hata koduna tercih ediler bir yöntemdir, ama bazı +// programcılar, özellikle C arkaplanı olanlar, aynı fikirde değildir. +// Bu durumda her bir fonksiyon çağrısını kontrol etmeli ve bir problem oluştuysa +// dosyayı kapatmalıyız. + +bool doSomethingWithAFile(const char* filename) +{ + FILE* fh = fopen(filename, "r"); // Dosyayı okuma modunda aç + if (fh == nullptr) // Başarısız olma durumunda dönen değer null olur + return false; // Başarısız olma durumunu çağırıcıya bildir + + // Başarısız olma durumunda her iki fonksiyonun da false döndürdüğünü kabul edelim + if (!doSomethingWithTheFile(fh)) { + fclose(fh); // Dosyayı kapatalım, akıntı olmasın. + return false; // Hatayı bildir + } + if (!doSomethingElseWithIt(fh)) { + fclose(fh); // Dosyayı kapatalım, akıntı olmasın. + return false; // Hatayı bildir + } + + fclose(fh); // Dosyayı kapat + return true; // Başarı durumunu ifade eder +} + +// C programcıları biraz goto kullanarak bu durumu temizler +bool doSomethingWithAFile(const char* filename) +{ + FILE* fh = fopen(filename, "r"); + if (fh == nullptr) + return false; + + if (!doSomethingWithTheFile(fh)) + goto failure; + + if (!doSomethingElseWithIt(fh)) + goto failure; + + fclose(fh); // Dosyayı kapat + return true; // Başarı durumunu ifade eder + +failure: + fclose(fh); + return false; // Hatayı bildir +} + +// Eğer fonksiyon istisnai durum yönetimi araçlarını kullanırsa +// işler daha temiz olur ama hala en iyi durumun altında kalır. +void doSomethingWithAFile(const char* filename) +{ + FILE* fh = fopen(filename, "r"); + if (fh == nullptr) + throw std::runtime_error("Could not open the file."); + + try { + doSomethingWithTheFile(fh); + doSomethingElseWithIt(fh); + } + catch (...) { + fclose(fh); // Hata durumunda dosyayı kapattığından emin ol + throw; // Sonra, tekrardan istisnai durum fırlat + } + + fclose(fh); // Dosyayı kapat + // Herşey başarılı +} + +// Şimdi aynı şeyi C++'ın dosya stream sınıfıyla (fstream) karşılaştıralım +// fstream, dosyayı kapatmak için kendi destructor'ını kullanır. +// Destructor'ın, nesne scope dışına çıktığında otomatik olarak çağrıldığını +// hatırlayın. +void doSomethingWithAFile(const std::string& filename) +{ + std::ifstream fh(filename); // Dosyayı aç + + // Dosyayla birşeyler yap + doSomethingWithTheFile(fh); + doSomethingElseWithIt(fh); + +} // Dosya, destructor tarafından otomatik olarak kapatıldı + +// Bunun _çok büyük_ avantajları var: +// 1. Ne olursa olursun, +// kaynak (bu örnekte dosya tutucusu) temizlenecektir. +// Destructor doğru yazıldığında, +// Tutucuyu kapatmayı unutma ve kaynak akıntısı _imkansız_dır. +// 2. Kodun çok daha temiz olduğuna dikkat edin. +// Destructor, dosyayı kapatma işini, endilenmemize gerek kalmadan +// arka planda halleder. +// 3. Kod, istisnai durumlara karşı korunaklıdır. +// İstisnai durum fonksiyonun herhangi bir yerinde fırlatılabilir ve +// temizleme işi gene de yapılır. + +// Bütün C++ kodu deyimleri RAII prensibini tüm kaynakları için kullanır. +// Ek örnekler şunlardır: +// - unique_ptr ve shared_ptr ile hafıza kullanımı +// - Tutucular - standard kütüphane linked list, +// vector (yani kendiliğinden boyu ayarlanan dizi), hash map vs. +// scope'un dışına çıktığında içerini otomatik olarak yok eden tüm yapılar. +// - lock_guard ve unique_lock kullanan mutex'ler + +/////////////////////////////////////// +// Lambda İfadeleri (C++11 ve yukarısı) +/////////////////////////////////////// + +// lambda'lar, tam olarak çağrıldığı yerde bir anonim fonksiyon tanımlamak +// veya fonksiyona argüman geçmek için uygun bir yoldur. + +// Mesela, pair'lardan oluşan bir vector'u, pair'ın ikinci değerine +// göre sıralamak isteyelim + +vector<pair<int, int> > tester; +tester.push_back(make_pair(3, 6)); +tester.push_back(make_pair(1, 9)); +tester.push_back(make_pair(5, 0)); + +// sort fonksiyonuna üçüncü argüman olarak lambda ifadesini geç +// sort, <algorithm> başlığında tanımlı + +sort(tester.begin(), tester.end(), [](const pair<int, int>& lhs, const pair<int, int>& rhs) { + return lhs.second < rhs.second; + }); + +// Lambda ifadesinin söz dizimine dikkat edin, +// lambda'daki [], değişkenleri "tutmak" için kullanılır +// "Tutma listesi", fonksiyon gövdesinde nelerin, ne şekilde erişilebilir olduğunu tanımlar +// Şunlardan biri olabilir: +// 1. bir değer : [x] + 2. bir referans : [&x] + 3. mevcut scope içindeki herhangi bir değişkene referans ile [&] + 4. 3 ile aynı, ama değer ile [=] +// Mesela: +vector<int> dog_ids; +// number_of_dogs = 3; +for(int i = 0; i < 3; i++) { + dog_ids.push_back(i); +} + +int weight[3] = {30, 50, 10}; + +// Mesela dog_ids vector'unu dog'ların ağırlıklarına göre sıralamak isteyelim +// Yani en sonunda şöyle olmalı: [2, 0, 1] + +// Burada lambda ifadesi oldukça kullanışlıdır + +sort(dog_ids.begin(), dog_ids.end(), [&weight](const int &lhs, const int &rhs) { + return weight[lhs] < weight[rhs]; + }); +// Dikkat edersen "weight" dizisini referans ile aldık. +// C++'da lambdalar hakkında daha fazla bilgi için : http://stackoverflow.com/questions/7627098/what-is-a-lambda-expression-in-c11 + +////////////////////////////////// +// Akıllı For (C++11 ve yukarısı) +////////////////////////////////// + +// Akıllı for döngüsünü bir tutucuyu dolaşmak için kullanabilirsin +int arr[] = {1, 10, 3}; + +for(int elem: arr){ + cout << elem << endl; +} + +// Tutucunun elemanlarının tipi için endişe etmeden "auto" kullanabilirsin +// Mesela: + +for(auto elem: arr) { + // arr dizisinin elemanlarıyla ilgili bir şeyler yap +} + +///////////////////// +// Güzel Şeyler +///////////////////// + +// C++ dilinin bakış açısı yeni başlayanlar için (hatta dili iyi bilenler için bile) +// şaşırtıcı olabilir. +// Bu bölüm, ne yazık ki, büyük ölçüde tam değil; C++ kendi ayağına ateş edilebilecek kolay +// dillerden biridir. + +// private metodları override edebilirsin! +class Foo { + virtual void bar(); +}; +class FooSub : public Foo { + virtual void bar(); // Foo::bar fonksiyonu override edilir! +}; + + +// 0 == false == NULL (çoğu zaman)! +bool* pt = new bool; +*pt = 0; // 'pt'nin gösterdiği değere false atar. +pt = 0; // 'pt'ye null pointer atar. Her iki satır uyarısız derlenir. + +// nullptr'ın bu meselenin bazılarını çözmesi beklenmiştir: +int* pt2 = new int; +*pt2 = nullptr; // Derlenmez. +pt2 = nullptr; // pt2'ye null atar. + +// bool tipleri için bir istisna vardır. +// Bu null pointer'ları if(!ptr) ile test etmek içindir. +// ama sonuç olarak bir bool değerine nullptr atayabilirsin! +*pt = nullptr; // '*pt' değeri bir boll olmasına rağmen, hala derlenir! + + +// '=' != '=' != '='! +// Calls Foo::Foo(const Foo&) or some variant (see move semantics) copy +// Foo::Foo(const Foo&) çağrısını veya kopyalama constructor'ının bir çeşidinin çağrısınıyapar(taşıma semantiklerine bknz.) +Foo f2; +Foo f1 = f2; + +// Foo::operator=(Foo&) çağrısını yapar. +Foo f1; +f1 = f2; + + +/////////////////////////////////////// +// Tuple (C++11 ve yukarısı) +/////////////////////////////////////// + +#include<tuple> + +// Ana fikir olarak, Tuple, eski veri yapılarına (C'deki struct'lar) benzer ama isimli veri üyeleri yerine +// elemanlarına tuple içindeki sırasına göre erişilir. + +// Tuple'ı inşa ederek başlayalım +// değişkenleri tuple içinde paketliyoruz +auto first = make_tuple(10, 'A'); +const int maxN = 1e9; +const int maxL = 15; +auto second = make_tuple(maxN, maxL); + +// 'first' tuple'ının değerlerini yazdırma +cout << get<0>(first) << " " << get<1>(first) << "\n"; // 10 A yazdırır + +// 'second' tuple'ının değerlerini yazdırma +cout << get<0>(second) << " " << get<1>(second) << "\n"; // 1000000000 15 yazdırır + +// Değişkenleri tuple'dan çıkarma + +int first_int; +char first_char; +tie(first_int, first_char) = first; +cout << first_int << " " << first_char << "\n"; // 10 A yazdırır + +// Ayrıca şu şekide de tuple oluşturabiliriz. + +tuple<int, char, double> third(11, 'A', 3.14141); +// tuple_size, tuple'daki eleman sayısını (constexpr olarak) döndürür + +cout << tuple_size<decltype(third)>::value << "\n"; // 3 yazdırır + +// tuple_cat, tuple'daki tüm elemanları aynı sırada birleştirir. + +auto concatenated_tuple = tuple_cat(first, second, third); +// concatenated_tuple = (10, 'A', 1e9, 15, 11, 'A', 3.14141) olur + +cout << get<0>(concatenated_tuple) << "\n"; // 10 yazdırır +cout << get<3>(concatenated_tuple) << "\n"; // 15 yazdırır +cout << get<5>(concatenated_tuple) << "\n"; // 'A' yazdırır + + +///////////////////// +// Tutucular +///////////////////// + +// Tutucular veya Standard Şablon Kütüphanesi(STL) önceden tanımlanmış şablonlar sunar. +// Bunlar elemanları için ayrılan hafıza alanını yönetir +// ve onlara erişim ve değiştirmek için üye fonksiyonlar sağlar + +// Bazı tutucular şunlardır: + +// Vector (Dinamik Dizi) +// koşma anında nesne dizisi veya list oluşturmamızı sağlar +#include <vector> +string val; +vector<string> my_vector; // vector'ü tanımla +cin >> val; +my_vector.push_back(val); // val değerini my_vector vectörüne push edecektir +my_vector.push_back(val); // val değerini yeniden push edecektir (şu an iki elemanı var) + +// vector içinde dolaşmak için iki seçenek var: +// ya klasik döngüyle (0. index'ten son index'e kadar iterasyon yaparak) +for (int i = 0; i < my_vector.size(); i++) { + cout << my_vector[i] << endl; // vector'ün elemanlarına uşamak için [] operatörünü kullanabiliriz +} + +// ya da iteratör kulllanarak: +vector<string>::iterator it; // vector için iterator tanımla +for (it = my_vector.begin(); it != my_vector.end(); ++it) { + cout << *it << endl; +} + +// Set(Küme) +// Set'ler benzersiz(unique) elemanları belirli bir sırada saklayan tutuculardır. +// Set, benzersiz değerleri, herhangi bir fonksiyon veya kod gerektirmeksizin, sıralı olarak + +#include<set> +set<int> ST; // int tipi için set tanımlar +ST.insert(30); // ST kümesini 30 değerini dahil eder +ST.insert(10); // ST kümesini 10 değerini dahil eder +ST.insert(20); // ST kümesini 20 değerini dahil eder +ST.insert(30); // ST kümesini 30 değerini dahil eder +// Şimdi kümedeki elemanlar aşağıdaki gibidir +// 10 20 30 + +// Bir eleman silmek için: +ST.erase(20); // 20 değerine sahip elemanı siler +// Set ST: 10 30 +// Iterator kullanarak Set içinde iterasyon yapmak için: +set<int>::iterator it; +for(it=ST.begin();it<ST.end();it++) { + cout << *it << endl; +} +// Output: +// 10 +// 30 + +// Tutucuyu tamamen silmek için Tutucu_Adi.clear() kullanırız +ST.clear(); +cout << ST.size(); // ST kümesinin eleman sayısı(size)nı yazdırır. +// Output: 0 + +// NOTE: Aynı elemanlari içerebilen kümle için multiset kullanırız + +// Map(Harita) +// Map, elemanları anahtar değer, haritalanmış değer şeklinde özel bir sırada saklar. +// anahtar_değer -> haritalanmış_değer + +#include<map> +map<char, int> mymap; // Anahtar char ve değer int olacak şekilde map tanımlar + +mymap.insert(pair<char,int>('A',1)); +// 1 değeri için A anahtar değerini ekler +mymap.insert(pair<char,int>('Z',26)); +// 26 değeri için Z anahtar değerini ekler + +// Map'te dolaşma +map<char,int>::iterator it; +for (it=mymap.begin(); it!=mymap.end(); ++it) + std::cout << it->first << "->" << it->second << '\n'; +// Output: +// A->1 +// Z->26 + +// Anahtar'a atanmış değeri bulmak için +it = mymap.find('Z'); +cout << it->second; + +// Output: 26 + + +///////////////////////////////////////////// +// Mantıksal ve Bit seviyesindeki operatörler +///////////////////////////////////////////// + +// Pek çok C++ operatörleri diğer dillerdekiyle aynıdır + +// Mantıksal operatörler + +// C++, bool ifadelerinde Kısa-devre değerlendirmesini kullanır yani ikinci argüman yalnızca ilk argüman +// ifadenin değerine karar vermek için yeterli değilse çalıştırılır + +true && false // **mantıksal ve** işlemi yapılır ve yanlış sonucu üretilir +true || false // **mantıksal veya** işlemi yapılır ve true sonucu üretilir +! true // **mantıksal değil** işlemi yapılır ve yalnış sonucu üretilir + +// Sembolleri kullanmak yerine onlara karşılık gelen anahtar kelimeler kullanılabilir +true and false // **mantıksal ve** işlemi yapılır ve yanlış sonucu üretilir +true or false // **mantıksal veya** işlemi yapılır ve true sonucu üretilir +not true // **mantıksal değil** işlemi yapılır ve yalnış sonucu üretilir + +// Bit seviyesindeki operatörler + +// **<<** Sola kaydırma operatörü +// << bitleri sola kaydırır +4 << 1 // 4'ün bitlerini 1 sola kaydırır ve 8 sonucunu verir +// x << n, x * 2^n olarak düşünülebilir + + +// **>>** Sağa kaydırma operatörü +// >> bitleri sağa kaydırır +4 >> 1 // 4'ün bitlerini 1 sağa kaydırır ve 2 sonucunu verir +// x >> n, x / 2^n olarak düşünülebilir + +~4 // Bit seviyesinde değil işlemini gerçekleştirir +4 | 3 // Bit seviyesinde veya işlemini gerçekleştirir +4 & 3 // Bit seviyesinde ve işlemini gerçekleştirir +4 ^ 3 // Bit seviyesinde xor işlemini gerçekleştirir + +// Eşdeğer anahtar kelimeler +compl 4 // Bit seviyesinde değil işlemini gerçekleştirir +4 bitor 3 // Bit seviyesinde veya işlemini gerçekleştiri +4 bitand 3 // Bit seviyesinde ve işlemini gerçekleştirir +4 xor 3 // Bit seviyesinde xor işlemini gerçekleştirir + + +``` +İleri okuma: + +Güncel bir referans +<http://cppreference.com/w/cpp> adresinde bulunabilir + +Ek kaynaklar <http://cplusplus.com> adresinde bulunabilir diff --git a/tr-tr/git-tr.html.markdown b/tr-tr/git-tr.html.markdown new file mode 100644 index 00000000..533bb21a --- /dev/null +++ b/tr-tr/git-tr.html.markdown @@ -0,0 +1,595 @@ +--- +category: tool +tool: git +contributors: + - ["Jake Prather", "http://github.com/JakeHP"] + - ["Leo Rudberg" , "http://github.com/LOZORD"] + - ["Betsy Lorton" , "http://github.com/schbetsy"] + - ["Bruno Volcov", "http://github.com/volcov"] + - ["Andrew Taylor", "http://github.com/andrewjt71"] + - ["Jason Stathopulos", "http://github.com/SpiritBreaker226"] + - ["Milo Gilad", "http://github.com/Myl0g"] + - ["Adem Budak", "https://github.com/p1v0t"] + +filename: LearnGit.txt +--- + +Git dağınık versiyon kontrol ve kaynak kod yönetim sistemidir. + +Bunu projenin bir seri anlık durumunu kaydederek yapar ve bu anlık durumları +kullanarak versiyon ve kaynak kodu yönetmeni sağlar. + +## Versiyonlama Konseptleri + +### Versiyon kontrol nedir? + +Versiyon kontrol, zaman içerisinde dosya(lar)daki değişikliği kaydeden sistemdir. + +### Merkezi Versiyonlama vs. Dağınık Versiyonlama + +* Merkezi versiyon kontrolü dosyaların eşitlenmesine, takibine ve yedeklenmesine odaklanır. +* Dağınık versiyon kontrolü değişimin paylaşılmasına odaklanır. Her değişiminin benzersiz bir adı vardır. +* Dağınık sistemlerin belirlenmiş bir yapısı yoktur. Git ile kolayca SVN'deki gibi merkezi bir sistem elde edebilirsin. + +[Daha fazla bilgi](http://git-scm.com/book/en/Getting-Started-About-Version-Control) + +### Neden Git? + +* Çevrimdışı çalışabilir +* Diğerleriyle beraber çalışmak kolaydır! +* Dallanma kolaydır! +* Dallanma hızlıdır! +* Git hızlıdır +* Git esnektir + +## Git Mimarisi + +### Repository + +Bir grup dosya, dizin, geriye dönük kayıt, commit, head. Bunları kaynak kodun veri +yapısı gibi düşünebilirsin, herbir kaynak kod "elemanı" seni kendi revizyon geçmişine +eriştirir. + +Bir git repo'su .git dizini ve çalışma ağacından oluşur. + +### .git Dizini (repository bileşeni) + +.git dizini bütün konfigrasyon, log, dallanma, HEAD ve daha fazlasını tutar. +[detaylı liste](http://gitready.com/advanced/2009/03/23/whats-inside-your-git-directory.html) + +### Çalışma Ağacı (repository bileşeni) + +Temelde repo'daki dizinlerin ve dosyalarındır. Sıkça çalışma ağacın olarak anılır. + +### Index (.git dizininin birleşeni) + +Index git'in evreleme alanıdır (staging area). Temelde çalışma ağacını Git repo'sundan +ayıran bir katmandır. Bu geliştiricilere neyin Git repo'suna gönderileceği hakkında daha +fazla güç verir. + +### Commit + +Bir git commit'i Çalışma Ağacındaki bir takım değişiklerdir. Mesela 5 tane dosya +eklemişsindir ve diğer 2 tanesini silmişindir, bu değişikler commit'te (anlık kayıtta) +tutulacaktır. Bu commit daha sonra diğer repo'lara bastırılabilir (pushed) ve bastırılmaz! + +### Branch + +Bir branch esasen yaptığın son commit'e göstericidir(pointer). Commit'lemeye devam ettiğinde, +bu gösterici otomatik olarak son commit'e güncellenir. + +### Tag + +Bir tag, tarihteki belirli bir noktanın işaretidir. İnsanlar bunu genelde +sürüm notları için kullanır (v1.0 vs.) + +### HEAD ve head (.git dizininin birleşenleri) + +HEAD mevcut branch'a bir göstericidir. Bir repository yalnızca 1 *aktif* +HEAD'e sahiptir. +head, commit'e bir göstericidir. Bir repository herhangi bir sayıda head'e sahip olabilir. + +### Git'in Stage'leri +* Modified - Dosyada değişikler yapıldı ama henüz Git Veritabanına commit yapılmadı. +* Staged - Modified edilmiş bir dosyayı, sonraki commit'e gitmek üzere işaretler. +* Committed - Dosyalar Git Veritabanına commit'lendi. + +### Kavramsal Kaynaklar + +* [Bilgisayar Bilimciler için Git](http://eagain.net/articles/git-for-computer-scientists/) +* [Tasarımcılar için Git](http://hoth.entp.com/output/git_for_designers.html) + +## Komutlar + +### init + +Boş bir Git repository'si oluştur. Git repository'sinin ayarları, depolanmış +bilgileri ve daha fazlası ".git" adlı dizinde (bir klasör) tutulur. + +```bash +$ git init +``` + +### config + +Ayarları yapılandırmak için. Repository, sistemin kendisi veya global yapılandırmalar +için olarabilir. (global yapılandırma dosyası `~/.gitconfig`). + +```bash +# Print & Set Some Basic Config Variables (Global) +$ git config --global user.email "MyEmail@Zoho.com" +$ git config --global user.name "My Name" +``` + +[git config hakkında daha fazla bilgi için.](http://git-scm.com/docs/git-config) + +### help + +Her bir komutun detaylı kılavuzuna hızlı bir erişim için. Ya da sadece bazı şeylerin +anlamı için hızlı bir hatırlatıcı için. + +```bash +# Quickly check available commands +$ git help + +# Check all available commands +$ git help -a + +# Command specific help - user manual +# git help <command_here> +$ git help add +$ git help commit +$ git help init +# or git <command_here> --help +$ git add --help +$ git commit --help +$ git init --help +``` + +### dosyaları ignore etme + +git'in bazı dosya(ları) ve klasör(leri) kasıtlı olarak takip etmemesi için. Genel +olarak,repository'de ne de olsa paylaşılacak, private ve temp dosyaları için. + +```bash +$ echo "temp/" >> .gitignore +$ echo "private_key" >> .gitignore +``` + +### status + +index dosyası(temelde çalıştığın repo) ve mevcut HEAD commit arasındaki farkı göstermek için. + +```bash +# Will display the branch, untracked files, changes and other differences +$ git status + +# To learn other "tid bits" about git status +$ git help status +``` + +### add + +Dosyaları staging area'ya eklemek için. Eğer yeni dosyaları staging area'ya `git add` +yapmazsanız, commit'lere eklenmez! + +```bash +# add a file in your current working directory +$ git add HelloWorld.java + +# add a file in a nested dir +$ git add /path/to/file/HelloWorld.c + +# Regular Expression support! +$ git add ./*.java + +# You can also add everything in your working directory to the staging area. +$ git add -A +``` +Bu yalnızca dosyayı staging area'a/index'e ekler, çalışılan dizine/repo'ya commit etmez. + +### branch + +Branch'ları yönetir. Bu komutu kullanarak, branch'ları görebilir, düzenleyebilir, oluşturabilir, silebilirsin. + +```bash +# list existing branches & remotes +$ git branch -a + +# create a new branch +$ git branch myNewBranch + +# delete a branch +$ git branch -d myBranch + +# rename a branch +# git branch -m <oldname> <newname> +$ git branch -m myBranchName myNewBranchName + +# edit a branch's description +$ git branch myBranchName --edit-description +``` + +### tag + +tag'leri yönetir + +```bash +# List tags +$ git tag + +# Create a annotated tag +# The -m specifies a tagging message, which is stored with the tag. +# If you don’t specify a message for an annotated tag, +# Git launches your editor so you can type it in. +$ git tag -a v2.0 -m 'my version 2.0' + +# Show info about tag +# That shows the tagger information, the date the commit was tagged, +# and the annotation message before showing the commit information. +$ git show v2.0 + +# Push a single tag to remote +$ git push origin v2.0 + +# Push a lot of tags to remote +$ git push origin --tags +``` + +### checkout + +index'in versiyonun eşlemek için çalışma ağacındaki,veya belirtilen ağactaki, tüm dosyaları günceller. + +```bash +# Checkout a repo - defaults to master branch +$ git checkout + +# Checkout a specified branch +$ git checkout branchName + +# Create a new branch & switch to it +# equivalent to "git branch <name>; git checkout <name>" + +$ git checkout -b newBranch +``` + +### clone + +Varolan bir repository'i yeni bir dizine clone'lar veya kopyalar. +Ayrıca clone'lanmış repodaki her bir branch için, uzak branch'a bastırmana izin veren, +uzak takip branch'ları ekler. + +```bash +# Clone learnxinyminutes-docs +$ git clone https://github.com/adambard/learnxinyminutes-docs.git + +# shallow clone - faster cloning that pulls only latest snapshot +$ git clone --depth 1 https://github.com/adambard/learnxinyminutes-docs.git + +# clone only a specific branch +$ git clone -b master-cn https://github.com/adambard/learnxinyminutes-docs.git --single-branch +``` + +### commit + +index'in mevcut içeriğini yeni bir "commit"te saklar. Bu commit, kullanıcının oluşturduğu +bir mesajı ve yapılan değişiklikleri saklar. + +```bash +# commit with a message +$ git commit -m "Added multiplyNumbers() function to HelloWorld.c" + +# signed commit with a message (user.signingkey must have been set +# with your GPG key e.g. git config --global user.signingkey 5173AAD5) +$ git commit -S -m "signed commit message" + +# automatically stage modified or deleted files, except new files, and then commit +$ git commit -a -m "Modified foo.php and removed bar.php" + +# change last commit (this deletes previous commit with a fresh commit) +$ git commit --amend -m "Correct message" +``` + +### diff + +Shows differences between a file in the working directory, index and commits. +Bir dosyanın, çalışma ağacı, index ve commit'ler arasındaki farklarını göster. + +```bash +# Show difference between your working dir and the index +$ git diff + +# Show differences between the index and the most recent commit. +$ git diff --cached + +# Show differences between your working dir and the most recent commit +$ git diff HEAD +``` + +### grep + +Bir repository'de hızlıca arama yapmana izin verir. + +İsteğe Bağlı Yapılandırmalar: + +```bash +# Thanks to Travis Jeffery for these +# Set line numbers to be shown in grep search results +$ git config --global grep.lineNumber true + +# Make search results more readable, including grouping +$ git config --global alias.g "grep --break --heading --line-number" +``` + +```bash +# Search for "variableName" in all java files +$ git grep 'variableName' -- '*.java' + +# Search for a line that contains "arrayListName" and, "add" or "remove" +$ git grep -e 'arrayListName' --and \( -e add -e remove \) +``` + +Daha fazla örnek için +[Git Grep Ninja](http://travisjeffery.com/b/2012/02/search-a-git-repo-like-a-ninja) + +### log + +Repository'deki commitleri gösterir. + +```bash +# Show all commits +$ git log + +# Show only commit message & ref +$ git log --oneline + +# Show merge commits only +$ git log --merges + +# Show all commits represented by an ASCII graph +$ git log --graph +``` + +### merge + +Dış commit'lerdeki değişiklikleri mevcut branch'a "merge" et (birleştir). + +```bash +# Merge the specified branch into the current. +$ git merge branchName + +# Always generate a merge commit when merging +$ git merge --no-ff branchName +``` + +### mv + +Bir dosyayı yeniden taşı veya yeniden adlandır + +```bash +# Renaming a file +$ git mv HelloWorld.c HelloNewWorld.c + +# Moving a file +$ git mv HelloWorld.c ./new/path/HelloWorld.c + +# Force rename or move +# "existingFile" already exists in the directory, will be overwritten +$ git mv -f myFile existingFile +``` + +### pull + +Bir repository'den çeker ve diğer branch'a merge eder. + +```bash +# Update your local repo, by merging in new changes +# from the remote "origin" and "master" branch. +# git pull <remote> <branch> +$ git pull origin master + +# By default, git pull will update your current branch +# by merging in new changes from its remote-tracking branch +$ git pull + +# Merge in changes from remote branch and rebase +# branch commits onto your local repo, like: "git fetch <remote> <branch>, git +# rebase <remote>/<branch>" +$ git pull origin master --rebase +``` + +### push + +Bir branch'taki değişikleri, uzak branch'a bastır ve birleştir. + +```bash +# Push and merge changes from a local repo to a +# remote named "origin" and "master" branch. +# git push <remote> <branch> +$ git push origin master + +# By default, git push will push and merge changes from +# the current branch to its remote-tracking branch +$ git push + +# To link up current local branch with a remote branch, add -u flag: +$ git push -u origin master +# Now, anytime you want to push from that same local branch, use shortcut: +$ git push +``` + +### stash + +Stash'leme çalışma dizinindeki kirli durumu alır ve bitmemiş değişiklikler +yığınına kaydeder. Bu değişikleri istediğin zaman tekrar uygulayabilirsin. + +Mesela git repo'nda bazı işler yaptın ama remote'dan pull yapmak istiyorsun. +Bazı dosyalarında kirli (commit'lenmemiş) değişiklikler olduğundan `git pull` +yapamazsın. Onun yerine önce `git stash` ile değişikliklerini yığına kaydet! + +(stash, sözlük anlamı: bir şeyi, özel bir yere güvenli biçimde saklamak) + +```bash +$ git stash +Saved working directory and index state \ + "WIP on master: 049d078 added the index file" + HEAD is now at 049d078 added the index file + (To restore them type "git stash apply") +``` + +Şimdi pull yapabilirsin! + +```bash +git pull +``` +`...changes apply...` + +Herşeyin tamam olduğunu kontrol et + +```bash +$ git status +# On branch master +nothing to commit, working directory clean +``` +Şu ana kadar neleri stash'lediğini `git stash list` kullanarak görebilirsin. +Stash'lenen şeyler Son-Giren-İlk-Çıkar şeklinde tutulduğundan en son değişim +en üste olacaktır. + +```bash +$ git stash list +stash@{0}: WIP on master: 049d078 added the index file +stash@{1}: WIP on master: c264051 Revert "added file_size" +stash@{2}: WIP on master: 21d80a5 added number to log +``` +Şimdi de kirli değişiklileri yığından çıkarıp uygulayalım. + +```bash +$ git stash pop +# On branch master +# Changes not staged for commit: +# (use "git add <file>..." to update what will be committed) +# +# modified: index.html +# modified: lib/simplegit.rb +# +``` + +`git stash apply` da aynı şeyi yapar + +Şimdi kendi işine dönmeye hazırsın! + +[Ek Okuma.](http://git-scm.com/book/en/v1/Git-Tools-Stashing) + +### rebase (dikkat) + +Branch'ta commit'lenen tüm değişimleri al ve onları başka bir branch'ta tekrar oynat +*Public repo'ya push edilmiş commit'leri rebase etme* + +```bash +# Rebase experimentBranch onto master +# git rebase <basebranch> <topicbranch> +$ git rebase master experimentBranch +``` + +[Ek Okuma.](http://git-scm.com/book/en/Git-Branching-Rebasing) + +### reset (dikkat) + +Reset the current HEAD to the specified state. This allows you to undo merges, +pulls, commits, adds, and more. It's a great command but also dangerous if you +don't know what you are doing. + +HEAD'i belirtilen duruma resetle. Bu merge'leri, pull'ları, commit'leri, add'leri +ve daha fazlasını geriye almanı sağlar. Muhteşem bir komuttur ama aynı zamanda, ne +yaptığını bilmiyorsan, tehlikelidir. + +```bash +# Reset the staging area, to match the latest commit (leaves dir unchanged) +$ git reset + +# Reset the staging area, to match the latest commit, and overwrite working dir +$ git reset --hard + +# Moves the current branch tip to the specified commit (leaves dir unchanged) +# all changes still exist in the directory. +$ git reset 31f2bb1 + +# Moves the current branch tip backward to the specified commit +# and makes the working dir match (deletes uncommitted changes and all commits +# after the specified commit). +$ git reset --hard 31f2bb1 +``` + +### reflog (dikkat) + +Reflog, verilen zaman içinde,default olarak 90 gündür, yaptığın git komutlarını listeler. + +Bu sana beklemediğin şekilde yanlış giden komutları geriye çevirme şansı verir. +(mesela, eğer bir rebase uygulamanı kırdıysa) + +Şu şekilde yapıbilirsin: + +1. `git reflog` rebase için tüm git komutlarını listele + +``` +38b323f HEAD@{0}: rebase -i (finish): returning to refs/heads/feature/add_git_reflog +38b323f HEAD@{1}: rebase -i (pick): Clarify inc/dec operators +4fff859 HEAD@{2}: rebase -i (pick): Update java.html.markdown +34ed963 HEAD@{3}: rebase -i (pick): [yaml/en] Add more resources (#1666) +ed8ddf2 HEAD@{4}: rebase -i (pick): pythonstatcomp spanish translation (#1748) +2e6c386 HEAD@{5}: rebase -i (start): checkout 02fb96d +``` +2. Nereye reset'leyeceğini seç, şu durumda `2e6c386` veya `HEAD@{5}` +3. 'git reset --hard HEAD@{5}' bu repo'nu seçilen head'e eşitler +4. Rebase'e yeniden başlayabilir veya onu yalnız bırakabilirsin. + +[Ek Okuma.](https://git-scm.com/docs/git-reflog) + +### revert + +Revert commit'leri geri almada kullanılır. Projenin durumunu önceki bir noktaya +alan reset ile karıştırılmamalıdır. Revert, belirtilen commit'in tersine yeni bir +commit ekleyecektir. + +```bash +# Revert a specified commit +$ git revert <commit> +``` + +### rm + +git add'in tersine, git rm çalışma ağacından dosyaları kaldırır. + +```bash +# remove HelloWorld.c +$ git rm HelloWorld.c + +# Remove a file from a nested dir +$ git rm /pather/to/the/file/HelloWorld.c +``` + +## Daha Fazla Bilgi + +* [tryGit - Git'i öğrenmek için eğlenceli interaktif bir yol](http://try.github.io/levels/1/challenges/1) + +* [Git Dallanmayı Öğren - Git'i web üzerinde öğrenmek için en görsel ve interaktif yol](http://learngitbranching.js.org/) + +* [Udemy Git Tutorial: Kapsayıcı bir kılavuz](https://blog.udemy.com/git-tutorial-a-comprehensive-guide/) + +* [Git Immersion - Git'in temelinden başlayan bir tur](http://gitimmersion.com/) + +* [git-scm - Video Tutorial](http://git-scm.com/videos) + +* [git-scm - Dökümantasyon](http://git-scm.com/docs) + +* [Atlassian Git - Tutorial & Workflow](https://www.atlassian.com/git/) + +* [SalesForce Kopya Kağıdı](http://res.cloudinary.com/hy4kyit2a/image/upload/SF_git_cheatsheet.pdf) + +* [GitGuys](http://www.gitguys.com/) + +* [Git - Basit bir kılavuz](http://rogerdudler.github.io/git-guide/index.html) + +* [Pro Git](http://www.git-scm.com/book/en/v2) + +* [Yeni başlayanlar için Git ve Github](http://product.hubspot.com/blog/git-and-github-tutorial-for-beginners) diff --git a/zh-cn/python3-cn.html.markdown b/zh-cn/python3-cn.html.markdown index 76455a46..211ce0c5 100644 --- a/zh-cn/python3-cn.html.markdown +++ b/zh-cn/python3-cn.html.markdown @@ -568,13 +568,14 @@ def double_numbers(iterable): yield i + i # 生成器只有在需要时才计算下一个值。它们每一次循环只生成一个值,而不是把所有的 -# 值全部算好。这意味着double_numbers不会生成大于15的数字。 +# 值全部算好。 # # range的返回值也是一个生成器,不然一个1到900000000的列表会花很多时间和内存。 # # 如果你想用一个Python的关键字当作变量名,可以加一个下划线来区分。 range_ = range(1, 900000000) # 当找到一个 >=30 的结果就会停 +# 这意味着 `double_numbers` 不会生成大于30的数。 for i in double_numbers(range_): print(i) if i >= 30: |