====== F# ====== ===== Básicos ===== ==== Primeras pinceladas ==== Puedes poner la clausula ''#light'' al principio de cada archivo de código. Esto hace que lo escrito en ese archivo permita una sintaxis más olgada, ya que por defecto F# es compatible con OCaml y este tiene una sintaxis muy restrictiva. \\ Para F# es importante el espaciado, es decir, los espacios tendrán relevancia en el código ya que código verticalmente alineado está considerado semánticamente relacionado. \\ Los comentarios serán... // This is a single-comment. Everything from the start is treated as a comment. (* This is a multiline comment *) /// This is a doc comment that can be converted to useful documentation. 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). \\ \\ 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). ==== Herramientas ==== === La consola interactiva === Te permite evaluar expresiones de F#, es el ejecutable ''fsi.exe'' (con mono es ''fsharpi''). Sobre esta podemos lanzar comandos como... printfn "Hello world!";; #r "System.Web.dll";; La consola evaluará el código una vez se introduzcan dos puntos y coma: '';;''. === El compilador === Es el "fsc.exe". === Enlaces de instalación === * 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/]] ===== Tipos de datos y operaciones ===== Los datos en F# no se asignan sino que se enlazan. Esto significa que al hacer: let x = 3 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: let a, b = 100, 200 // a=100, b=200 let x, y, z = 5, 4, 3 // x=5, y=4, z=3 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: let a = float32 100;; let a = float32(100);; // El uso de paréntesis es opcional. Otra forma de indicar el tipo que puede coger una variable es la siguiente (si no lo indicásemos asignaría un float): let a : double = 100.; 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 <-: let mutable x = 123 x <- 456 ==== 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: [] type m (* meters *) [] type s (* seconds *) > let distance = 123.5 // using meters - let time = 5.0 // using seconds - let speed = distance / time;; // mixing units val distance : float = 123.5 val time : float = 5.0 val speed : float = 24.7 //F# PowerPack (FSharp.PowerPack.dll)// es una librería de Microsoft con medidas predefinidas. ==== Strings ==== Para definir strings: let daughter = "Melissa" let pet = "Sugar" Podemos hacer strings multi-línea: let haiku = "No sky no earth - but still snowflakes fall" O strings de una sóla línea en múltiples acabando estas en \ : let haiku = "No sky\ no earth - but still\ snowflakes fall" Podemos acceder a los carácteres: let daughter = "kimberly" // string let first = daughter.[0] // first character, 'k' let last = daughter.[7] // last character, 'y' O convertir el string a bytes: > let countryBytes = "USA"B val countryBytes : byte array = [|85uy; 83uy; 65uy|] Existen varias operaciones que podemos hacer con un string: 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 También podemos construir strings largos utilizando ''StringBuilder'': let buf = new System.Text.StringBuilder() buf.Append("Mary had ") buf.Append("a little lamb, it's ") buf.Append("(you know the rest...)") ==== Condicionales ==== Existe el tipo de dato boolean: let t = true // true let f = false // false let x = t && f // false let y = t || f // true let fls = not true // false Para evaluarlo, como en otros lenguajes, utilizamos los if's. Hemos de tener en cuenta que en F# no existe el ''=='' sino el ''='' para hacer comparaciones de igual. \\ En F# el if devuelve una expresión que es asignable a una variable: 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?" Para no asignar un if llamaremos a ''ignore'' que recibe una expresión y la obvia: let a, b = 100, 200 (if a < b then "a < b" else "a is not less than b") |> ignore Los if's son expresiones que evaluan como ''unit''. ==== Bucles ==== Los bucles son expresiones que evaluan como ''unit''. === for..do === 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 === while === // 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 ===== Notas ===== * ''printfn'' funciona igual que String.Format: 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