Порядок исполнения кода F # - PullRequest
9 голосов
/ 03 июля 2010

еще один нубский вопрос относительно F #.

Если у меня есть следующий код ...

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

Вывод выглядит следующим образом ...

c
a
Example 1
b
Example 2
Example 3

Что здесь необычно, так это порядок выполнения кода. В предыдущем вопросе Брайан упомянул что-то о выражениях, я надеялся, что кто-нибудь сможет объяснить это немного подробнее. Похоже, что компилятор интеллектуально предварительно выполняет вещи для вычисления значений ... но я не знаю?

Ответы [ 2 ]

14 голосов
/ 03 июля 2010

ExeA и ExeC не функции, а отдельные значения. Компилятор гарантирует, что значения инициализируются в порядке, в котором они объявлены в исходном файле, поэтому здесь происходит следующее:

  1. ExeC инициализирует
  2. ExeA инициализирует
  3. Example 1 печатается с использованием инициализированного значения ExeA
  4. Функция ExeB вызывается как обычно
  5. Example 3 печатается с использованием инициализированного значения ExeC

Если вы хотите, чтобы ExeA и ExeC были действительно ленивыми - то есть контролировать, когда запускаются их побочные эффекты - вы можете превратить их в функции, которые принимают 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 ())
4 голосов
/ 03 июля 2010

В качестве ответа на ответ Тима я подумал, что вы могли бы по достоинству оценить дальнейшее понимание того, на что вы наткнулись.В вашем примере ExeC и ExeA используют функциональный стиль организации кода с помощью лексической области видимости и замыканий.Позвольте мне продемонстрировать более мощный пример.

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

    //...

Здесь снова timesPieDiv4 не является функцией, но имеет тело, которое содержит серию подвычислений, которые не подвергаются остальной части calc функция.На таком языке, как C #, у вас есть два варианта, ни один из которых мне не подходит.Первый вариант - просто объявить pie и pieDiv4 в основном теле calc, но тогда менее понятно, как они используются, и вы запачкаете пространство переменных.Другой вариант состоит в том, чтобы выделить эти суб-вычисления в отдельную частную вспомогательную функцию.Но мне не нравятся такие функции, потому что со многими становится сложно анализировать ваши сложные алгоритмы, так как вы постоянно копаетесь в поисках различных частей реализации.Плюс ко всему это много кода котельной плиты и передача значения.Вот почему функции F # по умолчанию являются «общедоступными», лексическая область видимости и замыкания позволяют вам иерархически организовывать «частные» функции и значения в ваших общедоступных функциях.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...