summaryrefslogtreecommitdiffhomepage
path: root/es-es
diff options
context:
space:
mode:
Diffstat (limited to 'es-es')
-rw-r--r--es-es/bf-es.html.markdown (renamed from es-es/brainfuck-es.html.markdown)20
-rw-r--r--es-es/c++-es.html.markdown2
-rw-r--r--es-es/forth-es.html.markdown226
-rw-r--r--es-es/git-es.html.markdown14
-rw-r--r--es-es/hack-es.html.markdown307
-rw-r--r--es-es/javascript-es.html.markdown24
-rw-r--r--es-es/json-es.html.markdown16
-rw-r--r--es-es/latex-es.html.markdown213
-rw-r--r--es-es/markdown-es.html.markdown16
-rw-r--r--es-es/objective-c-es.html.markdown851
-rw-r--r--es-es/php-es.html.markdown825
-rw-r--r--es-es/python-es.html.markdown14
-rw-r--r--es-es/python3-es.html.markdown8
-rw-r--r--es-es/r-es.html.markdown717
-rw-r--r--es-es/ruby-es.html.markdown6
-rw-r--r--es-es/rust-es.html.markdown324
-rw-r--r--es-es/swift-es.html.markdown596
-rw-r--r--es-es/yaml-es.html.markdown189
18 files changed, 4253 insertions, 115 deletions
diff --git a/es-es/brainfuck-es.html.markdown b/es-es/bf-es.html.markdown
index e33d672d..c93b8c3a 100644
--- a/es-es/brainfuck-es.html.markdown
+++ b/es-es/bf-es.html.markdown
@@ -1,5 +1,5 @@
---
-language: brainfuck
+language: bf
contributors:
- ["Prajit Ramachandran", "http://prajitr.github.io/"]
- ["Mathias Bynens", "http://mathiasbynens.be/"]
@@ -9,8 +9,10 @@ lang: es-es
---
Brainfuck (con mayúscula sólo al inicio de una oración) es un
-lenguaje de programación mínimo, computacionalmente universal
-en tamaño con sólo 8 comandos.
+lenguaje de programación extremadamente pequeño, Turing completo con sólo 8 comandos.
+
+Puedes probar brainfuck en tu navegador con [brainfuck-visualizer](http://fatiherikli.github.io/brainfuck-visualizer/).
+
```
@@ -18,7 +20,7 @@ Cualquier caracter que no sea "><+-.,[]" (sin incluir las comillas)
será ignorado.
Brainfuck es representado por un arreglo de 30,000 celdas inicializadas
-en cero y un apuntador en la celda actual.
+en cero y un puntero apuntando la celda actual.
Existen ocho comandos:
@@ -26,7 +28,7 @@ Existen ocho comandos:
- : Decrementa 1 al valor de la celda actual.
> : Mueve el apuntador a la siguiente celda. (a la derecha)
< : Mueve el apuntador a la celda anterior. (a la izquierda)
-. : Imprime el valor en ASCII de la celda actual (i.e. 65 = 'A')
+. : Imprime el valor en ASCII de la celda actual (p.e. 65 = 'A')
, : Lee un caracter como input y lo escribe en la celda actual.
[ : Si el valor en la celda actual es cero mueve el apuntador
hasta el primer ']' que encuentre. Si no es cero sigue a la
@@ -37,7 +39,7 @@ Existen ocho comandos:
[ y ] forman un while. Obviamente, deben estar balanceados.
-Ahora unos ejemplos de programas escritos con brainfuck.
+Estos son algunos ejemplos de programas escritos con brainfuck.
++++++ [ > ++++++++++ < - ] > +++++ .
@@ -63,7 +65,7 @@ Esto continúa hasta que la celda #1 contenga un cero. Cuando #1 contenga un
cero la celda #2 tendrá el valor inicial de #1. Como este ciclo siempre
terminara en la celda #1 nos movemos a la celda #2 e imprimimos (.).
-Ten en mente que los espacios son sólo para fines de legibilidad.
+Ten en cuenta que los espacios son sólo para fines de legibilidad.
Es lo mismo escribir el ejemplo de arriba que esto:
,[>+<-]>.
@@ -81,7 +83,7 @@ hasta la próxima vez. Para resolver este problema también incrementamos la
celda #4 y luego copiamos la celda #4 a la celda #2. La celda #3 contiene
el resultado.
```
-Y eso es brainfuck. ¿No tan difícil o sí? Como diversión, puedes escribir
+Y eso es brainfuck. No es tan difícil, ¿verdad? Como diversión, puedes escribir
tu propio intérprete de brainfuck o tu propio programa en brainfuck. El
intérprete es relativamente sencillo de hacer, pero si eres masoquista,
-intenta construir tu proprio intérprete de brainfuck... en brainfuck.
+puedes intentar construir tu propio intérprete de brainfuck... en brainfuck.
diff --git a/es-es/c++-es.html.markdown b/es-es/c++-es.html.markdown
index bcc775e5..07c8bc03 100644
--- a/es-es/c++-es.html.markdown
+++ b/es-es/c++-es.html.markdown
@@ -1,6 +1,6 @@
---
language: c++
-filename: learncpp.cpp
+filename: learncpp-es.cpp
contributors:
- ["Steven Basart", "http://github.com/xksteven"]
- ["Matt Kline", "https://github.com/mrkline"]
diff --git a/es-es/forth-es.html.markdown b/es-es/forth-es.html.markdown
new file mode 100644
index 00000000..edc5d38c
--- /dev/null
+++ b/es-es/forth-es.html.markdown
@@ -0,0 +1,226 @@
+---
+language: forth
+contributors:
+ - ["Horse M.D.", "http://github.com/HorseMD/"]
+translators:
+ - ["Zach Larsen", "http://zachariahlarsen.com/"]
+lang: es-es
+filename: learnforth-es.fs
+---
+
+Forth fue criado por Charles H. Moore en los 70s. Forth es un lenguaje imperativo, basado en pila y entorno de programación, siendo usado en proyectos como Open Firmware. También esta usado por NASA.
+
+Nota: Este articulo enfoca predominantemente en la Gforth implementación de Forth, pero casi todo
+de lo que esta escrito aquí debe funcionar en otro sitio.
+
+```
+\ Este es un comentario
+( Este es un comentario también pero solo esta usado cuando definiendo palabras. )
+
+\ --------------------------------- Precursor ----------------------------------
+
+\ Todo programación en Forth se hace manipulando el parámetro pila (mas
+\ común se refiere como "el pila").
+5 2 3 56 76 23 65 \ ok
+
+\ estos números se añadieron al pila desde izquierda a derecho.
+.s \ <7> 5 2 3 56 76 23 65 ok
+
+\ En Forth, todo es o una palabra o un numero.
+
+\ ------------------------------ Básico Aritmética ------------------------------
+
+\ Aritmética (de hecho casi todas palabras que requieren datos) funciona manipulando datos
+\ en el pila.
+5 4 + \ ok
+
+\ `.` saca lo alto resulto desde el pila:
+. \ 9 ok
+
+\ Mas ejemplos de aritmética:
+6 7 * . \ 42 ok
+1360 23 - . \ 1337 ok
+12 12 / . \ 1 ok
+13 2 mod . \ 1 ok
+
+99 negate . \ -99 ok
+-99 abs . \ 99 ok
+52 23 max . \ 52 ok
+52 23 min . \ 23 ok
+
+\ ----------------------------- Pila Manipulación -----------------------------
+
+\ Naturalmente, cuando trabajaremos con el pila, querremos algunos metidos útiles:
+
+3 dup - \ duplicar el primero articulo (1ra ahora igual a 2da): 3 - 3
+2 5 swap / \ intercambiar la primera con la segunda elemento: 5 / 2
+6 4 5 rot .s \ rotar los tres primero elementos: 4 5 6
+4 0 drop 2 / \ sacar el primero articulo (no imprima a la pantalla): 4 / 2
+1 2 3 nip .s \ sacar el segundo articulo (similar a drop): 1 3
+
+\ ---------------------- Mas Avanzado Pila Manipulación ----------------------
+
+1 2 3 4 tuck \ duplicar el primero articulo en el segundo hueco: 1 2 4 3 4 ok
+1 2 3 4 over \ duplicar el segundo articulo a la primera del pila: 1 2 3 4 3 ok
+1 2 3 4 2 roll \ *mover* el articulo en este posición a la primera del pila: 1 3 4 2 ok
+1 2 3 4 2 pick \ *duplicar* el articulo en este posición a la primera del pila: 1 2 3 4 2 ok
+
+\ Cuando refiere a pila indices, ellos son basado en cero.
+
+\ ------------------------------ Creando Palabras --------------------------------
+
+\ La `:` palabra hace que Forth entra modo de compilar hasta que se ve la `;` palabra.
+: cuadrado ( n -- n ) dup * ; \ ok
+5 cuadrado . \ 25 ok
+
+\ Podemos ver lo que hace una palabra también.:
+see cuadrado \ : cuadrado dup * ; ok
+
+\ -------------------------------- Condicionales --------------------------------
+
+\ -1 == cierto, 0 == falso. No obstante, valores que no son cero es usualmente tratado como
+\ siendo cierto:
+42 42 = \ -1 ok
+12 53 = \ 0 ok
+
+\ `if` es una palabra que solamente compila. `if` <cosas para hacer> `then` <los de mas del programa>.
+: ?>64 ( n -- n ) dup 64 > if ." Mas que 64!" then ; \ ok
+100 ?>64 \ Mas que 64! ok
+
+\ Else:
+: ?>64 ( n -- n ) dup 64 > if ." Mas que 64!" else ." Menos que 64!" then ;
+100 ?>64 \ Mas que 64! ok
+20 ?>64 \ Menos que 64! ok
+
+\ ------------------------------------ Loops -----------------------------------
+
+\ `do` también es una palabra que solamente compila.
+: miloop ( -- ) 5 0 do cr ." Hola!" loop ; \ ok
+miloop
+\ Hola!
+\ Hola!
+\ Hola!
+\ Hola!
+\ Hola! ok
+
+\ `do` espera dos números en el pila: el último numero y el primero numero.
+
+\ Podemos recibir el valor del indice mientras damos vuelta con `i`:
+: uno-a-12 ( -- ) 12 0 do i . loop ; \ ok
+uno-a-12 \ 0 1 2 3 4 5 6 7 8 9 10 11 12 ok
+
+\ `?do` funciona similarmente, pero salta el loop si el último y primero
+\ números son iguales.
+: cuadrados ( n -- ) 0 ?do i cuadrado . loop ; \ ok
+10 cuadrado \ 0 1 4 9 16 25 36 49 64 81 ok
+
+\ cambiar el "paso" con `+loop`:
+: treces ( n n -- ) ?do i . 3 +loop ; \ ok
+15 0 treces \ 0 3 6 9 12 ok
+
+\ Indefinido loops empiezan `begin` <cosas para hacer> <bandera> `until`:
+: death ( -- ) begin ." Ya hemos llegado?" 0 until ; \ ok
+
+\ ---------------------------- Variables y Memoria ----------------------------
+
+\ Use `variable` declarar `edad` ser un variable.
+variable edad \ ok
+
+\ Ahora escribimos 21 a edad con la palabra `!`.
+21 edad ! \ ok
+
+\ Por fin podemos imprimir nuestro variable usando la "leer" palabra `@`, que agregue el
+\ valor a la pila, or usa `?` que lee y imprime todo juntos.
+edad @ . \ 21 ok
+edad ? \ 21 ok
+
+\ Constantes son muy similar, pero no nos importa los direcciones de memoria:
+100 constant PUNTA-QUE-AQUA-HIERVA \ ok
+PUNTA-QUE-AQUA-HIERVA . \ 100 ok
+
+\ ----------------------------------- Arrays -----------------------------------
+
+\ Creando arrays es similar a variables, pero necesitamos alocar mas
+\ memoria a ellos.
+
+\ Puede usar `2 cells allot` para crear un array que es sea 3 cédulas de tamaño:
+variable minumeros 2 cells allot \ ok
+
+\ Inicializar todos los valores a 0
+minumeros 3 cells erase \ ok
+
+\ Alternativamente podemos usar `fill`:
+minumeros 3 cells 0 fill
+
+\ o podemos saltar todo arriba y inicializar con valores específicos:
+create minumeros 64 , 9001 , 1337 , \ ok (el último `,` es importante!)
+
+\ ...que es equivalente a:
+
+\ Manualmente escribiendo valores a cada indice:
+64 minumeros 0 cells + ! \ ok
+9001 minumeros 1 cells + ! \ ok
+1337 minumeros 2 cells + ! \ ok
+
+\ Leyendo valores en particular array indices:
+0 cells minumeros + ? \ 64 ok
+1 cells minumeros + ? \ 9001 ok
+
+\ Podemos simplificar un poco cuando hacemos una palabra que ayuda cuando manipulando arrays:
+: de-arr ( n n -- n ) cells + ; \ ok
+minumeros 2 de-arr ? \ 1337 ok
+
+\ Que podemos usar cuando escribimos también:
+20 minumeros 1 de-arr ! \ ok
+minumeros 1 de-arr ? \ 20 ok
+
+\ ------------------------------ El Pila de Regreso ------------------------------
+
+\ El pila de regreso se usa para retener punteros a cosas cuando palabras están
+\ ejecutando otras palabras como loops.
+
+\ Ya hemos visto un uso de esto: `i`, que duplica el primero del pila
+\ de regreso. `i` es equivalente a `r@`.
+: miloop ( -- ) 5 0 do r@ . loop ; \ ok
+
+\ También como leyendo, podemos agregar al pila de regreso y sacarlo:
+5 6 4 >r swap r> .s \ 6 5 4 ok
+
+\ NOTA: Porque Forth usa el pila de regreso por punteros de palabras, `>r` debe
+\ siempre ser seguido por un `r>`.
+
+\ ------------------------- Flotante Punto Operaciones --------------------------
+
+\ La mayoría Forths evitan el uso de flotante punto operaciones.
+8.3e 0.8e f+ f. \ 9.1 ok
+
+\ Usualmente agregamos al frente palabras con 'f' cuando usando flotantes:
+variable miflotantevar \ ok
+4.4e miflotantevar f! \ ok
+miflotantevar f@ f. \ 4.4 ok
+
+\ --------------------------------- Notas al Final --------------------------------
+
+\ Usando una palabra que no existe vaciara el pila. No obstante, también hay una palabra
+\ específicamente por esto:
+clearstack
+
+\ vaciar la pantalla:
+page
+
+\ Cargando Forth archivos:
+\ s" archivodeforth.fs" included
+
+\ Puede listar cada palabra en el diccionario de Forth (pero es una lista gigante!):
+\ words
+
+\ Terminando Gforth:
+\ bye
+
+```
+
+##Listo Para Mas?
+
+* [Starting Forth](http://www.forth.com/starting-forth/)
+* [Simple Forth](http://www.murphywong.net/hello/simple.htm)
+* [Thinking Forth](http://thinking-forth.sourceforge.net/)
diff --git a/es-es/git-es.html.markdown b/es-es/git-es.html.markdown
index 18b544b4..4e1e68ba 100644
--- a/es-es/git-es.html.markdown
+++ b/es-es/git-es.html.markdown
@@ -18,11 +18,11 @@ versionar y administrar nuestro código fuente.
## Versionamiento, conceptos.
-### Qué es el control de versiones?
+### ¿Qué es el control de versiones?
El control de versiones es un sistema que guarda todos los cambios realizados en
uno o varios archivos, a lo largo del tiempo.
-### Versionamiento centralizado vs Versionamiento Distribuido.
+### Versionamiento centralizado vs versionamiento distribuido.
+ El versionamiento centralizado se enfoca en sincronizar, rastrear, y respaldar
archivos.
@@ -33,9 +33,9 @@ uno o varios archivos, a lo largo del tiempo.
[Información adicional](http://git-scm.com/book/es/Empezando-Acerca-del-control-de-versiones)
-### Por qué usar Git?
+### ¿Por qué usar Git?
-* Se puede trabajar sin conexion.
+* Se puede trabajar sin conexión.
* ¡Colaborar con otros es sencillo!.
* Derivar, crear ramas del proyecto (aka: Branching) es fácil.
* Combinar (aka: Merging)
@@ -47,7 +47,7 @@ uno o varios archivos, a lo largo del tiempo.
### Repositorio
Un repositorio es un conjunto de archivos, directorios, registros, cambios (aka:
-comits), y encabezados (aka: heads). Imagina que un repositorio es una clase,
+commits), y encabezados (aka: heads). Imagina que un repositorio es una clase,
y que sus atributos otorgan acceso al historial del elemento, además de otras
cosas.
@@ -62,12 +62,12 @@ y mas.
### Directorio de trabajo (componentes del repositorio)
-Es basicamente los directorios y archivos dentro del repositorio. La mayoría de
+Es básicamente los directorios y archivos dentro del repositorio. La mayoría de
las veces se le llama "directorio de trabajo".
### Índice (componentes del directorio .git)
-El índice es el área de inicio en git. Es basicamente la capa que separa el
+El índice es el área de inicio en git. Es básicamente la capa que separa el
directorio de trabajo del repositorio en git. Esto otorga a los desarrolladores
más poder sobre lo que se envía y se recibe del repositorio.
diff --git a/es-es/hack-es.html.markdown b/es-es/hack-es.html.markdown
new file mode 100644
index 00000000..1059117a
--- /dev/null
+++ b/es-es/hack-es.html.markdown
@@ -0,0 +1,307 @@
+---
+language: Hack
+contributors:
+ - ["Stephen Holdaway", "https://github.com/stecman"]
+ - ["David Lima", "https://github.com/davelima"]
+translators:
+ - ["César Suárez", "https://github.com/csuarez"]
+lang: es-es
+filename: learnhack-es.hh
+---
+
+Hack es un superconjunto de PHP que se ejecuta en una máquina virtual llamada HHVM. Hack es casi totalmente compatible con código PHP ya existente y añade varias características típicas de los lenguajes de programación estáticamente tipados.
+
+En este artículo sólo se cubren las características específicas de Hack. Los detalles sobre la sintaxis de PHP están en el [artículo sobre PHP](http://learnxinyminutes.com/docs/php/) de esta misma web.
+
+```php
+<?hh
+
+// La sintaxis de Hack sólo se habilita para los ficheros que comienzan con
+// un marcador <?hh. Estos marcadores no pueden intercalarse con código HTML,
+// tal como se puede hacer con <?php. Al usar el marcador "<?hh //strict" el
+// comprobador de tipado en modo estricto se pone en modo estricto.
+
+// Indicando el tipo de parámetros escalares
+function repeat(string $word, int $count)
+{
+ $word = trim($word);
+ return str_repeat($word . ' ', $count);
+}
+
+// Indicando el tipo que devuelve una función
+function add(...$numbers) : int
+{
+ return array_sum($numbers);
+}
+
+// Las funciones que no devuelven nada usan el tipo "void"
+function truncate(resource $handle) : void
+{
+ // ...
+}
+
+// Al determinar un tipo, hay que indicar explícitamente si permite el valor
+// NULL
+function identity(?string $stringOrNull) : ?string
+{
+ return $stringOrNull;
+}
+
+// Se puede especificar el tipo de las propiedades de una clase
+class TypeHintedProperties
+{
+ public ?string $name;
+
+ protected int $id;
+
+ private float $score = 100.0;
+
+ // El comprobador de tipos de Hack fuerza que las propiedades tipadas
+ // tengan un valor por defecto o que estén asignadas en el constructor
+ public function __construct(int $id)
+ {
+ $this->id = $id;
+ }
+}
+
+
+// Funciones anónimas concisas (lambdas)
+$multiplier = 5;
+array_map($y ==> $y * $multiplier, [1, 2, 3]);
+
+
+// Genéricos
+class Box<T>
+{
+ protected T $data;
+
+ public function __construct(T $data) {
+ $this->data = $data;
+ }
+
+ public function getData(): T {
+ return $this->data;
+ }
+}
+
+function openBox(Box<int> $box) : int
+{
+ return $box->getData();
+}
+
+
+// Shapes
+//
+// Hack añade el concepto de shape para definir estructuras similares a
+// vectores, pero con un conjunto de claves garantizado y tipado
+type Point2D = shape('x' => int, 'y' => int);
+
+function distance(Point2D $a, Point2D $b) : float
+{
+ return sqrt(pow($b['x'] - $a['x'], 2) + pow($b['y'] - $a['y'], 2));
+}
+
+distance(
+ shape('x' => -1, 'y' => 5),
+ shape('x' => 2, 'y' => 50)
+);
+
+
+// Alias de tipos
+//
+// Hack permite crear alias para hacer que los tipos complejos sean más legibles
+newtype VectorArray = array<int, Vector<int>>;
+
+// Una tupla que contiene dos enteros
+newtype Point = (int, int);
+
+function addPoints(Point $p1, Point $p2) : Point
+{
+ return tuple($p1[0] + $p2[0], $p1[1] + $p2[1]);
+}
+
+addPoints(
+ tuple(1, 2),
+ tuple(5, 6)
+);
+
+
+// Enumerados de primera clase
+enum RoadType : int
+{
+ Road = 0;
+ Street = 1;
+ Avenue = 2;
+ Boulevard = 3;
+}
+
+function getRoadType() : RoadType
+{
+ return RoadType::Avenue;
+}
+
+
+// Promoción de argumentos en constructores
+//
+// Para evitar repetir una y otra vez la definición de constructores que
+// sólo asignan propiedades, Hack añade una sintaxis concisa para definir
+// propiedades junto al constructor.
+class ArgumentPromotion
+{
+ public function __construct(public string $name,
+ protected int $age,
+ private bool $isAwesome) {}
+}
+
+class WithoutArgumentPromotion
+{
+ public string $name;
+
+ protected int $age;
+
+ private bool $isAwesome;
+
+ public function __construct(string $name, int $age, bool $isAwesome)
+ {
+ $this->name = $name;
+ $this->age = $age;
+ $this->isAwesome = $isAwesome;
+ }
+}
+
+
+// Multitarea cooperativa
+//
+// "async" y "await" son dos palabras claves nuevas para realizar multi-tarea.
+// Esto no implica que se usen hilos, sólo permiten transferir el control de la
+// ejecución.
+{
+ for ($i = $start; $i <= $end; $i++) {
+ echo "$i ";
+
+ // Da a otras tareas la oportunidad de hacer algo
+ await RescheduleWaitHandle::create(RescheduleWaitHandle::QUEUE_DEFAULT, 0);
+ }
+}
+
+// Esto imprime "1 4 7 2 5 8 3 6 9"
+AwaitAllWaitHandle::fromArray([
+ cooperativePrint(1, 3),
+ cooperativePrint(4, 6),
+ cooperativePrint(7, 9)
+])->getWaitHandle()->join();
+
+
+// Atributos
+//
+// Los atributos son una especie de metadatos para funciones. Hack implementa
+// algunos atributos especiales para introducir esta característica.
+
+// El atributo especial __Memoize hace que el resultado de la función se cacheé.
+<<__Memoize>>
+function doExpensiveTask() : ?string
+{
+ return file_get_contents('http://example.com');
+}
+
+// Esta función se va a ejecutar sólo una vez:
+doExpensiveTask();
+doExpensiveTask();
+
+
+// El atributo __ConsistentConstruct indica al comprobador de tipos de Hack que
+// asegure que la signatura de __construct sea la misma para todas las
+// subclases.
+<<__ConsistentConstruct>>
+class ConsistentFoo
+{
+ public function __construct(int $x, float $y)
+ {
+ // ...
+ }
+
+ public function someMethod()
+ {
+ // ...
+ }
+}
+
+class ConsistentBar extends ConsistentFoo
+{
+ public function __construct(int $x, float $y)
+ {
+ // El comprobador de tipos de Hack fuerza que los constructores de
+ // los padres sean llamados.
+ parent::__construct($x, $y);
+
+ // ...
+ }
+
+ // La anotación __Override es un atributo opcional para que el comprobador
+ // de tipos fuerce que ese método esté sobrecargando un método de un padre
+ // o de un trait. Sino, fallará.
+ <<__Override>>
+ public function someMethod()
+ {
+ // ...
+ }
+}
+
+class InvalidFooSubclass extends ConsistentFoo
+{
+ // Este constructor no coincide con el padre y causará el siguiente error:
+ //
+ // "This object is of type ConsistentBaz. It is incompatible with this
+ // object of type ConsistentFoo because some of their methods are
+ // incompatible"
+ public function __construct(float $x)
+ {
+ // ...
+ }
+
+ // Usando la anotación __Override en un método que no sobrecarga nada se
+ // producirá el siguiente error:
+ //
+ // "InvalidFooSubclass::otherMethod() is marked as override; no non-private
+ // parent definition found or overridden parent is defined in non-<?hh
+ // code"
+ <<__Override>>
+ public function otherMethod()
+ {
+ // ...
+ }
+}
+
+
+// Los traits pueden implementar interfaces (PHP no soporta esto).
+interface KittenInterface
+{
+ public function play() : void;
+}
+
+trait CatTrait implements KittenInterface
+{
+ public function play() : void
+ {
+ // ...
+ }
+}
+
+class Samuel
+{
+ use CatTrait;
+}
+
+
+$cat = new Samuel();
+$cat instanceof KittenInterface === true; // True
+
+```
+
+## Más información
+
+Para obtener una explicación más detallada de las características que añade Hack a PHP visita la página de [referencia de Hack](http://docs.hhvm.com/manual/en/hacklangref.php) o la [página oficial de Hack](http://hacklang.org/) para información de caracter más general.
+
+Visita la [página oficial de HHVM](http://hhvm.com/) para ver las instrucciones de su instalación.
+
+También puedes visitar la [sección de características de PHP no soportadas por Hack](http://docs.hhvm.com/manual/en/hack.unsupported.php) para más detalles sobre la retrocompatibilidad entre Hack y PHP.
diff --git a/es-es/javascript-es.html.markdown b/es-es/javascript-es.html.markdown
index d475cf42..34428f42 100644
--- a/es-es/javascript-es.html.markdown
+++ b/es-es/javascript-es.html.markdown
@@ -23,14 +23,16 @@ Aunque JavaScript no sólo se limita a los navegadores web: Node.js, Un proyecto
[adam@brenecki.id.au](mailto:adam@brenecki.id.au).
```js
-// Los comentarios son como en C. Los comentarios de una sola línea comienzan con //,
+// Los comentarios en JavaScript son los mismos como comentarios en C.
+
+//Los comentarios de una sola línea comienzan con //,
/* y los comentarios multilínea comienzan
y terminan con */
// Cada sentencia puede ser terminada con punto y coma ;
hazAlgo();
-// ... aunque no es necesario, ya que el punto y coma se agrega automaticamente
+// ... aunque no es necesario, ya que el punto y coma se agrega automáticamente
// cada que se detecta una nueva línea, a excepción de algunos casos.
hazAlgo()
@@ -109,7 +111,7 @@ null == undefined; // = true
null === undefined; // false
// Los Strings funcionan como arreglos de caracteres
-// Puedes accesar a cada caracter con la función charAt()
+// Puedes acceder a cada caracter con la función charAt()
"Este es un String".charAt(0); // = 'E'
// ...o puedes usar la función substring() para acceder a pedazos más grandes
@@ -186,7 +188,7 @@ miObjeto.miLlave; // = "miValor"
// agregar nuevas llaves.
miObjeto.miTerceraLlave = true;
-// Si intentas accesar con una llave que aún no está asignada tendrás undefined.
+// Si intentas acceder con una llave que aún no está asignada tendrás undefined.
miObjeto.miCuartaLlave; // = undefined
///////////////////////////////////
@@ -301,7 +303,7 @@ i; // = 5 - en un lenguaje que da ámbitos por bloque esto sería undefined, per
//inmediatamente", que preveé variables temporales de fugarse al ámbito global
(function(){
var temporal = 5;
- // Podemos accesar al ámbito global asignando al 'objeto global', el cual
+ // Podemos acceder al ámbito global asignando al 'objeto global', el cual
// en un navegador siempre es 'window'. El objeto global puede tener
// un nombre diferente en ambientes distintos, por ejemplo Node.js .
window.permanente = 10;
@@ -321,7 +323,7 @@ function decirHolaCadaCincoSegundos(nombre){
alert(texto);
}
setTimeout(interna, 5000);
- // setTimeout es asíncrono, así que la funcion decirHolaCadaCincoSegundos
+ // setTimeout es asíncrono, así que la función decirHolaCadaCincoSegundos
// terminará inmediatamente, y setTimeout llamará a interna() a los cinco segundos
// Como interna está "cerrada dentro de" decirHolaCadaCindoSegundos, interna todavía tiene
// acceso a la variable 'texto' cuando es llamada.
@@ -339,7 +341,7 @@ var miObjeto = {
};
miObjeto.miFuncion(); // = "¡Hola Mundo!"
-// Cuando las funciones de un objeto son llamadas, pueden accesar a las variables
+// Cuando las funciones de un objeto son llamadas, pueden acceder a las variables
// del objeto con la palabra clave 'this'.
miObjeto = {
miString: "¡Hola Mundo!",
@@ -401,11 +403,11 @@ var MiConstructor = function(){
miNuevoObjeto = new MiConstructor(); // = {miNumero: 5}
miNuevoObjeto.miNumero; // = 5
-// Todos los objetos JavaScript tienen un 'prototipo'. Cuando vas a accesar a una
+// Todos los objetos JavaScript tienen un 'prototipo'. Cuando vas a acceder a una
// propiedad en un objeto que no existe en el objeto el intérprete buscará en
// el prototipo.
-// Algunas implementaciones de JavaScript te permiten accesar al prototipo de
+// Algunas implementaciones de JavaScript te permiten acceder al prototipo de
// un objeto con la propiedad __proto__. Mientras que esto es útil para explicar
// prototipos, no es parte del estándar; veremos formas estándar de usar prototipos
// más adelante.
@@ -440,7 +442,7 @@ miPrototipo.sentidoDeLaVida = 43;
miObjeto.sentidoDeLaVida; // = 43
// Mencionabamos anteriormente que __proto__ no está estandarizado, y que no
-// existe una forma estándar de accesar al prototipo de un objeto. De todas formas.
+// existe una forma estándar de acceder al prototipo de un objeto. De todas formas.
// hay dos formas de crear un nuevo objeto con un prototipo dado.
// El primer método es Object.create, el cual es una adición reciente a JavaScript,
@@ -476,7 +478,7 @@ typeof miNumero; // = 'number'
typeof miNumeroObjeto; // = 'object'
miNumero === miNumeroObjeyo; // = false
if (0){
- // Este código no se ejecutara porque 0 es false.
+ // Este código no se ejecutará porque 0 es false.
}
// Aún así, los objetos que envuelven y los prototipos por defecto comparten
diff --git a/es-es/json-es.html.markdown b/es-es/json-es.html.markdown
index fff678eb..c98049f9 100644
--- a/es-es/json-es.html.markdown
+++ b/es-es/json-es.html.markdown
@@ -21,22 +21,22 @@ JSON en su forma más pura no tiene comentarios, pero la mayoría de los parsead
"llaves": "siempre debe estar entre comillas (ya sean dobles o simples)",
"numeros": 0,
"strings": "Høla, múndo. Todo el unicode está permitido, así como \"escapar\".",
- "soporta booleanos?": true,
- "vacios": null,
+ "¿soporta booleanos?": true,
+ "vacíos": null,
"numero grande": 1.2e+100,
"objetos": {
- "comentario": "La mayoria de tu estructura vendra de objetos.",
+ "comentario": "La mayoría de tu estructura vendrá de objetos.",
"arreglo": [0, 1, 2, 3, "Los arreglos pueden contener cualquier cosa.", 5],
"otro objeto": {
- "comentario": "Estas cosas pueden estar anidadas, muy util."
+ "comentario": "Estas cosas pueden estar anidadas, muy útil."
}
},
- "tonteria": [
+ "tontería": [
{
"fuentes de potasio": ["bananas"]
},
@@ -50,10 +50,10 @@ JSON en su forma más pura no tiene comentarios, pero la mayoría de los parsead
"estilo alternativo": {
"comentario": "Mira esto!"
- , "posicion de la coma": "no importa - mientras este antes del valor, entonces sera valido"
- , "otro comentario": "que lindo"
+ , "posición de la coma": "no importa - mientras este antes del valor, entonces sera válido"
+ , "otro comentario": "qué lindo"
},
- "eso fue rapido": "Y, estas listo. Ahora sabes todo lo que JSON tiene para ofrecer."
+ "eso fue rapido": "Y, estás listo. Ahora sabes todo lo que JSON tiene para ofrecer."
}
```
diff --git a/es-es/latex-es.html.markdown b/es-es/latex-es.html.markdown
new file mode 100644
index 00000000..aff3c603
--- /dev/null
+++ b/es-es/latex-es.html.markdown
@@ -0,0 +1,213 @@
+---
+language: latex
+lang: es-es
+contributors:
+ - ["Chaitanya Krishna Ande", "http://icymist.github.io"]
+ - ["Colton Kohnke", "http://github.com/voltnor"]
+ - ["Sricharan Chiruvolu", "http://sricharan.xyz"]
+translators:
+ - ["Mario Pérez", "https://github.com/MarioPerezEsteso"]
+filename: learn-latex-es.tex
+---
+
+```tex
+% Todas las líneas comentadas comienzan con %
+% No existen los comentarios multilínea
+
+% LaTeX NO es un software de procesamiento de texto que cumple con
+% "Lo que ves es lo que tienes" como MS Word u OpenOffice
+
+% Todos los comandos de LaTeX comienzan con una contrabarra (\)
+
+% Los documentos LaTeX comienzan definiendo el tipo de documento que se va a
+% compilar. Algunos tipos de documentos son libros, informes, presentaciones,
+% etc. Las opciones para el documento comienzan en los corchetes []. En este
+% caso, se especifica que queremos utilizar una fuente de tamaño 12pt.
+\documentclass[12pt]{article}
+
+% A continuación, definimos los paquetes que utilizará el documento.
+% Si quieres incluir gráficos, texto coloreado o código fuente de otro lenguaje,
+% debes extender las funciones de LaTeX. Esto se consigue añadiendo paquetes.
+% A continuación se incluirán los paquetes float y caption para figuras.
+\usepackage{caption}
+\usepackage{float}
+
+% También podemos definir otras propiedades en el documento
+\author{Chaitanya Krishna Ande, Colton Kohnke \& Sricharan Chiruvolu}
+\date{\today}
+\title{Learn LaTeX in Y Minutes!}
+
+% Ahora estamos preparados para comenzar el documento
+% Todo lo que se encuentre antes de esta línea se llama "El Preámbulo"
+\begin{document}
+% Si especificamos el autor, fecha y título, LaTeX creará una página como título
+% por nosotros
+\maketitle
+
+% La mayoría de los artículos de investigación tienen un abstract. Es posible
+% utilizar comandos predefinidos para ello.
+% Esto debería aparecer en su orden lógico. Tras el título pero antes de las
+% secciones principales del cuerpo.
+% Este comando está disponible en los tipos de documentos article y report.
+\begin{abstract}
+ Documentación de LaTex escrita en LaTex.
+\end{abstract}
+
+% Los comandos de sección son intuitivos.
+% Todos los títulos de secciones son añadidos automáticamente a la tabla de contenidos.
+\section{Introducción}
+Hola, mi nombre es Mario Pérez y estoy traduciendo este documento para aprender LaTex.
+
+\section{Otra sección}
+Este es el texto de otra sección. Creo que necesitará una subsección.
+
+\subsection{Esto es una subsección} % Las subsecciones también son fáciles.
+Creo que necesitamos otra más.
+
+\subsubsection{Pitágoras}
+Mejor ahora.
+\label{subsec:pitagoras}
+
+% Utilizando el asterisco podemos decirle a LaTeX que no ponga los números de secciones y subsecciones.
+% Esto también funciona con otros comandos de LaTeX.
+\section*{Esto es una sección no numerada}
+¡No todas las secciones tienen que estar numeradas!
+
+\section{Algunas notas}
+LaTeX es generalmente bastante bueno situando el texto donde debe ir. Si una lína \\ necesita \\ ser \\ rota \\ puedes poner \textbackslash\textbackslash en el código fuente. \\
+
+\section{Listas}
+Las listas son de las cosas más fáciles de crear en LaTeX. Necesito ir a comprar mañana, así que vamos a crear una lista de la compra.
+\begin{enumerate} % Esto crea una lista numerada.
+ % \item crea un elemento
+ \item Ensalada.
+ \item 27 sandías.
+ \item Pescado.
+ % podemos incluso sobreescribir el número del ítem usando []
+ \item[cuántos?] Plátanos.
+
+ No es un ítem de la lista, pero sigue siendo parte de la enumeración.
+
+\end{enumerate} % Todos los contextos deben tener un final.
+
+\section{Matemáticas}
+
+Uno de los usos principales de LaTeX es la producción de artículos académicos o técnicos. Normalmente relacionados con la ciencia y las matemáticas. Debido a esto, necesitamos poder añadir símbolos especiales a nuestro artículo.\\
+
+En matemáticas hay muchos símbolos. Más de los que podemos encontrar en un teclado. Flechas o letras por nombrar un par.\\
+
+Algunos símbolos juegan un papel fundamental en muchos artículos de investigación matemática. Así es como se establece que todo Y pertenece a X: $\forall$ x $\in$ X. \\
+He necesitado añadir el signo $ antes de los símbolos. Esto se debe a que cuando escribimos, estamos en modo texto. Sin embargo, los símbolos solo pueden utilizarse en modo matemático, al cual se entra con el signo $.
+% Lo opuesto también se cumple. Una variable también puede ser mostrada en modo matemático, al que también se puede entrar con \[\]
+
+\[a^2 + b^2 = c^2 \]
+
+Mi letra griega favorita es $\xi$. También me gustan $\beta$, $\gamma$ y $\sigma$.
+Todavía no he encontrado una letra griega que LaTeX no conozca.
+
+Los operadores son también una parte esencial de un documento matemático:
+funciones trigonométricas ($\sin$, $\cos$, $\tan$), logaritmos y exponenciales ($\log$, $\exp$), límites ($\lim$), etc. tienen comandos predefinidos en LaTeX.
+
+Vamos a escribir una ecuación para ver cómo se hace: \\
+
+$\cos(2\theta) = \cos^{2}(\theta) - \sin^{2}(\theta)$
+
+Las fracciones (numeradores-denominadores) pueden escribirse de la siguiente forma:
+
+% 10 / 7
+$^{10}/_{7}$
+
+% Las fracciones relativamente complejas pueden escribirse como
+% \frac{numerador}{denominador}
+$\frac{n!}{k!(n - k)!}$ \\
+
+También podemos insertar ecuaciones en un contexto de ecuación.
+
+% Mostrar matemáticas en el contexto de ecuaciones
+\begin{equation} % entra en modo matemático
+ c^2 = a^2 + b^2.
+ \label{eq:pitagoras} % para referencias
+\end{equation} % Todos los contextos deben tener un final.
+
+Podemos referenciar nuestra nueva ecuación.
+Ecuación ~\ref{eq:pythagoras} también se conoce como el Teorema de Pitágoras, el cual también se encuentra en la sección ~\ref{subsec:pythagoras}. Muchas cosas pueden ser etiquetadas: figures, equations, sections, etc.
+
+Los sumatorios e integrales son escritor son los comandos sum e int:
+
+% Algunos compiladores de LaTeX se quejarán si hay líneas en blanco
+% En un contexto de ecuación.
+\begin{equation}
+ \sum_{i=0}^{5} f_{i}
+\end{equation}
+\begin{equation}
+ \int_{0}^{\infty} \mathrm{e}^{-x} \mathrm{d}x
+\end{equation}
+
+\section{Figuras}
+
+Vamos a insertar una figura. Situarla puede ser algo complicado.
+
+\begin{figure}[H] % H aquí establece la situación de la figura.
+ \centering % centra la figura en la página
+ % Inserta una figura escalada por 0.8 el ancho de la página.
+ %\includegraphics[width=0.8\linewidth]{right-triangle.png}
+ % La línea anterior ha sido comentada para poder compilar este archivo. Por favor, usa tu imaginación.
+ \caption{Triángulo con lados $a$, $b$, $c$}
+ \label{fig:right-triangle}
+\end{figure}
+
+\subsection{Tablas}
+También podemos insertar tablas de la misma manera que las figuras.
+
+\begin{table}[H]
+ \caption{Título para la tabla.}
+ % los argumentos en {} describen cómo cada fila va a ser representada.
+ \begin{tabular}{c|cc}
+ Número & Nombre & Apellido \\
+ \hline % una línea horizontal
+ 1 & Biggus & Dickus \\
+ 2 & Monty & Python
+ \end{tabular}
+\end{table}
+
+% \section{Hyperlinks} % En construcción
+
+\section{Haciendo que LaTeX no compile algo (por ejemplo, código fuente)}
+Digamos que queremos incluir código fuente dentro de nuestro documento LaTex. En ese caso, debemos indicarle a LaTeX que no trate de compilarlo y simplemente lo muestre en el documento. Esto lo realizamos en el contexto verbatim.
+
+% Hay otros paquetes para esta misma tarea, pero verbatim es el más básico.
+\begin{verbatim}
+ print("Hola Mundo!")
+ a%b; % Podemos usar los signos % en verbatim.
+ aleatorio = 4; # Número aleatorio
+\end{verbatim}
+
+\section{Compilación}
+
+Ahora mismo te estarás preguntando cómo compilar este fabuloso documento y obtener un documento PDF.\\
+Para obtener el documento final utilizando LaTeX hay que seguir los siguientes pasos:
+ \begin{enumerate}
+ \item Escribe el documento en texto plano.
+ \item Compila el código para producir un PDF.
+ Los pasos de compilación serán algo parecido a esto (en Linux): \\
+ \begin{verbatim}
+ $pdflatex learn-latex.tex learn-latex.pdf
+ \end{verbatim}
+ \end{enumerate}
+
+Un gran número de editores LaTeX combinan ambos pasos para que sea más sencillo obtener el documento.
+
+Escribe toda la información de formato en el paso 1 y con el paso 2 obtendrás el documento que has definido en el paso anterior.
+
+\section{End}
+
+Esto es todo por ahora.
+
+% fin del documento
+\end{document}
+```
+
+## Más información sobre LaTeX
+
+* El wikilibro LaTeX: [https://es.wikibooks.org/wiki/Manual_de_LaTeX](https://es.wikibooks.org/wiki/Manual_de_LaTeX)
+* Un tutorial real: [http://www.latex-tutorial.com/](http://www.latex-tutorial.com/)
diff --git a/es-es/markdown-es.html.markdown b/es-es/markdown-es.html.markdown
index d90e3eb5..0505b4cb 100644
--- a/es-es/markdown-es.html.markdown
+++ b/es-es/markdown-es.html.markdown
@@ -11,7 +11,7 @@ lang: es-es
Markdown fue creado por John Gruber en 2004. Su propósito es ser una sintaxis fácil de leer y escribir que se convierta
fácilmente a HTML (y, actualmente, otros formatos también).
-¡Denme todo la retroalimentación que quieran! / ¡Sientanse en la libertad de hacer forks o pull requests!
+¡Denme toda la retroalimentación que quieran! / ¡Sientanse en la libertad de hacer forks o pull requests!
```markdown
@@ -44,7 +44,7 @@ Esto es un h2
-------------
<!-- Estilos para texto plano -->
-<!-- El texto puede ser fácilmente estilizaedo con italicas, negritas o tachado
+<!-- El texto puede ser fácilmente estilizado con italicas, negritas o tachado
usando markdown -->
*Este texto está en itálicas.*
@@ -57,12 +57,12 @@ __Al igual que este texto.__
**_Al igual que este!_**
*__¡Y este!__*
-<!-- En Github Flavored Markdown, el cual es usado para mostrar archivos
-Markdown en Github, también tenemos: -->
+<!-- En GitHub Flavored Markdown, el cual es usado para mostrar archivos
+Markdown en GitHub, también tenemos: -->
~~Este texto está tachado.~~
-<!-- Los párrafos son una o múltuples líneas de texto adyacentes separadas por
+<!-- Los párrafos son una o múltiples líneas de texto adyacentes separadas por
una o múltiples líneas en blanco-->
Este es un párrafo. Estoy escribiendo un párrafo, ¿No es divertido?
@@ -150,7 +150,7 @@ para indentar dentro del código -->
¡John no sabía lo que la función `go_to()` hacía!
-<!-- Con Github Flavored Markdown, puedes usar una sintaxis especial para código -->
+<!-- Con GitHub Flavored Markdown, puedes usar una sintaxis especial para código -->
\`\`\`ruby <!-- quita esas comillas cuando lo hagas, deja sólo ```ruby ! -->
def foobar
@@ -158,7 +158,7 @@ def foobar
end
\`\`\` <!-- aquí también, sin comillas, sólo ``` -->
-<!-- El texto de arriba no necesita indentación, aparte Github usará
+<!-- El texto de arriba no necesita indentación, aparte GitHub usará
resaltará la sintaxis del lenguaje que especifiques después de ``` -->
<!-- Regla horizontal (<hr />) -->
@@ -231,7 +231,7 @@ Quiero escribir *este texto rodeado por asteriscos* pero no quiero que esté en
así que hago esto: \*Este texto está rodeado de asteriscos\*.
<!-- Tablas -->
-<!-- Las tablas sólo están disponibles en Github Flavored Markdown y son un poco pesadas,
+<!-- Las tablas sólo están disponibles en GitHub Flavored Markdown y son un poco pesadas,
pero si de verdad las quieres: -->
| Col1 | Col2 | Col3 |
diff --git a/es-es/objective-c-es.html.markdown b/es-es/objective-c-es.html.markdown
new file mode 100644
index 00000000..bdbce524
--- /dev/null
+++ b/es-es/objective-c-es.html.markdown
@@ -0,0 +1,851 @@
+---
+language: Objective-C
+contributors:
+ - ["Eugene Yagrushkin", "www.about.me/yagrushkin"]
+ - ["Yannick Loriot", "https://github.com/YannickL"]
+ - ["Levi Bostian", "https://github.com/levibostian"]
+translators:
+ - ["David Hsieh", "http://github.com/deivuh"]
+lang: es-es
+filename: LearnObjectiveC-es.m
+---
+Objective C es el lenguaje de programación principal utilizado por Apple para los sistemas operativos OS X y iOS y sus respectivos frameworks, Cocoa y Cocoa Touch.
+Es un lenguaje de programación para propósito general que le agrega al lenguaje de programación C una mensajería estilo "Smalltalk".
+
+
+```objective_c
+// Los comentarios de una sola línea inician con //
+
+/*
+Los comentarios de múltiples líneas se ven así.
+*/
+
+// Importa los encabezados de Foundation con #import
+// Utiliza <> para importar archivos globales (generalmente frameworks)
+// Utiliza "" para importar archivos locales (del proyecto)
+#import <Foundation/Foundation.h>
+#import "MyClass.h"
+
+// Si habilitas módulos para proyectos de iOS >= 7.0 u OS X >= 10.9 en
+// Xcode 5, puedes importarlos de la siguiente manera:
+@import Foundation;
+
+// El punto de entrada de tu programa es una función llamada
+// main con un tipo de retorno entero.
+int main (int argc, const char * argv[])
+{
+ // Crear un autorelease pool para manejar la memoria al programa
+ NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
+ // Si se utiliza el conteo automático de referencias (ARC),
+ // utiliza @autoreleasepool:
+ @autoreleasepool {
+
+ // Utiliza NSLog para imprimir líneas a la consola
+ NSLog(@"Hello World!"); // Imprimir el string "Hello World!"
+
+ ///////////////////////////////////////
+ // Tipos y variables
+ ///////////////////////////////////////
+
+ // Declaraciones de primitivos
+ int myPrimitive1 = 1;
+ long myPrimitive2 = 234554664565;
+
+ // Declaraciones de objetos
+ // Pon el * como prefijo de los nombre de las variables para declaraciones
+ // de objetos de tipos fuertes
+ MyClass *myObject1 = nil; // Tipo fuerte
+ id myObject2 = nil; // Tipo débil
+ // %@ es un objeto
+ // 'description' es una convención para mostrar el valor de los objetos
+ NSLog(@"%@ and %@", myObject1, [myObject2 description]);
+ // imprime => "(null) and (null)"
+
+ // String
+ NSString *worldString = @"World";
+ NSLog(@"Hello %@!", worldString); // imprime => "Hello World!"
+ // NSMutableString es una versión mutable del objeto NSString
+ NSMutableString *mutableString = [NSMutableString stringWithString:@"Hello"];
+ [mutableString appendString:@" World!"];
+ NSLog(@"%@", mutableString); // imprime => "Hello World!"
+
+ // Literales de caracteres
+ NSNumber *theLetterZNumber = @'Z';
+ char theLetterZ = [theLetterZNumber charValue]; // o 'Z'
+ NSLog(@"%c", theLetterZ);
+
+ // Literales de enteros
+ NSNumber *fortyTwoNumber = @42;
+ int fortyTwo = [fortyTwoNumber intValue]; // o 42
+ NSLog(@"%i", fortyTwo);
+
+ NSNumber *fortyTwoUnsignedNumber = @42U;
+ unsigned int fortyTwoUnsigned = [fortyTwoUnsignedNumber unsignedIntValue]; // o 42
+ NSLog(@"%u", fortyTwoUnsigned);
+
+ NSNumber *fortyTwoShortNumber = [NSNumber numberWithShort:42];
+ short fortyTwoShort = [fortyTwoShortNumber shortValue]; // o 42
+ NSLog(@"%hi", fortyTwoShort);
+
+ NSNumber *fortyOneShortNumber = [NSNumber numberWithShort:41];
+ unsigned short fortyOneUnsigned = [fortyOneShortNumber unsignedShortValue]; // o 41
+ NSLog(@"%u", fortyOneUnsigned);
+
+ NSNumber *fortyTwoLongNumber = @42L;
+ long fortyTwoLong = [fortyTwoLongNumber longValue]; // o 42
+ NSLog(@"%li", fortyTwoLong);
+
+ NSNumber *fiftyThreeLongNumber = @53L;
+ unsigned long fiftyThreeUnsigned = [fiftyThreeLongNumber unsignedLongValue]; // o 53
+ NSLog(@"%lu", fiftyThreeUnsigned);
+
+ // Literales de punto flotante
+ NSNumber *piFloatNumber = @3.141592654F;
+ float piFloat = [piFloatNumber floatValue]; // o 3.141592654f
+ NSLog(@"%f", piFloat); // imprime => 3.141592654
+ NSLog(@"%5.2f", piFloat); // imprime => " 3.14"
+
+ NSNumber *piDoubleNumber = @3.1415926535;
+ double piDouble = [piDoubleNumber doubleValue]; // o 3.1415926535
+ NSLog(@"%f", piDouble);
+ NSLog(@"%4.2f", piDouble); // imprime => "3.14"
+
+ // NSDecimalNumber es una clase de punto-fijo que es más preciso que float o double
+ NSDecimalNumber *oneDecNum = [NSDecimalNumber decimalNumberWithString:@"10.99"];
+ NSDecimalNumber *twoDecNum = [NSDecimalNumber decimalNumberWithString:@"5.002"];
+ // NSDecimalNumber no tiene la capacidad de utilizar los operadores estándares
+ // +, -, * , /, por lo que cuenta con sus propios operadores:
+ [oneDecNum decimalNumberByAdding:twoDecNum];
+ [oneDecNum decimalNumberBySubtracting:twoDecNum];
+ [oneDecNum decimalNumberByMultiplyingBy:twoDecNum];
+ [oneDecNum decimalNumberByDividingBy:twoDecNum];
+ NSLog(@"%@", oneDecNum); // imprime => 10.99 como NSDecimalNumber es inmutable
+
+ // Literales BOOL
+ NSNumber *yesNumber = @YES;
+ NSNumber *noNumber = @NO;
+ // o
+ BOOL yesBool = YES;
+ BOOL noBool = NO;
+ NSLog(@"%i", yesBool); // prints => 1
+
+ // Objecto arreglo
+ // Puede contener diferentes tipos de datos, pero deben de ser un objeto de
+ // Objective-C
+ NSArray *anArray = @[@1, @2, @3, @4];
+ NSNumber *thirdNumber = anArray[2];
+ NSLog(@"Third number = %@", thirdNumber); // imprime => "Third number = 3"
+ // NSMutableArray es una versión mutable de NSArray, permitiendo el cambio
+ // de los elementos del arreglo y el agrandado o encojimiento del objeto arreglo.
+ // Conveniente, pero no tan eficiente como NSArray en cuanto a rendimiento.
+ NSMutableArray *mutableArray = [NSMutableArray arrayWithCapacity:2];
+ [mutableArray addObject:@"Hello"];
+ [mutableArray addObject:@"World"];
+ [mutableArray removeObjectAtIndex:0];
+ NSLog(@"%@", [mutableArray objectAtIndex:0]); // imprime => "World"
+
+ // Objecto Diccionario
+ NSDictionary *aDictionary = @{ @"key1" : @"value1", @"key2" : @"value2" };
+ NSObject *valueObject = aDictionary[@"A Key"];
+ NSLog(@"Object = %@", valueObject); // imprime => "Object = (null)"
+ // NSMutableDictionary también está disponible como un objeto mutable
+ NSMutableDictionary *mutableDictionary = [NSMutableDictionary dictionaryWithCapacity:2];
+ [mutableDictionary setObject:@"value1" forKey:@"key1"];
+ [mutableDictionary setObject:@"value2" forKey:@"key2"];
+ [mutableDictionary removeObjectForKey:@"key1"];
+
+ // Objeto de Set
+ NSSet *set = [NSSet setWithObjects:@"Hello", @"Hello", @"World", nil];
+ NSLog(@"%@", set); // imprime => {(Hello, World)} (el orden puede variar)
+ // NSMutableSet también está disponible como un objeto mutable
+ NSMutableSet *mutableSet = [NSMutableSet setWithCapacity:2];
+ [mutableSet addObject:@"Hello"];
+ [mutableSet addObject:@"Hello"];
+ NSLog(@"%@", mutableSet); // prints => {(Hello)}
+
+ ///////////////////////////////////////
+ // Operadores
+ ///////////////////////////////////////
+
+ // Los operadores funcionan como en el lenguaje C
+ // Por ejemplo:
+ 2 + 5; // => 7
+ 4.2f + 5.1f; // => 9.3f
+ 3 == 2; // => 0 (NO)
+ 3 != 2; // => 1 (YES)
+ 1 && 1; // => 1 (and lógico)
+ 0 || 1; // => 1 (or lógico)
+ ~0x0F; // => 0xF0 (negación bitwise)
+ 0x0F & 0xF0; // => 0x00 (AND bitwise)
+ 0x01 << 1; // => 0x02 (acarreamiento a la izquierda bitwise (por 1))
+
+ ///////////////////////////////////////
+ // Estructuras de control
+ ///////////////////////////////////////
+
+ // Declaraciones If-Else
+ if (NO)
+ {
+ NSLog(@"I am never run");
+ } else if (0)
+ {
+ NSLog(@"I am also never run");
+ } else
+ {
+ NSLog(@"I print");
+ }
+
+ // Declaración Switch
+ switch (2)
+ {
+ case 0:
+ {
+ NSLog(@"I am never run");
+ } break;
+ case 1:
+ {
+ NSLog(@"I am also never run");
+ } break;
+ default:
+ {
+ NSLog(@"I print");
+ } break;
+ }
+
+ // Declaración de ciclos While
+ int ii = 0;
+ while (ii < 4)
+ {
+ NSLog(@"%d,", ii++); // ii++ incrementa ii en la misma línea, luego de
+ // utilizar su valor
+ } // imprime => "0,"
+ // "1,"
+ // "2,"
+ // "3,"
+
+ // Declaración de ciclos For
+ int jj;
+ for (jj=0; jj < 4; jj++)
+ {
+ NSLog(@"%d,", jj);
+ } // imprime => "0,"
+ // "1,"
+ // "2,"
+ // "3,"
+
+ // Declaraciones foreach
+ NSArray *values = @[@0, @1, @2, @3];
+ for (NSNumber *value in values)
+ {
+ NSLog(@"%@,", value);
+ } // imprime => "0,"
+ // "1,"
+ // "2,"
+ // "3,"
+
+ // Objeto de ciclos For. Puede ser utilizado con cualquier tipo de objecto de
+ // Objective-C
+ for (id item in values) {
+ NSLog(@"%@,", item);
+ } // imprime => "0,"
+ // "1,"
+ // "2,"
+ // "3,"
+
+ // Declaraciones Try-Catch-Finally
+ @try
+ {
+ // Tus declaraciones aquí
+ @throw [NSException exceptionWithName:@"FileNotFoundException"
+ reason:@"File Not Found on System" userInfo:nil];
+ } @catch (NSException * e) // utiliza: @catch (id exceptionName) para atrapar
+ // todos los objetos
+ {
+ NSLog(@"Exception: %@", e);
+ } @finally
+ {
+ NSLog(@"Finally. Time to clean up.");
+ } // imprime => "Exception: File Not Found on System"
+ // "Finally. Time to clean up."
+
+ // Los objetos NSError son útiles para argumentos de función para los
+ // errores de usuario.
+ NSError *error = [NSError errorWithDomain:@"Invalid email." code:4 userInfo:nil];
+
+ ///////////////////////////////////////
+ // Objetos
+ ///////////////////////////////////////
+
+ // Crea una instancia de objeto alocando memoria e inicializándola
+ // Un objeto no es completamente funcional hasta que ambos pasos hayan sido
+ // completados
+ MyClass *myObject = [[MyClass alloc] init];
+
+ // El modelo de programación orientada a objetos de Objective-C es basada en
+ // el envío de mensajes a instancias de objetos
+ // En Objective-C no se llama a un método; se envía un mensaje
+ [myObject instanceMethodWithParameter:@"Steve Jobs"];
+
+ // Limpiar la memoria que se utilizó en el programa
+ [pool drain];
+
+ // Fin de @autoreleasepool
+ }
+
+ // Fin del programa
+ return 0;
+}
+
+///////////////////////////////////////
+// Clases y funciones
+///////////////////////////////////////
+
+// Declara tu clase en archivo de encabezado (MyClass.h)
+// Sintaxis de declaración de clase:
+// @interface NombreDeClase : NombreDeClasePadre <ProtocolosImplementados>
+// {
+// type nombre; <= declaraciones de variables;
+// }
+// @property tipo nombre; <= declaración de propiedades
+// -/+ (tipo) Declaración de método; <= Declaración de método
+// @end
+@interface MyClass : NSObject <MyProtocol> // NSObject es la clase de objeto
+ // base de Objective-C.
+{
+ // Declaraciones de variables de instancia (puede existir en el archivo de
+ // interfaz o de implementación)
+ int count; // Acceso protegido por defecto.
+ @private id data; // Acceso privado (Más conveniente de declarar en el
+ // archivo de implementación)
+ NSString *name;
+}
+// Notación conveneinte para acceso público de las variables para generar un
+// método setter
+// Por defecto, el nombre del método setter 'set' seguido del nombre de
+// variable @property
+@property int propInt; // Nombre del método 'setter' = 'setPropInt'
+@property (copy) id copyId; // (copy) => Copia el objeto durante la asignación
+// (readonly) => No se le puede asignar un valor fuera de @interface
+@property (readonly) NSString *roString; // utiliza @synthesize en
+ // @implementation para crear un accesor
+// Puedes personalizar el nombre del getter y del setter en lugar de utilizar
+// el nombre por defecto "set".
+@property (getter=lengthGet, setter=lengthSet:) int length;
+
+// Métodos
++/- (return type)methodSignature:(Parameter Type *)parameterName;
+
+// + Para métodos de clase:
++ (NSString *)classMethod;
++ (MyClass *)myClassFromHeight:(NSNumber *)defaultHeight;
+
+// - Para métodos de instancia:
+- (NSString *)instanceMethodWithParameter:(NSString *)string;
+- (NSNumber *)methodAParameterAsString:(NSString*)string andAParameterAsNumber:(NSNumber *)number;
+
+// Métodos de constructor con argumentos
+- (id)initWithDistance:(int)defaultDistance;
+// Los nombres de los métodos de Objective-C son muy descriptivos.
+// Siempre nombra los métodos de acuerdo con sus argumentos
+
+@end // Define el final de la interfaz
+
+
+// Para acceder a las variables públicas desde el archivo de implementación,
+// @property genera un método setter automáticamente. El nombre del método
+// es 'set' seguido de un nombre de variable @property:
+MyClass *myClass = [[MyClass alloc] init]; // Crea una instancia del objeto MyClass
+[myClass setCount:10];
+NSLog(@"%d", [myClass count]); // imprime => 10
+// O utilizando los métodos getter y setter personalizados en @interface:
+[myClass lengthSet:32];
+NSLog(@"%i", [myClass lengthGet]); // imprime => 32
+// Por conveniencia, puedes utilizar la notación de punto para asignar y
+// acceder a las variables de una instancia de objeto.
+myClass.count = 45;
+NSLog(@"%i", myClass.count); // imprime => 45
+
+// Llama a métodos de clase:
+NSString *classMethodString = [MyClass classMethod];
+MyClass *classFromName = [MyClass myClassFromName:@"Hello"];
+
+// Llama a métodos de instancia:
+MyClass *myClass = [[MyClass alloc] init]; // Crea una instancia de objeto Myclass
+NSString *stringFromInstanceMethod = [myClass instanceMethodWithParameter:@"Hello"];
+
+// Selectors
+// Una forma dinámica de representar métodos. Utilizados para llamar métodos
+// de una clase, pasar métodos a través de funciones para avisar a otras clases
+// para que lo llamen, y para guardar métodos como una variable.
+// SEL es el tipo de dato. @selector() devuelve un selector del nombre de
+// método proveído methodAparameterAsString:andAParameterAsNumber: es un nombre
+// para un método en MyClass
+SEL selectorVar = @selector(methodAParameterAsString:andAParameterAsNumber:);
+if ([myClass respondsToSelector:selectorVar]) { // Revisa si la clase contiene el método
+ // Debe de poner todos los argumentos de método en un solo objeto para mandar una
+ // función performSelector.
+ NSArray *arguments = [NSArray arrayWithObjects:@"Hello", @4, nil];
+ [myClass performSelector:selectorVar withObject:arguments]; // Calls the method
+} else {
+ // NSStringFromSelector() devuelve un NSString del nombre de método de un selector dado
+ NSLog(@"MyClass does not have method: %@", NSStringFromSelector(selectedVar));
+}
+
+// Implementa los métodos de un archivo de implementación (MyClass.m):
+@implementation MyClass {
+ long distance; // Variable de instancia de acceso privado
+ NSNumber height;
+}
+
+// Para acceder a una variable pública del archivo de interfaz, utiliza '_' seguido del
+// nombre de la variable:
+_count = 5; // Hace referencia a "int count" de la interfaz de MyClass
+// Accede variables definidas en el archivo de implementación:
+distance = 18; // Hace referencia a "long distance" de la implementación de MyClass
+// Para utilizar una variable @property en el archivo de implementación, utiliza
+// @synthesize para crear una variable de acceso:
+@synthesize roString = _roString; // _roString ahora está disponible en @implementation
+
+// Lamado antes de llamar algún método o instanciar cualquier objeto
++ (void)initialize
+{
+ if (self == [MyClass class]) {
+ distance = 0;
+ }
+}
+
+// Contraparte para inicializar un método. Llamado cuando el contador de referencias
+// del objeto es cero
+- (void)dealloc
+{
+ [height release]; // Si no utilizas ARC, asegúrate de liberar las variables de
+ // objeto de las clases
+ [super dealloc]; // y llama el método dealloc de la clase padre
+}
+
+// Los constructores son una manera de crear instancias de una clase
+// Este es el constructor por defecto que es llamado cuando el objeto es inicializado.
+- (id)init
+{
+ if ((self = [super init])) // 'super' es utilizado para acceder a los
+ // métodos de la clase padre.
+ {
+ self.count = 1; // 'self' es utilizado para que el objeto se llame a sí mismo.
+ }
+ return self;
+}
+// Se pueden crear constructores que contiene argumentos
+- (id)initWithDistance:(int)defaultDistance
+{
+ distance = defaultDistance;
+ return self;
+}
+
++ (NSString *)classMethod
+{
+ return @"Some string";
+}
+
++ (MyClass *)myClassFromHeight:(NSNumber *)defaultHeight
+{
+ height = defaultHeight;
+ return [[self alloc] init];
+}
+
+- (NSString *)instanceMethodWithParameter:(NSString *)string
+{
+ return @"New string";
+}
+
+- (NSNumber *)methodAParameterAsString:(NSString*)string andAParameterAsNumber:(NSNumber *)number
+{
+ return @42;
+}
+
+// Objective-C no tiene declaraciones de métodos privados, pero pueden ser simulados.
+// Para simular un método privado, crea un método en @implementation pero no en @interface.
+- (NSNumber *)secretPrivateMethod {
+ return @72;
+}
+[self secretPrivateMethod]; // Calls private method
+
+// Métodos declarados dentro de MyProtocol
+- (void)myProtocolMethod
+{
+ // statements
+}
+
+@end // Declara el final de la implementación
+
+///////////////////////////////////////
+// Categorías
+///////////////////////////////////////
+// Una categoría es un grupo de métodos diseñados para extender una clase.
+// Te permiten agregar nuevos métodos a una clase existente por propósitos
+// de organización. Éstos no deben de serconfundidos con subclases.
+// Las subclases existen para CAMBIAR la funcionalidad de un objeto mientras
+// que las categoríasle AGREGAN funcionalidad de un objeto.
+// Las categorías te permiten:
+// -- Agregar métodos a una clase existente por propósitos de oganización.
+// -- Extender clases de objetos de Objective-C (ejemplo: NSString) para
+// agregar tus propios métodos.
+// -- Agregar la habilidad de crear métodos protegidos y privados para las clases.
+// NOTA: No sobreescribas los métodos de las clases base en una categoría
+// aunque tengas la habilidad de poder hacerlo. Sobreescribir métodos puede
+// causar errores en la compilación después entre diferentes categorías y
+// puede arruinar el propósito de las categorías de solo AGREGAR funcionalidad.
+// Utiliza subclass para sobreescribir métodos.
+
+// Aquí una clase base simple, Car.
+@interface Car : NSObject
+
+@property NSString *make;
+@property NSString *color;
+
+- (void)turnOn;
+- (void)accelerate;
+
+@end
+
+// Y la implementación de la clase simple, Car
+#import "Car.h"
+
+@implementation Car
+
+@synthesize make = _make;
+@synthesize color = _color;
+
+- (void)turnOn {
+ NSLog(@"Car is on.");
+}
+- (void)accelerate {
+ NSLog(@"Accelerating.");
+}
+
+@end
+
+// Ahora, si quisieramos crear un objeto Truck (Camión), crearíamos una
+// subclase de Car (Carro) como si le cambiaramos de funcionalidad de Car
+// para que se comporte como un camión. Pero digamos que únicamente queremos
+// agregar funcionalidad al Car (Carro) existente. Un buen ejemplo sería
+// limpiar el carro. Así que crearíamos una cateog®iea para agregar los
+// métodos de limpieza:
+// Archivo @interface: Car+Clean.h (NombreBaseDeClase+NombreDeCategoria.h)
+#import "Car.h" // Asegúrate de improtar la clase que deseas extener.
+
+@interface Car (Clean) // El nombre de la categoría está dentro de (),
+ // seguido del nombre de la clase base
+
+- (void)washWindows; // Nombres de los nuevos métodos que le agregamos
+ // a nuestro objeto Car
+- (void)wax;
+
+@end
+
+// Archivo @implementation: Car+Clean.m (NombreBaseDeClase+NombreDeCategoria.m)
+#import "Car+Clean.h" // Importa el archivo de @interface de la categoría Clean
+
+@implementation Car (Clean)
+
+- (void)washWindows {
+ NSLog(@"Windows washed.");
+}
+- (void)wax {
+ NSLog(@"Waxed.");
+}
+
+@end
+
+// Cualquier instancia del objeto Car tiene la habilidad de utilizar una
+// categoría. Todo lo que necesitan es importarlo:
+#import "Car+Clean.h" // Importa todas las diferentes categorías que
+ // necesites utilizar
+#import "Car.h" // También debes de importar la clase base para su
+ // funcionalidad original
+
+int main (int argc, const char * argv[]) {
+ @autoreleasepool {
+ Car *mustang = [[Car alloc] init];
+ mustang.color = @"Red";
+ mustang.make = @"Ford";
+
+ [mustang turnOn]; // Utiliza métodos de la clase base Car.
+ [mustang washWindows]; // Utiliza métodos de la categoría Clean de Car.
+ }
+ return 0;
+}
+
+// Objective-C no tiene declaraciones para métodos protegidos, pero los puedes
+// simular. Crea una categoría conteniendo todos los métodos protegidos,
+// luego importa ÚNICAMENTE al archivo @implementation de una clase que
+// pertenece a la clase Car.
+@interface Car (Protected) // Nombrando la categoría 'Protected' para
+ // recordar que los métodos están protegidos
+
+- (void)lockCar; // Los métodos enlistados aquí solo puedens ser creados
+ // por objetos Car
+
+@end
+// Para utilizar los métodos protegidos, importa la categoría,
+// luego implementa sus métodos:
+#import "Car+Protected.h" // Recuerda, importa únicamente el archivo
+ // de @implementation
+
+@implementation Car
+
+- (void)lockCar {
+ NSLog(@"Car locked."); // Las instancias de Car no puede utilizar
+ // lockCar porque no se encuentra en @interface
+}
+
+@end
+
+///////////////////////////////////////
+// Extensiones
+///////////////////////////////////////
+// Las Extensions te permiten sobreescribir atributos de propiedades de
+// acceso público y métodos de un @interface
+// Archivo @interface: Shape.h
+@interface Shape : NSObject
+
+@property (readonly) NSNumber *numOfSides;
+
+- (int)getNumOfSides;
+
+@end
+// Puedes sobreescribir la variable numOfSides o el métodos getNumOfSlides
+// para modificarlos con una extensión:
+// Archivo @implementation: Shape.m
+#import "Shape.h"
+// Las extensiones se encuentran en el mismo archivo que el archivo
+// de @implementation
+@interface Shape () // () después del nombre de la clase base declara
+ // una extensión
+
+@property (copy) NSNumber *numOfSides; // Hacer numOfSlides copy en lugar
+ // de readonly.
+-(NSNumber)getNumOfSides; // Hacer que getNumOfSides devuelva un NSNumber
+ // en lugar de un int.
+-(void)privateMethod; // También puedes crear una nuevos métodos privados
+ // dentro de las extensiones
+
+@end
+// @implementation principal:
+@implementation Shape
+
+@synthesize numOfSides = _numOfSides;
+
+-(NSNumber)getNumOfSides { // Todas las declaraciones dentro de extensions
+ // deben de ser dentro de @implementation
+ return _numOfSides;
+}
+-(void)privateMethod {
+ NSLog(@"Private method created by extension. Shape instances cannot call me.");
+}
+
+@end
+
+///////////////////////////////////////
+// Protocolos
+///////////////////////////////////////
+// Un protocolo declara métodos que pueden ser implementados por cualquier otra
+// clase. Los protocolos no son clases. Simplementen define una interfaz que
+// otros objetos deben de implementar.
+// Archivo @protocol: "CarUtilities.h"
+@protocol CarUtilities <NSObject> // <NSObject> => Nombre de otro protocolo
+ // que se incluye en éste
+ @property BOOL engineOn; // La clase que lo adopta debe de utilizar
+ // @synthesize para todas las @properties definidas
+ - (void)turnOnEngine; // y todos los métodos definidos
+@end
+// A continuación una clase ejemplo que implementa el protcolo
+#import "CarUtilities.h" // Importar el archivo @protocol.
+
+@interface Car : NSObject <CarUtilities> // El nombre del protocolo dentro de <>
+ // No necesitas los nombres de @property o métodos aquí para CarUtilities.
+ // Estos solo es requerido por @implementation.
+- (void)turnOnEngineWithUtilities:(id <CarUtilities>)car; // También Puedes
+ // utilizar protocolos
+ // como datos.
+@end
+// El @implementation necesita que se implementen @properties y métodos
+// del protocolo.
+@implementation Car : NSObject <CarUtilities>
+
+@synthesize engineOn = _engineOn; // Crear una declaración @synthesize para el
+ // @property engineOn.
+
+- (void)turnOnEngine { // Implementa turnOnEngine como quieras. Los
+ // protocolos no definen
+ _engineOn = YES; // cómo implementas un método, con tal de que lo implementes.
+}
+// Puedes utilizar un protocolo como data mientras sepas quee métodos y variables
+// tiene implementado.
+- (void)turnOnEngineWithCarUtilities:(id <CarUtilities>)objectOfSomeKind {
+ [objectOfSomeKind engineOn]; // Tienes acceso a las variables
+ [objectOfSomeKind turnOnEngine]; // y los métodos del objeto
+ [objectOfSomeKind engineOn]; // Puede o no puede ser YES. La clase lo
+ // implementa como se quiera.
+}
+
+@end
+// Las instancias de Car ahora tienen acceso al protocolo.
+Car *carInstance = [[Car alloc] init];
+[carInstance setEngineOn:NO];
+[carInstance turnOnEngine];
+if ([carInstance engineOn]) {
+ NSLog(@"Car engine is on."); // imprime => "Car engine is on."
+}
+// Asegúrate de revisar si un objeto de tipo 'id' implementa un protocolo antes
+// de llamar a sus métodos:
+if ([myClass conformsToProtocol:@protocol(CarUtilities)]) {
+ NSLog(@"This does not run as the MyClass class does not implement the CarUtilities protocol.");
+} else if ([carInstance conformsToProtocol:@protocol(CarUtilities)]) {
+ NSLog(@"This does run as the Car class implements the CarUtilities protocol.");
+}
+// Las categorías también pueden implementar protcolos: @interface Car
+// (CarCategory) <CarUtilities>
+// Puedes implementar varios protocolos:
+// @interface Car : NSObject <CarUtilities, CarCleaning>
+// NOTA: Si dos o más protocolos dependen entre sí, asegúrate de declararlos
+// de manera adelantada:
+#import "Brother.h"
+
+@protocol Brother; // Declaración adelantada. Sin ésto, el compilador
+ // tira un error.
+
+@protocol Sister <NSObject>
+
+- (void)beNiceToBrother:(id <Brother>)brother;
+
+@end
+
+// Ver si el problema es que Sister depende de Brother,
+// y Brother dependa de Sister.
+#import "Sister.h"
+
+@protocol Sister; // Estas líneas detienen la recursión, resolviendo el problema.
+
+@protocol Brother <NSObject>
+
+- (void)beNiceToSister:(id <Sister>)sister;
+
+@end
+
+
+///////////////////////////////////////
+// Bloques
+///////////////////////////////////////
+// Los bloques son declaraciones de código, tal como una función, pueden
+// ser utilizados como data.
+// A continuación un bloque simple con un argumento entero que devuelve
+// un el argumento más 4.
+int (^addUp)(int n); // Declarar una variable para almacenar el bloque.
+void (^noParameterBlockVar)(void); // Ejemplo de una declaración de variable
+ // de bloque sin argumentos.
+// Los bloques tienen acceso a variables del mismo ámbito. Pero las variables
+// son solo readonly y el valor pasado al bloque es el valor de la variable
+// cuando el bloque es creado.
+int outsideVar = 17; // Si modificamos outsideVar después de declarar addUp,
+ // outsideVar AÚN es 17.
+__block long mutableVar = 3; // __block hace que las variables se puedan
+ // escribir en bloques.
+addUp = ^(int n) { // Remueve (int n) para tener un bloque que no recibe
+ // ningún parámetro
+ NSLog(@"You may have as many lines in a block as you would like.");
+ NSSet *blockSet; // También puedes declarar variables locales.
+ mutableVar = 32; // Asignar un nuevo valor a la variable __block.
+ return n + outsideVar; // Declaraciones de retorno son opcionales.
+}
+int addUp = add(10 + 16); // Llama al bloque de código con argumentos.
+// Los bloques son usualmente utilizados como argumentos a funciones que
+// son llamados más adelante o para callbacks.
+@implementation BlockExample : NSObject
+
+ - (void)runBlock:(void (^)(NSString))block {
+ NSLog(@"Block argument returns nothing and takes in a NSString object.");
+ block(@"Argument given to block to execute."); // Calling block.
+ }
+
+ @end
+
+
+///////////////////////////////////////
+// Manejo de memoria
+///////////////////////////////////////
+/*
+Para cada objeto utilizado en una aplicación, la memoria debe de ser alocada
+para ese objeto. Cuando la aplicación termina de utilizar ese objeto, la
+memoria debe de ser desalocada para asegurar la eficiencia de la aplicación.
+Objetive-C no utiliza garbage collection, y en lugar de eso utiliza conteos
+de referencias. Mientras haya al menos una referencia del objeto (también
+conocido como tener un objeto de adueñado), entonces el objeto estará
+disponible para su uso.
+
+Cuando una instancia es dueña un objeto, su contador de referencia incrementa
+por uno. Cuando el objeto es liberado, el contador de referencia decrementa uno.
+Cuando el conteo de referencia es cero, el objeto es removido de la memoria.
+
+Con todas las interacciones de los objetos, sigue el patrón de:
+(1) Crear e lobjeto, (2) utiliza el objeto, (3) libera el objeto de la memoria.
+*/
+
+MyClass *classVar = [MyClass alloc]; // 'alloc' asigna uno al conteo de
+ // referencias de classVar. Devuelve un
+ // puntero al objeto
+[classVar release]; // Decrementa el conteo de referencias de classVar's
+// 'retain'
+// 'retain' adueña la instancia de objeto existente e incrementa el conteo de
+// referencia por uno. Devuelve un puntero al objeto.
+MyClass *newVar = [classVar retain]; // Si classVar es liberado, el objeto
+ // aún se queda en memoria porque newVar
+ // es el dueño.
+[classVar autorelease]; // Remueve el adueñamiento de un objeto al final del
+ // bloque @autoreleasepool. Devuelve un puntero al objeto.
+
+// @property puede utilizar 'retain' y 'assign' también para pequeñas
+// definiciones convenientes
+@property (retain) MyClass *instance; // Libera el valor viejo y retiene
+ // uno nuevo (referencia fuerte)
+@property (assign) NSSet *set; // Apunta a un nuevo valor sin retener/liberar
+ // una referencia vieja (débil)
+
+// Conteo Automático de Referencias (ARC)
+// Debido a que el manejo de memoria puede ser un dolor, en Xcode 4.2 y iOS 4
+// se introdujo el Conteo Automático de Referencias (ARC).
+// ARC es una funcionalidad del compilador que agrega retain, release y
+// autorealase automáticamente, así que al
+// utilizar ARC, no se debe de utilizar retain, release o autorelease.
+MyClass *arcMyClass = [[MyClass alloc] init];
+// ... código utilizando arcMyClass
+// Sin ARC, necesitarás llamar: [arcMyClass release] luego de terminar de
+// utilizar arcMyClass. Pero con ARC, no hay necesidad. Insertará
+// automáticamente la declaración de liberación.
+
+// Mientras que para los atributos de @property 'assign' y 'retain', con ARC
+// utilizarás 'weak' y 'strong'
+@property (weak) MyClass *weakVar; // 'weak' no adueña el objeto. El conteo de
+ // referencias de la instancia original
+// es fijado a ceor, weakVar automáticamente recibe el valor de nil para
+// evitar cualquier 'crashing'.
+@property (strong) MyClass *strongVar; // 'strong' se adueña del objeto.
+ // Asegura que el objeto se quede en memoria.
+
+// Para variables regulares (no variables de @property), utiliza lo siguiente:
+__strong NSString *strongString; // Por defecto. La variables de retenida en
+ // memoria hasta que se salga del ámbito.
+__weak NSSet *weakSet; // Referencia débil a un objeto existente. Cuando el
+ // objeto existente es liberado, weakSet le es asginado
+ // un valor nil
+__unsafe_unretained NSArray *unsafeArray; // Como __weak, pero unsafeArray no
+ // es asginado a nil cuando el objeto
+ // existente es liberado.
+
+```
+## Lecturas sugeridas
+
+[Wikipedia Objective-C](http://es.wikipedia.org/wiki/Objective-C)
+
+[Programming with Objective-C. Libro PDF de Apple](https://developer.apple.com/library/ios/documentation/cocoa/conceptual/ProgrammingWithObjectiveC/ProgrammingWithObjectiveC.pdf)
+
+[iOS For High School Students: Getting Started](http://www.raywenderlich.com/5600/ios-for-high-school-students-getting-started)
diff --git a/es-es/php-es.html.markdown b/es-es/php-es.html.markdown
new file mode 100644
index 00000000..fa52353c
--- /dev/null
+++ b/es-es/php-es.html.markdown
@@ -0,0 +1,825 @@
+---
+language: PHP
+contributors:
+ - ["Malcolm Fell", "http://emarref.net/"]
+ - ["Trismegiste", "https://github.com/Trismegiste"]
+translators:
+ - ["Mario Pérez", "https://github.com/MarioPerezEsteso"]
+lang: es-es
+filename: learnphp-es.php
+---
+
+Este documento explica el funcionamiento de PHP 5+.
+
+```php
+<?php // El código PHP debe estar dentro de etiquetas <?php
+
+// Si tu fichero php solo contiene código php, es una buena práctica
+// omitir la etiqueta de cierre php para prevenir salidas acidentales.
+
+// Dos barras comienzan un comentario de una línea.
+
+# También lo hará una almohadilla, pero // es más común
+
+/*
+ Escribir texto entre una barra-asterisco y asterisco-barra
+ crea un comentario multilínea.
+*/
+
+// Utiliza "echo" o "print" para imprimir por pantalla
+print('Hola '); // Imprime "Hola " sin salto de línea
+
+// () son opcionales para print y echo
+echo "Mundo\n"; // Imprime "Mundo" con un salto de línea
+// (todas las sentencias deben finalizar con un punto y coma)
+
+// Cualquier cosa fuera de las etiquetas <?php se imprime automáticamente
+?>
+¡Hola Mundo de nuevo!
+<?php
+
+
+/************************************
+ * Tipos y variables
+ */
+
+// Las variables comienzan con el símbolo $.
+// Una variable válida comienza con una letra o guión bajo,
+// seguida de cualquier cantidad de letras, números o guiones bajos.
+
+// Las variables booleanas no distinguen entre mayúsculas o minúsculas
+$boolean = true; // o TRUE o True
+$boolean = false; // o FALSE o False
+
+// Enteros
+$int1 = 12; // => 12
+$int2 = -12; // => -12
+$int3 = 012; // => 10 (un 0 al comienzo declara un número octal)
+$int4 = 0x0F; // => 15 (un 0x al comienzo declara un hexadecimal)
+
+// Floats (también conocidos como doubles)
+$float = 1.234;
+$float = 1.2e3;
+$float = 7E-10;
+
+// Eliminar variable
+unset($int1);
+
+// Operaciones aritméticas
+$suma = 1 + 1; // 2
+$diferencia = 2 - 1; // 1
+$producto = 2 * 2; // 4
+$cociente = 2 / 1; // 2
+
+// Operaciones aritméticas de escritura rápida
+$numero = 0;
+$numero += 1; // Incrementa $numero en 1
+echo $numero++; // Imprime 1 (incremento después la evaluación)
+echo ++$numero; // Imprime 3 (incremento antes de la evaluación)
+$numero /= $float; // Divide y asigna el cociente a $numero
+
+// Las cadenas de caracteres deben declararse entre comillas simples
+$sgl_quotes = '$String'; // => '$String'
+
+// Evita utilizar comillas dobles excepto para embeber otras variables
+$dbl_quotes = "This is a $sgl_quotes."; // => 'This is a $String.'
+
+// Los caracteres especiales solo son válidos entre comillas dobles
+$escaped = "Esto contiene \t un caracter tabulador.";
+$unescaped = 'Esto solo contiene una barra y una t: \t';
+
+// Rodea una variable entre corchetes si es necesario
+$dinero = "Tengo $${numero} en el banco.";
+
+// Desde PHP 5.3, los nowdocs pueden ser utilizados para multilíneas no interpoladas
+$nowdoc = <<<'END'
+Multi line
+string
+END;
+
+// Heredocs interpola cadenas de caracteres
+$heredoc = <<<END
+Multi line
+$sgl_quotes
+END;
+
+// La concatenación de cadenas de caracteres se realiza con .
+echo 'Esta cadena de caracteres ' . 'está concatenada';
+
+// Las cadenas de caracteres pueden ser pasadas como parámetros en un echo
+echo 'Multiples', 'Parametros', 'Validos'; // Devuelve 'MultiplesParametrosValidos'
+
+
+/********************************
+ * Constantes
+ */
+
+// Una constante se define utilizando define()
+// y nunca puede ser cambiada en tiempo de ejecución
+
+// un nombre válido para una constante debe comenzar con una letra o guión bajo,
+// seguido por cualquier número de letras, números o guiones bajos.
+define("FOO", "algo");
+
+// el acceso a una constante se puede realizar llamando a la variable elegida sin un símbolo de $
+echo FOO; // Devuelve 'algo'
+echo 'Esto imprime '.FOO; // Devuelve 'Esto imprime algo'
+
+
+
+/********************************
+ * Arrays
+ */
+
+// Todos los arrays en PHP son asociativos (hashmaps),
+
+// Los arrays asociativos son conocidos como hashmaps en algunos lenguajes.
+
+// Funciona con todas las versiones de php
+$asociativo = array('Uno' => 1, 'Dos' => 2, 'Tres' => 3);
+
+// PHP 5.4 introdujo una nueva sintaxis
+$asociativo = ['Uno' => 1, 'Dos' => 2, 'Tres' => 3];
+
+echo $asociativo['Uno']; // imprime 1
+
+// Lista literales implícitamente asignados con claves enteras
+$array = ['Uno', 'Dos', 'Tres'];
+echo $array[0]; // => "Uno"
+
+// Añadir un elemento al final de un array
+$array[] = 'Cuatro';
+// o
+array_push($array, 'Cinco');
+
+// Eliminar un elemento de un array
+unset($array[3]);
+
+/********************************
+ * Salidas por pantalla
+ */
+
+echo('¡Hola Mundo!');
+// Imprime ¡Hola Mundo! en stdout.
+// Stdout es la página web si se está ejecutando en un navegador.
+
+print('!Hola Mundo!'); // Es lo mismo que echo
+
+// No es necesario el paréntesis en echo y print
+echo '¡Hola Mundo!';
+print '¡Hola Mundo!';
+
+$parrafo = 'parrafo';
+
+echo 100; // Haz echo de escalares directamente
+echo $parrafo; // o de variables
+
+// Si las etiquetas cortas estás configuradas y tu versión de PHP es
+// la 5.4.0 o superior, puede utilizar la sintaxis abreviada de echo
+?>
+<p><?= $parrafo?></p>
+<?php
+
+$x = 1;
+$y = 2;
+$x = $y; // $x ahora contiene el mismo valor que $y
+$z = &$y;
+// $z contiene ahora una referencia a $y. Un cambio en el valor de
+// $z cambiará también el valor de $y, y viceversa.
+// $x sin embargo, tendrá el valor original de $y
+
+echo $x; // => 2
+echo $z; // => 2
+$y = 0;
+echo $x; // => 2
+echo $z; // => 0
+
+// Dump muestra el tipo y valor de una variable en stdout
+var_dump($z); // imprime int(0)
+
+// Para mostrar el valor de una variable en un formato legible para humanos
+print_r($array); // imprime: Array ( [0] => Uno [1] => Dos [2] => Tres )
+
+/********************************
+ * Lógica
+ */
+$a = 0;
+$b = '0';
+$c = '1';
+$d = '1';
+
+// assert lanza una advertencia si su argumento no es verdadero
+
+// Estas comparaciones siempre serán verdaderas, incluso si los tipos no son los mismos.
+assert($a == $b); // igualdad
+assert($c != $a); // desigualdad
+assert($c <> $a); // desigualdad alternativa
+assert($a < $c);
+assert($c > $b);
+assert($a <= $b);
+assert($c >= $d);
+
+// Los siguiente solo será verdadero si los valores coinciden y son del mismo tipo.
+assert($c === $d);
+assert($a !== $d);
+assert(1 === '1');
+assert(1 !== '1');
+
+// Operador 'Spaceship' (desde PHP 7)
+// Devuelve 0 si ambos valores son iguales
+// Devuelve 1 si el valor de la izquierda es mayor
+// Devuelve -1 si el valor de la derecha es mayor
+
+$a = 100;
+$b = 1000;
+
+echo $a <=> $a; // 0 porque son iguales
+echo $a <=> $b; // -1 porque $a < $b
+echo $b <=> $a; // 1 porque $b > $a
+
+// Las variables pueden ser convertidas entre tipos, dependiendo de su uso.
+
+$entero = 1;
+echo $entero + $entero; // => 2
+
+$string = '1';
+echo $string + $string; // => 2 (los strings son convertidos a enteros)
+
+$string = 'uno';
+echo $string + $string; // => 0
+// Muestra un 0 porque el operador + no puede convertir la cadena de caracteres 'uno' a un número
+
+// La conversión de tipos puede ser utilizada para tratar a una variable como otro tipo
+
+$boolean = (boolean) 1; // => true
+
+$cero = 0;
+$boolean = (boolean) $cero; // => false
+
+// También hay funciones dedicadas a la conversión de tipos
+$entero = 5;
+$string = strval($entero);
+
+$var = null; // Valor nulo
+
+
+/********************************
+ * Estructuras de control
+ */
+
+if (true) {
+ print 'He sido imprimido';
+}
+
+if (false) {
+ print 'Yo no';
+} else {
+ print 'He sido imprimido';
+}
+
+if (false) {
+ print 'No se imprime';
+} elseif(true) {
+ print 'Sí se imprime';
+}
+
+// operador ternario
+print (false ? 'No se imprime' : 'Sí se imprime');
+
+// atajo para el operador ternario desde PHP 5.3
+// equivalente de "$x ? $x : 'Sí'""
+$x = false;
+print($x ?: 'Sí');
+
+// operador 'no definido' desde php 7
+$a = null;
+$b = 'Imprime';
+echo $a ?? 'a no está definido'; // imprime 'a no está definido'
+echo $b ?? 'b no está definido'; // imprime 'Imprime'
+
+
+$x = 0;
+if ($x === '0') {
+ print 'No imprime';
+} elseif($x == '1') {
+ print 'No imprime';
+} else {
+ print 'Imprime';
+}
+
+
+
+// Esta sintaxis alternativa se utiliza para plantillas:
+?>
+
+<?php if ($x): ?>
+Esto se muestra si la evaluación es verdadera.
+<?php else: ?>
+En otro caso, se muestra esto.
+<?php endif; ?>
+
+<?php
+
+// Utiliza el switch para tener algo más de lógica.
+switch ($x) {
+ case '0':
+ print 'Switch does type coercion';
+ break; // Debes incluir un break para no seguir con los casos 'Dos' y 'Tres'
+ case 'Dos':
+ case 'Tres':
+ // Hacer algo si la variables es 'Dos' o 'Tres'
+ break;
+ default:
+ // Hacer algo por defecto
+}
+
+// Los bucles While, do...while y for te serán familiares
+$i = 0;
+while ($i < 5) {
+ echo $i++;
+}; // Imprime "01234"
+
+echo "\n";
+
+$i = 0;
+do {
+ echo $i++;
+} while ($i < 5); // Imprime "01234"
+
+echo "\n";
+
+for ($x = 0; $x < 10; $x++) {
+ echo $x;
+} // Imprime "0123456789"
+
+echo "\n";
+
+$ruedas = ['bicicleta' => 2, 'coche' => 4];
+
+// Los bucles foreach pueden iterar por arrays
+foreach ($ruedas as $numero_ruedas) {
+ echo $numero_ruedas;
+} // Imprime "24"
+
+echo "\n";
+
+// También se puede iterar sobre las claves, así como sobre los valores
+foreach ($ruedas as $vehiculo => $numero_ruedas) {
+ echo "Un $vehiculo tiene $numero_ruedas ruedas";
+}
+
+echo "\n";
+
+$i = 0;
+while ($i < 5) {
+ if ($i === 3) {
+ break; // Sale fuera del bucle while
+ }
+ echo $i++;
+} // Imprime "012"
+
+for ($i = 0; $i < 5; $i++) {
+ if ($i === 3) {
+ continue; // Se salta esta iteración del bucle
+ }
+ echo $i;
+} // Imprime "0124"
+
+
+/********************************
+ * Funciones
+ */
+
+// Define una función con "function":
+function mi_funcion () {
+ return 'Hola';
+}
+
+echo mi_funcion(); // => "Hola"
+
+// Un nombre válido de función comienza con una letra o guión bajo, seguido de cualquier
+// número de letras, números o guiones bajos.
+
+function anadir ($x, $y = 1) { // $y es opcional y por defecto es 1
+ $resultado = $x + $y;
+ return $resultado;
+}
+
+echo anadir(4); // => 5
+echo anadir(4, 2); // => 6
+
+// $resultado no es accesible fuera de la función
+// print $resultado; // Devuelve una advertencia.
+
+// Desde PHP 5.3 se pueden declarar funciones anónimas
+$inc = function ($x) {
+ return $x + 1;
+};
+
+echo $inc(2); // => 3
+
+function foo ($x, $y, $z) {
+ echo "$x - $y - $z";
+}
+
+// Las funciones pueden devolver funciones
+function bar ($x, $y) {
+ // Utiliza 'use' para meter variables de fuera de la función
+ return function ($z) use ($x, $y) {
+ foo($x, $y, $z);
+ };
+}
+
+$bar = bar('A', 'B');
+$bar('C'); // Imprime "A - B - C"
+
+// Puedes llamar a funciones utilizando cadenas de caracteres
+$nombre_funcion = 'add';
+echo $nombre_funcion(1, 2); // => 3
+// Es útil para determinarl qué función ejecutar.
+// O, utiliza call_user_func(callable $callback [, $parameter [, ... ]]);
+
+
+// Puedes obtener todos los parámetros pasados a una función
+function parametros() {
+ $numero_argumentos = func_num_args();
+ if ($numero_argumentos > 0) {
+ echo func_get_arg(0) . ' | ';
+ }
+ $args_array = func_get_args();
+ foreach ($args_array as $key => $arg) {
+ echo $key . ' - ' . $arg . ' | ';
+ }
+}
+
+parametros('Hola', 'Mundo'); // Hola | 0 - Hola | 1 - Mundo |
+
+// Desde PHP 5.6 se puede obtener un número variable de argumentos
+function variable($palabra, ...$lista) {
+ echo $palabra . " || ";
+ foreach ($lista as $item) {
+ echo $item . ' | ';
+ }
+}
+
+variable("Separa", "Hola", "Mundo") // Separa || Hola | Mundo |
+
+/********************************
+ * Includes
+ */
+
+<?php
+// Los ficheros PHP incluidos deben comenzar también con la etiqueta de <?php
+
+include 'mi-fichero.php';
+// El código de mi-fichero.php ya está disponible en el entorno actual.
+// Si el fichero no puede ser incluido (por ejemplo porque no se ha encontrado),
+// se muestra una advertencia.
+
+include_once 'mi-fichero.php';
+// Si el código del fichero mi-fichero.php ya ha sido incluido, ya no se
+// incluirá de nuevo. Este previene errores por múltiples declaraciones.
+
+require 'mi-fichero.php';
+require_once 'mi-fichero.php';
+// Es lo mismo que el include(), pero require() causará un error fatal si el archivo
+// no ha podido ser incluido.
+
+// Contenido de mi-include.php:
+<?php
+
+return 'Cualquier cosa.';
+// acabar archivo
+
+// Los include y require también pueden devolver un valor.
+$valor = include 'mi-include.php';
+
+// Los archivos son incluidos en función de la ruta data o, si ninguna ruta es
+// especificada se utilizará la directiva de configuración de include_path. Si el
+// fichero no se encuentra en el include_path, include comprobará la ruta del código
+// que lo llama antes de fallar.
+/* */
+
+/********************************
+ * Clases
+ */
+
+// Las clases son definidas con la palabra clave class
+
+class MiClase
+{
+ const MI_CONSTANTE = 'valor'; // Una constante
+
+ static $staticVar = 'static';
+
+ // Las variables estáticas y su visibilidad
+ public static $publicStaticVar = 'publicStatic';
+ // Accesible solo dentro de su clase
+ private static $privateStaticVar = 'privateStatic';
+ // Accesible desde la clase y las subclases
+ protected static $protectedStaticVar = 'protectedStatic';
+
+ // Las propiedades deben declarar su visibilidad
+ public $propiedad = 'public';
+ public $instanceProp;
+ protected $prot = 'protected'; // Accesible desde la clase y las subclases
+ private $priv = 'private'; // Accesible solo desde la clase
+
+ // Crear un constructor con __construct
+ public function __construct($instanceProp) {
+ // Accede a las variables de la instancia con $this
+ $this->instanceProp = $instanceProp;
+ }
+
+ // Los métodos son declarados como funciones dentro de una clase
+ public function miMetodo()
+ {
+ print 'MiClase';
+ }
+
+ // la palabra clave final hará una función no sobreescribible
+ final function noMePuedesSobreEscribir()
+ {
+ }
+
+/*
+ * Declarar propiedades de clase o métodos como estáticos los hace accesibles sin
+ * necesidad de instanciar la clase. Una propiedad declarada como estática no
+ * puede ser accedida mediante una instancia de la clase, pero sí mediante un
+ * método estático.
+ */
+
+ public static function miMetodoEstatico()
+ {
+ print 'Soy estático';
+ }
+}
+
+// Las constantes de una clase siempre pueden ser accedidas estáticamente
+echo MiClase::MI_CONSTANTE; // Muestra 'valor';
+
+echo MiClase::$staticVar; // Muestra 'static';
+MiClase::miMetodoEstatico(); // Muestra 'Soy estático';
+
+// Instancia una clase usando new
+$mi_clase = new MiClase('Una instancia');
+// Los paréntesis son opcionales si no se pasa ningún argumento.
+
+// Accede a los miembros de una clase utilizando ->
+echo $mi_clase->propiedad; // => "public"
+echo $mi_clase->instanceProp; // => "Una instancia"
+$mi_clase->miMetodo(); // => "MiClase"
+
+
+// Extender clases utilizando "extends"
+class MiOtraClase extends MiClase
+{
+ function imprimePropiedadProtegida()
+ {
+ echo $this->prot;
+ }
+
+ // Sobreescribe un método
+ function miMetodo()
+ {
+ parent::miMetodo();
+ print ' > MiOtraClase';
+ }
+}
+
+$mi_otra_clase = new MiOtraClase('Propiedad de instancia');
+$mi_otra_clase->imprimePropiedadProtegida(); // => Imprime "protected"
+$mi_otra_clase->miMetodo(); // Imprime "MiClase > MiOtraClase"
+
+final class NoMePuedesExtender
+{
+}
+
+// Puedes utilizar "métodos mágicos" para crear los getters y setters
+class MiClaseMapeada
+{
+ private $propiedad;
+
+ public function __get($key)
+ {
+ return $this->$key;
+ }
+
+ public function __set($key, $value)
+ {
+ $this->$key = $value;
+ }
+}
+
+$x = new MiClaseMapeada();
+echo $x->propiedad; // Utilizará el método __get()
+$x->propiedad = 'Algo'; // Utilizará el método __set()
+
+// Las clases pueden ser abstractas (utilizando la palabra clave abstract) o
+// implementando interfaces (utilizando la palabra clave implements).
+// Una interfaz puede ser declarada con la palabra clave interface.
+
+interface InterfazUno
+{
+ public function hazAlgo();
+}
+
+interface InterfazDos
+{
+ public function hazOtraCosa();
+}
+
+// las interfaces pueden ser extendidas
+interface InterfazTres extends InterfazDos
+{
+ public function hazCualquierOtraCosa();
+}
+
+abstract class MiClaseAbstracta implements InterfazUno
+{
+ public $x = 'hazAlgo';
+}
+
+class MiOtraClase extends MiClaseAbstracta implements InterfazDos
+{
+ public function hazAlgo()
+ {
+ echo $x;
+ }
+
+ public function hazOtraCosa()
+ {
+ echo 'hazOtraCosa';
+ }
+}
+
+
+// Las clases pueden implementar más de una interfaz
+class CualquierOtraClase implements InterfazUno, InterfazDos
+{
+ public function hazAlgo()
+ {
+ echo 'hazAlgo';
+ }
+
+ public function hazOtraCosa()
+ {
+ echo 'hazOtraCosa';
+ }
+}
+
+
+/********************************
+ * Traits
+ */
+
+// Los traits están disponibles desde PHP 5.4.0 y son declarados utilizando "trait"
+
+trait MiTrait
+{
+ public function miMetodoTrait()
+ {
+ print 'Tengo trait';
+ }
+}
+
+class MiClaseTrait
+{
+ use MiTrait;
+}
+
+$cls = new MiClaseTrait();
+$cls->miMetodoTrait(); // Imprime "Tengo trait"
+
+
+/********************************
+ * Namespaces
+ */
+
+// Esta sección está separada porque una declaración de namespace debe
+// ser la primera sentencia en un archivo. Vamos a suponer que no es el caso
+
+<?php
+
+// Por defecto, las clases existen en el namespace global y pueden ser llamadas
+// explícitamente con una contrabarra.
+
+$cls = new \MiClase();
+
+
+
+// Estableder el namespace para un archivo
+namespace Mi\Namespace;
+
+class MiClase
+{
+}
+
+// (de otro archivo)
+$cls = new Mi\Namespace\MiClase;
+
+// O de otro namespace.
+namespace Mi\Otro\Namespace;
+
+use Mi\Namespace\MiClase;
+
+$cls = new MiClase();
+
+// O se puede asignar un ales al namespace
+
+namespace Mi\Otro\Namespace;
+
+use Mi\Namespace as OtroNamespace;
+
+$cls = new OtroNamespace\MiClase();
+
+
+/**********************
+* Late Static Binding
+*
+*/
+
+class ClasePadre {
+ public static function quien() {
+ echo "Soy una " . __CLASS__ . "\n";
+ }
+ public static function test() {
+ // Auto referencia a la clase en la que el método está definido
+ self::quien();
+ // Referencia estáticamente a la clase donde el método ha sido llamado
+ static::quien();
+ }
+}
+
+ClasePadre::test();
+/*
+Soy una ClasePadre
+Soy una ClasePadre
+*/
+
+class ClaseHija extends ClasePadre {
+ public static function quien() {
+ echo "Pero soy una " . __CLASS__ . "\n";
+ }
+}
+
+ClaseHija::test();
+/*
+Soy una ClasePadre
+Pero soy una ClaseHija
+*/
+
+
+/**********************
+* Manejo de errores
+*
+*/
+
+// Una simple gestión de errores puede ser realizada con un bloque try catch
+
+try {
+ // Haz algo
+} catch (Exception $e) {
+ // Maneja la excepción
+}
+
+// Cuando se utilicen bloques try catch en un entorno con namespaces hay que
+// usar lo siguiente
+
+try {
+ // Haz algo
+} catch (\Exception $e) {
+ // Maneja la excepción
+}
+
+// Excepciones personalizadas
+
+class MiExcepcion extends Exception {}
+
+try {
+
+ $condicion = true;
+
+ if ($condicion) {
+ throw new MiExcepcion('Ha pasado algo');
+ }
+
+} catch (MiExcepcion $e) {
+ // Manejar la excepción
+}
+
+```
+
+## Más información
+
+Visita la [documentación oficial de PHP](http://www.php.net/manual/) para más referencias
+y apoyo de la comunidad.
+
+Si estás interesado en buenas prácticas, visita
+[PHP The Right Way](http://www.phptherightway.com/).
+
+Si vienes de un lenguaje con una buena gestión de paquetes, visita
+[Composer](http://getcomposer.org/).
+
+Para estándares comunes, visita el PHP Framework Interoperability Group
+[PSR standards](https://github.com/php-fig/fig-standards).
diff --git a/es-es/python-es.html.markdown b/es-es/python-es.html.markdown
index 4930eebc..a27203d1 100644
--- a/es-es/python-es.html.markdown
+++ b/es-es/python-es.html.markdown
@@ -9,8 +9,8 @@ lang: es-es
filename: learnpython-es.py
---
-Python fue creado por Guido Van Rossum en el principio de los 90'. Ahora es uno
-de los lenguajes más populares en existencia. Me enamoré de Python por su claridad sintáctica.
+Python fue creado por Guido Van Rossum en el principio de los 90. Ahora es uno
+de los lenguajes más populares que existen. Me enamoré de Python por su claridad sintáctica.
Es básicamente pseudocódigo ejecutable.
¡Comentarios serán muy apreciados! Pueden contactarme en [@louiedinh](http://twitter.com/louiedinh) o louiedinh [at] [servicio de email de google]
@@ -19,8 +19,8 @@ Nota: Este artículo aplica a Python 2.7 específicamente, pero debería ser apl
```python
# Comentarios de una línea comienzan con una almohadilla (o signo gato)
-""" Strings multilinea pueden escribirse
- usando tres "'s, y comunmente son usados
+""" Strings multilínea pueden escribirse
+ usando tres "'s, y comúnmente son usados
como comentarios.
"""
@@ -48,7 +48,7 @@ Nota: Este artículo aplica a Python 2.7 específicamente, pero debería ser apl
# Resultado de la división de enteros truncada para positivos y negativos
5 // 3 # => 1
-5.0 // 3.0 # => 1.0 # funciona con números en coma flotante
+5.0 // 3.0 # => 1.0 # funciona con números de coma flotante
-5 // 3 # => -2
-5.0 // 3.0 # => -2.0
@@ -436,7 +436,7 @@ class Humano(object):
def get_especie(cls):
return cls.especie
- # Un metodo estatico es llamado sin la clase o instancia como referencia
+ # Un metodo estático es llamado sin la clase o instancia como referencia
@staticmethod
def roncar():
return "*roncar*"
@@ -507,7 +507,7 @@ def duplicar_numeros(iterable):
# Nota: xrange es un generador que hace lo mismo que range.
# Crear una lista de 1 a 900000000 lleva mucho tiempo y ocupa mucho espacio.
# xrange crea un generador, mientras que range crea toda la lista.
-# Añadimos un guion bajo a los nombres de variable que coinciden con palabras
+# Añadimos un guión bajo a los nombres de variable que coinciden con palabras
# reservadas de python.
xrange_ = xrange(1, 900000000)
diff --git a/es-es/python3-es.html.markdown b/es-es/python3-es.html.markdown
index 1c69481a..05fd7065 100644
--- a/es-es/python3-es.html.markdown
+++ b/es-es/python3-es.html.markdown
@@ -97,7 +97,7 @@ not False # => True
None # => None
# No uses el símbolo de igualdad `==` para comparar objetos con None
-# Usa `is` en lugar de
+# Usa `is` en su lugar
"etc" is None #=> False
None is None #=> True
@@ -383,7 +383,7 @@ def keyword_args(**kwargs):
keyword_args(pie="grande", lago="ness") #=> {"pie": "grande", "lago": "ness"}
-# You can do both at once, if you like# Puedes hacer ambas a la vez si quieres
+# Puedes hacer ambas a la vez si quieres
def todos_los_argumentos(*args, **kwargs):
print args
print kwargs
@@ -478,7 +478,7 @@ Humano.roncar() #=> "*roncar*"
# Puedes importar módulos
import math
-print(math.sqrt(16)) #=> 4
+print(math.sqrt(16)) #=> 4.0
# Puedes obtener funciones específicas desde un módulo
from math import ceil, floor
@@ -511,7 +511,7 @@ def duplicar_numeros(iterable):
for i in iterable:
yield i + i
-# Un generador cera valores sobre la marcha.
+# Un generador crea valores sobre la marcha.
# En vez de generar y retornar todos los valores de una vez, crea uno en cada iteración.
# Esto significa que valores más grandes que 15 no serán procesados en 'duplicar_numeros'.
# Fíjate que 'range' es un generador. Crear una lista 1-900000000 tomaría mucho tiempo en crearse.
diff --git a/es-es/r-es.html.markdown b/es-es/r-es.html.markdown
new file mode 100644
index 00000000..2b710b27
--- /dev/null
+++ b/es-es/r-es.html.markdown
@@ -0,0 +1,717 @@
+---
+language: R
+contributors:
+ - ["e99n09", "http://github.com/e99n09"]
+ - ["isomorphismes", "http://twitter.com/isomorphisms"]
+translators:
+ - ["David Hsieh", "http://github.com/deivuh"]
+lang: es-es
+filename: learnr-es.r
+---
+
+R es un lenguaje de computación estadística. Tiene muchas librerías para cargar
+y limpiar sets de datos, ejecutar procedimientos estadísticos y generar
+gráficas. También puedes ejecutar comandos `R` dentro de un documento de
+LaTeX.
+
+```r
+
+# Los comentariso inician con símbolos numéricos.
+
+# No puedes hacer comentarios de múltiples líneas
+# pero puedes agrupar múltiples comentarios de esta manera.
+
+# En Windows puedes utilizar CTRL-ENTER para ejecutar una línea.
+# En Mac utilizas COMMAND-ENTER
+
+
+#############################################################################
+# Cosas que puedes hacer sin entender nada acerca de programación
+#############################################################################
+
+# En esta sección, mostramos algunas cosas chileras / cool que puedes hacer en
+# R sin entender nada de programación. No te preocupes en entender nada
+# de lo que hace este código. Solo disfruta!
+
+data() # Examinar sets de datos pre-cargados
+data(rivers) # Obtiene este: Lengths of Major North American Rivers"
+ls() # Fijarse que "rivers" ahora aparece en el workspace
+head(rivers) # Echarle un ojo al set de datos
+# 735 320 325 392 524 450
+
+length(rivers) # ¿Cuántos ríos fueron medidos?
+# 141
+summary(rivers) # ¿Cuáles son algunas estadísticas generales?
+# Min. 1st Qu. Median Mean 3rd Qu. Max.
+# 135.0 310.0 425.0 591.2 680.0 3710.0
+
+# Generar una gráfica tallo-y-hoja (Visualización de datos tipo histograma)
+stem(rivers)
+
+# El punto decimal son 2 dígitos a la derecha de |
+#
+# 0 | 4
+# 2 | 011223334555566667778888899900001111223333344455555666688888999
+# 4 | 111222333445566779001233344567
+# 6 | 000112233578012234468
+# 8 | 045790018
+# 10 | 04507
+# 12 | 1471
+# 14 | 56
+# 16 | 7
+# 18 | 9
+# 20 |
+# 22 | 25
+# 24 | 3
+# 26 |
+# 28 |
+# 30 |
+# 32 |
+# 34 |
+# 36 | 1
+
+stem(log(rivers)) # Fijarse que la data no es normal ni log-normal!
+# Toma eso, fundamentalistas de la curva de campana!
+
+# El punto decimal está a 1 dígito a la izquierda del |
+#
+# 48 | 1
+# 50 |
+# 52 | 15578
+# 54 | 44571222466689
+# 56 | 023334677000124455789
+# 58 | 00122366666999933445777
+# 60 | 122445567800133459
+# 62 | 112666799035
+# 64 | 00011334581257889
+# 66 | 003683579
+# 68 | 0019156
+# 70 | 079357
+# 72 | 89
+# 74 | 84
+# 76 | 56
+# 78 | 4
+# 80 |
+# 82 | 2
+
+# Generar un histograma:
+hist(rivers, col="#333333", border="white", breaks=25) # Juega con los estos parámetros
+hist(log(rivers), col="#333333", border="white", breaks=25) # Generarás más gráficas después
+
+# Aquí hay otro set de datos pre-cargado. R tiene bastantes de éstos.
+data(discoveries)
+plot(discoveries, col="#333333", lwd=3, xlab="Year",
+ main="Number of important discoveries per year")
+plot(discoveries, col="#333333", lwd=3, type = "h", xlab="Year",
+ main="Number of important discoveries per year")
+
+# En lugar de dejar el orden por defecto (por año),
+# podemos ordenar de tal manera que muestre qué es típico:
+sort(discoveries)
+# [1] 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2
+# [26] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 3 3
+# [51] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 4 4 4 4 4 4 4 4
+# [76] 4 4 4 4 5 5 5 5 5 5 5 6 6 6 6 6 6 7 7 7 7 8 9 10 12
+
+stem(discoveries, scale=2)
+#
+# El punto decimal se encuentra en |
+#
+# 0 | 000000000
+# 1 | 000000000000
+# 2 | 00000000000000000000000000
+# 3 | 00000000000000000000
+# 4 | 000000000000
+# 5 | 0000000
+# 6 | 000000
+# 7 | 0000
+# 8 | 0
+# 9 | 0
+# 10 | 0
+# 11 |
+# 12 | 0
+
+max(discoveries)
+# 12
+summary(discoveries)
+# Min. 1st Qu. Median Mean 3rd Qu. Max.
+# 0.0 2.0 3.0 3.1 4.0 12.0
+
+# Tirar los dados varias veces
+round(runif(7, min=.5, max=6.5))
+# 1 4 6 1 4 6 4
+# Tus números será diferente de los míos, a menos que tengamos el mismo valor
+# de random.seed(31337)
+
+# Dibuja de un Gaussian 9 veces
+rnorm(9)
+# [1] 0.07528471 1.03499859 1.34809556 -0.82356087 0.61638975 -1.88757271
+# [7] -0.59975593 0.57629164 1.08455362
+
+
+
+##################################################
+# Tipos de datos y aritmética básica
+##################################################
+
+# Ahora para la parte de programación orientada a objetos del tutorial.
+# En esta sección conocerás los tipos de datos importantes de R:
+# Enteros, numéricos, caracteres, lógicos, y factores.
+# Hay otros, pero esos son los que menos necesitas para empezar.
+
+# ENTEROS
+# Enteros de almacenamiento largo son escritos con L
+5L # 5
+class(5L) # "integer"
+# (Try ?class para más información en la función class().)
+# En R, cada valor único, como 5L, es considerado un vector de logitud 1
+length(5L) # 1
+# También puedes tener un vector de enteros con longitud > 1:
+c(4L, 5L, 8L, 3L) # 4 5 8 3
+length(c(4L, 5L, 8L, 3L)) # 4
+class(c(4L, 5L, 8L, 3L)) # "integer"
+
+# NUMÉRICOS
+# Un "numérico" es un número de punto flotante de doble precisión.
+5 # 5
+class(5) # "numeric"
+# Nuevamente, todo en R es un vector;
+# puedes hacer un vector numérico con más de un elemento
+c(3,3,3,2,2,1) # 3 3 3 2 2 1
+# También puedes utilizar el notación científica
+5e4 # 50000
+6.02e23 # Número de Avogadro
+1.6e-35 # Logintud Planck
+# También puedes tener números infinitamente grandes o pequeños
+class(Inf) # "numeric"
+class(-Inf) # "numeric"
+# Puede que uses "Inf", por ejemplo, en integrate(dnorm, 3, Inf);
+# esto obvia las tablas de puntos Z.
+
+# ARITMÉTICA BÁSICA
+# Puedes hacer aritmética con números
+# Haciendo aritmética en un mix de enteros y numéricos, te da otro numérico
+10L + 66L # 76 # entero mas entero da entero
+53.2 - 4 # 49.2 # entero menos entero da numérico
+2.0 * 2L # 4 # numérico veces entero da numérico
+3L / 4 # 0.75 # entero sobre numérico da numérico
+3 %% 2 # 1 # el residuo de dos numéricos es otro numérico
+# La aritmética ilegal rinde un "not-a-number"
+0 / 0 # NaN
+class(NaN) # "numeric"
+# Puedes hacer aritmética con dos vectores con longitud mayor a 1,
+# siempre que la longitud del vector mayor es un entero múltiplo del menor.
+c(1,2,3) + c(1,2,3) # 2 4 6
+
+# CARACTERES
+# No hay diferencia entre strings y caracteres en R
+"Horatio" # "Horatio"
+class("Horatio") # "character"
+class('H') # "character"
+# Ambos eran vectores de caracteres de longitud 1
+# Aquí hay uno más largo:
+c('alef', 'bet', 'gimmel', 'dalet', 'he')
+# =>
+# "alef" "bet" "gimmel" "dalet" "he"
+length(c("Call","me","Ishmael")) # 3
+# Puedes hacer operaciones regex en vectores de caracteres:
+substr("Fortuna multis dat nimis, nulli satis.", 9, 15) # "multis "
+gsub('u', 'ø', "Fortuna multis dat nimis, nulli satis.") # "Fortøna møltis dat nimis, nølli satis."
+# R tiene varios vectores predefinidos de caracteres
+letters
+# =>
+# [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s"
+# [20] "t" "u" "v" "w" "x" "y" "z"
+month.abb # "Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug" "Sep" "Oct" "Nov" "Dec"
+
+# LÓGICOS
+# En R, un "logical" es un boolean
+class(TRUE) # "logical"
+class(FALSE) # "logical"
+# Ese comportamiento es normal
+TRUE == TRUE # TRUE
+TRUE == FALSE # FALSE
+FALSE != FALSE # FALSE
+FALSE != TRUE # TRUE
+# El dato faltante (NA) es lógico también
+class(NA) # "logical"
+# Utiliza | y & para operaciones lógicas
+# OR
+TRUE | FALSE # TRUE
+# AND
+TRUE & FALSE # FALSE
+# Puedes probar si x es TRUE (verdadero)
+isTRUE(TRUE) # TRUE
+# Aquí tenemos un vector lógico con varios elementos:
+c('Z', 'o', 'r', 'r', 'o') == "Zorro" # FALSE FALSE FALSE FALSE FALSE
+c('Z', 'o', 'r', 'r', 'o') == "Z" # TRUE FALSE FALSE FALSE FALSE
+
+# FACTORES
+# La clase factor es para datos de categoría
+# Los factores pueden ser ordenados (como las calificaciones de los niños)
+# o sin orden (como el género)
+factor(c("female", "female", "male", NA, "female"))
+# female female male <NA> female
+# Levels: female male
+# Los "levels" son los valores que los datos categóricos pueden tener
+# Tomar nota que los datos faltantes no entran a los niveles
+levels(factor(c("male", "male", "female", NA, "female"))) # "female" "male"
+# Si un vector de factores tiene longitud 1, sus niveles también tendrán
+# una longitud de 1 también
+
+length(factor("male")) # 1
+length(levels(factor("male"))) # 1
+# Los factores son comúnmente vistos en marcos de dato, y una estructura de
+# datos que cubriremos después
+data(infert) # "Infertility after Spontaneous and Induced Abortion"
+levels(infert$education) # "0-5yrs" "6-11yrs" "12+ yrs"
+
+# NULL
+# "NULL" es uno raro; utilízalo para "limpiar" un vector
+class(NULL) # NULL
+parakeet = c("beak", "feathers", "wings", "eyes")
+parakeet
+# =>
+# [1] "beak" "feathers" "wings" "eyes"
+parakeet <- NULL
+parakeet
+# =>
+# NULL
+
+# COERCIÓN DE TIPO
+# La coerción de tipos es cuando forzas un valor diferente tipo al que puede tomar.
+as.character(c(6, 8)) # "6" "8"
+as.logical(c(1,0,1,1)) # TRUE FALSE TRUE TRUE
+# Si pones elementos de diferentes tipos en un vector, coerciones raras pasan:
+c(TRUE, 4) # 1 4
+c("dog", TRUE, 4) # "dog" "TRUE" "4"
+as.numeric("Bilbo")
+# =>
+# [1] NA
+# Warning message:
+# NAs introduced by coercion
+
+# También tomar nota: Esos solo eran datos de tipos básicos
+# Hay mucho más tipos de datos, como las fechas, series de tiempo, etc.
+
+
+##################################################
+# Variables, ciclos, condiciones (if/else)
+##################################################
+
+# A variable is like a box you store a value in for later use.
+# We call this "assigning" the value to the variable.
+# Having variables lets us write loops, functions, and if/else statements
+
+# VARIABLES
+# Muchas maneras de asignar valores:
+x = 5 # esto es posible
+y <- "1" # esto es preferido
+TRUE -> z # estos funciona pero es raro
+
+# CICLOS
+# Tenemos ciclos 'for'
+for (i in 1:4) {
+ print(i)
+}
+# Tenemos ciclos 'while'
+a <- 10
+while (a > 4) {
+ cat(a, "...", sep = "")
+ a <- a - 1
+}
+# Ten en mente que los ciclos 'for' y 'while' son lentos en R
+# Operaciones con vectores enteros (i.e. una fila o columna completa)
+# o tipos de función apply() (que discutiremos después) son preferidos
+
+# CONDICIONES (IF/ELSE)
+# De nuevo, bastante normal
+if (4 > 3) {
+ print("4 is greater than 3")
+} else {
+ print("4 is not greater than 3")
+}
+# =>
+# [1] "4 is greater than 3"
+
+# FUNCIONES
+# Definidos de la siguiente manera:
+jiggle <- function(x) {
+ x = x + rnorm(1, sd=.1) #agregar un poco de ruido (controlado)
+ return(x)
+}
+# Llamados como cualquier otra función de R
+jiggle(5) # 5±ε. luego de set.seed(2716057), jiggle(5)==5.005043
+
+
+
+###########################################################################
+# Estructura de datos: Vectores, matrices, marcos da datos y arreglos
+###########################################################################
+
+# UNIDIMENSIONAL
+
+# Empecemos desde el principio, y con algo que ya conoces: vectores.
+vec <- c(8, 9, 10, 11)
+vec # 8 9 10 11
+# Preguntamos por elementos específicos poniendo un subconjunto en corchetes
+# (Toma nota de que R empieza los conteos desde 1)
+vec[1] # 8
+letters[18] # "r"
+LETTERS[13] # "M"
+month.name[9] # "September"
+c(6, 8, 7, 5, 3, 0, 9)[3] # 7
+# También podes buscar por los índices de componentes específicos,
+which(vec %% 2 == 0) # 1 3
+# obtener la primera o las últimas entradas de un vector,
+head(vec, 1) # 8
+tail(vec, 2) # 10 11
+# o averiguar si cierto valor se encuentra dentro de un vector
+any(vec == 10) # TRUE
+# Si un índice "se pasa", obtendrás un NA:
+vec[6] # NA
+# Puedes encontrar la longitud de un vector con length()
+length(vec) # 4
+# Puedes realizar operaciones con vectores enteros o con subconjuntos de vectores
+vec * 4 # 16 20 24 28
+vec[2:3] * 5 # 25 30
+any(vec[2:3] == 8) # FALSE
+# y R tiene muchas funciones pre-definidas para resumir vectores
+mean(vec) # 9.5
+var(vec) # 1.666667
+sd(vec) # 1.290994
+max(vec) # 11
+min(vec) # 8
+sum(vec) # 38
+# Otras funciones pre-definidas:
+5:15 # 5 6 7 8 9 10 11 12 13 14 15
+seq(from=0, to=31337, by=1337)
+# =>
+# [1] 0 1337 2674 4011 5348 6685 8022 9359 10696 12033 13370 14707
+# [13] 16044 17381 18718 20055 21392 22729 24066 25403 26740 28077 29414 30751
+
+# BIDIMENCIONAL (TODO EN UNA CLASE)
+
+# Puedes hacer una matriz de las entradas todos de un mismo tipo como:
+mat <- matrix(nrow = 3, ncol = 2, c(1,2,3,4,5,6))
+mat
+# =>
+# [,1] [,2]
+# [1,] 1 4
+# [2,] 2 5
+# [3,] 3 6
+# A diferencia de un vector, una clase matriz es una 'matriz',
+# sin importar qué contiene
+class(mat) # => "matrix"
+# Consulta la primera fila
+mat[1,] # 1 4
+# Realiza una operación en la primera columna
+3 * mat[,1] # 3 6 9
+# Consulta por una celda específica
+mat[3,2] # 6
+
+# Transpone una matriz entera
+t(mat)
+# =>
+# [,1] [,2] [,3]
+# [1,] 1 2 3
+# [2,] 4 5 6
+
+# Multiplicación de matrices
+mat %*% t(mat)
+# =>
+# [,1] [,2] [,3]
+# [1,] 17 22 27
+# [2,] 22 29 36
+# [3,] 27 36 45
+
+# cbind() une vectores como columnas para hacer una matriz
+mat2 <- cbind(1:4, c("dog", "cat", "bird", "dog"))
+mat2
+# =>
+# [,1] [,2]
+# [1,] "1" "dog"
+# [2,] "2" "cat"
+# [3,] "3" "bird"
+# [4,] "4" "dog"
+class(mat2) # matrix
+# De nuevo, ten en cuenta lo que sucedió
+# Debido a que las matrices deben de contener todas las entradas del mismo tipo,
+# todo fue convertido a la clase caracter
+c(class(mat2[,1]), class(mat2[,2]))
+
+# rbind() une vectores como filas para hacer una matriz
+mat3 <- rbind(c(1,2,4,5), c(6,7,0,4))
+mat3
+# =>
+# [,1] [,2] [,3] [,4]
+# [1,] 1 2 4 5
+# [2,] 6 7 0 4
+# Ah, todo es de la misma clase. No hay coerciones. Mucho mejor.
+
+# BIDIMENSIONAL (DIFERENTES CLASES)
+
+# Para columnas de tipos diferentes, utiliza un data frame
+# Esta estructura de datos es muy útil para programación estadística,
+# una versión de ésta fue agregada a Python en el paquete "pandas".
+
+students <- data.frame(c("Cedric","Fred","George","Cho","Draco","Ginny"),
+ c(3,2,2,1,0,-1),
+ c("H", "G", "G", "R", "S", "G"))
+names(students) <- c("name", "year", "house") # name the columns
+class(students) # "data.frame"
+students
+# =>
+# name year house
+# 1 Cedric 3 H
+# 2 Fred 2 G
+# 3 George 2 G
+# 4 Cho 1 R
+# 5 Draco 0 S
+# 6 Ginny -1 G
+class(students$year) # "numeric"
+class(students[,3]) # "factor"
+# encontrar las dimensiones
+nrow(students) # 6
+ncol(students) # 3
+dim(students) # 6 3
+# La función data.frame() convierte vectores de caracteres en vectores
+# de factores por defecto; deshabilita este atributo
+# stringsAsFactors = FALSE cuando vayas a crear el data.frame
+?data.frame
+
+# Hay otras formas de hacer subconjuntos de data frames
+students$year # 3 2 2 1 0 -1
+students[,2] # 3 2 2 1 0 -1
+students[,"year"] # 3 2 2 1 0 -1
+
+# Una versión aumentada de la estructura data.frame es el data.table
+# Si estás trabajando huge o panel data, o necesitas unificar algunos
+# subconjuntos de datos, data.table puede ser una buena elección.
+# Aquí un tour:
+install.packages("data.table") # Descarga el paquete de CRAN
+require(data.table) # Cárgalo
+students <- as.data.table(students)
+students # Tomar en cuenta la diferencia de la impresión
+# =>
+# name year house
+# 1: Cedric 3 H
+# 2: Fred 2 G
+# 3: George 2 G
+# 4: Cho 1 R
+# 5: Draco 0 S
+# 6: Ginny -1 G
+students[name=="Ginny"] # obtener filas con name == "Ginny"
+# =>
+# name year house
+# 1: Ginny -1 G
+students[year==2] # obtener filas con year == 2
+# =>
+# name year house
+# 1: Fred 2 G
+# 2: George 2 G
+# data.table hace que la unificación de dos sets de datos sea fácil
+# Hagamos otro data.table para unifiar a los estudiantes
+founders <- data.table(house=c("G","H","R","S"),
+ founder=c("Godric","Helga","Rowena","Salazar"))
+founders
+# =>
+# house founder
+# 1: G Godric
+# 2: H Helga
+# 3: R Rowena
+# 4: S Salazar
+setkey(students, house)
+setkey(founders, house)
+students <- founders[students] # Unifica los dos sets de datos comparando "house"
+setnames(students, c("house","houseFounderName","studentName","year"))
+students[,order(c("name","year","house","houseFounderName")), with=F]
+# =>
+# studentName year house houseFounderName
+# 1: Fred 2 G Godric
+# 2: George 2 G Godric
+# 3: Ginny -1 G Godric
+# 4: Cedric 3 H Helga
+# 5: Cho 1 R Rowena
+# 6: Draco 0 S Salazar
+
+# data.table hace que sea fácil obtener resúmenes de las tablas
+students[,sum(year),by=house]
+# =>
+# house V1
+# 1: G 3
+# 2: H 3
+# 3: R 1
+# 4: S 0
+
+# Para eliminar una columna de un data.frame o data.table,
+# asignarle el valor NULL.
+students$houseFounderName <- NULL
+students
+# =>
+# studentName year house
+# 1: Fred 2 G
+# 2: George 2 G
+# 3: Ginny -1 G
+# 4: Cedric 3 H
+# 5: Cho 1 R
+# 6: Draco 0 S
+
+# Elimina una fila poniendo un subconjunto
+# Usando data.table:
+students[studentName != "Draco"]
+# =>
+# house studentName year
+# 1: G Fred 2
+# 2: G George 2
+# 3: G Ginny -1
+# 4: H Cedric 3
+# 5: R Cho 1
+# Usando data.frame:
+students <- as.data.frame(students)
+students[students$house != "G",]
+# =>
+# house houseFounderName studentName year
+# 4 H Helga Cedric 3
+# 5 R Rowena Cho 1
+# 6 S Salazar Draco 0
+
+# MULTI-DIMENSIONAL (TODOS LOS ELEMENTOS DE UN TIPO)
+
+# Arreglos crean una tabla de dimensión n
+# Todos los elementos deben de ser del mismo tipo
+# Puedes hacer una tabla bi-dimensional (como una matriz)
+array(c(c(1,2,4,5),c(8,9,3,6)), dim=c(2,4))
+# =>
+# [,1] [,2] [,3] [,4]
+# [1,] 1 4 8 3
+# [2,] 2 5 9 6
+# Puedes utilizar un arreglo para hacer una matriz tri-dimensional también
+array(c(c(c(2,300,4),c(8,9,0)),c(c(5,60,0),c(66,7,847))), dim=c(3,2,2))
+# =>
+# , , 1
+#
+# [,1] [,2]
+# [1,] 2 8
+# [2,] 300 9
+# [3,] 4 0
+#
+# , , 2
+#
+# [,1] [,2]
+# [1,] 5 66
+# [2,] 60 7
+# [3,] 0 847
+
+# LISTAS (MULTI-DIMENSIONAL, POSIBLEMENTE DESIGUALES, DE DIFERENTES TIPOS)
+
+# Finalmente, R tiene listas (de vectores)
+list1 <- list(time = 1:40)
+list1$price = c(rnorm(40,.5*list1$time,4)) # aleatorio
+list1
+# Puedes obtener elementos de una lista de la siguiente manera
+list1$time # Una manera
+list1[["time"]] # Otra manera
+list1[[1]] # Y otra manera
+# =>
+# [1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
+# [34] 34 35 36 37 38 39 40
+# Puedes crear una lista de subconjuntos como cualquier otro vector
+list1$price[4]
+
+# Las listas no son la estructura de datos más eficiente para trabajar en R;
+# a menos de que tengas una buena razón, deberías de quedarte con data.frames
+# Las listas son usualmente devueltas por funciones que realizan regresiones
+# lineales
+
+##################################################
+# La familia de funciones apply()
+##################################################
+
+# Te recuerdas de mat?
+mat
+# =>
+# [,1] [,2]
+# [1,] 1 4
+# [2,] 2 5
+# [3,] 3 6
+# Utiliza apply(X, MARGIN, FUN) paraaplicar una función FUN a la matriz X
+# sobre las filas (MAR = 1) o las columnas (MAR = 2)
+# Eso es, R aplica FUN sobre cada fila (o columna) de X, mucho más rápido que
+# lo que haría un ciclo 'for' o 'loop'
+apply(mat, MAR = 2, jiggle)
+# =>
+# [,1] [,2]
+# [1,] 3 15
+# [2,] 7 19
+# [3,] 11 23
+# Otras funciones: ?lapply, ?sapply
+
+# No te sientas muy intimidado; todos están de acuerdo que son confusas
+
+# El paquete plyr busca reemplazar (y mejorar) la familiar *apply()
+install.packages("plyr")
+require(plyr)
+?plyr
+
+
+
+#########################
+# Carga de datos
+#########################
+
+# "pets.csv" es un archivo en internet
+# (pero puede ser tan fácil como tener el archivo en tu computadora)
+pets <- read.csv("http://learnxinyminutes.com/docs/pets.csv")
+pets
+head(pets, 2) # primeras dos filas
+tail(pets, 1) # última fila
+
+# Para guardar un data frame o una matriz como un archivo .csv
+write.csv(pets, "pets2.csv") # para hacer un nuevo archivo .csv
+# definir el directorio de trabajo con setwd(), búscalo con getwd()
+
+# Prueba ?read.csv ?write.csv para más información
+
+
+#########################
+# Gráficas
+#########################
+
+# FUNCIONES PREDEFINIDAS DE GRAFICACIÓN
+# Gráficos de dispersión!
+plot(list1$time, list1$price, main = "fake data")
+# Regresiones!
+linearModel <- lm(price ~ time, data = list1)
+linearModel # Muestra el resultado de la regresión
+# Grafica la línea de regresión
+abline(linearModel, col = "red")
+# Obtiene una veridad de diagnósticos
+plot(linearModel)
+# Histogramas!
+hist(rpois(n = 10000, lambda = 5), col = "thistle")
+# Barras!
+barplot(c(1,4,5,1,2), names.arg = c("red","blue","purple","green","yellow"))
+
+# GGPLOT2
+# Pero éstas no son las gráficas más bonitas de R
+# Prueba el paquete ggplot2 para mayor variedad y mejores gráficas
+install.packages("ggplot2")
+require(ggplot2)
+?ggplot2
+pp <- ggplot(students, aes(x=house))
+pp + geom_histogram()
+ll <- as.data.table(list1)
+pp <- ggplot(ll, aes(x=time,price))
+pp + geom_point()
+# ggplot2 tiene una excelente documentación
+# (disponible en http://docs.ggplot2.org/current/)
+
+
+
+```
+
+## ¿Cómo obtengo R?
+
+* Obtén R y R GUI de [http://www.r-project.org/](http://www.r-project.org/)
+* [RStudio](http://www.rstudio.com/ide/) es otro GUI
diff --git a/es-es/ruby-es.html.markdown b/es-es/ruby-es.html.markdown
index d8b67fe7..e3e43c18 100644
--- a/es-es/ruby-es.html.markdown
+++ b/es-es/ruby-es.html.markdown
@@ -29,7 +29,7 @@ Nadie los usa.
Tu tampoco deberías
=end
-# Lo primero y principal: Todo es un objeto
+# En primer lugar: Todo es un objeto
# Los números son objetos
@@ -128,7 +128,7 @@ ruta = '/mal/nombre/'
# Los símbolos (son objetos)
# Los símbolos son inmutables, constantes reusables representadas internamente por un
-# valor entero. Son usalmente usados en vez de strings para expresar eficientemente
+# valor entero. Son normalmente usados en vez de strings para expresar eficientemente
# valores específicos y significativos
:pendiente.class #=> Symbol
@@ -156,7 +156,7 @@ arreglo[0] #=> 1
arreglo.first #=> 1
arreglo[12] #=> nil
-# Tal como la aritmética, el acceso como variable[índice]
+# Al igual que en aritmética, el acceso como variable[índice]
# es sólo azúcar sintáctica
# para llamar el método [] de un objeto
arreglo.[] 0 #=> 1
diff --git a/es-es/rust-es.html.markdown b/es-es/rust-es.html.markdown
new file mode 100644
index 00000000..b43cb815
--- /dev/null
+++ b/es-es/rust-es.html.markdown
@@ -0,0 +1,324 @@
+---
+language: rust
+contributors:
+ - ["P1start", "http://p1start.github.io/"]
+translators:
+ - ["Razican", "https://www.razican.com/"]
+filename: learnrust-es.rs
+lang: es-es
+---
+
+Rust es un lenguaje de programación desarrollado por Mozzilla Research. Rust
+combina el control del rendimiento a bajo nivel con la comodidad del alto nivel
+y garantías de seguridad.
+
+Consigue cumplir estos objetivos sin necesidad de un recolector de basura o
+runtime, haciendo posible usar las librerías de Rust como sustituto de C.
+
+La primera versión de Rust, la 0.1, fue lanzada en enero de 2012, y durante 3
+años el desarrollo fue tan rápido que hasta hace poco el uso de las versiones
+estables no era recomendable, y se aconsejaba usar las compilaciones nocturnas.
+
+El 15 de mayo de 2015 se lanzó Rust 1.0, con una garantía completa de
+retrocompatibilidad. A día de hoy los tiempos de compilación han mejorado mucho
+desde ese lanzamiento, así como otros aspectos del lenguaje y el compilador.
+Rust ha adoptado un modelo de desarrollo por series de publicaciones periódicas,
+con lanzamientos cada 6 semanas. Junto con cada lanzamiento, se lanza la beta de
+la siguiente versión.
+
+A pesar de que Rust es un lenguaje relativamente de bajo nivel, tiene conceptos
+funcionales que generalmente se encuentran en lenguajes de más alto nivel. Esto
+hace que Rust sea rápido y al mismo tiempo fácil y eficiente a la hora de
+programar.
+
+```rust
+// Esto es un comentario. Los comentarios de una sola línea se hacen así...
+/* ...y los de múltiples líneas así */
+
+//////////////////////////
+// 1. Conceptos básicos //
+//////////////////////////
+
+// Funciones
+// `i32` es el tipo para enteros de 32 bits con signo
+fn suma2(x: i32, y: i32) -> i32 {
+ // Retorno implícito (sin punto y coma)
+ x + y
+}
+
+// Función principal
+fn main() {
+ // N;umeros //
+
+ // Bindings (variables) inmutables
+ let x: i32 = 1;
+
+ // Sufijos para enteros / floats
+ let y: i32 = 13i32;
+ let f: f64 = 1.3f64;
+
+ // Inferencia de tipos
+ // La mayor parte del tiempo, el compilador de Rust puede inferir el tipo de
+ // una variable, por lo que no necesitas escribir una anotación de tipo
+ // explícita. A lo largo de este tutorial, los tipos están anotados
+ // explícitamente en varios sitios, pero solo con propósito demostrativo. La
+ // inferencia de tipos puede manejar esto por ti la mayor parte del tiempo.
+ let x_implicita = 1;
+ let f_implicita = 1.3;
+
+ // Aritmética
+ let sum = x + y + 13;
+
+ // Variable mutable
+ let mut mutable = 1;
+ mutable = 4;
+ mutable += 2;
+
+ // Strings (cadenas de caracteres) //
+
+ // Strings literales
+ let x: &str = "hola mundo!";
+
+ // Impresión por consola
+ println!("{} {}", f, x); // 1.3 hola mundo!
+
+ // Un `String` – una cadena en memoria dinámica (heap)
+ let s: String = "hola mundo".to_string();
+
+ // Una porión de cadena (slice) – una vista inmutable a otra cadena
+ // Esto es básicamente un puntero inmutable a un string string – en realidad
+ // no contiene los caracteres de la cadena, solo un puntero a algo que los
+ // tiene (en este caso, `s`)
+ let s_slice: &str = &s;
+
+ println!("{} {}", s, s_slice); // hola mundo hola mundo
+
+ // Vectores/arrays //
+
+ // A fixed-size array
+ let cuatro_enteros: [i32; 4] = [1, 2, 3, 4];
+
+ // Un array dinámico (vector)
+ let mut vector: Vec<i32> = vec![1, 2, 3, 4];
+ vector.push(5);
+
+ // Una porción (slice) – una vista inmutable a un vector o array
+ // Esto es parecido a un slice de un string, pero para vectores
+ let slice: &[i32] = &vector;
+
+ // Usa `{:?}` para imprimir algo en estilo debug
+ println!("{:?} {:?}", vector, slice); // [1, 2, 3, 4, 5] [1, 2, 3, 4, 5]
+
+ // Tuplas //
+
+ // Una tupla es un conjunto de tamaño fijo de valores. Pueden ser de diferente tipo.
+ let x: (i32, &str, f64) = (1, "hola", 3.4);
+
+ // Desestructurando `let`
+ let (a, b, c) = x;
+ println!("{} {} {}", a, b, c); // 1 hola 3.4
+
+ // Indexando
+ println!("{}", x.1); // hola
+
+ //////////////
+ // 2. Tipos //
+ //////////////
+
+ // Estructuras
+ struct Punto {
+ x: i32,
+ y: i32,
+ }
+
+ let origen: Punto = Punto { x: 0, y: 0 };
+
+ // Una estructura con campos sin nombre, una ‘estructura de tupla’
+ struct Punto2(i32, i32);
+
+ let origen2 = Punto2(0, 0);
+
+ // Enums básicos como en C
+ enum Direccion {
+ Izquierda,
+ Derecha,
+ Arriba,
+ Abajo,
+ }
+
+ let arriba = Direccion::Arriba;
+
+ // Enum con campos
+ enum OpcionalI32 {
+ UnI32(i32),
+ Nada,
+ }
+
+ let dos: OpcionalI32 = OpcionalI32::UnI32(2);
+ let nada = OpcionalI32::Nada;
+
+ // Genéricos //
+
+ struct Foo<T> { bar: T }
+
+ // Esto está definido en la librería estándar como `Option`
+ enum Opcional<T> {
+ AlgunVal(T),
+ SinVal,
+ }
+
+ // Métodos //
+
+ impl<T> Foo<T> {
+ // Los métodos reciben un parámetro explícito `self`
+ fn get_bar(self) -> T {
+ self.bar
+ }
+ }
+
+ let un_foo = Foo { bar: 1 };
+ println!("{}", un_foo.get_bar()); // 1
+
+ // Traits (conocidos como interfaces o typeclasses en otros lenguajes) //
+
+ trait Frobnicate<T> {
+ fn frobnicate(self) -> Option<T>;
+ }
+
+ impl<T> Frobnicate<T> for Foo<T> {
+ fn frobnicate(self) -> Option<T> {
+ Some(self.bar)
+ }
+ }
+
+ let otro_foo = Foo { bar: 1 };
+ println!("{:?}", otro_foo.frobnicate()); // Some(1)
+
+ /////////////////////////////////
+ // 3. Comparación con patrones //
+ /////////////////////////////////
+
+ let foo = OpcionalI32::UnI32(1);
+ match foo {
+ OpcionalI32::UnI32(n) => println!("es un i32: {}", n),
+ OpcionalI32::Nada => println!("no es nada!"),
+ }
+
+ // comparación de patrones avanzada
+ struct FooBar { x: i32, y: OpcionalI32 }
+ let bar = FooBar { x: 15, y: OpcionalI32::UnI32(32) };
+
+ match bar {
+ FooBar { x: 0, y: OpcionalI32::UnI32(0) } =>
+ println!("Los números son cero!"),
+ FooBar { x: n, y: OpcionalI32::UnI32(m) } if n == m =>
+ println!("Los números son iguales"),
+ FooBar { x: n, y: OpcionalI32::UnI32(m) } =>
+ println!("Números diferentes: {} {}", n, m),
+ FooBar { x: _, y: OpcionalI32::Nada } =>
+ println!("El segudo número no es nada!"),
+ }
+
+ /////////////////////////
+ // 4. Flujo de control //
+ /////////////////////////
+
+ // bucles `for`
+ let array = [1, 2, 3];
+ for i in array.iter() {
+ println!("{}", i);
+ }
+
+ // Rangos
+ for i in 0u32..10 {
+ print!("{} ", i);
+ }
+ println!("");
+ // imprime `0 1 2 3 4 5 6 7 8 9 `
+
+ // `if`
+ if 1 == 1 {
+ println!("Las matemáticas funcionan!");
+ } else {
+ println!("Oh no...");
+ }
+
+ // `if` como una expresión
+ let valor = if true {
+ "bueno"
+ } else {
+ "malo"
+ };
+
+ // bucle `while`
+ while 1 == 1 {
+ println!("El universo está funcionando correctamente.");
+ }
+
+ // Bucle infinito
+ loop {
+ println!("Hola!");
+ }
+
+ ////////////////////////////////////////
+ // 5. Seguridad de memoria y punteros //
+ ////////////////////////////////////////
+
+ // Posesión de punteros – solo uno puede ‘poseer’ un puntero en cada momento
+ // Esto significa que cuando la `Box` queda fuera del ámbito, puede ser
+ // liberada automáticamente de manera segura.
+ let mut mio: Box<i32> = Box::new(3);
+ *mio = 5; // dereferenciar
+ // Aquí, `ahora_es_mio`, toma posesión de `mio`. En otras palabras, `mio` se
+ // mueve.
+ let mut ahora_es_mio = mio;
+ *ahora_es_mio += 2;
+
+ println!("{}", ahora_es_mio); // 7
+ // println!("{}", mio); // esto no compilaría, porque `now_its_mine` es el
+ // que posee el puntero
+
+ // Referencia – un puntero inmutable que referencia a otro dato
+ // Cuando se crea una referencia a un valor, decimos que el valor ha sido
+ // ‘tomado prestado’.
+ // Mientras un valor está prestado como inmutable, no puede ser modificado o
+ // movido.
+ // Una prestación dura hasta el fin del ámbito en el que se creó.
+ let mut var = 4;
+ var = 3;
+ let ref_var: &i32 = &var;
+
+ println!("{}", var); // A diferencia de `mio`, `var` se puede seguir usando
+ println!("{}", *ref_var);
+ // var = 5; // esto no compilaría, porque `var` está prestada
+ // *ref_var = 6; // esto tampoco, porque `ref_var` es una referencia
+ // inmutable
+
+ // Referencia mutable
+ // Mientras que un valor está prestado como mutable, no puede ser accedido
+ // desde ningún otro sitio.
+ let mut var2 = 4;
+ let ref_var2: &mut i32 = &mut var2;
+ *ref_var2 += 2; // '*' se usa para apuntar al var2 prestado como mutable
+
+ println!("{}", *ref_var2); // 6 , //var2 no compilaría. //ref_var2 es de
+ // tipo &mut i32, por lo que guarda una
+ // referencia a un i32 no el valor.
+ // var2 = 2; // esto no compilaría porque `var2` está prestado
+}
+```
+
+## Lectura adicional
+
+Rust es mucho más que esto. Esto es solo lo más básico para que puedas entender
+las cosas más importantes. Para aprender más sobre Rust, lee [The Rust
+Programming Language](http://doc.rust-lang.org/book/index.html) y echa un
+vistazo al subreddit [/r/rust](http://reddit.com/r/rust). Los compañeros en el
+canal #rust en irc.mozilla.org también son muy buenos con los recien llegados.
+También puedes acceder a [Rust users](https://users.rust-lang.org/) a pedir
+ayuda o a [Rust internals](https://internals.rust-lang.org/) para aprender más
+sobre el lenguaje y colaborar en su desarrollo.
+
+También puedes probar Rust con un compilador online en el oficial [Rust
+playpen](http://play.rust-lang.org) o en la [web principal de
+Rust](http://rust-lang.org).
diff --git a/es-es/swift-es.html.markdown b/es-es/swift-es.html.markdown
new file mode 100644
index 00000000..c04ab02b
--- /dev/null
+++ b/es-es/swift-es.html.markdown
@@ -0,0 +1,596 @@
+---
+language: swift
+contributors:
+ - ["Grant Timmerman", "http://github.com/grant"]
+ - ["Christopher Bess", "http://github.com/cbess"]
+ - ["Joey Huang", "http://github.com/kamidox"]
+ - ["Anthony Nguyen", "http://github.com/anthonyn60"]
+translators:
+ - ["David Hsieh", "http://github.com/deivuh"]
+lang: es-es
+filename: learnswift-es.swift
+---
+
+Swift es un lenguaje de programación para el desarrollo en iOS y OS X creado
+por Apple. Diseñado para coexistir con Objective-C y ser más resistente contra
+el código erroneo, Swift fue introducido en el 2014 en el WWDC, la conferencia
+de desarrolladores de Apple.
+
+Véase también la guía oficial de Apple, [getting started guide](https://developer.apple.com/library/prerelease/ios/referencelibrary/GettingStarted/DevelopiOSAppsSwift/), el cual tiene un completo tutorial de Swift.
+
+
+```swift
+// Importar un módulo
+import UIKit
+
+//
+// MARK: Básicos
+//
+
+// XCode soporta referencias para anotar tu código y agregarlos a lista de la
+// barra de saltos.
+// MARK: Marca de sección
+// TODO: Hacer algo pronto
+// FIXME: Arreglar este código
+
+// En Swift 2, println y print fueron combinados en un solo método print.
+// Print añade una nueva línea automáticamente.
+print("Hola, mundo") // println ahora es print
+print("Hola, mundo", appendNewLine: false) // print sin agregar nueva línea
+
+// Valores de variables (var) pueden cambiar después de ser asignados
+// Valores de constrantes (let) no pueden cambiarse después de ser asignados
+
+var myVariable = 42
+let øπΩ = "value" // nombres de variable unicode
+let π = 3.1415926
+let convenience = "keyword" // nombre de variable contextual
+// Las declaraciones pueden ser separadas por punto y coma (;)
+let weak = "keyword"; let override = "another keyword"
+// Los acentos abiertos (``) permiten utilizar palabras clave como nombres de
+// variable
+let `class` = "keyword"
+let explicitDouble: Double = 70
+let intValue = 0007 // 7
+let largeIntValue = 77_000 // 77000
+let label = "some text " + String(myVariable) // Conversión (casting)
+let piText = "Pi = \(π), Pi 2 = \(π * 2)" // Interpolación de string
+
+// Valores específicos de la compilación (build)
+// utiliza la configuración -D
+#if false
+ print("No impreso")
+ let buildValue = 3
+#else
+ let buildValue = 7
+#endif
+print("Build value: \(buildValue)") // Build value: 7
+
+/*
+ Las opcionales son un aspecto del lenguaje Swift que permite el
+ almacenamiento de un valor `Some` (algo) o `None` (nada).
+
+ Debido a que Swift requiere que cada propiedad tenga un valor,
+ hasta un valor 'nil' debe de ser explicitamente almacenado como un
+ valor opcional.
+
+ Optional<T> es un enum.
+*/
+var someOptionalString: String? = "opcional" // Puede ser nil
+// Al igual que lo anterior, pero ? es un operador postfix (sufijo)
+var someOptionalString2: Optional<String> = "opcional"
+
+if someOptionalString != nil {
+ // No soy nil
+ if someOptionalString!.hasPrefix("opt") {
+ print("Tiene el prefijo")
+ }
+
+ let empty = someOptionalString?.isEmpty
+}
+someOptionalString = nil
+
+// Opcional implícitamente desenvuelto
+var unwrappedString: String! = "Un valor esperado."
+// Al igual que lo anterior, pero ! es un operador postfix (sufijo)
+var unwrappedString2: ImplicitlyUnwrappedOptional<String> = "Un valor esperado."
+
+if let someOptionalStringConstant = someOptionalString {
+ // tiene valor `Some` (algo), no nil
+ if !someOptionalStringConstant.hasPrefix("ok") {
+ // No tiene el prefijo
+ }
+}
+
+// Swift tiene soporte de almacenamiento para cualquier tipo de valor.
+// AnyObject == id
+// A diferencia de Objective-C `id`, AnyObject funciona con cualquier
+// valor (Class, Int, struct, etc)
+var anyObjectVar: AnyObject = 7
+anyObjectVar = "Cambiado a un valor string, no es buena práctica, pero posible."
+
+/*
+ Comentar aquí
+
+ /*
+ Comentarios anidados también son soportados
+ */
+*/
+
+//
+// MARK: Colecciones
+//
+
+/*
+ Tipos Array (arreglo) y Dictionary (diccionario) son structs (estructuras).
+ Así que `let` y `var` también indican si son mudables (var) o
+ inmutables (let) durante la declaración de sus tipos.
+*/
+
+// Array (arreglo)
+var shoppingList = ["catfish", "water", "lemons"]
+shoppingList[1] = "bottle of water"
+let emptyArray = [String]() // let == inmutable
+let emptyArray2 = Array<String>() // igual que lo anterior
+var emptyMutableArray = [String]() // var == mudable
+
+
+// Dictionary (diccionario)
+var occupations = [
+ "Malcolm": "Captain",
+ "kaylee": "Mechanic"
+]
+occupations["Jayne"] = "Public Relations"
+let emptyDictionary = [String: Float]() // let == inmutable
+let emptyDictionary2 = Dictionary<String, Float>() // igual que lo anterior
+var emptyMutableDictionary = [String: Float]() // var == mudable
+
+
+//
+// MARK: Flujo de control
+//
+
+// Ciclo for (array)
+let myArray = [1, 1, 2, 3, 5]
+for value in myArray {
+ if value == 1 {
+ print("Uno!")
+ } else {
+ print("No es uno!")
+ }
+}
+
+// Ciclo for (dictionary)
+var dict = ["uno": 1, "dos": 2]
+for (key, value) in dict {
+ print("\(key): \(value)")
+}
+
+// Ciclo for (range)
+for i in -1...shoppingList.count {
+ print(i)
+}
+shoppingList[1...2] = ["steak", "peacons"]
+// Utilizar ..< para excluir el último valor
+
+// Ciclo while
+var i = 1
+while i < 1000 {
+ i *= 2
+}
+
+// Ciclo do-while
+do {
+ print("Hola")
+} while 1 == 2
+
+// Switch
+// Muy potente, se puede pensar como declaraciones `if` con _azúcar sintáctico_
+// Soportan String, instancias de objetos, y primitivos (Int, Double, etc)
+let vegetable = "red pepper"
+switch vegetable {
+case "celery":
+ let vegetableComment = "Add some raisins and make ants on a log."
+case "cucumber", "watercress":
+ let vegetableComment = "That would make a good tea sandwich."
+case let localScopeValue where localScopeValue.hasSuffix("pepper"):
+ let vegetableComment = "Is it a spicy \(localScopeValue)?"
+default: // obligatorio (se debe cumplir con todos los posibles valores de entrada)
+ let vegetableComment = "Everything tastes good in soup."
+}
+
+
+//
+// MARK: Funciones
+//
+
+// Funciones son un tipo de primera-clase, quiere decir que pueden ser anidados
+// en funciones y pueden ser pasados como parámetros
+
+// Función en documentación de cabeceras Swift (formato reStructedText)
+
+/**
+ Una operación de saludo
+
+ - Una viñeta en la documentación
+ - Otra viñeta en la documentación
+
+ :param: name Un nombre
+ :param: day Un día
+ :returns: Un string que contiene el valor de name y day
+*/
+func greet(name: String, day: String) -> String {
+ return "Hola \(name), hoy es \(day)."
+}
+greet("Bob", "Martes")
+
+// Similar a lo anterior, a excepción del compartamiento de los parámetros
+// de la función
+func greet2(requiredName: String, externalParamName localParamName: String) -> String {
+ return "Hola \(requiredName), hoy es el día \(localParamName)"
+}
+greet2(requiredName:"John", externalParamName: "Domingo")
+
+// Función que devuelve múltiples valores en una tupla
+func getGasPrices() -> (Double, Double, Double) {
+ return (3.59, 3.69, 3.79)
+}
+let pricesTuple = getGasPrices()
+let price = pricesTuple.2 // 3.79
+// Ignorar tupla (u otros) valores utilizando _ (guión bajo)
+let (_, price1, _) = pricesTuple // price1 == 3.69
+print(price1 == pricesTuple.1) // true
+print("Gas price: \(price)")
+
+// Cantidad variable de argumentos
+func setup(numbers: Int...) {
+ // Es un arreglo
+ let number = numbers[0]
+ let argCount = numbers.count
+}
+
+// Pasando y devolviendo funciones
+func makeIncrementer() -> (Int -> Int) {
+ func addOne(number: Int) -> Int {
+ return 1 + number
+ }
+ return addOne
+}
+var increment = makeIncrementer()
+increment(7)
+
+// Pasando como referencia
+func swapTwoInts(inout a: Int, inout b: Int) {
+ let tempA = a
+ a = b
+ b = tempA
+}
+var someIntA = 7
+var someIntB = 3
+swapTwoInts(&someIntA, &someIntB)
+print(someIntB) // 7
+
+
+//
+// MARK: Closures (Clausuras)
+//
+var numbers = [1, 2, 6]
+
+// Las funciones son un caso especial de closure ({})
+
+// Ejemplo de closure.
+// `->` Separa los argumentos del tipo de retorno
+// `in` Separa la cabecera del cuerpo del closure
+numbers.map({
+ (number: Int) -> Int in
+ let result = 3 * number
+ return result
+})
+
+// Cuando se conoce el tipo, como en lo anterior, se puede hacer esto
+numbers = numbers.map({ number in 3 * number })
+// o esto
+//numbers = numbers.map({ $0 * 3 })
+
+print(numbers) // [3, 6, 18]
+
+// Closure restante
+numbers = sorted(numbers) { $0 > $1 }
+
+print(numbers) // [18, 6, 3]
+
+// Bastante corto, debido a que el operador < infiere los tipos
+
+numbers = sorted(numbers, < )
+
+print(numbers) // [3, 6, 18]
+
+//
+// MARK: Estructuras
+//
+
+// Las estructuras y las clases tienen capacidades similares
+struct NamesTable {
+ let names = [String]()
+
+ // Subscript personalizado
+ subscript(index: Int) -> String {
+ return names[index]
+ }
+}
+
+// Las estructuras tienen un inicializador designado autogenerado (implícitamente)
+let namesTable = NamesTable(names: ["Me", "Them"])
+let name = namesTable[1]
+print("Name is \(name)") // Name is Them
+
+//
+// MARK: Clases
+//
+
+// Las clases, las estructuras y sus miembros tienen tres niveles de control de acceso
+// Éstos son: internal (predeterminado), public, private
+
+public class Shape {
+ public func getArea() -> Int {
+ return 0;
+ }
+}
+
+// Todos los métodos y las propiedades de una clase son public (públicas)
+// Si solo necesitas almacenar datos en un objecto estructurado,
+// debes de utilizar `struct`
+
+internal class Rect: Shape {
+ var sideLength: Int = 1
+
+ // Getter y setter personalizado
+ private var perimeter: Int {
+ get {
+ return 4 * sideLength
+ }
+ set {
+ // `newValue` es una variable implícita disponible para los setters
+ sideLength = newValue / 4
+ }
+ }
+
+ // Lazily loading (inicialización bajo demanda) a una propiedad
+ // subShape queda como nil (sin inicializar) hasta que getter es llamado
+ lazy var subShape = Rect(sideLength: 4)
+
+ // Si no necesitas un getter y setter personalizado
+ // pero aún quieres ejecutar código antes y después de hacer get o set
+ // a una propiedad, puedes utilizar `willSet` y `didSet`
+ var identifier: String = "defaultID" {
+ // El argumento `willSet` será el nombre de variable para el nuevo valor
+ willSet(someIdentifier) {
+ print(someIdentifier)
+ }
+ }
+
+ init(sideLength: Int) {
+ self.sideLength = sideLength
+ // Siempre poner super.init de último al momento de inicializar propiedades
+ // personalizadas
+ super.init()
+ }
+
+ func shrink() {
+ if sideLength > 0 {
+ --sideLength
+ }
+ }
+
+ override func getArea() -> Int {
+ return sideLength * sideLength
+ }
+}
+
+// Una clase simple `Square` que extiende de `Rect`
+class Square: Rect {
+ convenience init() {
+ self.init(sideLength: 5)
+ }
+}
+
+var mySquare = Square()
+print(mySquare.getArea()) // 25
+mySquare.shrink()
+print(mySquare.sideLength) // 4
+
+// Conversión de tipo de instancia
+let aShape = mySquare as Shape
+
+// Comparar instancias, no es igual a == que compara objetos (equal to)
+if mySquare === mySquare {
+ print("Yep, it's mySquare")
+}
+
+// Inicialización (init) opcional
+class Circle: Shape {
+ var radius: Int
+ override func getArea() -> Int {
+ return 3 * radius * radius
+ }
+
+ // Un signo de interrogación como sufijo después de `init` es un init opcional
+ // que puede devolver nil
+ init?(radius: Int) {
+ self.radius = radius
+ super.init()
+
+ if radius <= 0 {
+ return nil
+ }
+ }
+}
+
+var myCircle = Circle(radius: 1)
+print(myCircle?.getArea()) // Optional(3)
+print(myCircle!.getArea()) // 3
+var myEmptyCircle = Circle(radius: -1)
+print(myEmptyCircle?.getArea()) // "nil"
+if let circle = myEmptyCircle {
+ // no será ejecutado debido a que myEmptyCircle es nil
+ print("circle is not nil")
+}
+
+
+//
+// MARK: Enums
+//
+
+
+// Los enums pueden ser opcionalmente de un tipo específico o de su propio tipo
+// Al igual que las clases, pueden contener métodos
+
+enum Suit {
+ case Spades, Hearts, Diamonds, Clubs
+ func getIcon() -> String {
+ switch self {
+ case .Spades: return "♤"
+ case .Hearts: return "♡"
+ case .Diamonds: return "♢"
+ case .Clubs: return "♧"
+ }
+ }
+}
+
+// Los valores de enum permite la sintaxis corta, sin necesidad de poner
+// el tipo del enum cuando la variable es declarada de manera explícita
+var suitValue: Suit = .Hearts
+
+// Enums de tipo no-entero requiere asignaciones de valores crudas directas
+enum BookName: String {
+ case John = "John"
+ case Luke = "Luke"
+}
+print("Name: \(BookName.John.rawValue)")
+
+// Enum con valores asociados
+enum Furniture {
+ // Asociación con Int
+ case Desk(height: Int)
+ // Asociación con String e Int
+ case Chair(String, Int)
+
+ func description() -> String {
+ switch self {
+ case .Desk(let height):
+ return "Desk with \(height) cm"
+ case .Chair(let brand, let height):
+ return "Chair of \(brand) with \(height) cm"
+ }
+ }
+}
+
+var desk: Furniture = .Desk(height: 80)
+print(desk.description()) // "Desk with 80 cm"
+var chair = Furniture.Chair("Foo", 40)
+print(chair.description()) // "Chair of Foo with 40 cm"
+
+
+//
+// MARK: Protocolos
+//
+
+// `protocol` puede requerir que los tipos tengan propiedades
+// de instancia específicas, métodos de instancia, métodos de tipo,
+// operadores, y subscripts
+
+
+protocol ShapeGenerator {
+ var enabled: Bool { get set }
+ func buildShape() -> Shape
+}
+
+// Protocolos declarados con @objc permiten funciones opcionales,
+// que te permite evaluar conformidad
+@objc protocol TransformShape {
+ optional func reshaped()
+ optional func canReshape() -> Bool
+}
+
+class MyShape: Rect {
+ var delegate: TransformShape?
+
+ func grow() {
+ sideLength += 2
+
+ // Pon un signo de interrogación después de la propiedad opcional,
+ // método, o subscript para ignorar un valor nil y devolver nil
+ // en lugar de tirar un error de tiempo de ejecución
+ // ("optional chaining")
+ if let allow = self.delegate?.canReshape?() {
+ // test for delegate then for method
+ self.delegate?.reshaped?()
+ }
+ }
+}
+
+
+//
+// MARK: Otros
+//
+
+// `extension`: Agrega funcionalidades a tipos existentes
+
+// Square ahora se "conforma" al protocolo `Printable`
+extension Square: Printable {
+ var description: String {
+ return "Area: \(self.getArea()) - ID: \(self.identifier)"
+ }
+}
+
+print("Square: \(mySquare)")
+
+// También puedes hacer extend a tipos prefabricados (built-in)
+extension Int {
+ var customProperty: String {
+ return "This is \(self)"
+ }
+
+ func multiplyBy(num: Int) -> Int {
+ return num * self
+ }
+}
+
+print(7.customProperty) // "This is 7"
+print(14.multiplyBy(3)) // 42
+
+// Generics: Similar Java y C#. Utiliza la palabra clave `where` para
+// especificar los requerimientos de los genéricos.
+
+func findIndex<T: Equatable>(array: [T], valueToFind: T) -> Int? {
+ for (index, value) in enumerate(array) {
+ if value == valueToFind {
+ return index
+ }
+ }
+ return nil
+}
+let foundAtIndex = findIndex([1, 2, 3, 4], 3)
+print(foundAtIndex == 2) // true
+
+// Operadores:
+// Operadores personalizados puede empezar con los siguientes caracteres:
+// / = - + * % < > ! & | ^ . ~
+// o
+// Caracteres unicode: math, symbol, arrow, dingbat, y line/box.
+prefix operator !!! {}
+
+// Un operador prefix que triplica la longitud del lado cuando es utilizado
+prefix func !!! (inout shape: Square) -> Square {
+ shape.sideLength *= 3
+ return shape
+}
+
+// Valor actual
+print(mySquare.sideLength) // 4
+
+// Cambiar la longitud del lado utilizando el operador !!!,
+// incrementa el tamaño por 3
+!!!mySquare
+print(mySquare.sideLength) // 12
+```
diff --git a/es-es/yaml-es.html.markdown b/es-es/yaml-es.html.markdown
index a5157b5d..cd3143fb 100644
--- a/es-es/yaml-es.html.markdown
+++ b/es-es/yaml-es.html.markdown
@@ -4,6 +4,7 @@ lang: es-es
filename: learnyaml-es.yaml
contributors:
- ["Adam Brenecki", "https://github.com/adambrenecki"]
+ - ["Everardo Medina","https://github.com/everblut"]
translators:
- ["Daniel Zendejas","https://github.com/DanielZendejas"]
---
@@ -14,7 +15,7 @@ leído y escrito por humanos.
Basa su funcionalidad en JSON, con la adición de líneas nuevas
e indentación inspirada en Python. A diferencia de Python, YAML
-no permite tabs literales.
+no permite tabulaciones literales.
```yaml
# Los comentarios en YAML se ven así.
@@ -38,97 +39,177 @@ llave con espacios: valor
llave: "Un string, entre comillas."
"Las llaves tambien pueden estar entre comillas.": "valor entre comillas"
-# Los strings de líneas múltiples pueden ser escritos
+# Los strings de líneas múltiples pueden ser escritos
# como un 'bloque literal' (usando pipes |)
# o como un 'bloque doblado' (usando >)
bloque_literal: |
Este bloque completo de texto será preservado como el valor de la llave
'bloque_literal', incluyendo los saltos de línea.
-
- Se continúa guardando la literal hasta que se cese la indentación.
+
+ Se continúa guardando la literal hasta que se cese la indentación.
Cualquier línea que tenga más indentación, mantendrá los espacios dados
(por ejemplo, estas líneas se guardarán con cuatro espacios)
-nloque_doblado: >
+bloque_doblado: >
De la misma forma que el valor de 'bloque_literal', todas estas
líneas se guardarán como una sola literal, pero en esta ocasión todos los
saltos de línea serán reemplazados por espacio.
- Las líneas en blanco, como la anterior, son convertidos a un salto de línea.
+ Las líneas en blanco, como la anterior, son convertidas a un salto de línea.
Las líneas con mayor indentación guardan sus saltos de línea.
Esta literal ocuparán dos líneas.
-########################
-# TIPOS DE COLECCIONES #
-########################
-
-# La indentación se usa para anidar.
+# La indentación se usa para anidar elementos
un_mapa_indentado:
llave: valor
otra_llave: otro valor
otro_mapa_indentado:
llave_interna: valor_interno
-# Las llaves de los mapas no deben ser strings necesariamente
+# Las llaves de los mapas no requieren ser strings necesariamente
0.25: una llave numérica
-# Las llaves también pueden ser objetos de multi línea, usando ? para indicar
-# el inicio de una llave
+# Las llaves también pueden ser objetos de multiples líneas,
+# usando ? para indicar el inicio de una llave
? |
Esto es una llave
que tiene múltiples líneas
: y este es su valor
-# YAML tambien permite colecciones como llaves, pero muchos lenguajes de
+########################
+# TIPOS DE COLECCIONES #
+########################
+
+# Las colecciones en YAML usan la indentación para delimitar el alcance
+# y cada elemento de la colección inicia en su propia línea.
+# YAML tambien permite colecciones como llaves, pero muchos lenguajes de
# programación se quejarán.
# Las secuencias (equivalentes a listas o arreglos) se ven así:
-una_secuencia:
- - Item 1
- - Item 2
- - 0.5 # las secuencias pueden tener distintos tipos en su contenido.
- - Item 4
- - llave: valor
- otra_llave: otro_valor
+- Amarillo
+- Verde
+- Azul
+
+# Se puede usar una secuencia como valor para una llave.
+secuencia:
+ - Elemento 1
+ - Elemento 2
+ - Elemento 3
+ - Elemento 4
+
+# Las secuencias pueden contener secuencias como elementos.
+- [Uno, Dos, Tres]
+- [Domingo, Lunes, Martes]
+- [Luna, Marte, Tierra]
+
+# Las secuencias pueden tener distintos tipos en su contenido.
+secuencia_combinada:
+ - texto
+ - 5
+ - 0.6
+ - llave: valor # se convierte en un json dentro de la secuencia
-
- Esta es una secuencia
- ...dentro de otra secuencia
-# Dado que todo JSON está incluído dentro de YAML, también puedes escribir
-# mapas con la sintaxis de JSON y secuencias:
-mapa_de_json: {"llave": "valor"}
-secuencia_de_json: [3, 2, 1, "despegue"]
+# Dado que todo JSON está incluído dentro de YAML, también puedes escribir
+# mapas con la sintaxis de JSON y secuencias:
+mapa_de_json_1: {"llave": "valor"}
+mapa_de_json_2:
+ llave: valor
+
+# Las secuencias tambien se pueden escribir como un arreglo al estilo JSON
+secuencia_de_json_1: [3, 2, 1, "despegue"]
+secuencia_de_json_2:
+ - 3
+ - 2
+ - 1
+ - "despegue"
+
+# YAML también soporta conjuntos usando el simbolo ?
+# y se ven de la siguiente forma:
+set:
+ ? item1
+ ? item2
+ ? item3
+
+# Se puede usar el tag !!set
+# Al igual que Python, los conjuntos sólo son mapas con valores nulos.
+# El ejemplo de arriba es equivalente a:
+set2:
+ item1: null
+ item2: null
+ item3: null
##################################
# CARACTERÍSTICAS EXTRAS DE YAML #
##################################
+# YAML usa tres guiones (---) para diferenciar entre directivas
+# y contenido del documento.
+# Por otra parte, tres puntos (...) se utilizan para indicar
+# el final del documento en casos especiales.
+
# YAML tiene funciones útiles llamadas 'anchors' (anclas), que te permiten
-# duplicar fácilmente contenido a lo largo de tu documento. En el ejemplo
-# a continuación, ambas llaves tendrán el mismo valor:
-contenido_anclado: &nombre_del_ancla Este string será el valor de las llaves
-otra_ancla: *nombre_del_ancla
-
-# YAML también tiene tags, que puedes usar para declarar tipos explícitamente.
-string_explícito: !!str 0.5
-# Algunos parseadores implementar tags específicas del lenguaje, como el
+# duplicar fácilmente contenido a lo largo de tu documento.
+# El ampersand indica la declaración del ancla,
+declara_ancla: &texto texto de la llave
+# el asterisco indica el uso de dicha ancla.
+usa_ancla: *texto # tendrá el valor "texto de la llave"
+
+################
+# TAGS EN YAML #
+################
+
+# En YAML, los nodos que no tienen un tag obtienen su tipo
+# según la aplicación que los use, al usar un tag
+# se pueden declarar tipos explícitamente.
+string_explicito: !!str 0.5 # !!str para declarar un string
+integer_explicito: !!int 5 # !!int para declarar un integer
+float_explicito: !!float 1.2 # !!float para declarar un float
+conjunto_explicito: !!set # !!set para declarar un conjunto
+ ? Uno
+ ? Dos
+ ? Tres
+mapa_ordenado_explicito: !!omap # !!omap para declarar un mapa ordenado
+- Primero: 1
+- Segundo: 2
+- Tercero: 3
+- Cuarto: 4
+
+# Tags para los numeros enteros
+llave_canonica: 5222
+llave_decimal: +5222
+llave_octal: 010
+llave_hexadecimal: 0xC
+
+#Tags para los numeros flotantes
+llave_canonica: 1.215e+3
+llave_exponencial: 12.3555e+02
+llave_fija: 12.15
+llave_negativa_infinita: -.inf
+llave_numero_invalido: .NaN
+
+# Tags para las fechas y horas
+llave_canonica: 2001-12-15T02:59:43.1Z
+llave_iso8601: 2001-12-14t21:59:43.10-05:00
+llave_con_espacios: 2001-12-14 21:59:43.10 -5
+llave_fecha: 2002-12-14
+
+# Además existen tags para
+null: #valor nulo
+booleans: [ true, false ] # Valores booleanos
+string: '012345' # Valor en string
+
+
+# Algunos parseadores implementan tags específicas del lenguaje, como el
# que se muestra a continuación, encargado de manejar números complejos en
# Python:
numero_complejo_python: !!python/complex 1+2j
-########################
-# TIPOS EXTRAS EN YAML #
-########################
-
-# Stirngs y números no son los únicos escalares que YAML puede entener.
-# YAML también puede parsear fechas en formato ISO .
-fechaHora: 2001-12-15T02:59:43.1Z
-fechaHora_con_espacios: 2001-12-14 21:59:43.10 -5
-fecha: 2002-12-14
-
-# La tag !!binary indica que un string es, en realidad, un blob
+# El tag !!binary indica que un string es en realidad un blob
# representado en base-64.
archivo_gif: !!binary |
R0lGODlhDAAMAIQAAP//9/X17unp5WZmZgAAAOfn515eXvPz7Y6OjuDg4J+fn5
@@ -136,16 +217,10 @@ archivo_gif: !!binary |
+f/++f/++f/++f/++f/++SH+Dk1hZGUgd2l0aCBHSU1QACwAAAAADAAMAAAFLC
AgjoEwnuNAFOhpEMTRiggcz4BNJHrv/zCFcLiwMWYNG84BwwEeECcgggoBADs=
-# YAML también tiene un tipo set, que se ve de la siguiente forma:
-set:
- ? item1
- ? item2
- ? item3
-
-# Al igual que Python, los sets sólo son mapas con valores nulos.
-# El ejemplo de arriba es equivalente a:
-set2:
- item1: null
- item2: null
- item3: null
```
+
+### Recursos adicionales
+
++ [Sitio oficial de YAML](http://yaml.org/)
++ [Parser en línea de de YAML](http://yaml-online-parser.appspot.com/)
++ [Validador en línea de YAML](http://codebeautify.org/yaml-validator)