У меня пока нет полного ответа, но это эссе Роджера Хуэя имеет молчаливую конструкцию, которую можно использовать для замены явных циклов while.Другой (связанный) способ - сделать внутреннюю логику блока неявным выражением, например:
FUNWITHTACIT =: ] , {: + {: +. 1 + #
rowland =: monad define
result =. >a:
t =. 7x
while. (# result) < y do.
t =. FUNWITHTACIT t
d =. | -/ _2 {. t
result =. ~.result,((d>1)#d)
end.
result
)
(хотя вы можете сохранить блок if для эффективности, так как я написал кодтаким образом, что result
изменяется независимо от того, было ли выполнено условие - если это не так, изменение не имеет никакого эффекта. Логика if
может быть даже записана обратно в молчаливое выражение, используяОператор повестки дня.)
Полное решение будет состоять в том, чтобы выяснить, как представить всю логику внутри цикла while в виде единой функции, а затем использовать трюк Роджера для реализации логики while в качестве неявного выражения.Я посмотрю, что у меня получится.
Кроме того, я заставил J собрать для меня FUNWITHTACIT
, взяв первые несколько строк вашего кода, подставив вручную функции, которые вы объявили для переменнойзначения (что я мог сделать, потому что все они работали с одним аргументом по-разному), заменил каждый экземпляр t
на y
и велел J построить неявный эквивалент полученного выражения:
]FUNWITHTACIT =: 13 : 'y,({:y)+(1+#y)+.({:y)'
] , {: + {: +. 1 + #
Использование 13 для объявления монады - это то, как J знает, как взять монаду (иначе явно объявленную с помощью 3 : 0
или monad define
, как вы написали в своей программе) и преобразовать явное выражение в неявное выражение.
EDIT:
Вот функции, которые я написал для avenue (2), о которых я упоминал в комментарии:
candfun =: 3 : '(] , {: + {: +. 1 + #)^:(y) 7'
firstdiff =: [: | 2 -/\ ]
triage =: [: /:~ [: ~. 1&~: # ]
rowland2 =: triage @firstdiff @candfun
Эта функция генерирует первые n-много номеров кандидатов, используяОтношение повторяемости Роуленда оценивает их первые различия, отбрасывает все первые различия, равные 1, отбрасывает все дубликаты и сортирует их в порядке возрастания.Я не думаю, что это пока полностью удовлетворительно, так как аргумент задает количество кандидатов, а не количество результатов.Но это все еще прогресс.
Пример:
rowland2 1000
3 5 7 11 13 23 47 101 233 467 941
Вот версия первой функции, которую я опубликовал, с минимальным размером каждого аргумента:
NB. rowrec takes y=(n,an) where n is the index and a(n) is the
NB. nth member of the rowland candidate sequence. The base case
NB. is rowrec 1 7. The output is (n+1,a(n+1)).
rowrec =: (1 + {.) , }. + [: +./ 1 0 + ]
rowland3 =: 3 : 0
result =. >a:
t =. 1 7
while. y > #result do.
ts =. (<"1)2 2 $ t,rowrec t
fdiff =. |2-/\,>(}.&.>) ts
if. 1~:fdiff do.
result =. ~. result,fdiff
end.
t =. ,>}.ts
end.
/:~ result
)
, который находит первые y-много различных простых чисел Роуленда и представляет их в порядке возрастания:
rowland3 20
3 5 7 11 13 23 47 53 101 233 467 941 1889 3779 7559 15131 30323 60647 121403 242807
Большая часть сложности этой функции связана с моей обработкой коробочных массивов.Это не очень красивый код, но он только хранит 4+#result
многих элементов данных (которые растут в масштабе журнала) в памяти во время вычислений.Исходная функция rowland
сохраняет (#t)+(#result)
элементов в памяти (которая растет в линейном масштабе).rowland2 y
создает массив из y
-много элементов, что делает его профиль памяти почти таким же, как rowland
, даже если он никогда не выходит за пределы указанной границы.Мне нравится rowland2
за его компактность, но без формулы для прогнозирования точного размера y
, необходимого для генерации n-многих различных простых чисел, эту задачу необходимо будет выполнить методом проб и ошибок и, следовательно, потенциально использоватьнамного больше циклов, чем rowland
или rowland3
при избыточных вычислениях.rowland3
, вероятно, более эффективен, чем моя версия rowland
, поскольку FUNWITHTACIT
пересчитывает #t
на каждую итерацию цикла - rowland3
просто увеличивает счетчик, который требует меньше вычислений.
Тем не менееЯ не доволен явными управляющими структурами rowland3
.Кажется, должен быть способ выполнить это поведение, используя рекурсию или что-то в этом роде.