2010-05-09 2 views
33

Wenn man in einer funktionalen Denkweise denkt, dass Funktionen rein sein sollen, kann man schlussfolgern, dass jede Funktion ohne Argumente im Grunde nur ein Wert ist.
Reallität kommt jedoch in den Weg, und mit verschiedenen Eingaben brauche ich vielleicht keine bestimmte Funktion, und wenn diese Funktion rechenintensiv ist, möchte ich sie nicht bewerten, wenn sie nicht benötigt wird.
Ich habe eine Problemumgehung gefunden, zu verwenden und es mit Func 1 oder was auch immer zu nennen, aber das fühlt sich dem Leser sehr nicht-idiomatisch und verwirrend an.F # - Funktion ohne Argumente?

Dies läuft auf eine Frage hinaus: Gibt es in F # eine geeignete Möglichkeit, eine Funktion mit null Argumenten zu deklarieren, ohne sie bei der Deklaration zu bewerten?

+0

Man könnte auch die Haltung einnehmen, dass Werte "im Grunde funktionieren ohne Argumente" sind, weshalb Haskell die Dinge sieht. Ich frage mich, warum F # in dieser Hinsicht anders ist. – jpaugh

+0

@self Es ist, weil Haskell standardmäßig auch faul ist; Keine Werte, einschließlich Funktionen, werden bei der Deklaration ausgewertet, es sei denn, der Programmierer fragt explizit danach. Die Semantik in F # ist standardmäßig strikt und sollte anders dargestellt werden. – jpaugh

Antwort

47

Das übliche Idiom ist die Definition der Funktion für ein Argument vom Typ Unit (let functionName() = 42). Es wird dann als functionName() aufgerufen. (Der Gerätetyp hat nur einen Wert, nämlich ().)

+0

hmm, aber Sie können einen Datensatztyp mit dieser Syntax nicht initialisieren (z. B. Typ Getter = {Name: Zeichenfolge; Funktion:() -> Zeichenfolge;} ist nicht zulässig). Irgendeine Idee, wie man das umgehen kann? – evolvedmicrobe

+0

@evolvedmicrobe Der Typ von '()' wird 'Einheit' genannt. – sepp2k

+0

danke für die Antwort, aber es kompiliert nicht. Ist es möglich, einen solchen Datensatztyp zu schreiben? – evolvedmicrobe

12

Ich denke, was Sie wollen, ist lazy.

let resource = 
    lazy(
     // expensive value init here 
    ) 

dann später, wenn Sie den Wert lesen müssen ...

resource.Value 

Wenn Sie noch nie die Value-Eigenschaft nennen, der Code innerhalb der lazy Block wird nie laufen, aber wenn Sie es tun nennen , dieser Code wird nicht mehr als einmal ausgeführt.

+1

Der Nachteil dieses Vorschlags ist, dass der Aufruf von 'resource.Value' immer denselben Wert zurückgibt, da er nur einmal ausgeführt wird, während der Rückgabewert der Funktion" parameterless "bei jedem Aufruf variieren kann. – Oliver

+0

Richtig, aber wenn die Funktion funktional rein ist und keine Argumente hat, gibt sie immer den gleichen Wert zurück. –

+0

Ich kann mir zwei Funktionen vorstellen, die immer einen anderen Wert zurückgeben: einen Zufallszahlengenerator und einen aktuellen Datum/Uhrzeit-Provider. Ich habe keine Ahnung, was _purity_ in functional terms_ bedeutet, aber diese scheinen gültige Beispiele zu sein, bei denen Ihr Lazy-Value-Ansatz nicht funktionieren würde. – Oliver