diff options
Diffstat (limited to 'es-es')
| -rw-r--r-- | es-es/clojure-es.html.markdown | 393 | ||||
| -rw-r--r-- | es-es/coffeescript-es.html.markdown | 4 | ||||
| -rw-r--r-- | es-es/csharp-es.html.markdown | 632 | ||||
| -rw-r--r-- | es-es/go-es.html.markdown | 301 | ||||
| -rw-r--r-- | es-es/perl-es.html.markdown | 160 | 
5 files changed, 1488 insertions, 2 deletions
| diff --git a/es-es/clojure-es.html.markdown b/es-es/clojure-es.html.markdown new file mode 100644 index 00000000..150d0bb2 --- /dev/null +++ b/es-es/clojure-es.html.markdown @@ -0,0 +1,393 @@ +--- +language: clojure +filename: learnclojure-es.clj +contributors: +    - ["Adam Bard", "http://adambard.com/"] +translators: +    - ["Antonio Hernández Blas", "https://twitter.com/nihilipster"] +    - ["Guillermo Vayá Pérez", "http://willyfrog.es"] +lang: es-es +--- + +Clojure es un lenguaje de la familia Lisp desarrollado sobre la Máquina Virtual +de Java. Tiene un énfasis mayor en la [programación funcional](https://es.wikipedia.org/wiki/Programación_funcional) pura +que Common Lisp, pero incluyendo la posibilidad de usar [SMT](https://es.wikipedia.org/wiki/Memoria_transacional) para manipular +el estado según se presente. + +Esta combinación le permite gestionar la concurrencia de manera muy sencilla +y a menudo automáticamente. + +(Necesitas la versión de Clojure 1.2 o posterior) + + +```clojure +; Los comentatios comienzan con punto y coma. + +; Clojure se escribe mediante "forms" (patrones), los cuales son +; listas de objectos entre paréntesis, separados por espacios en blanco. + +; El "reader" (lector) de Clojure asume que el primer objeto es una +; función o una macro que se va a llamar, y que el resto son argumentos. + +; El primer form en un archivo debe ser ns, para establecer el namespace (espacio de +; nombres) +(ns learnclojure) + +; Algunos ejemplos básicos: + +; str crea una cadena de caracteres a partir de sus argumentos +(str "Hello" " " "World") ; => "Hello World" + +; Las operaciones matemáticas son sencillas +(+ 1 1) ; => 2 +(- 2 1) ; => 1 +(* 1 2) ; => 2 +(/ 2 1) ; => 2 + +; La igualdad es = +(= 1 1) ; => true +(= 2 1) ; => false + +; También es necesaria la negación para las operaciones lógicas +(not true) ; => false + +; Cuando se anidan Los patrones, estos funcionan de la manera esperada +(+ 1 (- 3 2)) ; = 1 + (3 - 2) => 2 + +; Tipos +;;;;;;;;;;;;; + +; Clojure usa los tipos de objetos de Java para booleanos, strings (cadenas de +; caracteres) y números. +; Usa class para saber de qué tipo es. +(class 1); Los enteros son java.lang.Long por defecto +(class 1.); Los numeros en coma flotante son java.lang.Double +(class ""); Los strings van entre comillas dobles, y son +; son java.lang.String +(class false); Los Booleanos son java.lang.Boolean +(class nil); El valor "null" se escribe nil + +; Si quieres crear una lista de datos, precedela con una comilla +; simple para evitar su evaluación +'(+ 1 2) ; => (+ 1 2) +; (que es una abreviatura de (quote (+ 1 2)) ) + +; Puedes evaluar una lista precedida por comilla  con eval +(eval '(+ 1 2)) ; => 3 + +; Colecciones & Secuencias +;;;;;;;;;;;;;;;;;;; + +; Las Listas están basadas en las listas enlazadas, mientras que los Vectores en +; arrays. +; ¡Los Vectores y las Listas también son clases de Java! +(class [1 2 3]); => clojure.lang.PersistentVector +(class '(1 2 3)); => clojure.lang.PersistentList + +; Una lista podría ser escrita como (1 2 3), pero debemos ponerle una +; comilla simple delante para evitar que el reader piense que es una función. +; Además, (list 1 2 3) es lo mismo que '(1 2 3) + +; Las "Colecciones" son solo grupos de datos +; Tanto las listas como los vectores son colecciones: +(coll? '(1 2 3)) ; => true +(coll? [1 2 3]) ; => true + +; Las "Secuencias" (seqs) son descripciones abstractas de listas de datos. +; Solo las listas son seqs. +(seq? '(1 2 3)) ; => true +(seq? [1 2 3]) ; => false + +; Una seq solo necesita proporcionar una entrada cuando es accedida. +; Así que, las seqs pueden ser perezosas -- pueden establecer series infinitas: +(range 4) ; => (0 1 2 3) +(range) ; => (0 1 2 3 4 ...) (una serie infinita) +(take 4 (range)) ;  (0 1 2 3) + +; Usa cons para agregar un elemento al inicio de una lista o vector +(cons 4 [1 2 3]) ; => (4 1 2 3) +(cons 4 '(1 2 3)) ; => (4 1 2 3) + +; conj agregará un elemento a una colección en la forma más eficiente. +; Para listas, se añade al inicio. Para vectores, al final. +(conj [1 2 3] 4) ; => [1 2 3 4] +(conj '(1 2 3) 4) ; => (4 1 2 3) + +; Usa concat para concatenar listas o vectores +(concat [1 2] '(3 4)) ; => (1 2 3 4) + +; Usa filter y map para actuar sobre colecciones +(map inc [1 2 3]) ; => (2 3 4) +(filter even? [1 2 3]) ; => (2) + +; Usa reduce para combinar sus elementos +(reduce + [1 2 3 4]) +; = (+ (+ (+ 1 2) 3) 4) +; => 10 + +; reduce puede tener un argumento indicando su valor inicial. +(reduce conj [] '(3 2 1)) +; = (conj (conj (conj [] 3) 2) 1) +; => [3 2 1] + +; Funciones +;;;;;;;;;;;;;;;;;;;;; + +; Usa fn para crear nuevas funciones. Una función siempre devuelve +; su última expresión +(fn [] "Hello World") ; => fn + +; (Necesitas rodearlo con paréntesis para invocarla) +((fn [] "Hello World")) ; => "Hello World" + +; Puedes crear una var (variable) mediante def +(def x 1) +x ; => 1 + +; Asigna una función a una var +(def hello-world (fn [] "Hello World")) +(hello-world) ; => "Hello World" + +; Puedes defn como atajo para lo anterior +(defn hello-world [] "Hello World") + +; El [] es el vector de argumentos de la función. +(defn hello [name] +  (str "Hello " name)) +(hello "Steve") ; => "Hello Steve" + +; Otra abreviatura para crear funciones es: +(def hello2 #(str "Hello " %1)) +(hello2 "Fanny") ; => "Hello Fanny" + +; Puedes tener funciones multi-variadic: funciones con un numero variable de +; argumentos +(defn hello3 +  ([] "Hello World") +  ([name] (str "Hello " name))) +(hello3 "Jake") ; => "Hello Jake" +(hello3) ; => "Hello World" + +; Las funciones pueden usar argumentos extras dentro de un seq utilizable en la función +(defn count-args [& args] +  (str "You passed " (count args) " args: " args)) +(count-args 1 2 3) ; => "You passed 3 args: (1 2 3)" + +; Y puedes mezclarlos con el resto de argumentos declarados de la función. +(defn hello-count [name & args] +  (str "Hello " name ", you passed " (count args) " extra args")) +(hello-count "Finn" 1 2 3) +; => "Hello Finn, you passed 3 extra args" + + +; Mapas +;;;;;;;;;; + +; Mapas de Hash y mapas de arrays comparten una misma interfaz. Los mapas de Hash +; tienen búsquedas más rápidas pero no mantienen el orden de las claves. +(class {:a 1 :b 2 :c 3}) ; => clojure.lang.PersistentArrayMap +(class (hash-map :a 1 :b 2 :c 3)) ; => clojure.lang.PersistentHashMap + +; Los mapas de arrays se convertidos en mapas de Hash en la mayoría de +; operaciones si crecen mucho, por lo que no debes preocuparte. + +; Los mapas pueden usar cualquier tipo para sus claves, pero generalmente las +; keywords (palabras clave) son lo habitual. +; Las keywords son parecidas a cadenas de caracteres con algunas ventajas de eficiencia +(class :a) ; => clojure.lang.Keyword + +(def stringmap {"a" 1, "b" 2, "c" 3}) +stringmap  ; => {"a" 1, "b" 2, "c" 3} + +(def keymap {:a 1, :b 2, :c 3}) +keymap ; => {:a 1, :c 3, :b 2} + +; Por cierto, las comas son equivalentes a espacios en blanco y no hacen +; nada. + +; Recupera un valor de un mapa tratandolo como una función +(stringmap "a") ; => 1 +(keymap :a) ; => 1 + +; ¡Las keywords pueden ser usadas para recuperar su valor del mapa, también! +(:b keymap) ; => 2 + +; No lo intentes con strings. +;("a" stringmap) +; => Exception: java.lang.String cannot be cast to clojure.lang.IFn + +; Si preguntamos por una clave que no existe nos devuelve nil +(stringmap "d") ; => nil + +; Usa assoc para añadir nuevas claves a los mapas de Hash +(def newkeymap (assoc keymap :d 4)) +newkeymap ; => {:a 1, :b 2, :c 3, :d 4} + +; Pero recuerda, ¡los tipos de Clojure son inmutables! +keymap ; => {:a 1, :b 2, :c 3} + +; Usa dissoc para eliminar llaves +(dissoc keymap :a :b) ; => {:c 3} + +; Conjuntos +;;;;;; + +(class #{1 2 3}) ; => clojure.lang.PersistentHashSet +(set [1 2 3 1 2 3 3 2 1 3 2 1]) ; => #{1 2 3} + +; Añade un elemento con conj +(conj #{1 2 3} 4) ; => #{1 2 3 4} + +; Elimina elementos con disj +(disj #{1 2 3} 1) ; => #{2 3} + +; Comprueba su existencia usando el conjunto como una función: +(#{1 2 3} 1) ; => 1 +(#{1 2 3} 4) ; => nil + +; Hay más funciones en el namespace clojure.sets + +; Patrones útiles +;;;;;;;;;;;;;;;;; + +; Las construcciones lógicas en clojure son macros, y presentan el mismo aspecto +; que el resto de forms. +(if false "a" "b") ; => "b" +(if false "a") ; => nil + +; Usa let para crear un binding (asociación) temporal +(let [a 1 b 2] +  (> a b)) ; => false + +; Agrupa expresiones mediante do +(do +  (print "Hello") +  "World") ; => "World" (prints "Hello") + +; Las funciones tienen implicita la llamada a do +(defn print-and-say-hello [name] +  (print "Saying hello to " name) +  (str "Hello " name)) +(print-and-say-hello "Jeff") ;=> "Hello Jeff" (prints "Saying hello to Jeff") + +; Y el let también +(let [name "Urkel"] +  (print "Saying hello to " name) +  (str "Hello " name)) ; => "Hello Urkel" (prints "Saying hello to Urkel") + +; Módulos +;;;;;;;;;;;;;;; + +; Usa use para obtener todas las funciones del módulo +(use 'clojure.set) + +; Ahora podemos usar más operaciones de conjuntos +(intersection #{1 2 3} #{2 3 4}) ; => #{2 3} +(difference #{1 2 3} #{2 3 4}) ; => #{1} + +; Puedes escoger un subgrupo de funciones a importar, también +(use '[clojure.set :only [intersection]]) + +; Usa require para importar un módulo +(require 'clojure.string) + +; Usa / para llamar a las funciones de un módulo +; Aquí, el módulo es clojure.string y la función es blank? +(clojure.string/blank? "") ; => true + +; Puedes asignarle una abreviatura a un modulo al importarlo +(require '[clojure.string :as str]) +(str/replace "This is a test." #"[a-o]" str/upper-case) ; => "THIs Is A tEst." +; (#"" es una expresión regular) + +; Puedes usar require (y use, pero no lo hagas) desde un espacio de nombre +; usando :require, +; No necesitas preceder con comilla simple tus módulos si lo haces de esta +; forma. +(ns test +  (:require +    [clojure.string :as str] +    [clojure.set :as set])) + +; Java +;;;;;;;;;;;;;;;;; + +; Java tiene una enorme librería estándar, por lo que resulta util +; aprender como interactuar con ella. + +; Usa import para cargar un módulo de java +(import java.util.Date) + +; Puedes importar desde un ns también. +(ns test +  (:import java.util.Date +           java.util.Calendar)) + +; Usa el nombre de la clase con un "." al final para crear una nueva instancia +(Date.) ; <un objeto Date> + +; Usa "." para llamar a métodos o usa el atajo ".método" +(. (Date.) getTime) ; <un timestamp> +(.getTime (Date.)) ; exactamente la misma cosa + +; Usa / para llamar métodos estáticos. +(System/currentTimeMillis) ; <un timestamp> (System siempre está presente) + +; Usa doto para hacer frente al uso de clases (mutables) más tolerable +(import java.util.Calendar) +(doto (Calendar/getInstance) +  (.set 2000 1 1 0 0 0) +  .getTime) ; => A Date. set to 2000-01-01 00:00:00 + +; STM +;;;;;;;;;;;;;;;;; + +; Software Transactional Memory es un mecanismo que usa clojure para gestionar +; el estado persistente. Hay unas cuantas construcciones en clojure que +; hacen uso de este mecanismo. + +; Un atom es el más sencillo. Se le da un valor inicial +(def my-atom (atom {})) + +; Actualiza un atom con swap! +; swap! toma una función y la llama con el valor actual del atom +; como su primer argumento, y cualquier argumento restante como el segundo +(swap! my-atom assoc :a 1) ; Establece my-atom al resultado de (assoc {} :a 1) +(swap! my-atom assoc :b 2) ; Establece my-atom al resultado de (assoc {:a 1} :b 2) + +; Usa '@' para no referenciar al atom sino para obtener su valor +my-atom  ;=> Atom<#...> (Regresa el objeto Atom) +@my-atom ; => {:a 1 :b 2} + +; Un sencillo contador usando un atom sería +(def counter (atom 0)) +(defn inc-counter [] +  (swap! counter inc)) + +(inc-counter) +(inc-counter) +(inc-counter) +(inc-counter) +(inc-counter) + +@counter ; => 5 + +; Otros forms que utilizan STM son refs y agents. +; Refs: http://clojure.org/refs +; Agents: http://clojure.org/agents +### Lectura adicional + +Ésto queda lejos de ser exhaustivo, pero espero que sea suficiente para que puedas empezar tu camino. + +Clojure.org tiene muchos artículos: +[http://clojure.org/](http://clojure.org/) + +Clojuredocs.org contiene documentación con ejemplos para la mayoría de +funciones principales (pertenecientes al core): +[http://clojuredocs.org/quickref/Clojure%20Core](http://clojuredocs.org/quickref/Clojure%20Core) + +4Clojure es una genial forma de mejorar tus habilidades con clojure/FP: +[http://www.4clojure.com/](http://www.4clojure.com/) + +Clojure-doc.org (sí, de verdad) tiene un buen número de artículos con los que iniciarse en Clojure: +[http://clojure-doc.org/](http://clojure-doc.org/) diff --git a/es-es/coffeescript-es.html.markdown b/es-es/coffeescript-es.html.markdown index 78bb9be5..6bf430e6 100644 --- a/es-es/coffeescript-es.html.markdown +++ b/es-es/coffeescript-es.html.markdown @@ -44,7 +44,7 @@ math =  #  "cube": function(x) { return x * square(x); }  #} -# Símbolos: +# Número de argumentos variable:  race = (winner, runners...) ->    print winner, runners @@ -52,6 +52,6 @@ race = (winner, runners...) ->  alert "I knew it!" if elvis?  #=> if(typeof elvis !== "undefined" && elvis !== null) { alert("I knew it!"); } -# Colecciones por comprensión: +# Listas:  cubes = (math.cube num for num in list) #=> ...  ``` diff --git a/es-es/csharp-es.html.markdown b/es-es/csharp-es.html.markdown new file mode 100644 index 00000000..ef26d8ce --- /dev/null +++ b/es-es/csharp-es.html.markdown @@ -0,0 +1,632 @@ +--- +language: c# +contributors: +    - ["Irfan Charania", "https://github.com/irfancharania"] +    - ["Max Yankov", "https://github.com/golergka"] +translators: +    - ["Olfran Jiménez", "https://twitter.com/neslux"]	 +filename: LearnCSharp-es.cs +lang: es-es +--- + +C# es un lenguaje orientado a objetos elegante y de tipado seguro que +permite a los desarrolladores construir una variedad de aplicaciones +seguras y robustas que se ejecutan en el Framework .NET. + +[Lee más aquí.](http://msdn.microsoft.com/es-es/library/vstudio/z1zx9t92.aspx) + +```c# +// Los comentarios de una sola línea comienzan con // +/* +Los comentarios de múltiples líneas son de esta manera +*/ +/// <summary> +/// Este es un comentario de documentación XML +/// </summary> + +// Especifica el espacio de nombres que estará usando la aplicación +using System; +using System.Collections.Generic; + + +// Define un ambito para organizar el código en "paquetes" +namespace Learning +{ +	// Cada archivo .cs debe contener al menos una clase con el mismo nombre que el archivo +    // Se permite colocar cualquier nombre, pero no deberías por cuestiones de consistencia. +    public class LearnCSharp +    { +		// Una aplicación de consola debe tener un método main como punto de entrada +        public static void Main(string[] args) +        { +			// Usa Console.WriteLine para imprimir líneas +            Console.WriteLine("Hello World"); +            Console.WriteLine( +                "Integer: " + 10 + +                " Double: " + 3.14 + +                " Boolean: " + true); + +			// Para imprimir sin una nueva línea, usa Console.Write +            Console.Write("Hello "); +            Console.Write("World"); + + +            /////////////////////////////////////////////////// +            // Variables y Tipos +            // +            // Declara una variable usando <tipo> <nombre> +            /////////////////////////////////////////////////// + +            // Sbyte - Entero de 8 bits con signo +            // (-128 <= sbyte <= 127) +            sbyte fooSbyte = 100; + +            // Byte - Entero de 8 bits sin signo +            // (0 <= byte <= 255) +            byte fooByte = 100; + +            // Short - Entero de 16 bits con signo +            // (-32,768 <= short <= 32,767) +            short fooShort = 10000; + +            // Ushort - Entero de 16 bits sin signo +            // (0 <= ushort <= 65,535) +            ushort fooUshort = 10000; + +            // Integer - Entero de 32 bits con signo +            // (-2,147,483,648 <= int <= 2,147,483,647) +            int fooInt = 1; + +            // Uinteger - Entero de 32 bits sin signo +            // (0 <= uint <= 4,294,967,295) +            uint fooUint = 1; + +            // Long - Entero de 64 bits con signo +            // (-9,223,372,036,854,775,808 <= long <= 9,223,372,036,854,775,807) +            long fooLong = 100000L; +            // L es usado para indicar que esta variable es de tipo long o ulong +            // un valor sin este sufijo es tratado como int o uint dependiendo del tamaño. + +            // Ulong - Entero de 64 bits sin signo +            // (0 <= ulong <= 18,446,744,073,709,551,615) +            ulong fooUlong = 100000L; + +            // Float - Precisión simple de 32 bits. IEEE 754 Coma flotante +            // Precisión: 7 dígitos +            float fooFloat = 234.5f; +			// f es usado para indicar que el valor de esta variable es de tipo float +            // de otra manera sería tratado como si fuera de tipo double. + +            // Double - Doble precisión de 32 bits. IEEE 754 Coma flotante +            // Precisión: 15-16 dígitos +            double fooDouble = 123.4; + +            // Bool - true & false (verdadero y falso) +            bool fooBoolean = true; +            bool barBoolean = false; + +			// Char - Un solo caracter Unicode de 16 bits +            char fooChar = 'A'; + +            // Strings +            string fooString = "My string is here!"; +            Console.WriteLine(fooString); + +            // Formato de cadenas +            string fooFs = string.Format("Check Check, {0} {1}, {0} {1:0.0}", 1, 2); +            Console.WriteLine(fooFormattedString); + +            // Formato de fechas +            DateTime fooDate = DateTime.Now; +            Console.WriteLine(fooDate.ToString("hh:mm, dd MMM yyyy")); + +			// \n es un caracter de escape que comienza una nueva línea +            string barString = "Printing on a new line?\nNo Problem!"; +            Console.WriteLine(barString); + +            // Puede ser escrito mejor usando el símbolo @ +            string bazString = @"Here's some stuff +    on a new line!"; +            Console.WriteLine(bazString); + +            // Las comillas deben ser escapadas +            // usa \" para escaparlas +            string quotedString = "some \"quoted\" stuff"; +            Console.WriteLine(quotedString); + +			// usa "" cuando las cadenas comiencen con @ +            string quotedString2 = @"some MORE ""quoted"" stuff"; +            Console.WriteLine(quotedString2); + +			// Usa const o readonly para hacer las variables inmutables +			// los valores const son calculados en tiempo de compilación +            const int HOURS_I_WORK_PER_WEEK = 9001; + +            // Tipos que aceptan valores NULL (Nullable) +			// cualquier tipo de dato puede ser un tipo nulo añadiendole el sufijo ? +            // <tipo>? <variable> = <valor> +            int? nullable = null; +            Console.WriteLine("Nullable variable: " + nullable); + +			// Para usar valores nulos, tienes que usar la propiedad Value +			// o usar conversión explícita +            string? nullableString = "not null"; +            Console.WriteLine("Nullable value is: " + nullableString.Value + " or: " + (string) nullableString ); + +			// ?? is una manera corta de especificar valores por defecto +            // en caso de que la variable sea null +            int notNullable = nullable ?? 0; +            Console.WriteLine("Not nullable variable: " + notNullable); + +			// var - el compilador escogerá el tipo de dato más apropiado basado en el valor +            var fooImplicit = true; + +            /////////////////////////////////////////////////// +            // Estructura de datos +            /////////////////////////////////////////////////// +            Console.WriteLine("\n->Data Structures"); + +            // Arreglos +			// El tamaño del arreglo debe decidirse al momento de la declaración +            // El formato para declarar un arreglo es el siguiente: +            // <tipo_de_dato>[] <nombre_variable> = new <tipo_de_dato>[<tamaño>]; +            int[] intArray = new int[10]; +            string[] stringArray = new string[1]; +            bool[] boolArray = new bool[100]; + +			// Otra forma de declarar e inicializar un arreglo +            int[] y = { 9000, 1000, 1337 }; + +			// Indexar arreglos - Acceder a un elemento +            Console.WriteLine("intArray @ 0: " + intArray[0]); + +			// Los arreglos son de índice cero y son mutables. +            intArray[1] = 1; +            Console.WriteLine("intArray @ 1: " + intArray[1]); // => 1 + +            // Listas +			// Las listas son usadas más frecuentemente que los arreglos ya que son más flexibles +			// El formato para declarar una lista es el siguiente: +            // List<tipo_de_dato> <nombre_variable> = new List<tipo_de_dato>(); +            List<int> intList = new List<int>(); +            List<string> stringList = new List<string>(); + +            // Otra forma de declarar e inicializar una lista +            List<int> z = new List<int> { 9000, 1000, 1337 }; + +            // Indexar una lista - Acceder a un elemento +            // Las listas son de índice cero y son mutables. +            Console.WriteLine("z @ 0: " + z[2]); + +            // Las listas no tienen valores por defecto; +            // Un valor debe ser añadido antes de acceder al índice +            intList.Add(1); +            Console.WriteLine("intList @ 0: " + intList[0]); + + +            // Otras estructuras de datos a chequear: +            // +            // Pilas/Colas +            // Diccionarios +            // Colecciones de sólo lectura +            // Tuplas (.Net 4+) + + +            /////////////////////////////////////// +            // Operadores +            /////////////////////////////////////// +            Console.WriteLine("\n->Operators"); + +            int i1 = 1, i2 = 2; // Modo corto para múltiples declaraciones + +            // La aritmética es sencilla +            Console.WriteLine("1+2 = " + (i1 + i2)); // => 3 +            Console.WriteLine("2-1 = " + (i2 - i1)); // => 1 +            Console.WriteLine("2*1 = " + (i2 * i1)); // => 2 +            Console.WriteLine("1/2 = " + (i1 / i2)); // => 0 (0.5 truncated down) + +            // Módulo +            Console.WriteLine("11%3 = " + (11 % 3)); // => 2 + +            // Operadores de comparación +            Console.WriteLine("3 == 2? " + (3 == 2)); // => false +            Console.WriteLine("3 != 2? " + (3 != 2)); // => true +            Console.WriteLine("3 > 2? " + (3 > 2)); // => true +            Console.WriteLine("3 < 2? " + (3 < 2)); // => false +            Console.WriteLine("2 <= 2? " + (2 <= 2)); // => true +            Console.WriteLine("2 >= 2? " + (2 >= 2)); // => true + +            // Operadores a nivel de bits +            /* +            ~       Complemento a nivel de bits +            <<      Desplazamiento a la izquierda con signo +            >>      Desplazamiento a la derecha con signo +            >>>     Desplazamiento a la derecha sin signo +            &       AND a nivel de bits +            ^       XOR a nivel de bits +            |       OR a nivel de bits +            */ + +            // Incremento +            int i = 0; +            Console.WriteLine("\n->Inc/Dec-remento"); +            Console.WriteLine(i++); //i = 1. Posincrementación +            Console.WriteLine(++i); //i = 2. Preincremento +            Console.WriteLine(i--); //i = 1. Posdecremento +            Console.WriteLine(--i); //i = 0. Predecremento + + +            /////////////////////////////////////// +            // Estructuras de control +            /////////////////////////////////////// +            Console.WriteLine("\n->Control Structures"); + +            // Las condiciones if son como en lenguaje c +            int j = 10; +            if (j == 10) +            { +                Console.WriteLine("I get printed"); +            } +            else if (j > 10) +            { +                Console.WriteLine("I don't"); +            } +            else +            { +                Console.WriteLine("I also don't"); +            } + +            // Operador ternario +			// Un simple if/else puede ser escrito de la siguiente manera; +            // <condición> ? <true> : <false> +            string isTrue = (true) ? "True" : "False"; +            Console.WriteLine("Ternary demo: " + isTrue); + + +            // Bucle while +            int fooWhile = 0; +            while (fooWhile < 100) +            { +                //Console.WriteLine(fooWhile); +                //Incrementar el contador +                //Iterar 99 veces, fooWhile 0->99 +                fooWhile++; +            } +            Console.WriteLine("fooWhile Value: " + fooWhile); + +            // Bucle Do While +            int fooDoWhile = 0; +            do +            { +                //Console.WriteLine(fooDoWhile); +                //Incrementar el contador +                //Iterar 99 veces, fooDoWhile 0->99 +                fooDoWhile++; +            } while (fooDoWhile < 100); +            Console.WriteLine("fooDoWhile Value: " + fooDoWhile); + +            // Bucle For +            int fooFor; +            //Estructura del bucle for => for(<declaración_inicial>; <condición>; <incremento>) +            for (fooFor = 0; fooFor < 10; fooFor++) +            { +                //Console.WriteLine(fooFor); +                //Iterated 10 times, fooFor 0->9 +            } +            Console.WriteLine("fooFor Value: " + fooFor); + +            // Switch Case +			// El switch funciona con los tipos de datos byte, short, char e int +            // También funciona con las enumeraciones (discutidos en in Tipos Enum), +            // la clase string y algunas clases especiales que encapsulan +            // tipos primitivos: Character, Byte, Short, Integer. +            int month = 3; +            string monthString; +            switch (month) +            { +                case 1: +                    monthString = "January"; +                    break; +                case 2: +                    monthString = "February"; +                    break; +                case 3: +                    monthString = "March"; +                    break; +                default: +                    monthString = "Some other month"; +                    break; +            } +            Console.WriteLine("Switch Case Result: " + monthString); + + +            //////////////////////////////// +            // Conversión de tipos de datos +            //////////////////////////////// + +            // Convertir datos + +            // Convertir String a Integer +            // esto generará una excepción al fallar la conversión +            int.Parse("123");//retorna una versión entera de "123" + +            // TryParse establece la variable a un tipo por defecto +            // en este caso: 0 +            int tryInt; +            int.TryParse("123", out tryInt); + +            // Convertir Integer a String +            // La clase Convert tiene algunos métodos para facilitar las conversiones +            Convert.ToString(123); + +            /////////////////////////////////////// +            // Clases y Funciones +            /////////////////////////////////////// + +            Console.WriteLine("\n->Classes & Functions"); + +            // (Definición de la clase Bicycle (Bicicleta)) + +            // Usar new para instanciar una clase +            Bicycle trek = new Bicycle(); + +            // Llamar a los métodos del objeto +            trek.speedUp(3); // Siempre deberías usar métodos setter y métodos getter +            trek.setCadence(100); + +            // ToString es una convención para mostrar el valor del objeto. +            Console.WriteLine("trek info: " + trek.ToString()); + +            // Instanciar otra nueva bicicleta +            Bicycle octo = new Bicycle(5, 10); +            Console.WriteLine("octo info: " + octo.ToString()); + +            // Instanciar un Penny Farthing (Biciclo) +            PennyFarthing funbike = new PennyFarthing(1, 10); +            Console.WriteLine("funbike info: " + funbike.ToString()); + +            Console.Read(); +        } // Fin del método main + + +    } // Fin de la clase LearnCSharp + +    // Puedes incluir otras clases en un archivo .cs + + +    // Sintaxis para la declaración de clases: +    // <public/private/protected> class <nombre_de_clase>{ +    //    //campos, constructores, funciones todo adentro de la clase. +    //    //las funciones son llamadas métodos como en java. +    // } + +    public class Bicycle +    { +        // Campos/Variables de la clase Bicycle +        public int cadence; // Public: Accesible desde cualquier lado +        private int _speed;  // Private: Sólo es accesible desde dentro de la clase +        protected int gear; // Protected: Accesible desde clases y subclases +        internal int wheels; // Internal: Accesible en el ensamblado +        string name; // Todo es privado por defecto: Sólo es accesible desde dentro de esta clase + +        // Enum es un tipo valor que consiste un una serie de constantes con nombres +        public enum Brand +        { +            AIST, +            BMC, +            Electra, +            Gitane +        } +        // Definimos este tipo dentro de la clase Bicycle, por lo tanto es un tipo anidado +        // El código afuera de esta clase debería referenciar este tipo como Bicycle.Brand + +        public Brand brand; // Declaramos un tipo enum, podemos declarar un campo de este tipo + +        // Los miembros estáticos pertenecen al tipo mismo, no a un objeto en específico. +        static public int bicyclesCreated = 0; +        // Puedes acceder a ellos sin referenciar ningún objeto: +        // Console.WriteLine("Bicycles created: " + Bicycle.bicyclesCreated); + +        // Los valores readonly (Sólo lectura) son establecidos en tiempo de ejecución +        // sólo pueden ser asignados al momento de la declaración o dentro de un constructor +        readonly bool hasCardsInSpokes = false; // privado de sólo lectura + +        // Los constructores son una forma de crear clases +        // Este es un constructor por defecto +        private Bicycle() +        { +            gear = 1; +            cadence = 50; +            _speed = 5; +            name = "Bontrager"; +            brand = Brand.AIST; +            bicyclesCreated++; +        } + +        // Este es un constructor específico (contiene argumentos) +        public Bicycle(int startCadence, int startSpeed, int startGear, +                       string name, bool hasCardsInSpokes, Brand brand) +        { +            this.gear = startGear; // La palabra reservada "this" señala el objeto actual +            this.cadence = startCadence; +            this._speed = startSpeed; +            this.name = name; // Puede ser útil cuando hay un conflicto de nombres +            this.hasCardsInSpokes = hasCardsInSpokes; +            this.brand = brand; +        } + +        // Los constructores pueden ser encadenados +        public Bicycle(int startCadence, int startSpeed, Brand brand) : +            this(startCadence, startSpeed, 0, "big wheels", true) +        { +        } + +        // Sintaxis para Funciones: +        // <public/private/protected> <tipo_retorno> <nombre_funcion>(<args>) + +        // Las clases pueden implementar getters y setters para sus campos +        // o pueden implementar propiedades + +        // Sintaxis para la declaración de métodos: +        // <ámbito> <tipo_retorno> <nombre_método>(<argumentos>) +        public int GetCadence() +        { +            return cadence; +        } + +        // Los métodos void no requieren usar return +        public void SetCadence(int newValue) +        { +            cadence = newValue; +        } + +        // La palabra reservada virtual indica que este método puede ser sobrescrito +        public virtual void SetGear(int newValue) +        { +            gear = newValue; +        } + +        // Los parámetros de un método pueden tener valores por defecto. +		// En este caso, los métodos pueden ser llamados omitiendo esos parámetros +        public void SpeedUp(int increment = 1) +        { +            _speed += increment; +        } + +        public void SlowDown(int decrement = 1) +        { +            _speed -= decrement; +        } + +        // Propiedades y valores get/set +        // Cuando los datos sólo necesitan ser accedidos, considera usar propiedades. +        // Las propiedades pueden tener get, set o ambos +        private bool _hasTassles; // variable privada +        public bool HasTassles // acceso público +        { +            get { return _hasTassles; } +            set { _hasTassles = value; } +        } + +        // Las propiedades pueden ser auto implementadas +        public int FrameSize +        { +            get; +            // Puedes especificar modificadores de acceso tanto para get como para set +            // esto significa que sólo dentro de la clase Bicycle se puede modificar Framesize +            private set; +        } + +        //Método para mostrar los valores de atributos de este objeto. +        public override string ToString() +        { +            return "gear: " + gear + +                    " cadence: " + cadence + +                    " speed: " + _speed + +                    " name: " + name + +                    " cards in spokes: " + (hasCardsInSpokes ? "yes" : "no") + +                    "\n------------------------------\n" +                    ; +        } + +        // Los métodos también pueden ser estáticos. Puede ser útil para métodos de ayuda +        public static bool DidWeCreateEnoughBycles() +        { +            // Dentro de un método esático, +			// Sólo podemos hacer referencia a miembros estáticos de clases +            return bicyclesCreated > 9000; +        }   // Si tu clase sólo necesita miembros estáticos, +		    // considera establecer la clase como static. + +    } // fin de la clase Bicycle + +    // PennyFarthing es una subclase de Bicycle +    class PennyFarthing : Bicycle +    { +        // (Penny Farthings son las bicicletas con una rueda delantera enorme. +        // No tienen engranajes.) + +        // llamar al constructor de la clase padre +        public PennyFarthing(int startCadence, int startSpeed) : +            base(startCadence, startSpeed, 0, "PennyFarthing", true) +        { +        } + +        public override void SetGear(int gear) +        { +            gear = 0; +        } + +        public override string ToString() +        { +            string result = "PennyFarthing bicycle "; +            result += base.ToString(); // Llamar a la versión base del método +            return reuslt; +        } +    } + +    // Las interfaces sólo contienen las declaraciones +	// de los miembros, sin la implementación. +    interface IJumpable +    { +        void Jump(int meters); // todos los miembros de interfaces son implícitamente públicos +    } + +    interface IBreakable +    { +		// Las interfaces pueden contener tanto propiedades como métodos, campos y eventos +        bool Broken { get; } +    } + +	// Las clases sólo heredan de alguna otra clase, pero pueden implementar +	// cualquier cantidad de interfaces +    class MountainBike : Bicycle, IJumpable, IBreakable +    { +        int damage = 0; + +        public void Jump(int meters) +        { +            damage += meters; +        } + +        public void Broken +        { +            get +            { +                return damage > 100; +            } +        } +    } +} // Fin del espacio de nombres + +``` + +## Temas no cubiertos + + * Flags + * Attributes + * Generics (T), Delegates, Func, Actions, lambda expressions + * Static properties + * Exceptions, Abstraction + * LINQ + * ASP.NET (Web Forms/MVC/WebMatrix) + * Winforms + * Windows Presentation Foundation (WPF) + + + +## Lecturas recomendadas + + * [DotNetPerls](http://www.dotnetperls.com) + * [C# in Depth](http://manning.com/skeet2) + * [Programming C#](http://shop.oreilly.com/product/0636920024064.do) + * [LINQ](http://shop.oreilly.com/product/9780596519254.do) + * [MSDN Library](http://msdn.microsoft.com/es-es/library/618ayhy6.aspx) + * [ASP.NET MVC Tutorials](http://www.asp.net/mvc/tutorials) + * [ASP.NET Web Matrix Tutorials](http://www.asp.net/web-pages/tutorials) + * [ASP.NET Web Forms Tutorials](http://www.asp.net/web-forms/tutorials) + * [Windows Forms Programming in C#](http://www.amazon.com/Windows-Forms-Programming-Chris-Sells/dp/0321116208) + + + +[Convenciones de código de C#](http://msdn.microsoft.com/es-es/library/vstudio/ff926074.aspx) diff --git a/es-es/go-es.html.markdown b/es-es/go-es.html.markdown new file mode 100644 index 00000000..434f6713 --- /dev/null +++ b/es-es/go-es.html.markdown @@ -0,0 +1,301 @@ +--- +name: Go +category: language +language: Go +filename: learngo.go +contributors: +    - ["Sonia Keys", "https://github.com/soniakeys"] +translators: +    - ["Adrian Espinosa", "http://www.adrianespinosa.com"] +lang: es-es + + +--- + +Go fue creado por la necesidad de hacer el trabajo rápidamente.  No es la última +tendencia en informática, pero es la forma nueva y más rápida de resolver problemas reales. + +Tiene conceptos familiares de lenguajes imperativos con tipado estático. +Es rápido compilando y rápido al ejecutar, añade una concurrencia fácil de entender para las CPUs de varios núcleos de hoy en día, y tiene características que ayudan con la programación a gran escala. +Go viene con una librería estándar muy buena y una comunidad entusiasta. + +```go +// Comentario de una sola línea +/* Comentario  +   multi línea */ + +// La cláusula package aparece al comienzo de cada archivo fuente. +// Main es un nombre especial que declara un ejecutable en vez de una librería. +package main + +// La declaración Import declara los paquetes de librerías referenciados en este archivo. +import ( +    "fmt"      // Un paquete en la librería estándar de Go +    "net/http" // Sí, un servidor web! +    "strconv"  // Conversiones de cadenas +) + +// Definición de una función. Main es especial. Es el punto de entrada para el ejecutable. +// Te guste o no, Go utiliza llaves. +func main() { +    // Println imprime una línea a stdout. +    // Cualificalo con el nombre del paquete, fmt. +    fmt.Println("Hello world!") + +    // Llama a otra función de este paquete. +    beyondHello() +} + +// Las funciones llevan parámetros entre paréntesis. +// Si no hay parámetros, los paréntesis siguen siendo obligatorios. +func beyondHello() { +    var x int // Declaración de una variable. Las variables se deben declarar antes de  +    // utilizarlas. +    x = 3     // Asignación de variables. +    // Declaración "corta" con := para inferir el tipo, declarar y asignar. +    y := 4 +    sum, prod := learnMultiple(x, y)        // función devuelve dos valores +    fmt.Println("sum:", sum, "prod:", prod) // simple salida +    learnTypes()                            // < y minutes, learn more! +} + +// Las funciones pueden tener parámetros y (múltiples!) valores de retorno. +func learnMultiple(x, y int) (sum, prod int) { +    return x + y, x * y // devolver dos valores +} + +// Algunos tipos incorporados y literales. +func learnTypes() { +    // La declaración corta suele darte lo que quieres. +    s := "Learn Go!" // tipo cadena + +    s2 := ` Un tipo cadena "puro" puede incluir +saltos de línea.` // mismo tipo cadena + +    // Literal no ASCII. Los fuentes de Go son UTF-8. +    g := 'Σ' // tipo rune, un alias de uint32, alberga un punto unicode. +    f := 3.14195 // float64, el estándar IEEE-754 de coma flotante 64-bit +    c := 3 + 4i  // complex128, representado internamente por dos float64 +    // Sintaxis Var con inicializadores. +    var u uint = 7 // sin signo, pero la implementación depende del tamaño como en int +    var pi float32 = 22. / 7 + +    // Sintáxis de conversión con una declaración corta. +    n := byte('\n') // byte es un alias de uint8 + +    // Los Arrays tienen un tamaño fijo a la hora de compilar. +    var a4 [4]int           // un array de 4 ints, inicializados a 0 +    a3 := [...]int{3, 1, 5} // un array de 3 ints, inicializados como se indica + +    // Los Slices tienen tamaño dinámico. Los arrays y slices tienen sus ventajas +    // y desventajas pero los casos de uso para los slices son más comunes. +    s3 := []int{4, 5, 9}    // Comparar con a3. No hay puntos suspensivos +    s4 := make([]int, 4)    // Asigna slices de 4 ints, inicializados a 0 +    var d2 [][]float64      // solo declaración, sin asignación +    bs := []byte("a slice") // sintaxis de conversión de tipo + +    p, q := learnMemory() // declara p, q para ser un tipo puntero a int. +    fmt.Println(*p, *q)   // * sigue un puntero. Esto imprime dos ints. + +    // Los Maps son arrays asociativos dinámicos, como los hash o diccionarios +    // de otros lenguajes +    m := map[string]int{"three": 3, "four": 4} +    m["one"] = 1 + +    // Las variables no utilizadas en Go producen error. +    // El guión bajo permite "utilizar" una variable, pero descartar su valor. +    _, _, _, _, _, _, _, _, _ = s2, g, f, u, pi, n, a3, s4, bs +    // Esto cuenta como utilización de variables. +    fmt.Println(s, c, a4, s3, d2, m) + +    learnFlowControl() // vuelta al flujo +} + +// Go posee recolector de basura. Tiene puntero pero no aritmética de punteros. +// Puedes cometer un errores con un puntero nil, pero no incrementando un puntero. +func learnMemory() (p, q *int) { +    // q y p tienen un tipo puntero a int. +    p = new(int) // función incorporada que asigna memoria. +    // La asignación de int se inicializa a 0, p ya no es nil. +    s := make([]int, 20) // asigna 20 ints a un solo bloque de memoria. +    s[3] = 7             // asignar uno de ellos +    r := -2              // declarar otra variable local +    return &s[3], &r     // & toma la dirección de un objeto. +} + +func expensiveComputation() int { +    return 1e6 +} + +func learnFlowControl() { +    // La declaración If requiere llaves, pero no paréntesis. +    if true { +        fmt.Println("told ya") +    } +    // El formato está estandarizado por el comando "go fmt." +    if false { +        // pout +    } else { +        // gloat +    } +    // Utiliza switch preferiblemente para if encadenados. +    x := 1 +    switch x { +    case 0: +    case 1: +        // los cases no se mezclan, no requieren de "break" +    case 2: +        // no llega +    } +    // Como if, for no utiliza paréntesis tampoco. +    for x := 0; x < 3; x++ { // ++ es una sentencia +        fmt.Println("iteration", x) +    } +    // x == 1 aqui. + +    // For es la única sentencia de bucle en Go, pero tiene formas alternativas. +    for { // bucle infinito +        break    // solo bromeaba! +        continue // no llega +    } +    // Como en for, := en una sentencia if significa declarar y asignar primero, +    // luego comprobar y > x. +    if y := expensiveComputation(); y > x { +        x = y +    } +    // Los literales de funciones son "closures". +    xBig := func() bool { +        return x > 100 // referencia a x declarada encima de la sentencia switch. +    } +    fmt.Println("xBig:", xBig()) // verdadero (la última vez asignamos 1e6 a x) +    x /= 1e5                     // esto lo hace  == 10 +    fmt.Println("xBig:", xBig()) // ahora es falso + +    // Cuando lo necesites, te encantará. +    goto love +love: + +    learnInterfaces() // Buen material dentro de poco! +} + +// Define Stringer como un tipo interfaz con un método, String. +type Stringer interface { +    String() string +} + +// Define pair como un struct con dos campos int, x e y. +type pair struct { +    x, y int +} + +// Define un método del tipo pair. Pair ahora implementa Stringer. +func (p pair) String() string { // p se llama "recibidor" +    // Sprintf es otra función pública del paquete fmt. +    // La sintaxis con punto referencia campos de p. +    return fmt.Sprintf("(%d, %d)", p.x, p.y) +} + +func learnInterfaces() { +    // La sintaxis de llaves es un "literal struct". Evalúa a un struct +    // inicializado.  La sintaxis := declara e inicializa p a este struct. +    p := pair{3, 4} +    fmt.Println(p.String()) // llamar al método String de p, de tipo pair. +    var i Stringer          // declarar i como interfaz tipo Stringer. +    i = p                   // válido porque pair implementa Stringer +    // Llamar al metodo String de i, de tipo Stringer. Misma salida que arriba +    fmt.Println(i.String()) + +    // Las funciones en el paquete fmt llaman al método String para preguntar a un objeto +    // por una versión imprimible de si mismo +    fmt.Println(p) // salida igual que arriba. Println llama al método String. +    fmt.Println(i) // salida igual que arriba. + +    learnErrorHandling() +} + +func learnErrorHandling() { +    // ", ok" forma utilizada para saber si algo funcionó o no. +    m := map[int]string{3: "three", 4: "four"} +    if x, ok := m[1]; !ok { // ok será falso porque 1 no está en el map. +        fmt.Println("no one there") +    } else { +        fmt.Print(x) // x sería el valor, si estuviera en el map. +    } +    // Un valor de error comunica más información sobre el problema aparte de "ok". +    if _, err := strconv.Atoi("non-int"); err != nil { // _ descarta el valor +        // imprime "strconv.ParseInt: parsing "non-int": invalid syntax" +        fmt.Println(err) +    } +    // Revisarmeos las interfaces más tarde. Mientras tanto, +    learnConcurrency() +} + +// c es un canal,  un objeto de comunicación de concurrencia segura. +func inc(i int, c chan int) { +    c <- i + 1 // <- es el operador "enviar" cuando un canal aparece a la izquierda. +} + +// Utilizaremos inc para incrementar algunos números concurrentemente. +func learnConcurrency() { +    // Misma función make utilizada antes para crear un slice. Make asigna e +    // inicializa slices, maps, y channels. +    c := make(chan int) +    // Iniciar tres goroutines concurrentes. Los números serán incrementados +    // concurrentemente, quizás en paralelo si la máquina es capaz y +    // está correctamente configurada. Las tres envían al mismo channel. +    go inc(0, c) // go es una sentencia que inicia una nueva goroutine. +    go inc(10, c) +    go inc(-805, c) +    // Leer los tres resultados del channel e imprimirlos. +    // No se puede saber en que orden llegarán los resultados! +    fmt.Println(<-c, <-c, <-c) // channel a la derecha, <- es el operador "recibir". + +    cs := make(chan string)       // otro channel, este gestiona cadenas. +    cc := make(chan chan string)  // un channel de cadenas de channels. +    go func() { c <- 84 }()       // iniciar una nueva goroutine solo para enviar un valor. +    go func() { cs <- "wordy" }() // otra vez, para cs en esta ocasión +    // Select tiene una sintáxis parecida a la sentencia switch pero cada caso involucra +    // una operacion de channels. Selecciona un caso de forma aleatoria de los casos +    // que están listos para comunicarse. +    select { +    case i := <-c: // el valor recibido puede ser asignado a una variable +        fmt.Printf("it's a %T", i) +    case <-cs: // o el valor puede ser descartado +        fmt.Println("it's a string") +    case <-cc: // channel vacío, no está listo para la comunicación. +        fmt.Println("didn't happen.") +    } +    // En este punto un valor fue devuelvto de c o cs. Uno de las dos +    // goroutines que se iniciaron se ha completado, la otrá permancerá bloqueada. + +    learnWebProgramming() // Go lo hace. Tu también quieres hacerlo. +} + +// Una simple función del paquete http inicia un servidor web. +func learnWebProgramming() { +    // El primer parámetro de la direccinón TCP a la que escuchar. +    // El segundo parámetro es una interfaz, concretamente http.Handler. +    err := http.ListenAndServe(":8080", pair{}) +    fmt.Println(err) // no ignorar errores +} + +// Haz pair un http.Handler implementando su único método, ServeHTTP. +func (p pair) ServeHTTP(w http.ResponseWriter, r *http.Request) { +    // Servir datos con un método de http.ResponseWriter +    w.Write([]byte("You learned Go in Y minutes!")) +} +``` + +## Para leer más  + +La raíz de todas las cosas de Go es la [web oficial de Go](http://golang.org/). +Ahí puedes seguir el tutorial, jugar interactivamente y leer mucho. + +La propia definición del lenguaje también está altamente recomendada. Es fácil de leer +e increíblemente corta (como otras definiciones de lenguajes hoy en día) + +En la lista de lectura de estudiantes de Go está el código fuente de la +librería estándar. Muy bien documentada, demuestra lo mejor de Go leíble, comprendible, +estilo Go y formas Go. Pincha en el nombre de una función en la documentación +y te aparecerá el código fuente! + diff --git a/es-es/perl-es.html.markdown b/es-es/perl-es.html.markdown new file mode 100644 index 00000000..4f0c26c1 --- /dev/null +++ b/es-es/perl-es.html.markdown @@ -0,0 +1,160 @@ +--- +name: perl +category: language +language: perl +filename: learnperl-es.pl +contributors: +    - ["Korjavin Ivan", "http://github.com/korjavin"] +translators: +    - ["Francisco Gomez", "http://github.com/frncscgmz"] +lang: es-es +--- + +Perl 5 es un lenguaje de programación altamente capaz, rico en características con mas de 25 años de desarrollo. + +Perl 5 corre en mas de 100 plataformas desde portales hasta mainframes y es adecuado para realizar prototipos rápidos hasta desarrollar proyectos a gran escala. + +```perl +# Comentarios de una sola linea con un carácter hash. + +#### Tipos de variables en Perl + +# Las variables comienzan con el símbolo $. +# Un nombre de variable valido empieza con una letra o un guión bajo, +# seguido por cualquier numero de letras, números o guiones bajos. + +### Perl tiene tres tipos principales de variables: escalares, arreglos y hashes. + +## Escalares +# Un escalar representa un solo valor: +my $animal    = "camello"; +my $respuesta = 42; + +# Los valores escalares pueden ser cadenas de caracteres, números enteros o  +# de punto flotante, Perl automáticamente los convertirá como sea requerido. + +## Arreglos +# Un arreglo representa una lista de valores: +my @animales = {"camello","llama","buho"}; +my @numeros  = {23,42,69}; +my @mixto    = {"camello",42,1.23}; + + + +## Hashes +#   Un hash representa un conjunto de pares llave/valor: + +my %color_fruta = {"manzana","rojo","banana","amarillo"}; + +#  Puedes usar un espacio en blanco y el operador "=>" para asignarlos mas +#  fácilmente. + +my %color_fruta = ( +   manzana => "rojo", +   banana  => "amarillo", +   ); +# Los escalares, arreglos y hashes están mas documentados en perldata. (perldoc perldata). + +# Los tipos de datos mas complejos pueden ser construidos utilizando  +# referencias, las cuales te permiten construir listas y hashes dentro  +# de listas y hashes. + +#### Estructuras condicionales y de ciclos + +# Perl tiene la mayoría de las estructuras condicionales y de ciclos mas comunes. + +if ( $var ) { +     ... +} elsif ( $var eq 'bar' ) {  +     ... +} else { +     ... +} + +unless ( condicion ) { +                  ... +              } +# Esto es proporcionado como una version mas fácil de leer que "if (!condición)" + +# La post condición al modo Perl +print "Yow!" if $zippy; +print "No tenemos bananas" unless $bananas; + +# while +  while ( condicion ) { +                  ... +               } + + +# for y foreach +for ($i = 0; $i <= $max; $i++) { +                  ... +               } + +foreach (@array) { +                   print "Este elemento es $_\n"; +               } + + +#### Expresiones regulares + +# El soporte de expresiones regulares en Perl es muy amplio y profundo, y es  +# sujeto a una extensa documentación en perlrequick, perlretut, entre otros. +# Sin embargo, resumiendo: + +# Pareo simple +if (/foo/)       { ... }  # verdadero si $_ contiene "foo" +if ($a =~ /foo/) { ... }  # verdadero si $a contiene "foo" + +# Substitución simple +$a =~ s/foo/bar/;         # remplaza foo con bar en $a +$a =~ s/foo/bar/g;        # remplaza TODAS LAS INSTANCIAS de foo con bar en $a + + +#### Archivos e I/O + +# Puedes abrir un archivo para obtener datos o escribirlos utilizando la  +# función "open()". + +open(my $entrada, "<"  "entrada.txt") or die "No es posible abrir entrada.txt: $!"; +open(my $salida,  ">", "salida.txt")  or die "No es posible abrir salida.txt: $!"; +open(my $log,     ">>", "mi.log")     or die "No es posible abrir mi.log: $!"; + +# Es posible leer desde un gestor de archivo abierto utilizando el operador "<>"  +# operador. En contexto escalar leer una sola linea desde el gestor de  +# archivo, y en contexto de lista leer el archivo completo en donde, asigna  +# cada linea a un elemento de la lista. + +my $linea  = <$entrada>; +my @lineas = <$entrada>; + +#### Escribiendo subrutinas + +# Escribir subrutinas es fácil: + +sub logger { +   my $mensajelog = shift; +   open my $archivolog, ">>", "mi.log" or die "No es posible abrir mi.log: $!"; +   print $archivolog $mensajelog; +} + +# Ahora podemos utilizar la subrutina al igual que cualquier otra función  +# incorporada: + +logger("Tenemos una subrutina logger!"); + + +``` + +#### Utilizando módulos Perl + +Los módulos en Perl proveen una gama de funciones que te pueden ayudar a evitar reinventar la rueda, estas pueden ser descargadas desde CPAN( http://www.cpan.org/ ). Algunos de los módulos mas populares ya están incluidos con la misma distribución de Perl.  + +perlfaq contiene preguntas y respuestas relacionadas con muchas tareas comunes, y algunas veces provee sugerencias sobre buenos módulos CPAN para usar. + +#### Material de Lectura + +     - [perl-tutorial](http://perl-tutorial.org/) +     - [Aprende en www.perl.com](http://www.perl.org/learn.html) +     - [perldoc](http://perldoc.perl.org/) +     - y perl incorporado: `perldoc perlintro` | 
