2010-07-03 8 views
8

une autre question concernant F #.Ordre d'exécution de code F #

Si je le code suivant ...

let ExeC = 
    printfn "c" 
    3 

let ExeB b = 
    printfn "b" 
    2 

let ExeA = 
    printfn "a" 
    1 

printfn "Example %d " ExeA 
printfn "Example %d " (ExeB 1) 
printfn "Example %d " ExeC 

La sortie est la suivante ...

c 
a 
Example 1 
b 
Example 2 
Example 3 

Ce qui semble inhabituel ici est l'ordre que le code est en cours d'exécution. Dans une question précédente Brian a mentionné quelque chose à propos des expressions, j'espérais que quelqu'un pourrait l'expliquer un peu plus. Il semble presque que le compilateur prépare intelligemment des choses pour calculer des valeurs ... mais je ne sais pas?

Répondre

13

ExeA et ExeC ne sont pas des fonctions, mais des valeurs uniques. Le compilateur assure que les valeurs initialisent dans l'ordre dans lequel ils sont déclarés dans le fichier source, donc ce qui se passe ici est:

  1. ExeC initialise
  2. ExeA initialise
  3. Example 1 est imprimé, en utilisant ExeA « s La valeur initialisée
  4. La fonction ExeB est appelé normalement
  5. Example 3 est imprimé, en utilisant ExeC « s de valeur initialisée

Si vous voulez ExeA et ExeC être vraiment paresseux - qui est, de contrôler quand leurs effets secondaires courent - vous pouvez les transformer en fonctions qui acceptent unit:

let ExeC() = 
    printfn "c" 
    3 

let ExeB b = 
    printfn "b" 
    2 

let ExeA() = 
    printfn "a" 
    1 

printfn "Example %d " (ExeA()) 
printfn "Example %d " (ExeB 1) 
printfn "Example %d " (ExeC()) 
3

Comme suite jusqu'à la réponse de Tim, je pensais que vous pourriez apprécier un peu plus de perspicacité dans ce que vous avez trébuché sur. Dans votre exemple, ExeC et ExeA tirent parti du style fonctionnel de l'organisation du code à travers le scannage et les fermetures lexicales. Laissez-moi démontrer un exemple plus puissant.

let calc n = 
    //... 
    let timesPieDiv4 = 
     let pie = 3.14 
     let pieDiv4 = pie/4. 
     n * pieDiv4 

    //... 

Ici encore timesPieDiv4 n'est pas une fonction, mais il a un corps qui contient une série de calculs sous qui ne sont pas exposés au reste de la fonction calc. Dans une langue comme C#, vous avez deux options qui ne me plaisent pas. La première option consiste simplement à déclarer pie et pieDiv4 dans le corps principal de calc, mais alors il est moins clair comment ils sont utilisés et vous salez votre espace variable. L'autre option consiste à factoriser ces sous-calculs dans une fonction auxiliaire privée distincte. Mais je n'aime pas ces fonctions, car avec beaucoup il devient difficile d'analyser vos algorithmes complexes puisque vous êtes constamment à la recherche de différentes pièces de mise en œuvre. De plus, il y a beaucoup de code de plaque de chaudière et de valeur qui passe. C'est pourquoi les fonctions F # sont "publiques" par défaut, la portée lexicale et les fermetures vous permettent d'organiser hiérarchiquement des fonctions et des valeurs "privées" dans vos fonctions publiques.

+0

Merci Stephen - appréciez l'élaboration ultérieure! –