А>т.е. ни замыканий, ни операндов более 2-х нет(?) — как тогда на J будет выглядеть глагол foldl?
Если нужно передать несколько аргументов, то можно упаковать в массив или боксы. Вместо передачи двух аргументов можно передать склеенный аргумент "a , m". Глагол лепим слева:
v / m , a
0 0 0
Если же всё-таки очень хочется сделать именно три аргумента, то
foldl =: monad define
'v a l' =. y
v / l , a
)
foldl +`'' ; 10 ; 1 2 3
16
Штука "+`''" это атомное представление (atomic representation) глагола "+", в данном случае это список с одним элементом. А вообще, tie чаще используется чтобы слепить список для @.
Можно ещё воспользоваться тем, что в J код==данные:
foldl =: monad define
'v a l' =. y
ll =. l , a
". v , '/' , (5!:5) <'ll'
)
foldl '+' ; 10; i.10
55
Недостаток тут в том, что тип функции должен совпадать с типом элементов массива. Что в общем не всегда верно.
Как обычно бокс спешит на помощь. Типа:
boxme =: 1 : (':' ; '> (<x) u (<"_1 y)')
foldr2 =: each foldr boxme
foldl2 =: each foldl boxme
sum_of_chars =: + a. i. ]
0 sum_of_chars foldl 'ABCD'
|domain error
| u~/(|.y) ,x
0 sum_of_chars foldl2 'ABCD'
266
0 sum_of_chars~ foldr2 'ABCD'
266
Но вообще подобные вопросы возникают от попыток перенести идиомы из невекторного языка в J в лоб. И при этом часто пропадает весь смысл использования языка. Ни эффективности, ни лаконичности кода. Надо стараться избавляться от старых привычек и стремиться использовать богатый арсенал примитивных векторных операций на максимально высоких рангах, плюс "выращивание" более сложных конструкций путем тацитной композиции.
<Аноним>,
LCR>>Всё понятно, ты хочешь протаскивать состояние в глаголе? А>здесь инициализатор и глагол сначала применяется к ним, потом — к своим результатам. А>можно пример, чтобы в глаголе использовался и такой аккумулятор и и очередная(каждый раз следующая) строка матриицы? я уже совсем замучался — не пойму как это сделать
Посмотри внимательно на сумму:
(((a1 v m1) v m2) v m3)
Здесь аккумулятор a1 подаётся на вход функции v вместе с элементом m1 формируя новое неявное значение аккумулятора a2. Затем это новое значение аккумулятора a2 и элемент m2 подаётся на вход функции v формируя очередное новое неявное значение аккумулятора a3. Потом снова вычисляется "a3 v m3" и формируется новое значение аккумулятора a4 и в итоге оно становится результатом вычислений.
Лично я совершенно не вижу разницы между тем, что ты хочешь, и тем что я написал.
Про замыкания. Сначала прочитай последний абзац в сообщении MK
. Попробуй пересмотреть свои взгляды на структуру программы. Ты очевидно в курсе, что замыкание — это глагол с состоянием и это состояние херит всю идею глагола как функции. Теперь уже вызов глагола с тем же самым аргументом будет выдавать различные результаты. Если такие глаголы лепить с другими глаголами (а в J возможностей налепить хватает), то полученные фигуры вряд-ли будут прозрачны для понимания (за исключением совсем тривиальных случаев — для примера, представь, что все глаголы в quicksort выдавали бы различные результаты для одних и тех же аргументов). Поэтому, на мой взгляд, чем меньше таких глаголов — тем лучше.
Итак, ты услышал проповедь, продолжаем Пусть замыкание — это именно то, что тебе нужно. К сожалению, в J нет замыканий. Поэтому всё ниже, это просто workarounds. В J глаголы могут иметь побочные эффекты, и там есть глобальные (или глобальные в пределах локали) переменные. Есть функция cocreate, которая выдаёт уникальные числа при последовательных вызовах. На этом и можно сыграть.
cocreate ''
+-+
|6|
+-+
cocreate ''
+-+
|7|
+-+
Решение Олега Кобченко (ты видимо имел ввиду кривым это решение).
meanClosure =: adverb define
a =. cocreate ''
'mean__a n__a' =: m
a & (4 : 'mean__x =: n__x %~ y + mean__x * <: n__x [ n__x =: >: n__x' )
)
Это "инкрементальное" среднее — каждое новое значение вычисляется на основании предыдущего. Состояние внутри — это пара mean — текущее среднее и n — текущее количество.
есть вектор и некая матрица, надо провести что-то типа foldl — т.е. отдавать глаголу вектор и очередную строку матрицы, результатом применения глагола заменить начальный вектор(аккумулятор). затем взять следующую строку матрицы и новое значение вектора...
^: здесь не подходит(?) т.к. возвращаемое значение нужно не до уточнения. единственно, что вижу — бесконечная степень с условием или прямо for.
как можно просто решить такую задачу? и вообще задачи такого типа(функциональные), где активно используются операнды?
<Аноним>,
А>есть вектор и некая матрица, надо провести что-то типа foldl — т.е. отдавать глаголу вектор и очередную строку матрицы, результатом применения глагола заменить начальный вектор(аккумулятор). затем взять следующую строку матрицы и новое значение вектора... А>^: здесь не подходит(?) т.к. возвращаемое значение нужно не до уточнения. единственно, что вижу — бесконечная степень с условием или прямо for. А>как можно просто решить такую задачу? и вообще задачи такого типа(функциональные), где активно используются операнды?
foldl в J — это скорее '/', чем '^:'
] m =. 1 0 0 , 0 1 0 ,: 0 0 1
1 0 0
0 1 0
0 0 1
a =. 1 2 3
v =. <."0 NB. поэлементный минимум
1 2 3 v 3 2 1
1 2 1
v / m , a
0 0 0
- / m , a
0 _3 _2
1 0 0 - 0 1 0 - 0 0 1 - 1 2 3
0 _3 _2
Здравствуйте, Lazy Cjow Rhrr, Вы писали: LCR>foldl в J — это скорее '/', чем '^:' LCR> ...
такие конструкции я понимаю. но я не знаю как сделать вроде этого(erlang):
т.е. ни замыканий, ни операндов более 2-х нет(?) — как тогда на J будет выглядеть глагол foldl?
Re[4]: [J] как сделать foldl?
От:
Аноним
Дата:
01.05.07 10:49
Оценка:
спасибо за помошь! но это не foldl — здесь аккумулятор как таковой не используется. я же хочу получить такой эффект
m =: 3 4 $ i.12
acc =: 4 $ 0
v =: 3 : 0
acc =: acc + y
)
v"1 m
здесь для получения acc используется глобальная переменная — как от нее избавиться??
реализация замыканий через namespace слишком неудобна, дополнительным параметром acc передавать в функцию нельзя. эти два подхода из функционального программирования и в J они, насколько я понимаю, неприменимы. но тогда как?
Re[5]: [J] как сделать foldl?
От:
Аноним
Дата:
01.05.07 11:00
Оценка:
А>эти два подхода из функционального программирования и в J они, насколько я понимаю, неприменимы. но тогда как?
не считая прямого перебора индексов в цикле, естественно
<Аноним>
А>спасибо за помошь! но это не foldl — здесь аккумулятор как таковой не используется.
Ну как же, не используется?
А теперь сравни с:
m =. >: i. 5
a =. 1
F / m , a
+-------------------------------------+
|1 _F_ 2 _F_ 3 _F_ 4 _F_ 5 _F_ 6 _F_ 1|
+-------------------------------------+
Правда в данном случае это foldr , но аналогично foldl сделать как ты понимаешь — не фокус.
А>я же хочу получить такой эффект А>[code .. /code] А>здесь для получения acc используется глобальная переменная — как от нее избавиться??
Всё понятно, ты хочешь протаскивать состояние в глаголе?
verb =. monad define
'state a' =. y
(state + 1) ; (+: a + state)
)
verb^:4 (1; 1)
+-+--+
|5|68|
+-+--+
А>реализация замыканий через namespace слишком неудобна
чем?
А>дополнительным параметром acc передавать в функцию нельзя.
функцию менять нельзя?
Здравствуйте, Lazy Cjow Rhrr, Вы писали: LCR>Всё понятно, ты хочешь протаскивать состояние в глаголе?
здесь инициализатор и глагол сначала применяется к ним, потом — к своим результатам.
можно пример, чтобы в глаголе использовался и такой аккумулятор и и очередная(каждый раз следующая) строка матриицы? я уже совсем замучался — не пойму как это сделать
А>>реализация замыканий через namespace слишком неудобна LCR>чем?
в wiki на jsoftware есть такой пример — и он слишком похож на хак. т.е. если припрет, то в качестве замыканий пойдет, но хочется более простое решения А>>дополнительным параметром acc передавать в функцию нельзя. LCR>функцию менять нельзя?
не понял
Mikl Kurkov,
MK>Но вообще подобные вопросы возникают от попыток перенести идиомы из невекторного языка в J в лоб. И при этом часто пропадает весь смысл использования языка. Ни эффективности, ни лаконичности кода. Надо стараться избавляться от старых привычек и стремиться использовать богатый арсенал примитивных векторных операций на максимально высоких рангах, плюс "выращивание" более сложных конструкций путем тацитной композиции.