J язык. Я хочу выразить результат в виде функции
(+/%#)0:`(>:@$:)@.(3 :'?2')"0 i.10000
Работает как я полагаю. Ответ имеет тенденцию к 1. Теперь я хочу выразить этот результат в виде
f =: (+/%#)0:`(>:@$:)@.(3 :'?2')"0 i.
f 10000
Не работает
1 ответ
Неявная или Явная композиция
Соединение нескольких глаголов посредством сопоставления в J не создает конвейер, он создает "последовательность глаголов", которая имеет различную семантику.
То есть существительная фраза:
foo bar bar buz 10000
отличается от глагольной фразы:
f =: foo bar baz buz
f 10000
Если вы хотите конвейер глагола, вы должны использовать некоторую форму явной композиции (то есть обозначенную, а не подразумеваемую).
Чаще всего конвейеры состоят из монадических глаголов (преобразовывая один вход в один выход, который становится входом для следующего глагола), поэтому мы используем @:
(или же @
, но использование этого требует некоторого большего внимания к деталям), поэтому словесный эквивалент оригинальной именной фразы будет:
f =: foo @: bar @: baz @: buz
f 10000
Композиция и анонимная рекурсия
Учитывая, что в вашем случае у нас может возникнуть соблазн наивно написать:
(+/%#) @: (0:`(>:@$:)@.(3 :'?2')"0) @: i.
Заботясь обернуть средний глагол (0:`(>:@$:)@.(3 :'?2')"0
) в скобках, потому что мы хотим применить этот глагол, и только этот глагол, с нулевым рангом ("0
) и, в частности, применять среднее значение (+/ % #
) ко всем результатам, а не к каждому отдельному результату.
Но если мы сделаем это и запустим, мы быстро столкнемся с проблемой: бесконечной рекурсией.
В оригинальной именной фразе глагол 0:`(>:@$:)@.(3 :'?2')"0
стоял один, и поэтому $:
(анонимная рекурсия) в этом глаголе 0:`(>:@$:)@.(3 :'?2')"0
и только для 0:`(>:@$:)@.(3 :'?2')"0
,
Однако, как только мы переформулировали последовательность трех глаголов в конвейер (f
выше), то $:
встроен в f
и, следовательно, относится кf
,
Значение в этой формулировке f
, когда $:
рекурсы на 1, во-первых, i.
применяется к этому 1, в результате чего ,0
, затем ?
генерирует случайный бит, который с вероятностью 50% равен 1, а затем $:
рекурсы, которые i.
применяется к....
Это ловкая ловушка в J. Есть два традиционных решения.
Изоляция $:
Вы можете разбить ваш код на более мелкие именованные части:
f =: mean @: converge @: i.
mean =: +/ % #
converge =: 0:`(>:@$:)@.(3 :'?2')"0
который, потому что он изолирует $:
гарантирует, что это относится только к converge
,
Точно так же вы можете вставлять $:
внутри анонимного явного контекста, существенно ограничивающего его область действия:
f =: (+/%#) @: (verb def '0:`(>:@$:)@.(3 :'?2')"0 y') @: i.
Это все равно что ставить шоры на $:
: теперь он не может видеть за пределами verb def
, Некоторые молчаливые пуристы могут отказаться от этого подхода, но в какой-то момент интерпретатор J сам применил эту тактику, когда определение со встроенным $:
было исправлено с помощью f.
,
Решение
Учитывая ваше использование 3 : '?2'
Вы, кажется, довольны анонимным явным контекстом. Если это так, то, возможно, просто стоит взять всю свинью и просто захватить свою оригинальную, неизмененную существительную фразу как явный глагол:
meanConverge =: verb define
(+/%#) 0:`(>:@$:)@.(3 :'?2')"0 i. y
)
Но, если вы предпочитаете чисто молчаливое решение и хотите идти полным ходом в другом направлении, мы можем устранить даже 3 : '?2'
явный код:
f =: mean @: converge @: i.
mean =: +/ % #
converge =: 0:`(>:@$:)@.(?@2:)"0
И, конечно, есть способы переписать глагол, чтобы вообще избежать рекурсии, но это, вероятно, наносит ущерб цели упражнения.