F# (pronunciado F Sharp en inglés) es un lenguaje de programación multiparadigma de código abierto,[1] para la plataforma .NET, que conjunta la programación funcional con las disciplinas imperativa y orientada a objetos. Es una variante del lenguaje de programación ML y es compatible con la implementación Objective Caml. F# fue inicialmente desarrollado por Don Syme de Microsoft Research, pero actualmente está siendo desarrollado por la División de Desarrolladores de Microsoft y es distribuido como un lenguaje totalmente soportado en la plataforma .NET y Visual Studio 2010, 2012, 2013, 2015 y 2017.[2]
F# es un lenguaje fuertemente tipado que utiliza inferencia de tipos. Como resultado, los tipos no necesitan estar declarados explícitamente por el programador; estos serán deducidos por el compilador durante el proceso de compilación. Sin embargo, F# también permite la declaración explícita de tipos de datos. Por ser un lenguaje .NET, F# soporta los objetos y tipos de .NET; F# permite al programador programar de una manera que se asemeja más a como pensamos. Por ejemplo: en la cafetería para pedir un café, nosotros generalmente no le decimos al mesero exactamente los pasos para hacer el café, solo pedimos un café con ciertas características. De tal forma que tenemos menos espacio para cometer errores, porque simplemente escribimos menos código. También facilita enormemente la creación de código asincrónico y paralelo, cosa que en otros lenguajes de .NET nos llevaría mucho más tiempo.
General
Programación Funcional
F# es un lenguaje de programación primeramente funcional, fuertemente tipado, que usa la inferencia de tipos. Los tipos no
necesitan ser explícitamente declarados por el programador; serán deducidos en proceso de compilación. F# también permite
notaciones explícitas de tipos y requiere de esto en algunas situaciones. F# es un lenguaje de expresiones basadas en evaluación impaciente. Las funciones y expresiones que no retornan ningún valor tienen como tipo de retorno unit
. F# usa la palabra clave let
para enlazar valores a nombres. Por ejemplo:
let x = 3 + 4
enlaza el valor 7
al nombre x
.
Nuevos tipos son definidos usando la palabra clave type
. Para una programación funcional, F# provee los tipos
tuple, record, discriminated union, list y option. Una tupla representa una colección de
n valores. El valor n es llamado la aridad de la tupla. Una 3-tuple podría ser representado como (A, B, C)
, donde A, B y C son valores con posiblemente diferente tipos. Una tupla puede ser usada solamente para almacenar
valores cuando el número de valores es conocido en tiempo de diseño y permanece constante durante la ejecución.
Un record es un tipo donde los datos son nombrados, por ejemplo: { Name:string; Age:int }
. Los récords
pueden ser creados como { Name="AB"; Age=42 }
. La palabra clave with
es usada para crear una copia
de un récord, por ejemplo: { r with Name="CD" }
, el cual crea un nuevo récord copiando r
y
cambiando el valor del campo Name
(asumiendo que el récord creado en el ejemplo anterior fue nombrado
r
).
Un tipo discriminated union es un type-safe versión de las uniones de C.
Por ejemplo:
type A =
| UnionCaseX of string
| UnionCaseY of int
Los valores de la unión pueden corresponder a cualquiera de los dos casos de unión. Los tipos de los valores de cada caso de
unión es incluido en la definición de cada caso. El tipo list es una lista enlazada inmutable representada usando la notación head::tail
(::
el operador cons) o de forma de encabezado corto [item1; item2; item3]
. Una lista vacía se denota como []
. El tipo option es un tipo de unión discriminada con elección Some(x)
o None
. Los tipos de F# pueden ser genéricos, implementado como tipos genéricos de .NET.
F# soporta funciones lambda y clausuras. Todas las funciones en F# son
inmutables. Las funciones pueden ser curried. Las funciones pueden ser pasadas como argumento a otras
funciones. Como otros lenguajes de programación funcional, F# permite la composición de funciones
usando el operador >>
.
F# provee expresiones de secuencia[3] que define una secuencia seq { ... }
, lista [ ...
]
o array [| ... |]
a través de código que genera valores. Por ejemplo:
seq { for b in 0 .. 25 do
if b < 15 then
yield b*b }
forma una secuencia de los cuadrados de los números de 0 a 14 filtrando afuera por los números que están en un rango de 0 a 25. Las secuencias son generadas a medida que va haciendo falta (i.e. are evaluación lazy), mientras que las listas y arrays son evaluadas impacientemente. F# usa pattern matching para enlazar valores a nombres. Pattern matching es también usado cuando se está accediendo a uniones discriminadas. F# también soporta Active Patterns como un pattern matching extendido.[4] Este es usado, por ejemplo, cuando existen múltiples formas de matchear con un tipo. F# soporta una sintaxis general para la definición de composiciones llamado computation expressions. Secuencias de expresiones, computaciones asíncronas y consultas son clases particulares de computation expressions. "Computation expressions" son una implementación de monad pattern.[3]
Programación Imperativa
F# soporta la programación imperativa e incluye
for
cicloswhile
ciclos- arrays, creados con la sintaxis
[| ... |]
- hash table, creado con la sintaxis
dict [ ... ]
o
System.Collections.Generic.Dictionary<_,_>
type).
Valores y campos de records también pueden ser etiquetados como mutable
. Por ejemplo:
// Define 'x' con valor inicial '1'
let mutable x = 1
// Cambia el valor de 'x' a '3'
x <- 3
También, F# soporta acceso a todos los tipos y objetos del CLI como los definidos en:
System.Collections.Generic
.
Programación orientada a objetos
F# como recursos para programar orientado objetos incluye:
- dot-notation (e.g.
x.Name
) - expresiones de objetos (e.g.
{ new obj() with member x.ToString() = "hello" }
) - construcción de objetos (e.g.
new Form()
) - tipos tests (e.g.
x :? string
) - type coercions (e.g.
x :?> string
) - argumentos (e.g.
x.Method(someArgument=1)
) - setters (e.g.
new Form(Text="Hello")
) - argumentos opcionales (e.g.
x.Method(OptionalArgument=1)
En los patterns para programar con objetos se incluye:
- type tests (e.g.
:? string as s
) - active patterns, el cual puede ser definido sobre tipos de objetos.[4]
Las definiciones de objetos en F# pueden ser clases, estructuras (struct), interfaz, enum o delegados, correspondiendo a las formas de definición encontradas en C#. Por ejemplo, aquí se muestra una clase con un constructor tomando un nombre y una edad, y declarando dos propiedades.
/// Una simple definición de tipo de objeto
type Person(name : string, age : int) =
member x.Name = name
member x.Age = age
Programación Asíncrona
F# soporta programación asíncrona a través de asynchronous workflows.[5] "Asynchronous workflow" es definido
como una secuencia de comandos dentro de un async{ ... }
, por ejemplo:
let asynctask =
async { let req = WebRequest.Create(url)
let! response = req.GetResponseAsync()
use stream = response.GetResponseStream()
use streamreader = new System.IO.StreamReader(stream)
return streamreader.ReadToEnd()
El let!
permite que el resto del bloque async pueda ser definido como un delegado y pasado como Callback (informática) de una operación asíncrona. Esto soluciona el problema de la [[inversion of
control|inversión de control]].[5] El bloque async es invocado usando la función Async.RunSynchronously
. Múltiples bloques async son ejecutados en paralelo usando la función
Async.Parallel
que toma una lista de objetos async
(en el ejemplo, asynctask
es un
objeto async) y crea otro objeto async para correr las tareas en las listas en paralelo. Luego, el objeto resultante es
invocado usando Async.RunSynchronously
.[5]
Programación en Paralelo
La programación en paralelo es soportada parcialmente a través de Async.Parallel
, Async.Start
y
otras operaciones que corren bloques asíncronos en paralelo.
Meta-programación
F# permite algunas formas de sintaxis personalizadas con el fin de darle soporte a un incrustamiento personalizado, particularmente a través de "computation expressions".
F# incluye un plugin para meta-programación en tiempo de ejecución llamado quotations.[6] Una expresión quotation evalúa una representación de sintaxis abstracta de expresiones de F#. Una definición etiquetada con el atributo [<ReflectedDefinition>]
puede también ser accedida de la forma quotation. Las F# quotations son usadas
para varios propósitos incluyendo compilar código F# a JavaScript y GPU.
Information Rich
F# 3.0 introdujo una forma de meta-programación en tiempo de compilación a través de una generación de tipos estáticamente extensibles llamados F# type providers.[7] F# type providers permite al compilador de F# y herramientas ser extendidas con componentes que proporcionan información de tipo al compilador. F# type providers ha sido usado para dar acceso a tipos fuertemente tipados para conectar el origen de la información en una manera escalable.[8]
En F# 3.0 el F# quotation y las computation expression son combinadas para implementar consultas LINQ.[9] Por ejemplo:
// Usa el OData type provider para crear tipos que puedan ser usados para acceder a Northwind database.
open Microsoft.FSharp.Data.TypeProviders
type Northwind = ODataService<"http://services.odata.org/Northwind/Northwind.svc">
let db = Northwind.GetDataContext()
// A query expression.
let query1 = query { for customer in db.Customers do
select customer }
La combinación de type providers, consultas y programación funcional fuertemente tipado es conocido como information rich programming.[10]
Agente
F# soporta una variante del modelo de programación Actor a través de la implementación en memoria de agentes asíncronos. Por ejemplo, el siguiente código define un agente y envía 2 mensajes:
let counter =
MailboxProcessor.Start(fun inbox ->
let rec loop n =
async { do printfn "n = %d, waiting..." n
let! msg = inbox.Receive()
return! loop(n+msg) }
loop 0)
counter.Post(5);;
counter.Post(17);;
Herramientas de Desarrollo
F# puede ser desarrollado con cualquier editor de texto. Hay soportes específicos para el en varios editores, por ejemplo Emacs.
La herramienta Visual F# de Microsoft incluye completa integración en el IDE Visual Studio. Con el servicio del lenguaje instalado, Visual Studio puede ser usado para crear proyectos de F# y el Visual Studio debugger usado para depurar código F#. Además las herramientas de Visual F# vienen con una consola interactiva que puede ser usada para ejecutar código F# como está siendo escrito.
WebSharper es una plataforma para la utilización de JavaScript and HTML5. MonoDevelop es un entorno de desarrollo integrado para Linux, Mac y Windows incluyendo soporte para una consola interactiva. SharpDevelop soporta F# desde la versión 3.0. LINQPad soporta F# desde la versión 2.X.
Áreas de Aplicación
F# es un lenguaje de propósito general.
Programación Web
F# es usado en conjunto con ASP.NET, knockoutJS y otros frameworks del lado del servidor y del lado del cliente.[11]
F# es una parte central del framework WebSharper donde el código F# es ejecutado como un código .NET en el servidor y como código JavaScript en el lado cliente.
Scripting
F# es sobre todo usado como un lenguaje de scripting, principalmente para escritorio.[12]
Comunidad Código Abierto
La comunidad de código abierto de F# incluye la F# Software Foundation y la F# Open Source Group at GitHub.
Ejemplos
Un corto y pequeño ejemplo:
// Esto es un comentario para el programa de ejemplo Hello World.
printfn "Hello World!"
Una clase persona con un constructor que espera name, age y dos propiedades.
/// Este es el comentario para la documentacion de la definicion de un tipo
type Person(name : string, age : int) =
member x.Name = name
member x.Age = age
Un simple ejemplo que es sobre todo usado para demostrar la sintaxis de un lenguaje funcional:
/// Este es el comentario para la documentación de una función
let rec factorial n =
match n with
| 0 -> 1
| _ -> n * factorial (n - 1)
Ejemplos de iteraciones:
/// Iteración usando un ciclo 'for'
let printList lst =
for x in lst do
printfn "%d" x
/// Iteración usando una función de alto nivel
let printList2 lst =
List.iter (printfn "%d") lst
/// Iteración usando una función recursiva y pattern matching
let rec printList3 lst =
match lst with
| [] -> ()
| h :: t ->
printfn "%d" h
printList3 t
Ejemplos de Fibonacci:
/// Numero n de fibonacci
let rec fib n =
match n with
| 0 | 1 -> n
| _ -> fib (n - 1) + fib (n - 2)
/// Otra aproximación, una secuencia lazy infinita de fibonacci
let fibSeq = Seq.unfold (fun (a,b) -> Some(a+b, (b, a+b))) (1,1)
// Imprime los números de fibonacci pares
[1 .. 10]
|> List.map fib
|> List.filter (fun n -> (n % 2) = 0)
|> printList
// Algunas cosas usando listas
[ for i in 1..10 do
let r = fib i
if r % 2 = 0 then yield r ]
|> printList
Un ejemplo con Windows Forms:
// Abre la librería Windows Forms
open System.Windows.Forms
// Crea una ventana y setea algunas propiedades
let form = new Form(Visible=true, TopMost=true, Text="Welcome to F#")
// Crea una etiqueta para mostrar algún texto en el formulario
let label =
let x = 3 + (4 * 5)
new Label(Text = sprintf "x = %d" x)
//Añade la etiqueta al formulario
form.Controls.Add(label)
// Finalmente, corre el formulario
[<System.STAThread>]
Application.Run(form)
Ejemplo de programación paralela asíncrona:
/// Detectando números primos
let isPrime (n:int) =
let bound = int (sqrt (float n))
seq {2 .. bound} |> Seq.forall (fun x -> n % x <> 0)
// Usando async workflows
let primeAsync n =
async { return (n, isPrime n) }
/// Retornando primos entre m y n usando hilos
let primes m n =
seq {m .. n}
|> Seq.map primeAsync
|> Async.Parallel
|> Async.RunSynchronously
|> Array.filter snd
|> Array.map fst
// Corriendo una prueba
primes 1000000 1002000
|> Array.iter (printfn "%d")
Véase también
Notas
- ↑ dsyme. «Announcing the F# 3.0 Open Source Code Drop». Consultado el 24 de septiembre de 2012.
- ↑ S. Somasegar. «F# - A functional Programming Language». Consultado el 18 de octubre de 2007.
- ↑ a b «Some Details on F# Computation Expressions». Consultado el 14 de diciembre de 2007.
- ↑ a b «Pattern Matching in F# Part 2 : Active Patterns». Consultado el 24 de noviembre de 2012.
- ↑ a b c «Introducing F# Asynchronous Workflows». Consultado el 14 de diciembre de 2007.
- ↑ «Code Quotations (F#)». Consultado el 24 de noviembre de 2012.
- ↑ «Type Providers». Consultado el 24 de noviembre de 2012.
- ↑ «New Tech Report from Microsoft Research: Strongly-Typed Language Support for Internet-Scale Information Sources». Consultado el 24 de noviembre de 2012.
- ↑ «Query Expressions (F#)». Consultado el 24 de noviembre de 2012.
- ↑ «F# 3.0 – LINQ + Type Providers = Information Rich Programming». Consultado el 24 de noviembre de 2012.
- ↑ «Web Stacks for F#». Archivado desde el original el 3 de mayo de 2013. Consultado el 24 de noviembre de 2012.
- ↑ «Scripting in F#». Consultado el 25 de noviembre de 2012.
Referencias
- Syme, Don; Granicz, Adam; Cisternino, Antonio (2007). Expert F#. Apress.
- Harrop, Jon (2010). Visual F# 2010 for Technical Computing. Flying Frog Consultancy.
- Pickering, Robert (2007). Foundations of F#. Apress.
- Smith, Chris (2009). Programming F#. O'Reilly.
- Petricek, Tomas (2009). Real World Functional Programming With Examples in F# and C#. Manning Publications.
- Microsoft inc. (2017). https://www.visualstudio.com/es/vs/whatsnew/
- Lenguajes de programación (2015). https://web.archive.org/web/20170312195940/https://line.do/es/lenguajes-de-programacion/m9e/vertical
Enlaces externos
- The F# Software Foundation
- The F# Open Source Group at GitHub
- The Visual F# Developer Center Archivado el 19 de noviembre de 2008 en Wayback Machine.
- Try F#, for learning F# in your browser
- F# Snippets Site
- The Visual F# team blog
- The original Microsoft Research website for F#
- Planet F# Archivado el 13 de febrero de 2009 en Wayback Machine.
- The F# Survival Guide, Dec 2009 (Web-based book)
- The F# 3.0 Language Specification
- An introduction to F# programming