diff options
Diffstat (limited to 'es-es/fsharp-es.html.markdown')
| -rw-r--r-- | es-es/fsharp-es.html.markdown | 629 | 
1 files changed, 629 insertions, 0 deletions
| diff --git a/es-es/fsharp-es.html.markdown b/es-es/fsharp-es.html.markdown new file mode 100644 index 00000000..b7f80c44 --- /dev/null +++ b/es-es/fsharp-es.html.markdown @@ -0,0 +1,629 @@ +--- +language: F# +lang: es-es +contributors: +  - ['Scott Wlaschin', 'http://fsharpforfunandprofit.com/'] +translators: +  - ['Angel Arciniega', 'https://github.com/AngelsProjects'] +filename: learnfsharp-es.fs +--- + +F# es un lenguaje de programación funcional y orientado a objetos. Es gratis y su código fuente está abierto. Se ejecuta en Linux, Mac, Windows y más. + +Tiene un poderoso sistema de tipado que atrapa muchos errores de tiempo de compilación, pero usa inferencias de tipados que le permiten ser leídos como un lenguaje dinámico. + +La sintaxis de F# es diferente de los lenguajes que heredan de C. + +- Las llaves no se usan para delimitar bloques de código. En cambio, se usa sangría (como en Python). +- Los espacios se usan para separar parámetros en lugar de comas. + +Si quiere probar el siguiente código, puede ir a [tryfsharp.org](http://www.tryfsharp.org/Create) y pegarlo en [REPL](https://es.wikipedia.org/wiki/REPL). + +```fsharp +// Los comentarios de una línea se escibren con una doble diagonal +(* Los comentarios multilínea usan parentesis (* . . . *) + +-final del comentario multilínea- *) + +// ================================================ +// Syntaxis básica +// ================================================ + +// ------ "Variables" (pero no realmente) ------ +// La palabra reservada "let" define un valor (inmutable) +let miEntero = 5 +let miFlotante = 3.14 +let miCadena = "hola"           // Tenga en cuenta que no es necesario ningún tipado + +// ------ Listas ------ +let dosACinco = [2;3;4;5]        // Los corchetes crean una lista con +                                 // punto y coma para delimitadores. +let unoACinco = 1 :: dosACinco   // :: Crea una lista con un nuevo elemento +// El resultado es [1;2;3;4;5] +let ceroACinco = [0;1] @ dosACinco   // @ Concatena dos listas + +// IMPORTANTE: las comas no se usan para delimitar, +// solo punto y coma ! + +// ------ Funciones ------ +// La palabra reservada "let" también define el nombre de una función. +let cuadrado x = x * x          // Tenga en cuenta que no se usa paréntesis. +cuadrado 3                      // Ahora, ejecutemos la función. +                              // De nuevo, sin paréntesis. + +let agregar x y = x + y           // ¡No use add (x, y)! Eso significa +                              // algo completamente diferente. +agregar 2 3                       // Ahora, ejecutemos la función. + +// Para definir una función en varias líneas, usemos la sangría. +// Los puntos y coma no son necesarios. +let pares lista = +   let esPar x = x%2 = 0     // Establece "esPar" como una función anidada +   List.filter esPar lista    // List.filter es una función de la biblioteca +                              // dos parámetros: una función que devuelve un +                              // booleano y una lista en la que trabajar + +pares unoACinco               // Ahora, ejecutemos la función. + +// Puedes usar paréntesis para aclarar. +// En este ejemplo, "map" se ejecuta primero, con dos argumentos, +// entonces "sum" se ejecuta en el resultado. +// Sin los paréntesis, "List.map" se pasará como argumento a List.sum. +let sumaDeCuadradosHasta100 = +   List.sum ( List.map cuadrado [1..100] ) + +// Puedes redirigir la salida de una función a otra con "|>" +// Redirigir datos es muy común en F#, como con los pipes de UNIX. + +// Aquí está la misma función sumOfSquares escrita usando pipes +let sumaDeCuadradosHasta100piped = +   [1..100] |> List.map cuadrado |> List.sum  // "cuadrado" se declara antes + +// Puede definir lambdas (funciones anónimas) gracias a la palabra clave "fun" +let sumaDeCuadradosHasta100ConFuncion = +   [1..100] |> List.map (fun x -> x*x) |> List.sum + +// En F#, no hay palabra clave "return". Una función siempre regresa +// el valor de la última expresión utilizada. + +// ------ Coincidencia de patrones ------ +// Match..with .. es una sobrecarga de la condición de case/ switch. +let coincidenciaDePatronSimple = +   let x = "a" +   match x with +    | "a" -> printfn "x es a" +    | "b" -> printfn "x es b" +    | _ -> printfn "x es algo mas"   // guion bajo corresponde con todos los demás + +// F# no permite valores nulos por defecto - debe usar el tipado de Option +// y luego coincide con el patrón. +// Some(..) y None son aproximadamente análogos a los envoltorios Nullable +let valorValido = Some(99) +let valorInvalido = None + +// En este ejemplo, match..with encuentra una coincidencia con "Some" y "None", +// y muestra el valor de "Some" al mismo tiempo. +let coincidenciaDePatronDeOpciones entrada = +   match entrada with +    | Some i -> printfn "la entrada es un int=%d" i +    | None -> printfn "entrada faltante" + +coincidenciaDePatronDeOpciones validValue +coincidenciaDePatronDeOpciones invalidValue + +// ------ Viendo ------ +// Las funciones printf/printfn son similares a las funciones +// Console.Write/WriteLine de C#. +printfn "Imprimiendo un int %i, a float %f, a bool %b" 1 2.0 true +printfn "Un string %s, y algo generico %A" "hola" [1;2;3;4] + +// También hay funciones printf/sprintfn para formatear datos +// en cadena. Es similar al String.Format de C#. + +// ================================================ +// Mas sobre funciones +// ================================================ + +// F# es un verdadero lenguaje funcional - las funciones son +// entidades de primer nivel y se pueden combinar fácilmente +// para crear construcciones poderosas + +// Los módulos se utilizan para agrupar funciones juntas. +// Se requiere sangría para cada módulo anidado. +module EjemploDeFuncion = + +    // define una función de suma simple +    let agregar x y = x + y + +    // uso básico de una función +    let a = agregar 1 2 +    printfn "1+2 = %i" a + +    // aplicación parcial para "hornear en" los parámetros (?) +    let agregar42 = agregar 42 +    let b = agregar42 1 +    printfn "42+1 = %i" b + +    // composición para combinar funciones +    let agregar1 = agregar 1 +    let agregar2 = agregar 2 +    let agregar3 = agregar1 >> agregar2 +    let c = agregar3 7 +    printfn "3+7 = %i" c + +    // funciones de primer nivel +    [1..10] |> List.map agregar3 |> printfn "la nueva lista es %A" + +    // listas de funciones y más +    let agregar6 = [agregar1; agregar2; agregar3] |> List.reduce (>>) +    let d = agregar6 7 +    printfn "1+2+3+7 = %i" d + +// ================================================ +// Lista de colecciones +// ================================================ + +// Il y a trois types de collection ordonnée : +// * Les listes sont les collections immutables les plus basiques +// * Les tableaux sont mutables et plus efficients +// * Les séquences sont lazy et infinies (e.g. un enumerator) +// +// Des autres collections incluent des maps immutables et des sets +// plus toutes les collections de .NET + +module EjemplosDeLista = + +    // las listas utilizan corchetes +    let lista1 = ["a";"b"] +    let lista2 = "c" :: lista1    // :: para una adición al principio +    let lista3 = lista1 @ lista2   // @ para la concatenación + +    // Lista de comprensión (alias generadores) +    let cuadrados = [for i in 1..10 do yield i*i] + +    //  Generador de números primos +    let rec tamiz = function +        | (p::xs) -> p :: tamiz [ for x in xs do if x % p > 0 then yield x ] +        | []      -> [] +    let primos = tamiz [2..50] +    printfn "%A" primos + +    // coincidencia de patrones para listas +    let listaDeCoincidencias unaLista = +        match unaLista with +        | [] -> printfn "la lista esta vacia" +        | [primero] -> printfn "la lista tiene un elemento %A " primero +        | [primero; segundo] -> printfn "la lista es %A y %A" primero segundo +        | _ -> printfn "la lista tiene mas de dos elementos" + +    listaDeCoincidencias [1;2;3;4] +    listaDeCoincidencias [1;2] +    listaDeCoincidencias [1] +    listaDeCoincidencias [] + +    // Récursion en utilisant les listes +    let rec suma unaLista = +        match unaLista with +        | [] -> 0 +        | x::xs -> x + suma xs +    suma [1..10] + +    // ----------------------------------------- +    // Funciones de la biblioteca estándar +    // ----------------------------------------- + +    // mapeo +    let agregar3 x = x + 3 +    [1..10] |> List.map agregar3 + +    // filtrado +    let par x = x % 2 = 0 +    [1..10] |> List.filter par + +    // mucho más - consulte la documentación + +module EjemploDeArreglo = + +    // los arreglos usan corchetes con barras. +    let arreglo1 = [| "a";"b" |] +    let primero = arreglo1.[0]        // se accede al índice usando un punto + +    // la coincidencia de patrones de los arreglos es la misma que la de las listas +    let coincidenciaDeArreglos una Lista = +        match unaLista with +        | [| |] -> printfn "la matriz esta vacia" +        | [| primero |] -> printfn "el arreglo tiene un elemento %A " primero +        | [| primero; second |] -> printfn "el arreglo es %A y %A" primero segundo +        | _ -> printfn "el arreglo tiene mas de dos elementos" + +    coincidenciaDeArreglos [| 1;2;3;4 |] + +    // La biblioteca estándar funciona como listas +    [| 1..10 |] +    |> Array.map (fun i -> i+3) +    |> Array.filter (fun i -> i%2 = 0) +    |> Array.iter (printfn "el valor es %i. ") + +module EjemploDeSecuencia = + +    // Las secuencias usan llaves +    let secuencia1 = seq { yield "a"; yield "b" } + +    // Las secuencias pueden usar yield y +    // puede contener subsecuencias +    let extranio = seq { +        // "yield" agrega un elemento +        yield 1; yield 2; + +        // "yield!" agrega una subsecuencia completa +        yield! [5..10] +        yield! seq { +            for i in 1..10 do +              if i%2 = 0 then yield i }} +    // prueba +    extranio |> Seq.toList + +    // Las secuencias se pueden crear usando "unfold" +    // Esta es la secuencia de fibonacci +    let fib = Seq.unfold (fun (fst,snd) -> +        Some(fst + snd, (snd, fst + snd))) (0,1) + +    // prueba +    let fib10 = fib |> Seq.take 10 |> Seq.toList +    printf "Los primeros 10 fib son %A" fib10 + +// ================================================ +// Tipos de datos +// ================================================ + +module EejemploDeTipoDeDatos = + +    // Todos los datos son inmutables por defecto + +     // las tuplas son tipos anónimos simples y rápidos +     // - Usamos una coma para crear una tupla +    let dosTuplas = 1,2 +    let tresTuplas = "a",2,true + +    // Combinación de patrones para desempaquetar +    let x,y = dosTuplas  // asignado x=1 y=2 + +    // ------------------------------------ +    // Los tipos de registro tienen campos con nombre +    // ------------------------------------ + +    // Usamos "type" con llaves para definir un tipo de registro +    type Persona = {Nombre:string; Apellido:string} + +    // Usamos "let" con llaves para crear un registro +    let persona1 = {Nombre="John"; Apellido="Doe"} + +    // Combinación de patrones para desempaquetar +    let {Nombre=nombre} = persona1    // asignado nombre="john" + +    // ------------------------------------ +    // Los tipos de unión (o variantes) tienen un conjunto de elección +     // Solo un caso puede ser válido a la vez. +    // ------------------------------------ + +    // Usamos "type" con barra/pipe para definir una unión estándar +    type Temp = +        | GradosC of float +        | GradosF of float + +    // Una de estas opciones se usa para crear una +    let temp1 = GradosF 98.6 +    let temp2 = GradosC 37.0 + +    // Coincidencia de patrón en todos los casos para desempaquetar (?) +    let imprimirTemp = function +       | GradosC t -> printfn "%f gradC" t +       | GradosF t -> printfn "%f gradF" t + +    imprimirTemp temp1 +    imprimirTemp temp2 + +    // ------------------------------------ +    // Tipos recursivos +    // ------------------------------------ + +    // Los tipos se pueden combinar recursivamente de formas complejas +    // sin tener que crear subclases +    type Empleado = +      | Trabajador of Persona +      | Gerente of Empleado lista + +    let jdoe = {Nombre="John";Apellido="Doe"} +    let trabajador = Trabajador jdoe + +    // ------------------------------------ +    // Modelado con tipados (?) +    // ------------------------------------ + +    // Los tipos de unión son excelentes para modelar el estado sin usar banderas (?) +    type DireccionDeCorreo = +        | DireccionDeCorreoValido of string +        | DireccionDeCorreoInvalido of string + +    let intentarEnviarCorreo correoElectronico = +        match correoElectronico with // uso de patrones de coincidencia +        | DireccionDeCorreoValido direccion -> ()   // enviar +        | DireccionDeCorreoInvalido direccion -> () // no enviar + +    // Combinar juntos, los tipos de unión y tipos de registro +     // ofrece una base excelente para el diseño impulsado por el dominio. +     // Puedes crear cientos de pequeños tipos que reflejarán fielmente +     // el dominio. + +    type ArticuloDelCarrito = { CodigoDelProducto: string; Cantidad: int } +    type Pago = Pago of float +    type DatosActivosDelCarrito = { ArticulosSinPagar: ArticuloDelCarrito lista } +    type DatosPagadosDelCarrito = { ArticulosPagados: ArticuloDelCarrito lista; Pago: Pago} + +    type CarritoDeCompras = +        | CarritoVacio  // sin datos +        | CarritoActivo of DatosActivosDelCarrito +        | CarritoPagado of DatosPagadosDelCarrito + +    // ------------------------------------ +    // Comportamiento nativo de los tipos +    // ------------------------------------ + +    // Los tipos nativos tienen el comportamiento más útil "listo para usar", sin ningún código para agregar. +     // * Inmutabilidad +     // * Bonita depuración de impresión +     // * Igualdad y comparación +     // * Serialización + +     // La impresión bonita se usa con %A +    printfn "dosTuplas=%A,\nPersona=%A,\nTemp=%A,\nEmpleado=%A" +             dosTuplas persona1 temp1 trabajador + +    // La igualdad y la comparación son innatas +     // Aquí hay un ejemplo con tarjetas. +    type JuegoDeCartas = Trebol | Diamante | Espada | Corazon +    type Rango = Dos | Tres | Cuatro | Cinco | Seis | Siete | Ocho +                | Nueve | Diez | Jack | Reina | Rey | As + +    let mano = [ Trebol,As; Corazon,Tres; Corazon,As; +                 Espada,Jack; Diamante,Dos; Diamante,As ] + +    // orden +    List.sort mano |> printfn "la mano ordenada es (de menos a mayor) %A" +    List.max mano |> printfn "la carta más alta es%A" +    List.min mano |> printfn "la carta más baja es %A" + +// ================================================ +// Patrones activos +// ================================================ + +module EjemplosDePatronesActivos = + +    // F# tiene un tipo particular de coincidencia de patrón llamado "patrones activos" +    // donde el patrón puede ser analizado o detectado dinámicamente. + +    // "clips de banana" es la sintaxis de los patrones activos + +    // por ejemplo, definimos un patrón "activo" para que coincida con los tipos de "caracteres" ... +    let (|Digito|Latra|EspacioEnBlanco|Otros|) ch = +       if System.Char.IsDigit(ch) then Digito +       else if System.Char.IsLetter(ch) then Letra +       else if System.Char.IsWhiteSpace(ch) then EspacioEnBlanco +       else Otros + +    // ... y luego lo usamos para hacer que la lógica de análisis sea más clara +    let ImprimirCaracter ch = +      match ch with +      | Digito -> printfn "%c es un Digito" ch +      | Letra -> printfn "%c es una Letra" ch +      | Whitespace -> printfn "%c es un Espacio en blanco" ch +      | _ -> printfn "%c es algo mas" ch + +    // ver una lista +    ['a';'b';'1';' ';'-';'c'] |> List.iter ImprimirCaracter + +    // ----------------------------------------- +    // FizzBuzz usando patrones activos +    // ----------------------------------------- + +    // Puede crear un patrón de coincidencia parcial también +    // Solo usamos un guión bajo en la definición y devolvemos Some si coincide. +    let (|MultDe3|_|) i = if i % 3 = 0 then Some MultDe3 else None +    let (|MultDe5|_|) i = if i % 5 = 0 then Some MultDe5 else None + +    // la función principal +    let fizzBuzz i = +      match i with +      | MultDe3 & MultDe5 -> printf "FizzBuzz, " +      | MultDe3 -> printf "Fizz, " +      | MultDe5 -> printf "Buzz, " +      | _ -> printf "%i, " i + +    // prueba +    [1..20] |> List.iter fizzBuzz + +// ================================================ +// concisión +// ================================================ + +module EjemploDeAlgoritmo = + +    // F# tiene una alta relación señal / ruido, lo que permite leer el código +    // casi como un algoritmo real + +    // ------ Ejemplo: definir una función sumaDeCuadrados ------ +    let sumaDeCuadrados n = +       [1..n]                   // 1) Tome todos los números del 1 al n +       |> List.map cuadrado     // 2) Elevar cada uno de ellos al cuadrado +       |> List.sum              // 3) Realiza su suma + +    // prueba +    sumaDeCuadrados 100 |> printfn "Suma de cuadrados = %A" + +    // ------ Ejemplo: definir una función de ordenación ------ +    let rec ordenar lista = +       match lista with +       // Si la lista está vacía +       | [] -> +            []                              // devolvemos una lista vacía +       // si la lista no está vacía +       | primerElemento::otrosElementos ->  // tomamos el primer elemento +            let elementosMasPequenios =     // extraemos los elementos más pequeños +                otrosElementos              // tomamos el resto +                |> List.filter (fun e -> e < primerElemento) +                |> ordenar                  // y los ordenamos +            let elementosMasGrandes =       // extraemos el mas grande +                otrosElementos              // de los que permanecen +                |> List.filter (fun e -> e >= primerElemento) +                |> ordenar                  // y los ordenamos +            // Combinamos las 3 piezas en una nueva lista que devolvemos +            List.concat [elementosMasPequenios; [primerElemento]; elementosMasGrandes] + +    // prueba +    ordenar [1;5;23;18;9;1;3] |> printfn "Ordenado = %A" + +// ================================================ +// Código asíncrono +// ================================================ + +module AsyncExample = + +    // F# incluye características para ayudar con el código asíncrono +    // sin conocer la "pirámide del destino" +    // +    // El siguiente ejemplo descarga una secuencia de página web en paralelo. + +    open System.Net +    open System +    open System.IO +    open Microsoft.FSharp.Control.CommonExtensions + +    // Recuperar el contenido de una URL de forma asincrónica +    let extraerUrlAsync url = +        async {   // La palabra clave "async" y llaves +                  // crear un objeto "asincrónico" +            let solicitud = WebRequest.Create(Uri(url)) +            use! respuesta = solicitud.AsyncGetResponse() +                // use! es una tarea asincrónica +            use flujoDeDatos = resp.GetResponseStream() +                // "use" dispara automáticamente la funcion close() +                // en los recursos al final de las llaves +            use lector = new IO.StreamReader(flujoDeDatos) +            let html = lector.ReadToEnd() +            printfn "terminó la descarga %s" url +            } + +    // una lista de sitios para informar +    let sitios = ["http://www.bing.com"; +                 "http://www.google.com"; +                 "http://www.microsoft.com"; +                 "http://www.amazon.com"; +                 "http://www.yahoo.com"] + +    // ¡Aqui vamos! +    sitios +    |> List.map extraerUrlAsync // crear una lista de tareas asíncrona +    |> Async.Parallel           // decirle a las tareas que se desarrollan en paralelo +    |> Async.RunSynchronously   // ¡Empieza! + +// ================================================ +// Compatibilidad .NET +// ================================================ + +module EjemploCompatibilidadNet = + +    // F# puede hacer casi cualquier cosa que C# pueda hacer, y se ajusta +    // perfectamente con bibliotecas .NET o Mono. + +    // ------- Trabaja con las funciones de las bibliotecas existentes  ------- + +    let (i1success,i1) = System.Int32.TryParse("123"); +    if i1success then printfn "convertido como %i" i1 else printfn "conversion fallida" + +    // ------- Implementar interfaces sobre la marcha! ------- + +    // Crea un nuevo objeto que implemente IDisposable +    let crearRecurso name = +       { new System.IDisposable +         with member this.Dispose() = printfn "%s creado" name } + +    let utilizarYDisponerDeRecursos = +        use r1 = crearRecurso "primer recurso" +        printfn "usando primer recurso" +        for i in [1..3] do +            let nombreDelRecurso = sprintf "\tinner resource %d" i +            use temp = crearRecurso nombreDelRecurso +            printfn "\thacer algo con %s" nombreDelRecurso +        use r2 = crearRecurso "segundo recurso" +        printfn "usando segundo recurso" +        printfn "hecho." + +    // ------- Código orientado a objetos ------- + +    // F# es también un verdadero lenguaje OO. +    // Admite clases, herencia, métodos virtuales, etc. + +    // interfaz de tipo genérico +    type IEnumerator<'a> = +        abstract member Actual : 'a +        abstract MoverSiguiente : unit -> bool + +    // Clase base abstracta con métodos virtuales +    [<AbstractClass>] +    type Figura() = +        // propiedades de solo lectura +        abstract member Ancho : int with get +        abstract member Alto : int with get +        // método no virtual +        member this.AreaDelimitadora = this.Alto * this.Ancho +        // método virtual con implementación de la clase base +        abstract member Imprimir : unit -> unit +        default this.Imprimir () = printfn "Soy una Figura" + +    // clase concreta que hereda de su clase base y sobrecarga +    type Rectangulo(x:int, y:int) = +        inherit Figura() +        override this.Ancho = x +        override this.Alto = y +        override this.Imprimir ()  = printfn "Soy un Rectangulo" + +    // prueba +    let r = Rectangulo(2,3) +    printfn "La anchura es %i" r.Ancho +    printfn "El area es %i" r.AreaDelimitadora +    r.Imprimir() + +    // ------- extensión de método  ------- + +    // Al igual que en C#, F# puede extender las clases existentes con extensiones de método. +    type System.String with +       member this.EmpiezaConA = this.EmpiezaCon "A" + +    // prueba +    let s = "Alice" +    printfn "'%s' empieza con una 'A' = %A" s s.EmpiezaConA + +    // ------- eventos ------- + +    type MiBoton() = +        let eventoClick = new Event<_>() + +        [<CLIEvent>] +        member this.AlHacerClick = eventoClick.Publish + +        member this.PruebaEvento(arg) = +            eventoClick.Trigger(this, arg) + +    // prueba +    let miBoton = new MiBoton() +    miBoton.AlHacerClick.Add(fun (sender, arg) -> +            printfn "Haga clic en el evento con arg=%O" arg) + +    miBoton.PruebaEvento("Hola Mundo!") +``` + +## Más información + +Para más demostraciones de F#, visite el sitio [Try F#](http://www.tryfsharp.org/Learn), o sigue la serie [why use F#](http://fsharpforfunandprofit.com/why-use-fsharp/). + +Aprenda más sobre F# en [fsharp.org](http://fsharp.org/). | 
