mirror of
https://github.com/adambard/learnxinyminutes-docs.git
synced 2024-11-22 12:32:09 +03:00
Add F# tutorial in Spanish
New tutorial of F# in spanish from Angel Arciniega
This commit is contained in:
parent
5e4c651c6c
commit
aa51a89522
629
es-es/fsharp-es.html.markdown
Normal file
629
es-es/fsharp-es.html.markdown
Normal file
@ -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/).
|
Loading…
Reference in New Issue
Block a user