Re[3]: [J] как сделать foldl?
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 01.05.07 09:41
Оценка: 6 (1) :)
<Аноним>

А>такие конструкции я понимаю. но я не знаю как сделать вроде этого(erlang):

foldl(F, Acc, [ ]) -> 
    Acc.
foldl(F, Acc, [Hd|Tail]) ->     
    foldl(F, F(Hd, Acc), Tail).

А>т.е. ни замыканий, ни операндов более 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
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re: Усовершенствованная версия foldl
От: Mikl Kurkov Россия  
Дата: 04.05.07 20:56
Оценка: 6 (1) +1
Здравствуйте, Lazy Cjow Rhrr, Вы писали:

LCR>>

LCR>
LCR>foldl =: monad define
LCR>  'v a l' =. y
LCR>  ll =. l , a
LCR>  ". v , '/' , (5!:5) <'ll'
LCR>)
LCR>

LCR>Присутствует лёгкое неудовлетворение от кривого использования '".' Так будет лучше:
LCR>
LCR>foldl =: monad define
LCR>  'v a l' =. y
LCR>  ". 'u =. ', v
LCR>  u / l , a
LCR>)
LCR>   foldl '+' ; 11; i.10
LCR>56
LCR>


По-моему тут использование наречия напрашивается. Типа:
foldr =: 1 : (':' ; 'u / y , x')

(6 - foldr i.4) -: (0 - (1 - (2 - (3 - 6))))
1

NB. вычисление в J идет справа налево, поэтому foldl немного сложнее

foldl =: 1 : (':' ; 'u~ / (|. y) , x')
(6 - foldl i.4) -: ((((6 - 0) - 1) - 2) - 3)
1


Недостаток тут в том, что тип функции должен совпадать с типом элементов массива. Что в общем не всегда верно.
Как обычно бокс спешит на помощь. Типа:

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

--
Mikl
Re[7]: [J] как сделать foldl?
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 05.05.07 10:21
Оценка: 8 (1)
<Аноним>,

LCR>>Всё понятно, ты хочешь протаскивать состояние в глаголе?

А>здесь инициализатор и глагол сначала применяется к ним, потом — к своим результатам.
А>можно пример, чтобы в глаголе использовался и такой аккумулятор и и очередная(каждый раз следующая) строка матриицы? я уже совсем замучался — не пойму как это сделать

Посмотри внимательно на сумму:
(((a1 v m1) v m2) v m3)

Здесь аккумулятор a1 подаётся на вход функции v вместе с элементом m1 формируя новое неявное значение аккумулятора a2. Затем это новое значение аккумулятора a2 и элемент m2 подаётся на вход функции v формируя очередное новое неявное значение аккумулятора a3. Потом снова вычисляется "a3 v m3" и формируется новое значение аккумулятора a4 и в итоге оно становится результатом вычислений.

Лично я совершенно не вижу разницы между тем, что ты хочешь, и тем что я написал.

Про замыкания. Сначала прочитай последний абзац в сообщении MK
Автор: Mikl Kurkov
Дата: 05.05.07
. Попробуй пересмотреть свои взгляды на структуру программы. Ты очевидно в курсе, что замыкание — это глагол с состоянием и это состояние херит всю идею глагола как функции. Теперь уже вызов глагола с тем же самым аргументом будет выдавать различные результаты. Если такие глаголы лепить с другими глаголами (а в 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 — текущее количество.
   incrMean =. 0 0 meanClosure
   incrMean 5
5
   incrMean 5
5
   incrMean 4
4.66667
   incrMean 4
4.5


Более засахаренное решение, но в сущности являющимся хаком, через memory-mapped файлы (win32 only):
http://www.jsoftware.com/svn/DanBron/trunk/uncategorized/lexicalclosure.ijs
   load 'lexicalclosure.ijs'
   sumClosure =: 4 : 'x = y % x' lexicalClosureOnRHA
   sum0 =. 0 sumClosure
     sum0 1
1
     sum0 1
2
     sum0 _2
0


Ду хаст. Удачи.
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Усовершенствованная версия foldl
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 01.05.07 10:13
Оценка: 6 (1)
LCR>
foldl =: monad define
  'v a l' =. y
  ll =. l , a
  ". v , '/' , (5!:5) <'ll'
)

Присутствует лёгкое неудовлетворение от кривого использования '".' Так будет лучше:
foldl =: monad define
  'v a l' =. y
  ". 'u =. ', v
  u / l , a
)
   foldl '+' ; 11; i.10
56
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
[J] как сделать foldl?
От: Аноним  
Дата: 30.04.07 12:15
Оценка:
есть вектор и некая матрица, надо провести что-то типа foldl — т.е. отдавать глаголу вектор и очередную строку матрицы, результатом применения глагола заменить начальный вектор(аккумулятор). затем взять следующую строку матрицы и новое значение вектора...
^: здесь не подходит(?) т.к. возвращаемое значение нужно не до уточнения. единственно, что вижу — бесконечная степень с условием или прямо for.
как можно просто решить такую задачу? и вообще задачи такого типа(функциональные), где активно используются операнды?
Re: [J] как сделать foldl?
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 01.05.07 07:28
Оценка:
<Аноним>,

А>есть вектор и некая матрица, надо провести что-то типа 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
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re[2]: [J] как сделать foldl?
От: Аноним  
Дата: 01.05.07 08:20
Оценка:
Здравствуйте, Lazy Cjow Rhrr, Вы писали:
LCR>foldl в J — это скорее '/', чем '^:'
LCR> ...
такие конструкции я понимаю. но я не знаю как сделать вроде этого(erlang):
foldl(F, Acc, [ ]) -> 
    Acc.
foldl(F, Acc, [Hd|Tail]) ->     
    foldl(F, F(Hd, Acc), Tail).

т.е. ни замыканий, ни операндов более 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 они, насколько я понимаю, неприменимы. но тогда как?
не считая прямого перебора индексов в цикле, естественно
Re[5]: [J] как сделать foldl?
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 02.05.07 12:48
Оценка:
<Аноним>

А>спасибо за помошь! но это не 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 передавать в функцию нельзя.

функцию менять нельзя?
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re[6]: [J] как сделать foldl?
От: Аноним  
Дата: 02.05.07 15:44
Оценка:
Здравствуйте, Lazy Cjow Rhrr, Вы писали:
LCR>Всё понятно, ты хочешь протаскивать состояние в глаголе?
здесь инициализатор и глагол сначала применяется к ним, потом — к своим результатам.
можно пример, чтобы в глаголе использовался и такой аккумулятор и и очередная(каждый раз следующая) строка матриицы? я уже совсем замучался — не пойму как это сделать

А>>реализация замыканий через namespace слишком неудобна

LCR>чем?
в wiki на jsoftware есть такой пример — и он слишком похож на хак. т.е. если припрет, то в качестве замыканий пойдет, но хочется более простое решения
А>>дополнительным параметром acc передавать в функцию нельзя.
LCR>функцию менять нельзя?
не понял
Re[2]: Усовершенствованная версия foldl
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 05.05.07 10:21
Оценка:
Mikl Kurkov,

MK>Но вообще подобные вопросы возникают от попыток перенести идиомы из невекторного языка в J в лоб. И при этом часто пропадает весь смысл использования языка. Ни эффективности, ни лаконичности кода. Надо стараться избавляться от старых привычек и стремиться использовать богатый арсенал примитивных векторных операций на максимально высоких рангах, плюс "выращивание" более сложных конструкций путем тацитной композиции.


В общем, трудно не согласиться.
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.