Простой пример вызова по необходимости

< с массивами numpy делает элементарное сравнение. Это означает, что он возвращает массив, где есть True, где условие истинно и False, если нет. Здесь нужна строка np.require, так что она фактически использует массивы NumPy. Вы можете отбросить np.require, если вы предварительно перепутали свои data и dt с np.array s.

Затем результат добавляется (по элементам) в числовой массив. В этом контексте True равен 1, а False равен нулю.

>>> dt < b  # which elements are smaller than b?
array([ True,  True, False, False, False])

>>> 0 + (dt  < b)  # boolean arrays in arithmetic operations with numbers
array([1, 1, 0, 0, 0])

Таким образом, он добавляет 1 к каждому элементу из data, где элемент из dt меньше 8.

5
задан 4castle 19 January 2019 в 01:28
поделиться

1 ответ

обновление: простой пример, запрашиваемый для:

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 всегда вычисляется ровно один раз, до входа в тело функции, даже если он не используется где-либо в теле функции.


Вот мое понимание этого в контексте Хаскелла.

Согласно Википедии , «вызов по необходимости - это запомненный вариант вызова по имени, где, если аргумент функции оценивается, это значение сохраняется для последующего использования». [ 1122]

Вызов по имени:

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 .

См .: Совместное использование и неразделение комбинатора с фиксированной точкой и связанных с ним записей и комментариев (среди них это и его ссылки, например, Можно ли использовать сложение для создания бесконечных списков? ).

0
ответ дан Will Ness 19 January 2019 в 01:28
поделиться