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

И, конечно, есть способы переписать глагол, чтобы вообще избежать рекурсии, но это, вероятно, наносит ущерб цели упражнения.

Другие вопросы по тегам