Требуются примеры использования first class function и patte
От: VladD2 Российская Империя www.nemerle.org
Дата: 20.11.06 15:08
Оценка: 1 (1)
Когода кто-то пишет статьи о фунциональном программировании, то почему-то в качестве примеров всегда используются вещи вроде фунций Фибоначи и тому подобной бесполезной фигни.

Это приводит к тому, что у людей закрадывается сомнение, что данные возможности полезны в области математики, парсинга или еще какой-то специализированной области оторванной от жизни.

Предлагаю совместными усилиями подобрать набор примеров которые с одной стороны не требовали бы вникания в некоторую сложную задачу с другой демонстрировали приемущества функциональных языков (first class-функций, алгеброических типов, сопоставления с образцом).

Приветсвуются любые примеры.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: Требуются примеры использования first class function и p
От: Gajdalager Украина  
Дата: 20.11.06 15:29
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Когода кто-то пишет статьи о фунциональном программировании, то почему-то в качестве примеров всегда используются вещи вроде фунций Фибоначи и тому подобной бесполезной фигни.


VD>Это приводит к тому, что у людей закрадывается сомнение, что данные возможности полезны в области математики, парсинга или еще какой-то специализированной области оторванной от жизни.


VD>Предлагаю совместными усилиями подобрать набор примеров которые с одной стороны не требовали бы вникания в некоторую сложную задачу с другой демонстрировали приемущества функциональных языков (first class-функций, алгеброических типов, сопоставления с образцом).


VD>Приветсвуются любые примеры.

За! Правда, сам с ходу ничего предложить не могу, т.к. только учусь... Однако, хотелось, чтобы задачи были реализованы на ИЯ(С++, С#, Java, Python, Ruby), ФЯ (List, ML, Haskel, Erlang) и гибридных (Величайший Язык Современности, Scala, OCaml).. Думаю, достаточно бросить клич, и любители языков засыплют реализациями.. А потом все это склеить — и получим side-by-side сравнение, причем достаточно полезное, так как новичкам (таким, как я), легче будет увидеть, где лучше использовать функциональный подход, а где — императивный.
Re: Требуются примеры использования first class function и p
От: Mamut Швеция http://dmitriid.com
Дата: 20.11.06 16:12
Оценка:
VD>Приветсвуются любые примеры.

Для затравки quicksort и insertion sort на Эрланге сгодятся?

Как оказалось, не все знают, что такое quicksort. Только на прошлой неделе пришлось объяснять...
... << RSDN@Home 1.2.0 alpha rev. 655>>


dmitriid.comGitHubLinkedIn
Re: Требуются примеры использования first class function и p
От: Quintanar Россия  
Дата: 20.11.06 16:12
Оценка:
alpha blend:

let rseed = ref 1234;;

let random () =
    let nrs = (!rseed) * 214013 + 2531011 in
    rseed := nrs;
    (nrs lsr 16) land 0x7FFFFFFF;;

let rec lcreate func lst = function
     0 -> lst
|    n -> lcreate func ((func n)::lst) (n-1);;

let applay_mods mods h n =
    let (x,y) = (n mod h, n / h) in
    let ffun el f = f el x y in
    List.fold_left ffun (0,0,0,0) mods;;

let create_modifier w h _ =
    let x1 = (random ()) mod w
    and y1 = (random ()) mod h
    and x2 = (random ()) mod w
    and y2 = (random ()) mod h
    and cr = (random ()) mod 255
    and cg = (random ()) mod 255
    and cb = (random ()) mod 255
    and ca = (random ()) mod 255 in
    let (nx1,nx2) = if (x1 > x2) then (x2, x1-x2+1) else (x1, x2-x1+1)
    and (ny1,ny2) = if (y1 > y2) then (y2, y1-y2+1) else (y1, y2-y1+1) in
    fun ((r,g,b,a) as point) x y ->
        if ((x < nx1) || (x > nx2) || (y < ny1) || (y > ny2)) then point else 
        let nr = ((((cr-r)*ca) lsr 8) + r) land 255
        and ng = ((((cg-g)*ca) lsr 8) + g) land 255
        and nb = ((((cb-b)*ca) lsr 8) + b) land 255
        and na = (ca*a-((ca*a) lsr 8)) land 255 in
        (nr, ng, nb, na);;

let test_alpha_blend w h n =
    let mods = lcreate (create_modifier w h) [] n in
    lcreate (applay_mods mods h) [] (w*h);;

let main () =
    let w = 1000
    and h = 1000
    and n = 1000 in
    test_alpha_blend w h n;;

main ();;
Re: Требуются примеры использования first class function и p
От: Quintanar Россия  
Дата: 20.11.06 16:15
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Приветсвуются любые примеры.


Continuations in OCaml
Автор: Quintanar
Дата: 14.03.05
Re[2]: Требуются примеры использования first class function
От: VladD2 Российская Империя www.nemerle.org
Дата: 20.11.06 16:44
Оценка:
Здравствуйте, Mamut, Вы писали:

VD>>Приветсвуются любые примеры.


M>Для затравки quicksort и insertion sort на Эрланге сгодятся?


Сгодится. Но примеры не к черту. Кому нужны супер тормозные реализации алгоритмов давно в оптимальном виде имеющиеся влюбой библиотеке?

Нужны просые примеры для демонстрации сути подхода. Лучше чето-нить из того что многие используют на прктике. Ну, там работа с данными, ГУИ (возможно) или еще что-то.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: Требуются примеры использования first class function
От: VladD2 Российская Империя www.nemerle.org
Дата: 20.11.06 16:44
Оценка:
Здравствуйте, Quintanar, Вы писали:

Я наверно не плохо изложил свою мысль. Ни в коем случае не нужны сложные алгоритмы. К тмоу же средний программист применяет альфа блэндинг еще резе чем Фибоначи.

Я сам в ступоре. Не раз испоьзовал те же FCF на практике, но как-то все это частные решения и как пример они лохо подходят.

А есть ли какие-нибудь совсем простые примеры (туториалы, что ли)? Может там поискать?
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: Требуются примеры использования first class function и p
От: Андрей Хропов Россия  
Дата: 20.11.06 17:06
Оценка: 40 (2)
Здравствуйте, VladD2, Вы писали:

Тут есть кое-что.

Хороший пример паттерн-матчинга — парсинг XML (да и текста тоже):
Собственно в туториалах к Немерле есть.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: Требуются примеры использования first class function
От: PhantomIvan  
Дата: 20.11.06 17:09
Оценка:
VD>Я сам в ступоре.

так ты вопрос задал, навроде "приведите примеры использования циклов и полиморфизма"...
конечно сразу не догадаешься что тут вместо коллекций и фигур на экране в пример приводить...

тут наверно, как в императивщине — смотришь в чужой код, иногда думаешь, о! интересный оборот...
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: Требуются примеры использования first class function и p
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 20.11.06 17:15
Оценка:
VladD2,

VD>Приветсвуются любые примеры.


Конечно, хотелось бы универсальный пример, показывающий что:
1. Функции могут присвоены переменным.
2. Функции могут быть переданы как параметры.
3. Функции могут быть возвращены как значения.
4. Функции могут учавствовать в определении структур данных.

Пример охватывающий сразу три первых пункта: символьное дифференцирование — на вход подаётся функция, на выходе тоже функция.

Тривиальный пример на четвёртый пункт — реализация хэш-таблицы. Мне не нравится он тем, что функция-параметр статическая (после определения не меняется) — не видно преимуществ по сравнению с указателями.

Более сложный пример подразумевает хранение в качестве ключа "символ", а в качестве значения какой-нибудь функции для последующей диспетчеризации, скажем реализации интерпретатора. Ничего не стоит реализовать определение новых операций с возможностью непосредственного исполнения.
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re[3]: Требуются примеры использования first class function
От: Алексей П Россия  
Дата: 20.11.06 18:16
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Ну, там работа с данными, ГУИ (возможно) или еще что-то.

Для ГУИ здорово подходят макросы Nemerle, пока дизайнера форм нет, и частичное применение. Вот про макросы (из реального проекта):
CreateNameValueDialog(150, this,
{
    | "Number of inputs" => udInputs : NumericUpDown ( Maximum = 8, Value = 1)
    | "Number of outputs" => udOutputs : NumericUpDown ( Minimum = 1, Maximum = 8, Value = 1)
})

Что делает, мне кажется, примерно ясно. Заодно может задекларировать поля в классе, если их нет.
Только использовать подобные фишки в качестве примеров не стоит наверно... А для FCF хороший пример — какой-нить парсер, или лучше преобразователь деревьев.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[2]: Требуются примеры использования first class function
От: PhantomIvan  
Дата: 20.11.06 18:59
Оценка:
LCR>Конечно, хотелось бы универсальный пример, показывающий что:
LCR>1. Функции могут присвоены переменным.
LCR>2. Функции могут быть переданы как параметры.
LCR>3. Функции могут быть возвращены как значения.
LCR>4. Функции могут учавствовать в определении структур данных.

LCR>Пример охватывающий сразу три первых пункта: символьное дифференцирование — на вход подаётся функция, на выходе тоже функция.


вот здесь я не понял, то есть совсем не понял... (потому что математическая функция и программная функция, это 2 большие разницы)
можно чуть подробней, т.к. мне это очень интересно

LCR>Тривиальный пример на четвёртый пункт — реализация хэш-таблицы. Мне не нравится он тем, что функция-параметр статическая (после определения не меняется) — не видно преимуществ по сравнению с указателями.


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


тут тоже не понял (в т.ч. что это за "символ"), но это в принципе, менее важно
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[2]: Требуются примеры использования first class function
От: DrDred Россия  
Дата: 20.11.06 20:14
Оценка: 30 (1)
Здравствуйте, Андрей Хропов, Вы писали:

АХ>Здравствуйте, VladD2, Вы писали:


АХ>Тут есть кое-что.


АХ>Хороший пример паттерн-матчинга — парсинг XML (да и текста тоже):

АХ>Собственно в туториалах к Немерле есть.

Вот аналогичный(?) пример на Scala
и вообще вот эта страница.
--
WBR, Alexander
Re: Требуются примеры использования first class function и p
От: wonderboy  
Дата: 20.11.06 20:51
Оценка:
Здравствуйте, VladD2, Вы писали:

Очень поддерживаю инициативу. Весьма интересная проблема.


VD>Это приводит к тому, что у людей закрадывается сомнение, что данные возможности полезны в области математики, парсинга или еще какой-то специализированной области оторванной от жизни.


А может быть так оно и есть?


VD>Предлагаю совместными усилиями подобрать набор примеров которые с одной стороны не требовали бы вникания в некоторую сложную задачу с другой демонстрировали приемущества функциональных языков (first class-функций, алгеброических типов, сопоставления с образцом).


Мне понравился пример паттерн матчинга в Yet Another Haskell Tutorial. Раздел 7.4. Там и алгебраические типы есть, и задача не слишком оторванная от жизни (цвета в виде названий и в форме RGB). Да и вообще в этом тьюториале довольно много неплохих примеров, имхо.


VD>Приветсвуются любые примеры.


В какой форме готовить будем?


PS. Может быть у меня опыта маловато в ФП, но всеже красота функционального решения, имхо, особенно хорошо чувствуется именно в нетривиальных задачах.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: Требуются примеры использования first class function и p
От: IT Россия linq2db.com
Дата: 21.11.06 00:25
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Приветсвуются любые примеры.


http://www.rsdn.ru/Forum/?mid=2151110
Автор: IT
Дата: 08.10.06
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Re: Требуются примеры использования first class function и p
От: Tonal- Россия www.promsoft.ru
Дата: 21.11.06 06:24
Оценка: +1
Конечные автоматы — например разбор какого-нибудь лога, или поднятие XMLя через SAX.
Да и в GUI-е довольно частое явление.
Re: Требуются примеры использования first class function и p
От: Mirrorer  
Дата: 21.11.06 10:26
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Предлагаю совместными усилиями подобрать набор примеров которые с одной стороны не требовали бы вникания в некоторую сложную задачу с другой демонстрировали приемущества функциональных языков (first class-функций, алгеброических типов, сопоставления с образцом).


VD>Приветсвуются любые примеры.


Можно подглядеть здесь.

А вообще примеры в Scala By Example слизаны с SICP
... << RSDN@Home 1.2.0 silent >>
Re[3]: Требуются примеры использования first class function
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 21.11.06 10:28
Оценка: 76 (13)
PhantomIvan,

LCR>>Пример охватывающий сразу три первых пункта: символьное дифференцирование — на вход подаётся функция, на выходе тоже функция.


PI>вот здесь я не понял, то есть совсем не понял... (потому что математическая функция и программная функция, это 2 большие разницы)

PI>можно чуть подробней, т.к. мне это очень интересно

Да, совершенно верно (про выделенное). На этом примере хорошо видна разница между указателями на функции и ФВП. А также разница между Лиспом и не-Лиспом.

Итак, предположим, у нас есть некоторый вычислительный алгоритм, которому требуется для работы как сама функция f, так и её производная df (ну например, метод Ньютона, или скажем мы делаем свой собственный Maple ).

У нас есть путь классический — каждый раз когда нам понадобится запустить алгоритм для новой функции f, мы определяем новое тело для функции f и новое тело для функции df. Перекомпилируем. Запускаем... В случае Java/C# у нас есть костыли типа эмиттеров-загрузчиков.

В качестве альтернативы мы можем написать класс-интерпретатор, обёртку над AST, и операция дифференцирования будет расковыривать AST и генерировать новое T. У этого решения есть недостатки, в частности тот, что внешняя функция должна лезть в кишки интерпретатора. Придётся создавать абстрактный слой доступа к AST и т.п. Ну и этот велосипед конечно же будет подчиняться 10-му закону Гринспуна.

Вот путь Лиспа. Нам нужно просто написать функции типа (number? ...), (variable? ...).
(define (deriv exp var)
  (cond ((number? exp) 0)
        ((variable? exp)
          (if (same-variable? exp var) 1 0))
        ((sum? exp)
          (make-sum (deriv (addend exp) var) 
                    (deriv (augend exp) var)))
        ((product? exp)
          (make-sum
            (make-product (multiplier exp)
                          (deriv (multiplicand exp) var))
            (make-product (deriv (multiplier exp) var)
                          (multiplicand exp))))
        (else
          (error "unknown expression type -- DERIV" exp))))

Тогда например
(deriv '(* (* x y) (+ x 3)) 'x)
(+ (* (* x y) (+ 1 0))
   (* (+ (* x 0) (* 1 y))
      (+  x 3)))

То, что выдала функция deriv — это полноценная функция. Её можно например передать в функцию рисования графиков, и будет нарисован график. Если полученное выражение кажется многословным, можно утоптать до минимального вида совершенно аналогичной функцией simplify. (В примере ниже будет одна из реализаций этой функции).

Вот путь Хаскеля. Поскольку в данном случае у нас уже нет волшебного порошка code is data is code , то придётся использовать алгебраические типы. Но с другой стороны это и преимущество, потому что уже работает паттерн-матчинг вместо (cond ...). Выглядеть это будет примерно так:
-- строительные блоки для выражений
infixl 5 :+
infixl 6 :*
data Exp = Num Integer
         | Var Sym
         | Exp :+ Exp
         | Exp :* Exp deriving (Eq,Show)

data Sym = X | Y deriving (Eq,Show)

main = do let exp = (Num 4 :* Var X :* Var X)
          let deriv = d exp X
          putStrLn $ "Original expression : " ++ (show exp)
          putStrLn $ "Derivative : " ++ (show $ simplify deriv)
          putStrLn $ "Derivative evaluated at X=10 : "
                     ++ (show $ eval (d exp X) [(X,10)])

-- взять производную
d (Num n)  x = Num 0
d (Var y)  x | x==y      = Num 1
             | otherwise = Num 0 
d (f :+ g) x = (d f x) :+ (d g x)
d (f :* g) x = (d f x) :* g :+ f :* (d g x)

-- вычислить выражение типа Exp...
eval (Num x) env = x
eval (Var x) env = case (lookup x env) of 
                        (Just n)  -> n
                        (Nothing) -> error $ "no variable "++(show x)++" in env"
eval (x :+ y) env = eval x env + eval y env
eval (x :* y) env = eval x env * eval y env

-- несколько алгебраических правил для упрощения
simp (x :+ y) | x == y = simp (Num 2):*x
simp ((Num 0) :+ x) = simp x
simp (x :+ (Num 0)) = simp x
simp ((Num x) :+ (Num y)) = Num (x+y)
simp (x :+ y) = simp x :+ simp y
simp ((Num 0) :* x) = Num 0
simp (x :* (Num 0)) = Num 0
simp ((Num 1) :* x) = simp x
simp (x :* (Num 1)) = simp x
simp ((Num x) :* (Num y)) = Num (x*y)
simp (x :* y) = simp x :* simp y
simp x = x

-- применять правила упрощения до тех пор, пока выражение не перестанет меняться
simplify x = let a = iterate simp x
                 fix = dropWhile (\(c,d)->c/=d) $ zip a (tail a)
             in (fst.head) fix

Вышеприведённый код выведет примерно следующее:
Original expression : (Num 4 :* Var X) :* Var X
Derivative : Num 2 :* (Num 4 :* Var X)
Derivative evaluated at X=10 : 80


Владу скорее всего пример не понравится, потому что слишком заумный и оторванный от жизни. А мне очень нравится, более того, могу сказать, что современные оптимизаторы в компиляторах — это функции типа simp, только естественно гораздо более сложные.
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re[4]: Требуются примеры использования first class function
От: Mirrorer  
Дата: 21.11.06 10:46
Оценка: 1 (1)
Здравствуйте, Lazy Cjow Rhrr, Вы писали:

Большое человеческое спасибо за пример на Haskell.
... << RSDN@Home 1.2.0 silent >>
Re[4]: Требуются примеры использования first class function
От: PhantomIvan  
Дата: 21.11.06 11:16
Оценка:
LCR>>>Пример охватывающий сразу три первых пункта: символьное дифференцирование — на вход подаётся функция, на выходе тоже функция.

PI>>вот здесь я не понял, то есть совсем не понял... (потому что математическая функция и программная функция, это 2 большие разницы)

PI>>можно чуть подробней, т.к. мне это очень интересно

LCR>В качестве альтернативы мы можем написать класс-интерпретатор, обёртку над AST, и операция дифференцирования будет расковыривать AST и генерировать новое T. У этого решения есть недостатки, в частности тот, что внешняя функция должна лезть в кишки интерпретатора. Придётся создавать абстрактный слой доступа к AST и т.п. Ну и этот велосипед конечно же будет подчиняться 10-му закону Гринспуна.


вот, я как-нибудь подобное реализую, а что такое 10 закон Гринспуна? что все сложное ломается?

LCR>Вот путь Лиспа.


вот эта вот концепция: code is data is code очень даже подходит для символьных вычислений
но я как статически типизированный мэн, должен спросить: насколько реально это перетянуть к себе?
(как насчет: вычисляем в рантайм -> кидаем обратно в сорс?)

LCR>Вот путь Хаскеля.


он уже ближе к статике, не так ли?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[5]: Требуются примеры использования first class function
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 21.11.06 11:43
Оценка:
PhantomIvan,

PI>вот, я как-нибудь подобное реализую, а что такое 10 закон Гринспуна? что все сложное ломается?

Greenspun's Tenth Rule of Programming: "Any sufficiently complicated C or Fortran program contains an ad-hoc, informally-specified bug-ridden slow implementation of half of Common Lisp."


PI>вот эта вот концепция: code is data is code очень даже подходит для символьных вычислений

PI>но я как статически типизированный мэн, должен спросить: насколько реально это перетянуть к себе?
PI>(как насчет: вычисляем в рантайм -> кидаем обратно в сорс?)

У нас есть статический метод Calc.f(double x), тебе надо его расковырять (о, мне это будет очень интересно увидеть), к структуре данных, полученной после расковырки применяется функция deriv, затем по полученной структуре эмиттим класс CalcD с методом df(double x) и грузим его класслоадером. Это реализуемо, но мне не нравится это решение.

LCR>>Вот путь Хаскеля.

PI>он уже ближе к статике, не так ли?
Да, ближе.
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re[5]: Требуются примеры использования first class function
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 21.11.06 11:46
Оценка:
Mirrorer,

M>Большое человеческое спасибо за пример на Haskell.


Взаимно.
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re[5]: Требуются примеры использования first class function
От: Курилка Россия http://kirya.narod.ru/
Дата: 21.11.06 12:08
Оценка: 4 (1)
Здравствуйте, PhantomIvan, Вы писали:

PI>вот эта вот концепция: code is data is code очень даже подходит для символьных вычислений

PI>но я как статически типизированный мэн, должен спросить: насколько реально это перетянуть к себе?
PI>(как насчет: вычисляем в рантайм -> кидаем обратно в сорс?)

здесь (D-Expressions: Lisp Power, Dylan Style) есть дока про то как лисповые макросы к обычному синтаксису применить, может к статике/динамике не относится, пок ещё не дошли руки прочитать
Re[2]: Требуются примеры использования first class function
От: Трурль  
Дата: 21.11.06 13:37
Оценка: 21 (3) +1
Здравствуйте, Lazy Cjow Rhrr, Вы писали:

LCR>Конечно, хотелось бы универсальный пример, показывающий что:

LCR>1. Функции могут присвоены переменным.
LCR>2. Функции могут быть переданы как параметры.
LCR>3. Функции могут быть возвращены как значения.
LCR>4. Функции могут учавствовать в определении структур данных.

Мне очень понравился пример из известной статьи, когда Функции использовались для представления геометрических областей.
> type Region = Point -> Bool

> circle :: Radius -> Region -- creates a region with given radius
> outside :: Region -> Region -- the logical negation of a region
> (/\) :: Region -> Region -> Region -- the intersection of two regions

> annulus :: Radius -> Radius -> Region
> annulus r1 r2 = outside (circle r1) /\ circle r2
Re[3]: Требуются примеры использования first class function
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 21.11.06 14:10
Оценка:
Трурль,

Т>Мне очень понравился пример из известной статьи, когда Функции использовались для представления геометрических областей.

Т>
>> type Region = Point -> Bool

>> circle :: Radius -> Region -- creates a region with given radius
>> outside :: Region -> Region -- the logical negation of a region
>> (/\) :: Region -> Region -> Region -- the intersection of two regions

>> annulus :: Radius -> Radius -> Region
>> annulus r1 r2 = outside (circle r1) /\ circle r2
Т>


Хм, интересная идея. А в чём преимущество по сравнению с представлением области с помощью АТД?
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re[4]: Требуются примеры использования first class function
От: Programmierer AG  
Дата: 21.11.06 16:02
Оценка: 11 (1)
Lazy Cjow Rhrr wrote:

> Хм, интересная идея. А в чём преимущество по сравнению с представлением области с помощью АТД?


Вот, набросал для сравнения:
-- Вариант 1

infixl 5 /\
infixl 5 \/

type Point = (Float, Float)

type Region = Point -> Bool

p `inRegion` r = r p

circle (x,y) r = \(x',y') -> (x-x')2 + (y-y')2 < r2
rectangle (x1,y1) (x2,y2) =
    \(x,y) -> x > min x1 x2 && x < max x1 x2 &&
              y > min y1 y2 && y < max y1 y2
outside r = \p -> not (p `inRegion` r)
x /\ y = \p -> (p `inRegion` x) && (p `inRegion` y)
x \/ y = \p -> (p `inRegion` x) || (p `inRegion` y)

-- Вариант 2

infixl 5 /\
infixl 5 \/

type Point = (Float, Float)

data Region = Circle Point Float         |
              Rectangle Point Point      |
              Outside Region             |
              Intersection Region Region |
              Union Region Region

-- функции-конструкторы для единообразия примитивных
-- и сложных регионов
circle = Circle
rectangle = Rectangle
outside = Outside
(/\) = Intersection
(\/) = Union

(x,y) `inRegion` (Circle (x',y') r) = (x-x')2 + (y-y')2 < r2
(x,y) `inRegion` (Rectangle (x1,y1) (x2,y2)) =
    x > min x1 x2 && x < max x1 x2 && y > min y1 y2 && y < max y1 y2
p `inRegion` (Outside r) = not (p `inRegion` r)
p `inRegion` (Intersection x y) = (p `inRegion` x) && (p `inRegion` y)
p `inRegion` (Union x y) = (p `inRegion` x) || (p `inRegion` y)

-- клиентский код
annulus center r1 r2 = outside (circle center r1) /\ (circle center r2)


Количество кода сравнимо, но первый вариант чуть элегантнее, хотя это
субъективно. Ну и чище с философской точки зрения . Какое определение
правильнее: регион — это правило, позволяющее отличить внутренние точки
от внешних, или регион — это круг, прямоугольник и их
пересечения/объединения? Но это больше эстетические отличия,
практические мне видятся такими: у АТД-варианта преимущество в том, что
легко добавлять новые операции. У HOF-варианта преимущество в том, что
примитивы не отличаются от сложных регионов; пользователь такой
библиотеки может добавлять новые примитивы, не изменяя определение типа
Region.

Мне вот интересно, отличаются ли эти варианты по производительности (при
условии, что проверка принадлежности точки сложным регионам выполняется
часто)? В первом варианте функция создания сложного региона (вроде
annulus) фактически конструирует функцию принадлежности, которую тут же,
при компиляции, можно оптимизировать; во втором же случае мы просто
конструируем AST, которое может интерпретироваться в рантайме. Просто
глупая идея, возникшая по ходу, не факт, что компилятор будет
оптимизировать первый вариант или не будет оптимизировать второй.
Posted via RSDN NNTP Server 2.0
Re[5]: Требуются примеры использования first class function
От: Programmierer AG  
Дата: 21.11.06 16:04
Оценка:
Здравствуйте, Programmierer AG, Вы писали:

PA>circle (x,y) r = \(x',y') -> (x-x')2 + (y-y')2 < r2

должно быть (x-x')^2 + (y-y')^2 < r^2, при копировании крышки потерялись.
Re[4]: Требуются примеры использования first class function
От: VladD2 Российская Империя www.nemerle.org
Дата: 21.11.06 17:00
Оценка:
Здравствуйте, Lazy Cjow Rhrr, Вы писали:

LCR>Владу скорее всего пример не понравится, потому что слишком заумный и оторванный от жизни.


+1

LCR>А мне очень нравится, более того, могу сказать, что современные оптимизаторы в компиляторах — это функции типа simp, только естественно гораздо более сложные.


У меня нет задачи поразить читателя познаниями в области оптимизаций в компиляторах. У меня задача объяснить людям никогда до этого не видивших возможностей Х, то что они могут быть им полезны, и что эти возможности не являются просто заумными закорючками.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: Требуются примеры использования first class function
От: VladD2 Российская Империя www.nemerle.org
Дата: 21.11.06 17:00
Оценка:
Здравствуйте, Mirrorer, Вы писали:

M>Можно подглядеть здесь.


M>А вообще примеры в Scala By Example слизаны с SICP


Мне нужны конкретные примеры, а не ссылки в не ссылки в общем направлени.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: Требуются примеры использования first class function
От: Dr.Gigabit  
Дата: 21.11.06 17:58
Оценка: -1
LCR>>А мне очень нравится, более того, могу сказать, что современные оптимизаторы в компиляторах — это функции типа simp, только естественно гораздо более сложные.

VD>У меня нет задачи поразить читателя познаниями в области оптимизаций в компиляторах. У меня задача объяснить людям никогда до этого не видивших возможностей Х, то что они могут быть им полезны, и что эти возможности не являются просто заумными закорючками.


Видимо следует читать "объяснить людям никогда до этого не видивших возможностей N"
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: Требуются примеры использования first class function
От: Mirrorer  
Дата: 21.11.06 18:46
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Здравствуйте, Mirrorer, Вы писали:


M>>Можно подглядеть здесь.


M>>А вообще примеры в Scala By Example слизаны с SICP


VD>Мне нужны конкретные примеры, а не ссылки в не ссылки в общем направлени.

A function in Scala is a “first-class value”. Like any other value, it may be passed as
a parameter or returned as a result. Functions which take other functions as parameters
or return them as results are called higher-order functions. This chapter
introduces higher-order functions and shows how they provide a flexible mechanism
for program composition.
As a motivating example, consider the following three related tasks:
1. Write a function to sumall integers between two given numbers a and b:
def sumInts(a: int, b: int): int =
    if (a > b) 0 else a + sumInts(a + 1, b)

2. Write a function to sumthe squares of all integers between two given numbers
a and b:
def square(x: int): int = x * x
def sumSquares(a: int, b: int): int =
    if (a > b) 0 else square(a) + sumSquares(a + 1, b)

3. Write a function to sum the powers 2n of all integers n between two given
numbers a and b:
def powerOfTwo(x: int): int = if (x == 0) 1 else x * powerOfTwo(x 1)
def sumPowersOfTwo(a: int, b: int): int =
    if (a > b) 0 else powerOfTwo(a) + sumPowersOfTwo(a + 1, b)

These functions are all instances of Sum[a..b] f (n) for different values of f . We can factor
out the common pattern by defining a function sum:
def sum(f: int => int, a: int, b: int): double =
    if (a > b) 0 else f(a) + sum(f, a + 1, b)

The type int => int is the type of functions that take arguments of type int and
return results of type int. So sum is a function which takes another function as a
parameter. In other words, sum is a higher-order function.
Using sum, we can formulate the three summing functions as follows.
def sumInts(a: int, b: int): int = sum(id, a, b)
def sumSquares(a: int, b: int): int = sum(square, a, b)
def sumPowersOfTwo(a: int, b: int): int = sum(powerOfTwo, a, b)
    where
def id(x: int): int = x
def square(x: int): int = x * x
def powerOfTwo(x: int): int = if (x == 0) 1 else x * powerOfTwo(x 1)
Re[5]: Требуются примеры использования first class function
От: Mirrorer  
Дата: 21.11.06 18:55
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Здравствуйте, Lazy Cjow Rhrr, Вы писали:


LCR>>Владу скорее всего пример не понравится, потому что слишком заумный и оторванный от жизни.


VD>+1


А как насчет реализации модного GoF паттерна Interpreter ?
Re[4]: Требуются примеры использования first class function
От: PhantomIvan  
Дата: 21.11.06 19:28
Оценка:
M>>>А вообще примеры в Scala By Example слизаны с SICP

вот, скала — вот с чем надо сравнить немерле
а то может у них что-то еще есть чего нет в немерле, кроме трейтов
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[6]: Требуются примеры использования first class function
От: PhantomIvan  
Дата: 21.11.06 19:41
Оценка: -1
PI>>вот, я как-нибудь подобное реализую, а что такое 10 закон Гринспуна? что все сложное ломается?
LCR>

LCR>Greenspun's Tenth Rule of Programming: "Any sufficiently complicated C or Fortran program contains an ad-hoc, informally-specified bug-ridden slow implementation of half of Common Lisp."


Гринспун явно считал, что свет на Лиспе клином сошелся

PI>>вот эта вот концепция: code is data is code очень даже подходит для символьных вычислений

PI>>но я как статически типизированный мэн, должен спросить: насколько реально это перетянуть к себе?
PI>>(как насчет: вычисляем в рантайм -> кидаем обратно в сорс?)

LCR>У нас есть статический метод Calc.f(double x), тебе надо его расковырять (о, мне это будет очень интересно увидеть), к структуре данных, полученной после расковырки применяется функция deriv, затем по полученной структуре эмиттим класс CalcD с методом df(double x) и грузим его класслоадером. Это реализуемо, но мне не нравится это решение.


ага, мне тоже не нравится, когда буду делать (на немерле) — получится ближе к хаскелю (деревья однако)
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[5]: Требуются примеры использования first class function
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 22.11.06 00:25
Оценка: +1
VladD2,

LCR>>Владу скорее всего пример не понравится, потому что слишком заумный и оторванный от жизни.


VD>+1


ЮИЙО! Я однако мысли научился читать!

VD>У меня нет задачи поразить читателя познаниями в области оптимизаций в компиляторах. У меня задача объяснить людям никогда до этого не видивших возможностей Х, то что они могут быть им полезны, и что эти возможности не являются просто заумными закорючками.


Да всё это понятно. С одной стороны, пример должен быть достаточно простым, чтобы не перегружать читателя. Но с другой стороны, пример должен быть достаточно сложный, чтобы продемонстрировать существенность различий между решениями. А если добавить сюда то, что есть очень скептически настроенные товарищи, как например

I can't really imagine needing anything else in a language that isn't catered for in c# or vb.net for example.
...
I write in .net. I can't think of why I'd need another language.

то задача поиска подходящих примеров становится ну просто очень сложной...

PS: Цитата взята с why do people keep creating new languages.
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re[6]: Требуются примеры использования first class function
От: VladD2 Российская Империя www.nemerle.org
Дата: 22.11.06 01:23
Оценка:
Здравствуйте, Mirrorer, Вы писали:

M>А как насчет реализации модного GoF паттерна Interpreter ?


А кому он реально нужен?
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: Требуются примеры использования first class function
От: VladD2 Российская Империя www.nemerle.org
Дата: 22.11.06 01:23
Оценка:
Здравствуйте, Lazy Cjow Rhrr, Вы писали:

LCR>Да всё это понятно. С одной стороны, пример должен быть достаточно простым, чтобы не перегружать читателя. Но с другой стороны, пример должен быть достаточно сложный, чтобы продемонстрировать существенность различий между решениями.


Именно. Причем он еще не должен быть надуманным. В общем, но не должен вызывать никаких отрицательных эмоций.

LCR> А если добавить сюда то, что есть очень скептически настроенные товарищи, как например...


Что-то вроде. Но део не в радикальных взглядах. Дело в синдроме Блаб-программиста. Надеюсь про это пояснять не потребуется?

LCR>то задача поиска подходящих примеров становится ну просто очень сложной...


Просто и доходичво объяснить совсем непонятные вещи в принципе очень сложная задача. К сожалению когда мы привыкаем к чему-то, то восвсем забываем как работал наш мозг до знакомства с этим чем-то. И это приводит к тому, что мы плохо объясняем. Для ФП это настоящий бич.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: Требуются примеры использования first class function
От: VladD2 Российская Империя www.nemerle.org
Дата: 22.11.06 01:23
Оценка:
Здравствуйте, Алексей П, Вы писали:

АП>Для ГУИ здорово подходят макросы Nemerle,


Макросы можно продемонстрировать на тысячах примеров. И их суть (в общем) понятна почти всем. Я говорю о функциональных изысках вроде функции первоклассные объеты и сопоставление с образцом.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: Требуются примеры использования first class function
От: VladD2 Российская Империя www.nemerle.org
Дата: 22.11.06 01:23
Оценка:
Здравствуйте, PhantomIvan, Вы писали:

PI>тут наверно, как в императивщине — смотришь в чужой код, иногда думаешь, о! интересный оборот...


Вот и нужны такие места. Но так чтобы примеры не были надумаными, были понятны большиству и при этом демонстрировали реальные приемущества.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: Требуются примеры использования first class function
От: Tonal- Россия www.promsoft.ru
Дата: 22.11.06 05:32
Оценка:
Я как то делал оба варианта на С++.
Первый — на шаблонах, второй на виртуальности.
Как вы думаете — какой был быстрее?
Re[5]: Требуются примеры использования first class function
От: Трурль  
Дата: 22.11.06 06:09
Оценка:
Здравствуйте, Programmierer AG, Вы писали:

PA>Вот, набросал для сравнения:

PA>
PA>outside r = \p -> not (p `inRegion` r)
PA>x /\ y = \p -> (p `inRegion` x) && (p `inRegion` y)
PA>x \/ y = \p -> (p `inRegion` x) || (p `inRegion` y)
PA>

вот этот кусок можно было бы записать и попроще
outside  = not
(/\) = (&&)
(\/) = (||)

.
Re[7]: Требуются примеры использования first class function
От: Mirrorer  
Дата: 22.11.06 06:40
Оценка: 5 (2)
Здравствуйте, VladD2, Вы писали:


M>>А как насчет реализации модного GoF паттерна Interpreter ?


VD>А кому он реально нужен?


Наверное тем, кому нужен DSL. Другое дело что некоторые языки позволяют использовать макросы. Но, с другой стороны, можно сделать расширеный пример.
DSL без паттена матчинга, с паттерн матчингом, на макросах.

А по поводу примеров на паттерн матчинг в Grokking Nemerle
здесь есть более менее приличный пример с RGB цветами.
Но есть подозрение что этот пример переделан из нижеприведенного куска Yet Another Haskell tutorial

Pattern matching is one of the most powerful features of Haskell (and most functional
programming languages). It is most commonly used in conjunction with case expressions,
which we have already seen in Section 3.5. Let's return to our Color example
from Section 4.5. I'll repeat the definition we already had for the datatype:

data Color
    = Red
    | Orange
    | Yellow
    | Green
    | Blue
    | Purple
    | White
    | Black
    | Custom Int Int Int -- R G B components
deriving (Show,Eq)

We then want to write a function that will convert between something of type Color
and a triple of Ints, which correspond to the RGB values, respectively. Specifically, if
we see a Color which is Red, we want to return (255,0,0), since this is the RGB
value for red. So we write that (remember that piecewise function definitions are just
case statements):
colorToRGB Red = (255,0,0)

If we see a Color which is Orange, we want to return (255,128,0); and if we
see Yellow, we want to return (255,255,0), and so on. Finally, if we see a custom
color, which is comprised of three components, we want to make a triple out of these,
so we write:
colorToRGB Orange = (255,128,0)
colorToRGB Yellow = (255,255,0)
colorToRGB Green = (0,255,0)
colorToRGB Blue = (0,0,255)
colorToRGB Purple = (255,0,255)
colorToRGB White = (255,255,255)
colorToRGB Black = (0,0,0)
colorToRGB (Custom r g b) = (r,g,b)

Then, in our interpreter, if we type:
Color> colorToRGB Yellow
(255,255,0)

What is happening is this: we create a value, call it x, which has value Red. We
then apply this to colorToRGB. We check to see if we can ?match? x against Red.
This match fails because according to the definition of Eq Color, Red is not equal
to Yellow. We continue down the definitions of colorToRGB and try to match
Yellow against Orange. This fails, too. We the try to match Yellow against
Yellow, which succeeds, so we use this function definition, which simply returns
the value (255,255,0), as expected.
Suppose instead, we used a custom color:
Color> colorToRGB (Custom 50 200 100)
(50,200,100)
We apply the same matching process, failing on all values from Red to Black.
We then get to try to match Custom 50 200 100 against Custom r g b. We
can see that the Custom part matches, so then we go see if the subelements match. In
the matching, the variables r, g and b are essentially wild cards, so there is no trouble
matching r with 50, g with 200 and b with 100. As a ?side-effect? of this matching, r
gets the value 50, g gets the value 200 and b gets the value 100. So the entire match
succeeded and we look at the definition of this part of the function and bundle up the
triple using the matched values of r, g and b.
We can also write a function to check to see if a Color is a custom color or not:
isCustomColor (Custom _ _ _) = True
isCustomColor _ = False

When we apply a value to isCustomColor it tries to match that value against
Custom . This match will succeed if the value is Custom x y z for any x,
y and z. The (underscore) character is a ?wildcard? and will match anything, but will
not do the binding that would happen if you put a variable name there. If this match
succeeds, the function returns True; however, if this match fails, it goes on to the next
line, which will match anything and then return False.
For some reason we might want to define a function which tells us whether a given
color is ?bright? or not, where my definition of ?bright? is that one of its RGB components
is equal to 255 (admittedly and arbitrary definition, but it's simply an example).
We could define this function as:
isBright = isBright' . colorToRGB
    where     isBright' (255,_,_) = True
            isBright' (_,255,_) = True
            isBright' (_,_,255) = True
            isBright' _ = False

Let's dwell on this definition for a second. The isBright function is the composition
of our previously defined function colorToRGB and a helper function isBright',
which tells us if a given RGB value is bright or not. We could replace the first line here

with isBright c = isBright' (colorToRGB c) but there is no need to explicitly
write the parameter here, so we don't. Again, this function composition style
of programming takes some getting used to, so I will try to use it frequently in this
tutorial.
The isBright' helper function takes the RGB triple produced by colorToRGB.
It first tries to match it against (255, , ) which succeeds if the value has 255 in
its first position. If this match succeeds, isBright' returns True and so does
isBright. The second and third line of definition check for 255 in the second and
third position in the triple, respectively. The fourth line, the fallthrough, matches everything
else and reports it as not bright.
We might want to also write a function to convert between RGB triples and Colors.
We could simple stick everything in a Custom constructor, but this would defeat the
purpose; we want to use the Custom slot only for values which don't match the prede
fined colors. However, we don't want to allow the user to construct custom colors
like (600,-40,99) since these are invalid RGB values. We could throw an error if such
a value is given, but this can be difficult to deal with. Instead, we use the Maybe
datatype. This is defined (in the Prelude) as:
data Maybe a = Nothing
| Just a

The way we use this is as follows: our rgbToColor function returns a value of
type Maybe Color. If the RGB value passed to our function is invalid, we return
Nothing, which corresponds to a failure. If, on the other hand, the RGB value is
valid, we create the appropriate Color value and return Just that. The code to do this
is:
rgbToColor 255 0 0 = Just Red
rgbToColor 255 128 0 = Just Orange
rgbToColor 255 255 0 = Just Yellow
rgbToColor 0 255 0 = Just Green
rgbToColor 0 0 255 = Just Blue
rgbToColor 255 0 255 = Just Purple
rgbToColor 255 255 255 = Just White
rgbToColor 0 0 0 = Just Black
rgbToColor r g b =
    if     0 <= r && r <= 255 &&
        0 <= g && g <= 255 &&
        0 <= b && b <= 255
    then Just (Custom r g b)
    else Nothing -- invalid RGB value

The first eight lines match the RGB arguments against the predefined values and,
if they match, rgbToColor returns Just the appropriate color. If none of these
matches, the last definition of rgbToColor matches the first argument against r, the

second against g and the third against b (which causes the side-effect of binding these
values). It then checks to see if these values are valid (each is greater than or equal to
zero and less than or equal to 255). If so, it returns Just (Custom r g b); if not,
it returns Nothing corresponding to an invalid color.
Using this, we can write a function that checks to see if a right RGB value is valid:
rgbIsValid r g b = rgbIsValid' (rgbToColor r g b)
where rgbIsValid' (Just _) = True
    rgbIsValid' _ = False

Here, we compose the helper function rgbIsValid' with our function rgbToColor.
The helper function checks to see if the value returned by rgbToColor is Just anything
(the wildcard). If so, it returns True. If not, it matches anything and returns
False.
Pattern matching isn't magic, though. You can only match against datatypes; you
cannot match against functions. For instance, the following is invalid:
f x = x + 1
g (f x) = x

Even though the intended meaning of g is clear (i.e., g x = x — 1), the compiler
doesn't know in general that f has an inverse function, so it can't perform matches
like this.

... << RSDN@Home 1.2.0 silent >>
Re[4]: Требуются примеры использования first class function
От: ie Россия http://ziez.blogspot.com/
Дата: 22.11.06 06:59
Оценка:
Здравствуйте, Mirrorer, Вы писали:

VD>>Мне нужны конкретные примеры, а не ссылки в не ссылки в общем направлени.

M>
M>def sumInts(a: int, b: int): int = sum(id, a, b)
M>def sumSquares(a: int, b: int): int = sum(square, a, b)
M>def sumPowersOfTwo(a: int, b: int): int = sum(powerOfTwo, a, b)
M>    where
M>def id(x: int): int = x
M>def square(x: int): int = x * x
M>def powerOfTwo(x: int): int = if (x == 0) 1 else x * powerOfTwo(x 1)
M>


[оффтоп]
Затеял утреннюю разминку мозгов - втыкание в мир J :))
За базу взял приведенные примеры.

Определил 7 глаголов:

genArr =. ((0{q)+i.@>:@-@-/@q=.2&{.) .NB Генерируем массив по заданным границам [genArr 2 6 -> 2 3 4 5 6]

.NB следующие 3 можно было бы и не вводить, но для наглядности пущай будут
square =. *:    .NB Другие варианты: square =. 3 : 'y^2' или square =. 3 : 'y*y'
powerOfTwo =. ! .NB Если я все правильно понял, в примере на Scala потерялся минус и powerOfTwo не что иное, как факториал.
                .NB Можно выразить через другие примитивы: powerOfTwo =. */@(1&}.)@i.@>:
sum =. +/

sumInts =. sum@genArr
sumSquares =. sum@square@genArr
sumPowerOfTwo =. sum@powerOfTwo@genArr

.NB собственно использование:

sumInts 2 6        .NB выводит: 20
sumSquares 2 6     .NB выводит: 90
sumPowerOfTwo 2 6  .NB тут мои мозги закипели, выводит: 2 6 24 120 720... Почему?!!  :xz: 
.NB причем: "sum powerOfTwo@genArr 2 6" в отличае от "sum@powerOfTwo@genArr 2 6" выводит все правильно.
.NB аналогичная ситуация для случая с использованием стандартного square, т.е. "square =. *:", а для переопределенных вариантов все ок
[/оффтоп]


Все же хотелось бы более глобальный пример, какое-нибудь завершенное приложение, аля "Судоку солвер", но менее алгоритмически нацеленный. Кстати, что до "Судоку солвера", по мне так достаточно хороший пример демонстрации подходов в тех или иных языках.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Превратим окружающую нас среду в воскресенье.
Re[5]: Требуются примеры использования first class function
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 22.11.06 07:55
Оценка:
ie,

ie>Затеял утреннюю разминку мозгов — втыкание в мир J

ie>За базу взял приведенные примеры.

...
ie>sumPowerOfTwo 2 6  .NB тут мои мозги закипели, выводит: 2 6 24 120 720... Почему?!!  :xz:

Потому что поведение глагола сильно зависит ранга. Правильным решением будет определить так:
sumInts =. sum@:genArr
sumSquares =. sum@:square@genArr
sumPowerOfTwo =. sum@:powerOfTwo@genArr

Либо вместо @: написать @"_. В любом случае, рекомендую полностью ознакомиться с 6-й главой J4C (если конечно интерес к J не мимолётный).

Ещё я не понял, почему функция называется sumPowerOfTwo, когда ты рисуешь факториал
   2&^ i. 10
1 2 4 8 16 32 64 128 256 512
   ! i.10
1 1 2 6 24 120 720 5040 40320 362880


ie>Все же хотелось бы более глобальный пример, какое-нибудь завершенное приложение, аля "Судоку солвер", но менее алгоритмически нацеленный. Кстати, что до "Судоку солвера", по мне так достаточно хороший пример демонстрации подходов в тех или иных языках.


Это всего-лишь рекурсивный поиск с откатом Мне с моим чахлым воображением трудно представить, что в разных языках решения могут быть существенно разными. Единственный момент — это реализация с хвостовой рекурсией и без.
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re[5]: Требуются примеры использования first class function
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 22.11.06 08:22
Оценка:
ie,

ie>genArr =. ((0{q)+i.@>:@-@-/@q=.2&{.) .NB Генерируем массив по заданным границам [genArr 2 6 -> 2 3 4 5 6]

Ещё можно воспользоваться вилками, что даёт несколько более компактный результат:
   genArr =. {. + i. @: ([: >: }.-{.)
   genArr 2 6
2 3 4 5 6


Кстати, а что это ты заинтересовалсо? Насколько я могу судить, здесь (т.е. на рсдн) J не в почёте...
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re[6]: Требуются примеры использования first class function
От: Mirrorer  
Дата: 22.11.06 08:31
Оценка: +2
Здравствуйте, Lazy Cjow Rhrr, Вы писали:


LCR>Кстати, а что это ты заинтересовалсо? Насколько я могу судить, здесь (т.е. на рсдн) J не в почёте...


Лично я без RSDN скорее всего и не услышал о таком языке
И заинтересовался как раз после примеров в Этюдах, так что вот ...

А потрогать язык хотя бы для понимания того, что и даже вот так вот можно, ИМХО полезно
... << RSDN@Home 1.2.0 Pink Floyd — Nobody Home >>
Re[6]: Требуются примеры использования first class function
От: Programmierer AG  
Дата: 22.11.06 08:31
Оценка: +1
Трурль wrote:
> PA>
> PA>outside r = \p -> not (p `inRegion` r)
> PA>x /\ y = \p -> (p `inRegion` x) && (p `inRegion` y)
> PA>x \/ y = \p -> (p `inRegion` x) || (p `inRegion` y)
> PA>

> вот этот кусок можно было бы записать и попроще
>
> outside  = not
> (/\) = (&&)
> (\/) = (||)
>


Чего-то я не понимаю, как это упрощение должно работать
[code]
ERROR "hudak94.hs":45 — Type error in application
*** Expression : outside (circle center r1) /\ circle center r2
*** Term : circle center r2
*** Type : (a,a) -> Bool
*** Does not match : Bool
[code]

Не разовьешь мысль?
Я тут вижу разве что возможность вместо (p `inRegion` r) писать (r p),
но, как сказано в статье:

This function was strictly unnecessary, and resulted in more lines of
code, but was considered to be an elegant form of self-documentation.

Posted via RSDN NNTP Server 2.0
Re[6]: Требуются примеры использования first class function
От: Mirrorer  
Дата: 22.11.06 08:53
Оценка: +1 :)
Здравствуйте, Lazy Cjow Rhrr, Вы писали:


ie>>Все же хотелось бы более глобальный пример, какое-нибудь завершенное приложение, аля "Судоку солвер", но менее алгоритмически нацеленный. Кстати, что до "Судоку солвера", по мне так достаточно хороший пример демонстрации подходов в тех или иных языках.


LCR>Это всего-лишь рекурсивный поиск с откатом Мне с моим чахлым воображением трудно представить, что в разных языках решения могут быть существенно разными. Единственный момент — это реализация с хвостовой рекурсией и без.


Всего лишь рекурсивный поиск с откатом, говоришь ? Трудно представить существенно разные значения говоришь ?
Красота!
Автор: Lazy Cjow Rhrr
Дата: 06.12.05
... << RSDN@Home 1.2.0 Pink Floyd — Waiting For The Worms >>
Re[5]: Требуются примеры использования first class function
От: Programmierer AG  
Дата: 22.11.06 08:58
Оценка: 25 (1)
ie wrote:

> Все же хотелось бы более глобальный пример, какое-нибудь завершенное приложение, аля "Судоку солвер", но менее алгоритмически нацеленный.


Записки dr_klm
читал? Там введение в язык с подробным разбором процесса решения задачи.
Правда, насчет "менее алгоритмически нацеленный" не уверен.

Вот еще забавная ссылка с участием того же Метлова:
At Play with J: Metlov’s<br />
Triumph
.
Posted via RSDN NNTP Server 2.0
Re[6]: Требуются примеры использования first class function
От: ie Россия http://ziez.blogspot.com/
Дата: 22.11.06 09:31
Оценка:
Здравствуйте, Lazy Cjow Rhrr, Вы писали:

LCR>
ie>>sumPowerOfTwo 2 6  .NB тут мои мозги закипели, выводит: 2 6 24 120 720... Почему?!!  :xz: 
LCR>

LCR>Потому что поведение глагола сильно зависит ранга. Правильным решением будет определить так:
LCR>
LCR>sumInts =. sum@:genArr
LCR>sumSquares =. sum@:square@genArr
LCR>sumPowerOfTwo =. sum@:powerOfTwo@genArr
LCR>

LCR>Либо вместо @: написать @"_.



LCR>В любом случае, рекомендую полностью ознакомиться с 6-й главой J4C (если конечно интерес к J не мимолётный).


Да и с другими тоже не мешало бы, пока успел лишь в слуварь глянуть, да кое-какие примеры поглядеть.

LCR>Ещё я не понял, почему функция называется sumPowerOfTwo, когда ты рисуешь факториал

LCR>
LCR>   2&^ i. 10
LCR>1 2 4 8 16 32 64 128 256 512
LCR>   ! i.10
LCR>1 1 2 6 24 120 720 5040 40320 362880
LCR>


Дык, я тоже не понимаю почему в примере функция с названием powerOfTwo имеет такое тело:
def powerOfTwo(x: int): int = if (x == 0) 1 else x * powerOfTwo(x - 1)



ie>>Все же хотелось бы более глобальный пример, какое-нибудь завершенное приложение, аля "Судоку солвер", но менее алгоритмически нацеленный. Кстати, что до "Судоку солвера", по мне так достаточно хороший пример демонстрации подходов в тех или иных языках.


LCR>Это всего-лишь рекурсивный поиск с откатом Мне с моим чахлым воображением трудно представить, что в разных языках решения могут быть существенно разными. Единственный момент — это реализация с хвостовой рекурсией и без.


Ну тем не менее те же паттерн-матчинг и first class-функции себя проявить вполне могут. Плюс можно и GUI сюда прикрутить, опять же разнообразие подходов скудный GUI не покажет, но хоть видно будет, что Haskell таки можно сделать GUI.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Превратим окружающую нас среду в воскресенье.
Re[6]: Требуются примеры использования first class function
От: ie Россия http://ziez.blogspot.com/
Дата: 22.11.06 09:50
Оценка:
Здравствуйте, Lazy Cjow Rhrr, Вы писали:

LCR>
ie>>genArr =. ((0{q)+i.@>:@-@-/@q=.2&{.) .NB Генерируем массив по заданным границам [genArr 2 6 -> 2 3 4 5 6]
LCR>

LCR>Ещё можно воспользоваться вилками, что даёт несколько более компактный результат:
LCR>
LCR>   genArr =. {. + i. @: ([: >: }.-{.)
LCR>   genArr 2 6
LCR>2 3 4 5 6
LCR>




Только не соображу в чем бонус cap'а ( [: ). Если я все верно понял ([: v1 v2) == (v1 @: v2), а для чего он еще нужен пока не знаю. Хотя пока толком и не разбирался с ним.

LCR>Кстати, а что это ты заинтересовалсо? Насколько я могу судить, здесь (т.е. на рсдн) J не в почёте...


Для общего развития Да и вообще классная головоломка, судоку отдыхает
... << RSDN@Home 1.2.0 alpha rev. 0>>
Превратим окружающую нас среду в воскресенье.
Re[6]: Требуются примеры использования first class function
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 22.11.06 10:54
Оценка: 30 (1)
PA>Вот еще забавная ссылка с участием того же Метлова:

Глеб, ты малость ошибся со второй ссылой
At Play with J: Metlov’s Triumph.

А вот ещё ссылка на JWiki, материала — колбасить-непереколбасить.

И наконец, интересный сайт, где в частности J тоже затрагивается.
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re: Требуются примеры использования first class function и p
От: FR  
Дата: 22.11.06 10:55
Оценка: 20 (2)
Здравствуйте, VladD2, Вы писали:

VD>Приветсвуются любые примеры.


Совсем примитивный пример можно?
Как рекурсия и неизменяемые переменные делают код более понятным (про производительность помолчим ), в стандартной библиотеке D есть функция split, которая делит строку по стандартным разделителям:

char[][] split(char[] s)
{
    size_t i;
    size_t istart = 0;
    bool inword = false;
    char[][] words;

    for (i = 0; i < s.length; i++)
    {
    switch (s[i])
    {
        case ' ':
        case '\t':
        case '\f':
        case '\r':
        case '\n':
        case '\v':
        if (inword)
        {
            words ~= s[istart .. i];
            inword = false;
        }
        break;

        default:
        if (!inword)
        {   istart = i;
            inword = true;
        }
        break;
    }
    }
    if (inword)
    words ~= s[istart .. i];
    return words;
}


Вот ее переделка в "функциональном" стиле:

alias char[] string;

string[] split(string s)
{
    bool is_delimiter(char c, string m)
    {
    if(m == "") return false;
    if(c == m[0]) return true;
    return is_delimiter(c, m[1 .. m.length]);
    }

    string[] r_split(string s, string word)
    {
    if(s == "") return [word];
    
    if(is_delimiter(s[0], " \n\t\f\r\n\v")) 
        return [word] ~ r_split(s[1 .. s.length], "");
    
    return r_split(s[1 .. s.length], word ~ s[0]);
    }
 
return  r_split(s, "");
}
Re[7]: Требуются примеры использования first class function
От: Mamut Швеция http://dmitriid.com
Дата: 22.11.06 11:34
Оценка:
LCR>Глеб, ты малость ошибся со второй ссылой
LCR>At Play with J: Metlov’s Triumph.

Здесь мой мозг окончательно взорвался (такое происходит каждый раз, как я вижу J )
... << RSDN@Home 1.2.0 alpha rev. 655>>


dmitriid.comGitHubLinkedIn
Re[8]: Требуются примеры использования first class function
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 22.11.06 11:43
Оценка: :))
Mamut,

M>Здесь мой мозг окончательно взорвался (такое происходит каждый раз, как я вижу J )


Он там смухлевал! В то время как остальные участники долго и нудно подсчитывали количество треугольников переборными алгоритмами и соревновались, кто компактнее нарисует цикл, этот нехороший человек, редиска значит, взял и вывел формулу! А именно, если у нас m точек на одной стороне, n точек на другой стороне, то количество треугольников будет
\frac{1}{2}mn(m+n)

и когда m==n, формула просто вырождается в n^3. Вот эти формулки он и пощщитал с помощью J.

Я ж говорю — мухлёвщик
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re[8]: Требуются примеры использования first class function
От: ie Россия http://ziez.blogspot.com/
Дата: 22.11.06 11:48
Оценка: :))) :)
Здравствуйте, Mamut, Вы писали:

M>Здесь мой мозг окончательно взорвался (такое происходит каждый раз, как я вижу J )


Аналогично! И вообще, час J с утра и рабочий день пропал
... << RSDN@Home 1.2.0 alpha rev. 0>>
Превратим окружающую нас среду в воскресенье.
Re[7]: Требуются примеры использования first class function
От: Programmierer AG  
Дата: 22.11.06 12:43
Оценка:
Lazy Cjow Rhrr wrote:
> PA>Вот еще забавная ссылка с участием того же Метлова:
>
> Глеб, ты малость ошибся со второй ссылой
> At Play with J: Metlov’s Triumph.
Виноват, спасибо за поправку. Это все чертов clipboard в Linux .

> И наконец, интересный сайт, где в частности J тоже затрагивается.

Ну, куда ж без него родимого. Только вот тут, к моему сожалению, в
последнее время много философии и мало кода .
Posted via RSDN NNTP Server 2.0
Re[7]: JRuby, RubyCLR, IronPython - зачем?
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 22.11.06 12:50
Оценка: 11 (2)
Mirrorer,

ie>>>Все же хотелось бы более глобальный пример, какое-нибудь завершенное приложение, аля "Судоку солвер", но менее алгоритмически нацеленный. Кстати, что до "Судоку солвера", по мне так достаточно хороший пример демонстрации подходов в тех или иных языках.


LCR>>Это всего-лишь рекурсивный поиск с откатом Мне с моим чахлым воображением трудно представить, что в разных языках решения могут быть существенно разными. Единственный момент — это реализация с хвостовой рекурсией и без.


M>Всего лишь рекурсивный поиск с откатом, говоришь ? Трудно представить существенно разные решения говоришь ?

M>Красота!
Автор: Lazy Cjow Rhrr
Дата: 06.12.05


Ну, прищучил... Но! Эта "красота" — рекурсивный поиск с откатом. Рекурсия хвостовая, и подбор-откат делается в параметрах.

Я потом немного прошвырнулся по инету и увидел много решений разных.

Наткнулся на решение на VB. Чтобы не издеваться над читателями, я его приводить не буду, просто ссылу дам: http://www.di-mgt.com.au/src/sudoku.bas.html Рекурсивный поиск с откатом, но подбор-откат на стеке, ключевое место здесь
Public Function TryGuess() As Boolean
...
    ' Fill in with the next guess; work through all possibles
    For TrialIndex = 1 To nMaxGuesses
        nValue = TheNthPossible(GuessIndex, TrialIndex)
        If nValue <= 0 Then
            MsgBox "Run out of guesses!"
            Exit Function
        End If
        
        Call SetSquare(nValue, GuessIndex)
        
        If TrySolve() Then
            ' We are done
            Exit For
        Else
            Call UndoGuess(mnGuessLevel)
        End If
    Next
    
    ' If we're not there yet, we try another (recursive) guess at the next level
    If MissingValues() > 0 Then
        Call TryGuess
    End If
End Function


Ещё одно решение на Хаскеле. Я его спёр отсюдава:
import List

type T = (Int,Int) -> [Int]

main = do
  s <- getContents
  putStr $ unlines $ map disp $ solve [input s]

solve :: [T] -> [T]
solve s = foldr search s idx where
    search p l = [mark (p,n) s | s <- l, n <- s p]

mark :: ((Int,Int),Int) -> T -> T
mark (p@(i,j),n) s q@(x,y) =
  if p==q then [n] else
  if x==i || y==j || e x i && e y j then delete n $ s q else s q
  where e a b = div (a-1) 3==div (b-1) 3

disp :: T -> String
disp s  = unlines [unwords [show $ head $ s (i,j) | j <- [1..9]] | i <- [1..9]]

input :: String -> T
input s = foldr mark (const [1..9]) $
  [(p,n) | (p,n) <- zip idx $ map read $ lines s >>= words, n>0]

idx :: [(Int,Int)]
idx = [(i,j) | i <- [1..9], j <- [1..9]]

И опять же рекурсивный поиск с откатом: вон тама функция mark — это либо адванс, либо откат, в зависимости от того, как попадёт.

Тем не менее ты прав , не все решения упираются в рекурсивный поиск. Если подумать, можно ещё способы напридумывать. Можно сначала сделать поиск вариантов, которые гарантированно разрешимы сразу, или разрешимы в предположении чего-то, и длина предположений будет увеличиваться. Итеративный поиск такой... (На этом моё воображение выдохлось).
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re[2]: Требуются примеры использования first class function
От: Gajdalager Украина  
Дата: 22.11.06 12:57
Оценка: 5 (1)
Здравствуйте, FR, Вы писали:

FR>Здравствуйте, VladD2, Вы писали:


FR>Вот ее переделка в "функциональном" стиле:


FR>
FR>alias char[] string;

FR>string[] split(string s)
FR>{
FR>    bool is_delimiter(char c, string m)
FR>    {
FR>    if(m == "") return false;
FR>    if(c == m[0]) return true;
FR>    return is_delimiter(c, m[1 .. m.length]);
FR>    }

FR>    string[] r_split(string s, string word)
FR>    {
FR>    if(s == "") return [word];
    
FR>    if(is_delimiter(s[0], " \n\t\f\r\n\v")) 
FR>        return [word] ~ r_split(s[1 .. s.length], "");
    
FR>    return r_split(s[1 .. s.length], word ~ s[0]);
FR>    }
 
FR>return  r_split(s, "");
FR>}
FR>

Вот то же, но со списками, паттерн матчингом и каррингом

object main extends Application {
  def split(s: String) = {
    def isCharInList(delims: List[Char])(c: Char): Boolean = delims match {
      case Nil  => false
      case head :: tail => if(head == c) true else isCharInList(tail)(c)
    }
    def isDelimiter = &isCharInList("\n\t\r ".toList)
    def resList(l: List[Char], word: String): List[String] = l match {
      case Nil  => List(word)
      case x :: xs if isDelimiter(x) => word :: resList(xs, "")
      case x :: xs => resList(xs, word + x)
    }
    resList(testStr.toList, "").filter(x => x != "")
  }
  val testStr = " word1   word2\t\t\t\t\n\nword3"
  Console.println(split(testStr))
}
Re[3]: Требуются примеры использования first class function
От: Gajdalager Украина  
Дата: 22.11.06 13:00
Оценка:
Здравствуйте, Gajdalager, Вы писали:

Извиняюсь, посмотрел, и увидел еще одно очевидное удучшение читабельности:
resList(testStr.toList, "").filter("".!=)
Re[8]: JRuby, RubyCLR, IronPython - зачем?
От: Mirrorer  
Дата: 22.11.06 13:13
Оценка: +1 :)
Здравствуйте, Lazy Cjow Rhrr, Вы писали:

M>>Всего лишь рекурсивный поиск с откатом, говоришь ? Трудно представить существенно разные решения говоришь ?

M>>Красота!
Автор: Lazy Cjow Rhrr
Дата: 06.12.05


LCR>Ну, прищучил... Но! Эта "красота" — рекурсивный поиск с откатом. Рекурсия хвостовая, и подбор-откат делается в параметрах.

Ну это да, идея больше относилась к существенно разным решениям. То есть идея то одна, а реализация в "Красоте" — ухх!


LCR>Тем не менее ты прав , не все решения упираются в рекурсивный поиск. Если подумать, можно ещё способы напридумывать.

Угу. Вывести какую-нибудь формулу для получения готового решения допустим, и записать ее в 1 строчку на J
... << RSDN@Home 1.2.0 Deep Purple — Maybe I'm A Leo >>
Re[6]: Требуются примеры использования first class function
От: Кодт Россия  
Дата: 22.11.06 13:14
Оценка:
Здравствуйте, Трурль, Вы писали:

PA>>outside r = \p -> not (p `inRegion` r)
PA>>x /\ y = \p -> (p `inRegion` x) && (p `inRegion` y)
PA>>x \/ y = \p -> (p `inRegion` x) || (p `inRegion` y)

Т>вот этот кусок можно было бы записать и попроще
Т>outside  = not
Т>(/\) = (&&)
Т>(\/) = (||)


Нет.
inRegion {- x  p -} = ($) -- x $ p = p x
-- поэтому ниже мы его выплавим

outside {- x   p -} = f_gx    (not) {- x   p -}
(/\)    {- x y p -} = f_gx_hx (&&)  {- x y p -}
(\/)    {- x y p -} = f_gx_hx (||)  {- x y p -}

-- где комбинаторы
f_gx    f g x   = f (g x)       -- хорошо известный (.)
f_gx_hx f g h x = f (g x) (h x) -- лень выводить (в базисе Прелюдии будет выглядеть страшно)
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[7]: Требуются примеры использования first class function
От: Programmierer AG  
Дата: 22.11.06 13:36
Оценка:
Кодт wrote:
>
> inRegion {- x  p -} = ($) -- x $ p = p x
> -- поэтому ниже мы его выплавим
-- на самом деле inRegion = flip ($)
>
Posted via RSDN NNTP Server 2.0
Re[7]: Требуются примеры использования first class function
От: Трурль  
Дата: 22.11.06 14:49
Оценка: 99 (3)
Здравствуйте, Кодт, Вы писали:

К>Нет.



К>
К>inRegion {- x  p -} = ($) -- x $ p = p x
К>-- поэтому ниже мы его выплавим

К>outside {- x   p -} = f_gx    (not) {- x   p -}
К>(/\)    {- x y p -} = f_gx_hx (&&)  {- x y p -}
К>(\/)    {- x y p -} = f_gx_hx (||)  {- x y p -}

К>-- где комбинаторы
К>f_gx    f g x   = f (g x)       -- хорошо известный (.)
К>f_gx_hx f g h x = f (g x) (h x) -- лень выводить (в базисе Прелюдии будет выглядеть страшно)
К>

Вот примерно то же собирался написать.
В качестве f_gx_hx (aka lift2 aka fork ) можно применить liftM2. Только надо обьяснить Хаскелю, что (a->) — тоже монада.
instance Monad ((->) a) where
    return  a = \x-> a
    (>>=) f g  = \x-> g (f x) x

lift2 :: (a -> b -> c) -> (d -> a) -> (d -> b) -> d -> c 
lift2 = liftM2 

lift1 = (.)

outside = lift1 not
(/\) =  lift2 (&&)
(\/) =  lift2 (||)
Re[5]: Требуются примеры использования first class function
От: PhantomIvan  
Дата: 22.11.06 15:19
Оценка:
PI>>тут наверно, как в императивщине — смотришь в чужой код, иногда думаешь, о! интересный оборот...

VD>Вот и нужны такие места. Но так чтобы примеры не были надумаными, были понятны большиству и при этом демонстрировали реальные приемущества.


то есть насколько "не надуманные"? настолько, чтобы действительно реальные применения были?

а можно настолько реальные, что это просто скопированные кусочки из своих программ будут?

попробуем пример из интеграции: вот функция в составе тест-пакета, тестирует фичу "find references" (нахождение в коде всех ссылок на некоторую переменную, метод, функцию, т.д.)

public FindUsages(line: string, testCase : int, declaration : Location, starter : string) : bool
{
    в тестовом сорце встречаются строки вида 
        mutable acquired = false; // definition {2} acquired     (явное указание объявлений в комментах)
    и строки вида
        acquired = true;  // usage {2}


    выявляем, что ищем
    def name = starter.Substring(starter.IndexOf('}') + 1).Trim();
    def position = line.IndexOf(name);
    def location = Location(declaration.File, declaration.Line, position, declaration.Line, position + name.Length);
    WriteLine($"\nSearching for usages of '$name' (test case: $testCase, location: $location)... ");
    выявили эн вхождений, для которых будем тестировать find references пакета интеграции
    def shouldFindRing = MakeUsage(line, declaration, name, starter) ::
        ScanSources(checkPhrase, testCase).Map((line, _, location, _) => MakeUsage(line, location, name, checkPhrase));
    Write($"\n Should find $(shouldFindRing.Length) usages... ");
    
    для каждого вхождения имитируем клик на нём юзером, и выбор команды find references
    получается список из эн списков, каждый из которых должен быть равен другому
    (действие команды не зависит от того, на каком вхождении кликнул юзер)
    def foundMultiple =
        shouldFindRing.Map(goto =>
        {
            def location = goto.Location;
            def shift = if (name.Length > 1) 1 else 0;
            TheEngine.Project.GetUsages(location.File, location.Line, location.Column + shift).ToList()
        });
    Assert.IsFalse(foundMultiple.IsEmpty); что-то найти мы должны
    здесь собственно, применяем функциональный стиль для проверки равенства этих списков
    def found = foundMultiple.FoldLeft(foundMultiple.Head, (ring, ring') =>
    {
        mutable coincide = false;
        def warning = "Find Usages should produce the same results, disregarding on which usage a user places a cursor";
        try
        {
            coincide = FoldLeft2(ring, ring', true, (a, b, coincideToTheLeft) =>
                if (coincideToTheLeft) a.Location.CompareLines(b.Location) == 0 else false);
        }
        catch
        {
            | _ => coincide = false;
        }
        when (stopAfterFirstFailedTest)
            Assert.IsTrue(coincide, warning);
        ring
    });
    Write($"found $(found.Length) usages, checking for correspondance... ");
    
    а дальше нужно проверить, что найдено действительно то, что должно быть найденно, но это уже другая история...
    def success = FoundUsagesAreRight(testCase, shouldFindRing, found);
    def message = if (success) "ok" else "incorrect!.. saving changes...";
    WriteLine(message);
    success
}


вроде бы неплохой пример применения свёрток (по 1 списку и под 2 спискам) и лямбд
естественно, можно и циклами то же самое, но уже не нужно
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[6]: Требуются примеры использования first class function
От: PhantomIvan  
Дата: 22.11.06 15:25
Оценка:
а, ещё там затесался Map:
PI>
PI>    def shouldFindRing = MakeUsage(line, declaration, name, starter) ::
PI>        ScanSources(checkPhrase, testCase).Map((line, _, location, _) => MakeUsage(line, location, name, checkPhrase));
PI>


плюс эти функции для тестирования, аналогичные FindUsages объявляются с одной и той же сигнатурой, и потом "раннер" тестов проходит по их списку, вызывая одну за другой — вот функции как 1-класс ситизен
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[8]: Требуются примеры использования first class function
От: Кодт Россия  
Дата: 22.11.06 15:36
Оценка:
Здравствуйте, Programmierer AG, Вы писали:

>> inRegion {- x  p -} = ($) -- x $ p = p x
>> -- поэтому ниже мы его выплавим
PA>-- на самом деле inRegion = flip ($)


Э, позвольте!
flip ($) x y = ($) y x = y $ x = x y
flip ($) = id

Другое дело, что я очепятался в комментарии Вот она, блеск и нищета кратких идентификаторов.
Так будет понятнее:
point `inRegion` region = region point = point $ region
inRegion = ($)
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[9]: Требуются примеры использования first class function
От: Programmierer AG  
Дата: 22.11.06 15:43
Оценка:
Кодт wrote:
>
> point `inRegion` region = region point = point $ region
> inRegion = ($)
>

То ли у меня вырубились мозги (что неудивительно после соседнего ответа
Трурля на тему instance Monad((->)a)...), то ли ты упорно ошибаешься при
этом переходе:
region point = point $ region

($) не переставляет аргументы местами, f $ x = f x, проверь:
Prelude>:t ($)
($) :: (a -> b) -> a -> b
Posted via RSDN NNTP Server 2.0
Re[9]: Требуются примеры использования first class function
От: Programmierer AG  
Дата: 22.11.06 15:51
Оценка:
Кодт wrote:
>
> flip ($) = id
>

flip ($) не равен id, он эквивалентен (|>) из стандартной библиотеки F#,
я его использую каждый день для таких вот конвейеров:
key_value_pairs |>
sort (fun (_, x) (_, y) -> compare y x) |>
first 10 |> map fst |> String.concat ";" |> print_endline

Unix-way!
Posted via RSDN NNTP Server 2.0
Re[10]: Требуются примеры использования first class function
От: Кодт Россия  
Дата: 22.11.06 16:57
Оценка:
Здравствуйте, Programmierer AG, Вы писали:

PA>flip ($) не равен id, он эквивалентен (|>) из стандартной библиотеки F#,


Каюсь, заглючило.
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[8]: JRuby, RubyCLR, IronPython - зачем?
От: Programmierer AG  
Дата: 22.11.06 17:23
Оценка:
Lazy Cjow Rhrr wrote:
> Ещё одно решение на Хаскеле. Я его спёр отсюдава:
> И опять же рекурсивный поиск с откатом: вон тама функция mark — это либо адванс, либо откат, в зависимости от того, как попадёт.
Отличная трава! Часа 3 курил . Реализация тормозная, но сколько
красивых фокусов! Замечательная иллюстрация ленивости — для меня как
новичка было совершенно неочевидно из кода, что все решения будут
выводиться на экран по мере нахождения.

С твоей интерпретацией функции mark я не согласен: это всегда один шаг в
пространстве решений, откатов тут нет. Тупиковые ветви дерева решений
отфильтруются потом:
    search p l = [mark (p,n) s | s <- l, n <- s p]
                                        -- ^^^^^^^^ здесь s p вернет
                                        -- пустой список, если позиция
                                        -- на доске бесперспективная


Кстати, еще один впечатляющий пример представления данных в виде функции
(это к вопросу: "Хм, интересная идея. А в чём преимущество по сравнению
с представлением области с помощью АТД?").
Posted via RSDN NNTP Server 2.0
Re[9]: Требуются примеры использования first class function
От: VladD2 Российская Империя www.nemerle.org
Дата: 22.11.06 17:41
Оценка: :)))
Здравствуйте, ie, Вы писали:

ie>Аналогично! И вообще, час J с утра и рабочий день пропал


Хорошо вам. А я для этой цели по старинке водку да коньяк использую. А они денег стоят.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[10]: Требуются примеры использования first class function
От: PhantomIvan  
Дата: 22.11.06 18:10
Оценка:
ie>>Аналогично! И вообще, час J с утра и рабочий день пропал

VD>Хорошо вам. А я для этой цели по старинке водку да коньяк использую. А они денег стоят.


ты тоже с утра?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: Требуются примеры использования first class function
От: FR  
Дата: 22.11.06 19:59
Оценка: 12 (1)
Здравствуйте, Gajdalager, Вы писали:

G>Вот то же, но со списками, паттерн матчингом и каррингом


Интересно только, код кажется стал менее понятным

Лучше примерно так:
def split(s, delim = lambda c : c in " \n\t\f\r\n\v", word = ""):
    if not s: return [word]
    
    if delim(s[0]): return [word] + split(s[1:], delim, "")
        
    return split(s[1:], delim, word + s[0])
Re[3]: Требуются примеры использования first class function
От: FR  
Дата: 22.11.06 20:01
Оценка:
Здравствуйте, Gajdalager, Вы писали:

G>Вот то же, но со списками, паттерн матчингом и каррингом


Еще тут Re: BOOST, .NET, String.Split и производительность…
Автор: VladD2
Дата: 21.09.06
тоже такое есть.
Re[2]: Требуются примеры использования first class function
От: VladD2 Российская Империя www.nemerle.org
Дата: 22.11.06 20:22
Оценка: 17 (2)
Здравствуйте, FR, Вы писали:

Попытался создать гибридный аналог этих функций обладающий высоким быстродействием но в то же время более менее компактный и более понятный. Вот что из этого вышло:
Split2(str : string) : array[string]
{
    mutable i = 0; 
    def next () { if (i < str.Length) { def ch = str[i]; i++; ch } else '\0' } 
    def word = Text.StringBuilder();
    def words = Generic.List();
    def addWord() { when (word.Length != 0) { words.Add(word.ToString()); word.Length = 0; } }
    def split(_)
    {
        | '\t' | '\n' | '\'' | ' ' => addWord();          split(next())
        | '\0'                     => addWord();
        | x                        => _ = word.Append(x); split(next())
    }
    
    split(next());
    words.ToArray();
}

Практически никаких лишних действий или выделений памяти, но и результат не очень компактен. Хотя, по-моему, намного более понятный чем оба тваои варианта.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: Требуются примеры использования first class function
От: FR  
Дата: 22.11.06 20:30
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Здравствуйте, FR, Вы писали:


VD>Попытался создать гибридный аналог этих функций обладающий высоким быстродействием но в то же время более менее компактный и более понятный. Вот что из этого вышло:


....

VD>Практически никаких лишних действий или выделений памяти, но и результат не очень компактен. Хотя, по-моему, намного более понятный чем оба тваои варианта.


Интересно, но код уже не функциональный
Выделенное неправда
Re[4]: Требуются примеры использования first class function
От: FR  
Дата: 22.11.06 21:19
Оценка:
Здравствуйте, FR, Вы писали:

FR>Лучше примерно так:

FR>
FR>def split(s, delim = lambda c : c in " \n\t\f\r\n\v", word = ""):
FR>    if not s: return [word]
    
FR>    if delim(s[0]): return [word] + split(s[1:], delim, "")
        
FR>    return split(s[1:], delim, word + s[0])
FR>


еще вариант с ФВП, и без рекурсии:
def split2(s, delim = lambda c : c in " \n\t\f\r\n\v"):
    def _(sum, c):
        if delim(c): return sum + [""]
        return sum[:-1] + [sum[-1] + c]
        
    return reduce(_, s, [""])
Re[4]: Требуются примеры использования first class function
От: VladD2 Российская Империя www.nemerle.org
Дата: 23.11.06 00:15
Оценка: +1
Здравствуйте, FR, Вы писали:

VD>>Практически никаких лишних действий или выделений памяти, но и результат не очень компактен. Хотя, по-моему, намного более понятный чем оба тваои варианта.


FR>Выделенное неправда


Это не правда или не правда. Это мое мнение. Ты конечно можешь с ним быт не согласен, но это уже твое мнение.

Этот код мне кажется проще, так как в нем есть четка декомпозиция. Я легко читаю алгоримт. Вот мы выделяем слово, а вот добавляем его в список... В то же время чисто императивный вариант так велик, что за одтельными микро-действиями не видно сути алгоритма. А рекурсивный столь сжат, что его уже приходится расшивровывать. "Лишние" функции в этом примере я воспринимаю как документирование.

FR>Интересно, но код уже не функциональный


Я и говорю "гибридный". Но я в догматики ФП не записывался. Я выбираю решения на основе анализа разных факторов. "Просто" более короткий код не всегда лучше. А вот более короткий и эффективный другое дело.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: Требуются примеры использования first class function и p
От: Зверёк Харьковский  
Дата: 23.11.06 02:52
Оценка: 1 (1)
Здравствуйте, VladD2, Вы писали:

VD>Когода кто-то пишет статьи о фунциональном программировании, то почему-то в качестве примеров всегда используются вещи вроде фунций Фибоначи и тому подобной бесполезной фигни.


VD>Это приводит к тому, что у людей закрадывается сомнение, что данные возможности полезны в области математики, парсинга или еще какой-то специализированной области оторванной от жизни.


VD>Предлагаю совместными усилиями подобрать набор примеров которые с одной стороны не требовали бы вникания в некоторую сложную задачу с другой демонстрировали приемущества функциональных языков (first class-функций, алгеброических типов, сопоставления с образцом).


VD>Приветсвуются любые примеры.


Ну, неплохой пример, в общем-то, на поверхности лежит:

widget.on_mouse_down {|button, x, y| ...} #функция-обработчик всех сообщений mouse_down
widget.on_mouse_down(LEFT_BUTTON) {|x, y| ...} #сюда паттерн-матчатся только left_mouse_down

#и т.п.
widget.on_key_press{|key, shifts| ...}
widget.on_key_press(Key::A){|shifts| ...}
widget.on_key_press(Key::A, Key::SHIFT){ ...}
widget.on_key_press(nil, Key::SHIFT){|key| ...}


Демонстрирует: передачу функции как параметра, ее хранение в переменной, паттерн-матчинг.
Ы?

По-моему, достаточно "близкий к телу" пример.
FAQ — це мiй ай-кью!
Re[10]: Требуются примеры использования first class function
От: Andrei N.Sobchuck Украина www.smalltalk.ru
Дата: 23.11.06 08:17
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Хорошо вам. А я для этой цели по старинке водку да коньяк использую. А они денег стоят.


Коньяк с водкой и с утра? Плохо Неиерле на тебя повлиял
http://www.smalltalk.ru | << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Я ненавижу Hibernate
Автор: Andrei N.Sobchuck
Дата: 08.01.08
!
Re[8]: Требуются примеры использования first class function
От: Андрей Хропов Россия  
Дата: 23.11.06 09:49
Оценка:
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[9]: JRuby, RubyCLR, IronPython - зачем?
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 23.11.06 12:21
Оценка:
Programmierer AG,

PA>С твоей интерпретацией функции mark я не согласен: это всегда один шаг в

PA>пространстве решений, откатов тут нет. Тупиковые ветви дерева решений
PA>отфильтруются потом: ...

Прежде чем ответить, я тоже должен разобрать по кусочкам этот шедевр.

PA>Кстати, еще один впечатляющий пример представления данных в виде функции

PA>(это к вопросу: "Хм, интересная идея. А в чём преимущество по сравнению
PA>с представлением области с помощью АТД?").

Угу, буду смотреть.
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re[11]: Требуются примеры использования first class function
От: VladD2 Российская Империя www.nemerle.org
Дата: 23.11.06 14:02
Оценка: :)
Здравствуйте, Andrei N.Sobchuck, Вы писали:

ANS>Коньяк с водкой и с утра? Плохо Неиерле на тебя повлиял


Это старая русская привычка. Способ создать себе выходной.
Звучит она так. С утра выпил — весь день свободен.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: Требуются примеры использования first class function
От: VladD2 Российская Империя www.nemerle.org
Дата: 23.11.06 14:02
Оценка:
Здравствуйте, Зверёк Харьковский, Вы писали:


ЗХ>Демонстрирует: передачу функции как параметра, ее хранение в переменной, паттерн-матчинг.


Видимо я не совсем догоняю смысл этого кода. Поясни по подробнее.
Это, кстати, был Руби?
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: Требуются примеры использования first class function
От: Зверёк Харьковский  
Дата: 24.11.06 00:14
Оценка: 35 (2)
Здравствуйте, VladD2, Вы писали:

ЗХ>>Демонстрирует: передачу функции как параметра, ее хранение в переменной, паттерн-матчинг.


VD>Это, кстати, был Руби?


Ya.

VD>Видимо я не совсем догоняю смысл этого кода. Поясни по подробнее.


В Руби блоки (лямбды) определяются вот так:

#это мы определили переменную-лямбду
l = lambda{|param1, param2, param3| code}

#а это мы определяем блок переданный в функцию myfoo
myfoo(param1, param2){|block_param1, block_param2| code}

#другой вариант того же синтаксиса:
myfoo(param1, param2) do |block_param1, block_param2| code end
#или даже так:
myfoo param1, param2 do |block_param1, block_param2| code end

#пример использования на реальной библиотечной функции:
arr = [1,2,3,4]
print arr.sort{|left, right| right <=> left} #задаем лямбду сравнивающую значения
#этот код выведет [4, 3, 2, 1]

#функция, одним из параметров которой является лямбда, может выглядеть так:

def sort  #неявный параметр-блок не указывается...
   ...
   result = yield(left, right) #...и вызывается yield'ом
   ...
end

#а может выглядеть так:
#параметр-блок указывается явно, на то, что он должен быть блоком, указывает &
def sort(&block)  
   ...
   some_variable = block  #блок теперь обычная переменная, его можно хранить, передавать, возвращать...
   block.call(a,b,c) #ну и вызывать, конечно.
   ...
end


Пока понятно? Теперь, на основе этого, расшифровываем мои записи:
#есть объект widget
#его функция on_key_press вызывается с параметром-блоком; у блока есть параметры key, shifts
widget.on_key_press{|key, shifts| ...}

#сама функция on_key_press может выглядеть так:
class Widget
  def on_key_press(*arg, &handler)
    #* перед arg - оператор свертки, функция может принять любое количество аргументов 
    #и все они окажутся в массиве arg
    #в данной функции arg представляют собой паттерн, которому должно соответствовать событие
    #чтобы оно было отдиспатчено в handler
    
    #сохраняем обработчик в хеш:
    @handlers_hash[arg] = handler
  end

  #а вот что происходит где-то внутри window_proc:
  def window_proc(message_params)
    @handlers_hash.each do |key, value|
       message_params.match(key){|*match_res| value.call(*match_res)  }
    end
  end
end


Вот эта строчка:
message_params.match(key){|*match_res| value.call(*match_res) }
выполняет паттерн-матчинг на паттерне-фильтре события; если матчинг успешен, выполяняет блок, с передачей ему результатов матчинга.

#например, если мы установили такой обработчик:
widget.on_key_press(Key::A){|shifts| ...}

#то где-то в window_proc он будет вызыван, только в случае если нажата клавиша A 
#и любое сочетание Alt, Ctrl, Shift; при этом сочетание "шифтов" будет передано в блок.


Примерно понятно?
FAQ — це мiй ай-кью!
Re: Требуются примеры использования first class function и p
От: Mamut Швеция http://dmitriid.com
Дата: 25.11.06 12:44
Оценка: +1
VD>Приветсвуются любые примеры.

Хм. Может перевод на Erlang
Автор: Lazy Cjow Rhrr
Дата: 16.03.06
версии на Хаскеле
Автор: Трурль
Дата: 09.03.06
из Этюдов
Автор: Mamut
Дата: 04.03.06
?
... << RSDN@Home 1.2.0 alpha rev. 668>>


dmitriid.comGitHubLinkedIn
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.