====== 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