Die meisten F # Material tut erklären, dass alle Top-Level-Anweisungen in einem Modul von oben nach unten auf Deklaration ausgeführt werden. Mit anderen Worten, was Sie deklariert haben, ist keine Funktion, sondern ein Wert, der beim Ausführen des Programms einmal gebunden ist.
Es hilft wirklich, den reflektierten Code zu sehen. Ich habe eine einfache Datei:
let juliet = "awesome"
let juliet2() = "awesome"
Der kompilierte Code etwa wie folgt aussieht:
public static string juliet
{
[CompilerGenerated, DebuggerNonUserCode]
get
{
return "awesome";
}
}
//...
public static string juliet2()
{
return "awesome";
}
So ist eine statische Eigenschaft, die andere eine Funktion ist. Dies ist eine wünschenswerte Eigenschaft, weil sich vorstellen, wenn wir so etwas wie dieses hatte:
let x = someLongRunningDatabaseCall()
Wir wollen nur x
einmal gebunden sein, wir wollen es nicht Datenbank Funktion jedes Mal aufzurufen wir x
zugreifen.
Zusätzlich können wir interessante Code wie folgt schreiben:
> 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
Da isInNebraska
ist ein Wert, dessen sofort ausgewertet. Es passiert einfach, dass sein Datentyp (string -> bool)
ist, so dass es wie eine Funktion aussieht. Als Ergebnis füllen wir nur unsere cities
Menge einmal, selbst wenn wir die Funktion 1000 mal aufrufen.
Lassen Sie uns diesen Code auf diese vergleichen:
> 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
Hoppla, schaffen wir eine neue Städte setzen jedes Mal rufen wir die Funktion.
Also gibt es definitiv eine legitime und echte Unterscheidung zwischen Werten und Funktionen.
Schönes Beispiel. Für alle Interessierten wird im Buch "Expert F #" (Kapitel 8) diese Diskussion im Zusammenhang mit dem Entwerfen von Funktionen für eine effiziente partielle Anwendung etwas weiter entwickelt. – itowlson
Ich denke, es gibt hier einen Fehler: Es gibt nicht viel Unterschied zwischen einer statischen Eigenschaft und einer statischen Methode, da beide Methoden hinter den Kulissen sind, und ein Zugriff auf eine Eigenschaft ist eigentlich ein Methodenaufruf (deshalb können Sie markieren eine Eigenschaft als * virtuell *). Ich kann dein "wünschenswertes Eigentum" nicht sehen. –
Ich glaube, dass der Unterschied darin besteht, dass, wenn Sie "julietNoFunction = ..." haben, die statische Eigenschaft einfach einen in einem statischen Feld gespeicherten Wert zurückgibt und dieser Wert nur einmal im statischen Konstruktor des generierten Typs berechnet wird Modul. Ich denke, ich habe das in Reflector gesehen, aber ich bin mir nicht mehr sicher. Wie auch immer, die Art, wie Sie es präsentieren, zeigt überhaupt keine Vorteile bei der Verwendung von 'let juliet = ...' über 'let juliet() = ...'. –