обновление: простой пример:
ff 0 = 1
ff 1 = 1
ff n = go (ff (n-1))
where
go x = x + x
При вызове по имени каждый вызов go
оценивает ff (n-1)
дважды, каждый для каждого появления x
в своем определении (поскольку +
является строгим в обоих аргументах, т.е. требует значений оба).
При вызове по требованию аргумент go
вычисляется не более одного раза. В частности, здесь значение x
определяется только один раз и используется повторно для второго появления x
в выражении x + x
. Если бы в этом не было необходимости, x
не был бы оценен вообще, так же, как и вызов по имени.
При вызове по значению аргумент go
всегда вычисляется ровно один раз, до ввода тела функции, даже если он не используется где-либо в теле функции.
Вот мое понимание этого в контексте Haskell.
Согласно Википедии , "вызов по необходимости - это запомненный вариант вызова по имени, где, если аргумент функции оценивается, это значение сохраняется для последующего использования."
Позвоните по имени:
take 10 . filter even $ [1..]
С одним потребителем произведенная стоимость исчезает после производства, так что это также может быть вызов по имени.
Позвоните по необходимости:
import qualified Data.List.Ordered as O
h = 1 : map (2*) h <> map (3*) h <> map (5*) h
where
(<>) = O.union
Разница в том, что здесь список h
повторно используется несколькими потребителями в разных темпах, поэтому важно, чтобы полученные значения запоминались. В языке вызовов по имени здесь было бы много копий вычислительных усилий, потому что вычислительное выражение для h
будет подставляться в каждом из его вхождений, вызывая отдельные вычисления для каждого. В языке по требованию - способном , таком как Haskell, результаты вычисления элементов h
распределяются между каждой ссылкой на h
.
Другим примером является то, что большинство любых данных, определенных fix
, доступны только по запросу. С помощью кол-ва по значению мы можем получить комбинатор Y .
См .: Совместный доступ и неразделение комбинатора с фиксированной точкой и связанных с ним записей и комментариев (среди них this и его ссылки, например Можно ли использовать метод fold для создания бесконечных списков? ).