La mayoría del material F # does explica que todas las declaraciones de nivel superior en un módulo se ejecutan desde arriba hacia abajo en la declaración. En otras palabras, lo que has declarado no es una función, sino un valor que se vincula una vez cuando se ejecuta el programa.
Realmente ayuda a ver el código reflejado. Tengo un archivo simple:
let juliet = "awesome"
let juliet2() = "awesome"
El código compilado se ve algo como esto:
public static string juliet
{
[CompilerGenerated, DebuggerNonUserCode]
get
{
return "awesome";
}
}
//...
public static string juliet2()
{
return "awesome";
}
Así que se trata de una propiedad estática, la otra es una función. Esta es una propiedad deseable, porque imaginar si tuviéramos algo como esto:
let x = someLongRunningDatabaseCall()
única Queremos x
en obligarse vez, no queremos que se invoque la función de base de datos cada vez que se accede a x
.
Además, podemos escribir código interesante como esto:
> let isInNebraska =
printfn "Creating cities set"
let cities = set ["Omaha"; "Bellevue"; "Lincoln"; "Papillion"; "La Vista"; "Ralston"]
fun n -> cities.Contains(n);;
Creating cities set
val isInNebraska : (string -> bool)
> isInNebraska "Omaha";;
val it : bool = true
> isInNebraska "Okaloosa";;
val it : bool = false
Desde isInNebraska
es un valor, su evaluadas inmediatamente. Sucede que su tipo de datos es (string -> bool)
, por lo que parece como una función. Como resultado, solo llenamos nuestro conjunto cities
una vez, incluso si invocamos la función 1000 veces.
Comparemos ese código para esto:
> let isInNebraska2 n =
printfn "Creating cities set"
let cities = set ["Omaha"; "Bellevue"; "Lincoln"; "Papillion"; "La Vista"; "Ralston"]
cities.Contains(n);;
val isInNebraska2 : string -> bool
> isInNebraska2 "Omaha";;
Creating cities set
val it : bool = true
> isInNebraska2 "Okaloosa";;
Creating cities set
val it : bool = false
Vaya, estamos creando una nueva ciudades para crear cada vez que se invoca la función.
Por lo tanto, definitivamente existe una distinción legítima y real entre valores y funciones.
Buen ejemplo. Para cualquiera que esté interesado, el libro "Expert F #" (capítulo 8) desarrolla esta discusión un poco más en el contexto del diseño de funciones para una aplicación parcial eficiente. – itowlson
Creo que hay un error aquí: no hay mucha diferencia entre una propiedad estática y un método estático en que ** ambos son métodos ** detrás de escena, y el acceso a una propiedad es en realidad una llamada a método (es por eso que puedes marcar una propiedad como * virtual *). No puedo ver tu "propiedad deseable". –
Creo que la diferencia es que cuando tiene 'let julietNoFunction = ...' la propiedad estática simplemente devolverá un valor almacenado en un campo estático, y este valor se calcula solo una vez en el constructor estático del tipo generado para el módulo. Creo que he visto esto en Reflector, pero ya no estoy seguro. De todas formas, la forma en que lo presentas no muestra ninguna ventaja en el uso de 'let juliet = ...' sobre 'let juliet() = ...'. –