11
votes

F # Évaluation paresseuse vs non paresseux

Je viens de commencer F # alors s'il vous plaît soyez gentil si c'est basique.

J'ai lu qu'une fonction marquée paresseuse n'est évaluée qu'une fois, puis mis en cache. Par exemple: xxx

comparé à cette version qui fonctionnerait à chaque fois que cela s'appelle: xxx

en fonction de cela, Devrait toutes les fonctions être faite paresseuse? Quand ne voudriez-vous pas? Cela vient du matériel dans le livre "Début F #" .


1 commentaires

Quelle version de f # est-ce? J'ai une séquence qui agit paresseusement, mais n'a pas été ouvertement créée de cette façon. J'essaie de le forcer à compléter.


3 Réponses :


6
votes

Si les exécutions de fonction ont des effets secondaires et il est important de voir les effets secondaires chaque fois que la fonction est appelée (disons qu'il enveloppe une fonction d'E / S), vous ne voudrez pas que ce soit paresseux.

Il existe également des fonctions si triviales qui les exécutant à chaque fois sont plus rapides que la mise en cache de la valeur -


0 commentaires

5
votes

let eagerfunc = (1 + 1) est une liaison Let et ne sera exécutée qu'une seule fois. Soit Eaggerfunc () = (1 + 1) est une fonction acceptant unité (rien) et renvoyer un int . Il s'exécutera à chaque fois que cela s'appelle. En un sens, chaque fonction est paresseuse, c'est-à-dire qu'elle ne s'exécute que lorsqu'elle est appelée. Cependant, le mot-clé paresseux (et system.lazy , qu'il renvoie) exécutera l'expression / la fonction donnée au plus une fois. Les appels ultérieurs vers la propriété renvoient le résultat mis en cache. Ceci est utile lorsque le calcul de la valeur est coûteux.

De nombreuses fonctions ne conviendront pas à une utilisation avec paresseux car ils sont non déterministes (peuvent renvoyer un résultat différent avec chaque invocation) ou paramétré. Bien sûr, il est possible d'utiliser une version entièrement appliquée (une valeur est fournie pour chaque paramètre) de telles fonctions, mais la variabilité est généralement souhaitée.


0 commentaires

18
votes

Tout d'abord, il peut être utile de noter qu'aucune des choses que vous avez définies est une fonction - eAgerfunc code> et TheValue code> sont des valeurs de type int code> et Lazyfunc code> est une valeur de type paresseux code>. Donné xxx pré>

et p>

// throws an exception if x = 0.0
let eagerDivision x =
    let oneOverX = 1.0 / x
    if x = 0.0 then
        printfn "Tried to divide by zero" // too late, this line is never reached
    else
        printfn "One over x is: %f" oneOverX

// succeeds even if x = 0.0, since the quotient is lazily evaluated
let lazyDivision x =
    let oneOverX = lazy (1.0 / x)
    if x = 0.0 then
        printfn "Tried to divide by zero"
    else
        printfn "One over x is: %f" oneOverX.Value


2 commentaires

N'utilise pas () implique que c'est une fonction? Bons points dans tous les cas. Vous avez raison mes exemples sont super triviaux.


@Yuck - parenthèses signifient différentes choses dans différents contextes. Lorsque vous les utilisez comme (1 + 1) , ils servent simplement à indiquer le regroupement et la priorité. Si vous aviez défini let eagerfuncunc () = ... alors les parenthèses indiquent que eargerfunc est une fonction, mais notez que cela est différent de ce que vous avez écrit.