Muestra las diferencias entre dos versiones de la página.
| Ambos lados, revisión anterior Revisión previa Próxima revisión | Revisión previa | ||
|
functional:fsharp [2011/01/25 13:17] alfred |
functional:fsharp [2020/05/09 09:25] (actual) |
||
|---|---|---|---|
| Línea 1: | Línea 1: | ||
| ====== F# ====== | ====== F# ====== | ||
| ===== Básicos ===== | ===== Básicos ===== | ||
| + | |||
| Línea 13: | Línea 14: | ||
| /// This is a doc comment that can be converted to useful documentation. | /// This is a doc comment that can be converted to useful documentation. | ||
| </code> | </code> | ||
| - | En F# cada "comando" de código es una expresión, esto significa que todo comando genera un valor de un tipo de datos concreto. \\ | + | En F# cada "comando" de código es una expresión, esto significa que todo comando genera un valor de un tipo de datos concreto. \\ \\ |
| - | El comando ''open'' sería el equivalente a ''using'' de C#, open importa un namespace de una librería .NET (y, como en C#, necesitas hacer referencia a la DLL correspondiente). \\ | + | El comando ''open'' sería el equivalente a ''using'' de C#, open importa un namespace de una librería .NET (y, como en C#, necesitas hacer referencia a la DLL correspondiente). \\ \\ |
| - | Por defecto se agregan los siguientes namespaces: ''Microsoft.FSharp.Core'' (tipado de datos), ''Microsoft.FSharp.Core.Operators'' (operadores), ''Microsoft.FSharp.Collections'' (colecciones), ''Microsoft.FSharp.Control'' (construcciones de lazy evaluation y flujos asíncronos), ''Microsoft.FSharp.Text'' (funciones de IO). \\ | + | Por defecto se agregan los siguientes namespaces: ''Microsoft.FSharp.Core'' (tipado de datos), ''Microsoft.FSharp.Core.Operators'' (operadores), ''Microsoft.FSharp.Collections'' (colecciones), ''Microsoft.FSharp.Control'' (construcciones de lazy evaluation y flujos asíncronos), ''Microsoft.FSharp.Text'' (funciones de IO). |
| Línea 33: | Línea 35: | ||
| * Para la instalación en otros operativos distintos a Windows: [[http://fsxplat.codeplex.com/]] | * Para la instalación en otros operativos distintos a Windows: [[http://fsxplat.codeplex.com/]] | ||
| * Para la instalación de la extensión de MonoDevelop: [[http://functional-variations.net/monodevelop/]] | * Para la instalación de la extensión de MonoDevelop: [[http://functional-variations.net/monodevelop/]] | ||
| + | |||
| + | |||
| + | |||
| + | |||
| + | |||
| + | |||
| + | |||
| + | |||
| + | |||
| + | |||
| + | |||
| + | |||
| + | |||
| + | ===== Tipos de datos y operaciones ===== | ||
| + | Los datos en F# no se asignan sino que se enlazan. Esto significa que al hacer: | ||
| + | <code> | ||
| + | let x = 3 | ||
| + | </code> | ||
| + | Se enlaza x con el símbolo o, en este caso, valor numérico 3, si luego se volviese a enlazar con otro valor el 3 quedaría abandonado y a la espera del garbage colector. \\ | ||
| + | ''let'' soporta la asignación múltiple: | ||
| + | <code> | ||
| + | let a, b = 100, 200 // a=100, b=200 | ||
| + | let x, y, z = 5, 4, 3 // x=5, y=4, z=3 | ||
| + | </code> | ||
| + | F# soporta el tipo ''void'' para interoperar con otros lenguajes .NET y el tipo ''unit'' expresado como: ''()''. El tipo unit significa "ningún valor" (sí, como el void). \\ | ||
| + | Aunque F# puede indicar automáticamente el valor de una variable, es posible que queramos especificar el tipo de resultado mediante el nombre de este: | ||
| + | <code> | ||
| + | let a = float32 100;; | ||
| + | let a = float32(100);; // El uso de paréntesis es opcional. | ||
| + | </code> | ||
| + | Otra forma de indicar el tipo que puede coger una variable es la siguiente (si no lo indicásemos asignaría un float): | ||
| + | <code> | ||
| + | let a : double = 100.; | ||
| + | </code> | ||
| + | Generalmente al cambiar el dato al que apunta lo que ocurre es que se crea uno nuevo y se enlaza este, pero para indicar que una variable es alterable usamos la palabra mutable; luego, para actualizar el valor utilizaremos <nowiki><-</nowiki>: | ||
| + | <code> | ||
| + | let mutable x = 123 | ||
| + | x <- 456 | ||
| + | </code> | ||
| + | |||
| + | |||
| + | ==== Numéricos ==== | ||
| + | Un número, como por ejemplo 100, es interpretado como un integer de 32 bits, si queremos que sea un short escribiríamos 100s. Los tipos de datos que existen son: | ||
| + | {{ functional:fsharp:numeric_data_types.png |}} | ||
| + | La forma de expresar números es: | ||
| + | - Hexadecimal: mediante el prefijo 0x: ''0x7F''. | ||
| + | - Octal: un cero seguido de una 'o' minúscula: ''0o103''. | ||
| + | - Binario: un cero seguido de una 'b': ''0b1001''. | ||
| + | Podemos definir unidades de medida: | ||
| + | <code> | ||
| + | [<Measure>] type m (* meters *) | ||
| + | [<Measure>] type s (* seconds *) | ||
| + | |||
| + | > let distance = 123.5<m> // using meters | ||
| + | - let time = 5.0<s> // using seconds | ||
| + | - let speed = distance / time;; // mixing units | ||
| + | val distance : float<m> = 123.5 | ||
| + | val time : float<s> = 5.0 | ||
| + | val speed : float<m/s> = 24.7 | ||
| + | </code> | ||
| + | //F# PowerPack (FSharp.PowerPack.dll)// es una librería de Microsoft con medidas predefinidas. | ||
| + | |||
| + | ==== Strings ==== | ||
| + | Para definir strings: | ||
| + | <code> | ||
| + | let daughter = "Melissa" | ||
| + | let pet = "Sugar" | ||
| + | </code> | ||
| + | Podemos hacer strings multi-línea: | ||
| + | <code> | ||
| + | let haiku = "No sky | ||
| + | no earth - but still | ||
| + | snowflakes fall" | ||
| + | </code> | ||
| + | O strings de una sóla línea en múltiples acabando estas en \ : | ||
| + | <code> | ||
| + | let haiku = "No sky\ | ||
| + | no earth - but still\ | ||
| + | snowflakes fall" | ||
| + | </code> | ||
| + | Podemos acceder a los carácteres: | ||
| + | <code> | ||
| + | let daughter = "kimberly" // string | ||
| + | let first = daughter.[0] // first character, 'k' | ||
| + | let last = daughter.[7] // last character, 'y' | ||
| + | </code> | ||
| + | O convertir el string a bytes: | ||
| + | <code> | ||
| + | > let countryBytes = "USA"B | ||
| + | val countryBytes : byte array = [|85uy; 83uy; 65uy|] | ||
| + | </code> | ||
| + | Existen varias operaciones que podemos hacer con un string: | ||
| + | <code> | ||
| + | let fullname = "Mary "+ "Smith" // concatenation | ||
| + | let s = "hello " + string 100 // concatenation, string conversion operator | ||
| + | let len = fullname.Length // 10 | ||
| + | let i = fullname.StartsWith("Mary") // true | ||
| + | </code> | ||
| + | También podemos construir strings largos utilizando ''StringBuilder'': | ||
| + | <code> | ||
| + | let buf = new System.Text.StringBuilder() | ||
| + | buf.Append("Mary had ") | ||
| + | buf.Append("a little lamb, it's ") | ||
| + | buf.Append("(you know the rest...)") | ||
| + | </code> | ||
| + | |||
| + | |||
| + | ==== Condicionales ==== | ||
| + | Existe el tipo de dato boolean: | ||
| + | <code> | ||
| + | let t = true // true | ||
| + | let f = false // false | ||
| + | let x = t && f // false | ||
| + | let y = t || f // true | ||
| + | let fls = not true // false | ||
| + | </code> | ||
| + | Para evaluarlo, como en otros lenguajes, utilizamos los if's. Hemos de tener en cuenta que en F# no existe el ''<nowiki>==</nowiki>'' sino el ''='' para hacer comparaciones de igual. \\ | ||
| + | En F# el if devuelve una expresión que es asignable a una variable: | ||
| + | <code> | ||
| + | let name, pin = "bob", 123 | ||
| + | let securityMessage = | ||
| + | if name = "bob" && pin = 123 then "welcome bob!" | ||
| + | elif name = "sally" && pin = 456 then "welcome sally!" | ||
| + | else "access denied" | ||
| + | |||
| + | let name = "bob" | ||
| + | let s = | ||
| + | if name="bob" then | ||
| + | printfn "bob is a palindrome" | ||
| + | "bob backwards is still bob" | ||
| + | else | ||
| + | printfn "access denied" | ||
| + | "who are you?" | ||
| + | </code> | ||
| + | Para no asignar un if llamaremos a ''ignore'' que recibe una expresión y la obvia: | ||
| + | <code> | ||
| + | let a, b = 100, 200 | ||
| + | (if a < b then "a < b" else "a is not less than b") |> ignore | ||
| + | </code> | ||
| + | Los if's son expresiones que evaluan como ''unit''. | ||
| + | |||
| + | ==== Bucles ==== | ||
| + | Los bucles son expresiones que evaluan como ''unit''. | ||
| + | === for..do === | ||
| + | <code> | ||
| + | for i = 1 to 10 do | ||
| + | printfn "i = %d" i | ||
| + | |||
| + | // Count from 1 to 10, with identifiers | ||
| + | let a, b = 1, 10 | ||
| + | for k = a to b do | ||
| + | printfn "k = %d" k | ||
| + | |||
| + | // Count down from 10 (down) to 1 | ||
| + | for j = 10 downto 1 do | ||
| + | printfn "j = %d" j | ||
| + | |||
| + | // Sum the first 5 non-zero integers. | ||
| + | // This is quite "imperative." We'll see its functional cousin later. | ||
| + | let mutable sum = 0 | ||
| + | for n = 1 to 5 do | ||
| + | sum <- sum + n | ||
| + | printfn "current sum = %d" sum | ||
| + | </code> | ||
| + | === while === | ||
| + | <code> | ||
| + | // Output numbers from 1-10 and squares | ||
| + | let mutable n = 1 | ||
| + | while n <= 10 do | ||
| + | let sq = n * n | ||
| + | printfn "%d %d" n sq | ||
| + | n <- n + 1 | ||
| + | |||
| + | // Note mutable applies to both identifiers below | ||
| + | let mutable a, b = 1, 10 | ||
| + | while b > a do | ||
| + | printfn "%d %d" a b | ||
| + | a <- a + 1 | ||
| + | b <- b - 1 | ||
| + | |||
| + | // Using parentheses and Boolean conjuction | ||
| + | let mutable a, b, c = 1, 10, 0 | ||
| + | while ((a < b) && (c < 3)) do | ||
| + | printfn "%d %d %d" a b c | ||
| + | c <- c + 2 | ||
| + | </code> | ||
| + | |||
| + | ===== Notas ===== | ||
| + | * ''printfn'' funciona igual que String.Format: | ||
| + | <code> | ||
| + | let city = "Boston" | ||
| + | let temp = 63.5 | ||
| + | printfn "The mean temperature for %s is %f" city temp // Imprimirá: The mean temperature for Boston is 63.500000 | ||
| + | </code> | ||
| + | |||