Translate

sábado, 16 de diciembre de 2017

Primeros pasos con F#

Si bien hemos hablado de F# en el blog nunca hice un post del lenguaje en si, bueno vamos a cambiar eso.

Si vamos a la pagina de F# nos dira que es un lenguaje open source, multiplataforma y funcional. Capaz de resolver problemas complejos de forma simple.

Por que utilizar o aprender F#?

  • Concisión. F # no está lleno de "ruido" de codificación, como llaves, punto y coma, etc. Casi nunca tiene que especificar el tipo de un objeto, gracias a un potente sistema de inferencia de tipo. Y generalmente requiere menos líneas de código para resolver el mismo problema.
  • Conveniente. Muchas tareas de programación comunes son mucho más simples en F#. Esto incluye cosas como crear y usar definiciones de tipos complejos, hacer el procesamiento de listas, comparación e igualdad, máquinas de estado y mucho más. Y debido a que las funciones son objetos de primera clase, es muy fácil crear código poderoso y reutilizable creando funciones que tienen otras funciones como parámetros, o que combinan funciones existentes para crear nuevas funcionalidades.
  • Exactitud. F# tiene un sistema de tipo muy poderoso que evita muchos errores comunes, como las excepciones de referencia nula. Además, a menudo puede codificar la lógica de negocios utilizando el sistema de tipo en sí, de modo que es realmente imposible escribir código incorrecto, porque se detecta en tiempo de compilación como un error de tipo.
  • Concurrencia: F# tiene una serie de herramientas y bibliotecas integradas para ayudar con los sistemas de programación cuando ocurre más de una cosa a la vez. La programación asincrónica es directamente compatible, como lo es el paralelismo. F# también tiene un sistema de cola de mensajes y un excelente soporte para el manejo de eventos y programación reactiva. Y debido a que las estructuras de datos son inmutables por defecto, compartir estado y evitar bloqueos es mucho más fácil.
  • Completo. Aunque F # es un lenguaje funcional de corazón, admite otros estilos que no son 100% puros, lo que facilita mucho la interacción con el mundo no puro de sitios web, bases de datos, otras aplicaciones, etc. En particular, F# está diseñado como un lenguaje híbrido funcional / OO, por lo que puede hacer casi todo lo que C# puede hacer también. Por supuesto, F# se integra sin problemas con el ecosistema .NET, que le da acceso a todas las herramientas y bibliotecas .NET de terceros. Finalmente, es parte de Visual Studio, lo que significa que obtiene un buen editor con soporte IntelliSense, un depurador y muchos complementos para pruebas unitarias, control de código fuente y otras tareas de desarrollo.


Aquí hay una descripción general muy rápida sobre cómo leer el código F# para los recién llegados que no estén familiarizados con la sintaxis. La sintaxis F# es muy clara y directa cuando te acostumbras. En muchos sentidos, es más simple que la sintaxis C#, con menos palabras clave y casos especiales.

El siguiente código de ejemplo es un script sencillo de F # que muestra la mayoría de los conceptos que necesita de forma regular.

// single line comments use a double slash
(* multi line comments use (* . . . *) pair -end of multi line comment- *)

// ======== "Variables" (but not really) ==========
// The "let" keyword defines an (immutable) value
let myInt = 5
let myFloat = 3.14
let myString = "hello" //note that no types needed

// ======== Lists ============
let twoToFive = [2;3;4;5]        // Square brackets create a list with
                                 // semicolon delimiters.
let oneToFive = 1 :: twoToFive   // :: creates list with new 1st element
// The result is [1;2;3;4;5]
let zeroToFive = [0;1] @ twoToFive   // @ concats two lists

// IMPORTANT: commas are never used as delimiters, only semicolons!

// ======== Functions ========
// The "let" keyword also defines a named function.
let square x = x * x          // Note that no parens are used.
square 3                      // Now run the function. Again, no parens.

let add x y = x + y           // don't use add (x,y)! It means something
                              // completely different.
add 2 3                       // Now run the function.

// to define a multiline function, just use indents. No semicolons needed.
let evens list =
   let isEven x = x%2 = 0     // Define "isEven" as an inner ("nested") function
   List.filter isEven list    // List.filter is a library function
                              // with two parameters: a boolean function
                              // and a list to work on

evens oneToFive               // Now run the function

// You can use parens to clarify precedence. In this example,
// do "map" first, with two args, then do "sum" on the result.
// Without the parens, "List.map" would be passed as an arg to List.sum
let sumOfSquaresTo100 =
   List.sum ( List.map square [1..100] )

// You can pipe the output of one operation to the next using "|>"
// Here is the same sumOfSquares function written using pipes
let sumOfSquaresTo100piped =
   [1..100] |> List.map square |> List.sum  // "square" was defined earlier

// you can define lambdas (anonymous functions) using the "fun" keyword
let sumOfSquaresTo100withFun =
   [1..100] |> List.map (fun x->x*x) |> List.sum

// In F# returns are implicit -- no "return" needed. A function always
// returns the value of the last expression used.

// ======== Pattern Matching ========
// Match..with.. is a supercharged case/switch statement.
let simplePatternMatch =
   let x = "a"
   match x with
    | "a" -> printfn "x is a"
    | "b" -> printfn "x is b"
    | _ -> printfn "x is something else"   // underscore matches anything

// Some(..) and None are roughly analogous to Nullable wrappers
let validValue = Some(99)
let invalidValue = None

// In this example, match..with matches the "Some" and the "None",
// and also unpacks the value in the "Some" at the same time.
let optionPatternMatch input =
   match input with
    | Some i -> printfn "input is an int=%d" i
    | None -> printfn "input is missing"

optionPatternMatch validValue
optionPatternMatch invalidValue

// ========= Complex Data Types =========

// Tuple types are pairs, triples, etc. Tuples use commas.
let twoTuple = 1,2
let threeTuple = "a",2,true

// Record types have named fields. Semicolons are separators.
type Person = {First:string; Last:string}
let person1 = {First="john"; Last="Doe"}

// Union types have choices. Vertical bars are separators.
type Temp =
| DegreesC of float
| DegreesF of float
let temp = DegreesF 98.6

// Types can be combined recursively in complex ways.
// E.g. here is a union type that contains a list of the same type:
type Employee =
  | Worker of Person
  | Manager of Employee list
let jdoe = {First="John";Last="Doe"}
let worker = Worker jdoe

// ========= Printing =========
// The printf/printfn functions are similar to the
// Console.Write/WriteLine functions in C#.
printfn "Printing an int %i, a float %f, a bool %b" 1 2.0 true
printfn "A string %s, and something generic %A" "hello" [1;2;3;4]

// all complex types have pretty printing built in
printfn "twoTuple=%A,\nPerson=%A,\nTemp=%A,\nEmployee=%A"
         twoTuple person1 temp worker

// There are also sprintf/sprintfn functions for formatting data
// into a string, similar to String.Format.


Dejo link: