LINUX.ORG.RU

Как стать гуру ФП

 , ,


0

1

Берёшь модно выглядящий ЯП, например coffeescript, пишешь:

size = (xs) -> xs.length
concat = (xs) -> (ys) -> xs.concat(ys)

map = (f) -> (xs) ->
    [y, ys...] = xs
    if (size xs)
        (concat [f y]) ((map f) ys)
    else
        []

Пробуешь:

coffee> (map (x) -> x * 2) [1..5]
[ 2, 4, 6, 8, 10 ]

Потом пишешь filter:

filter = (f) -> (xs) ->
    [y, ys...] = xs
    if not (size xs)
        []
    else if (f y)
        (concat [y]) ((filter f) ys)
    else
        (filter f) ys

Пробуешь:

coffee> filter((x) -> x > 5) [1..10]
[ 6, 7, 8, 9, 10 ]

Теперь ты знаешь ФП лучше среднего хаскелиста и лиспера лора!

А ещё благодаря такому подходу легко можно реализовать модные сейчас трансдьюсеры:

transduce = (fns) -> (xs) ->
    [f, fs...] = fns
    if (size fns) 
        (transduce fs)(f xs)
    else
        xs

Использование:

coffee> transduce([(map (x) -> x * 2), (filter (x) -> x < 10), (map (x) -> x ** 2)]) [1..10]
[ 4, 16, 36, 64 ]

Свёртки:

reduce = (f) -> (xs) -> (m) ->
    [y, ys...] = xs
    if (size xs)
        ((reduce f) ys)((f y) m)
    else
        m

coffee> reduce((x) -> (y) -> x + y)([1..10])(0)
55

reverse = (xs) ->
    aux = (m) -> (ys) ->
        [z, zs...] = ys    
        if (size ys)
            (aux (concat([z]) m)) zs
        else
            m

    (aux []) xs

coffee> reverse [1..5]
[ 5, 4, 3, 2, 1 ]

reducer = (r) -> (m) -> ((f) -> (xs) -> r(f)(xs)(m))
reduceLeft = (f) -> (xs) -> (m) -> transduce([reverse, reducer(reduce)(m)(f)])(xs)
coffee> reduceLeft((x) -> (m) -> x + m)([1..10])(0)
55

reducer нужен для того чтобы reduce(Left) имел интерфейс трансдьюсера (как у map и filter вызванные с функцией, и собственно transduce).

update: Самое главное не забывать называть переменные f, xs, x и тд.

update 2: И да, легко получить RangeError: Maximum call stack size exceededю

update 3: Превратил однострочники в многострочникию



Последнее исправление: holuiitipun (всего исправлений: 8)
Ответ на: комментарий от holuiitipun

Но ты именно так и предлагаешь делать.

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

vimquest
()
Ответ на: комментарий от holuiitipun

Функции высшего порядка

Это и в сях есть

каррирование

Например?

вот это всё.

Где все то? Пока тут лишь передача и вызов функций, фп то где?

loz ★★★★★
()
Ответ на: комментарий от vimquest

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

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

loz ★★★★★
()
Последнее исправление: loz (всего исправлений: 1)
Ответ на: комментарий от vimquest

Синтаксис препроцессором можно изменить

Да, нужно придумать еще один язык, написать ему свой рантайм, написать на нем еще один анализатор синтаксиса целевого языка и генератор кода на нем. Зачем один язык, когда можно иметь два? и не поспоришь.

loz ★★★★★
()
Последнее исправление: loz (всего исправлений: 1)
Ответ на: комментарий от Reset

Пайпы есть во всех языках, т.к. это просто композиция. Трансдьюсеры - штука более мощная и выразительная.

anonymous
()
Ответ на: комментарий от anonymous

Пайпы есть во всех языках, т.к. это просто композиция. Трансдьюсеры - штука более мощная и выразительная.

...но по сути тоже самое

Debasher ★★★★★
()
Ответ на: комментарий от loz

Отличительные признаки ФП: функции как объекты первого класса и две операции: применение функции и композиция функций.

buddhist ★★★★★
()

Да это же гурам на смех.

buddhist ★★★★★
()
Ответ на: комментарий от buddhist

А я например за то, что главный признак фп это чистота, а хранение, применение и передача функций как объектов первого класса это мелочи.

loz ★★★★★
()
Ответ на: комментарий от loz

Надеюсь не то, которое позволит называть си, плюсы, питон и прочее функциональными языками.

В С уже появились замыкания? Функция может возвращать функцию?

Насчёт плюсов ничего не знаю, но python мультипарадигменный ЯП - на нём можно ФП.

holuiitipun
() автор топика
Ответ на: комментарий от loz

А я например за то, что главный признак фп это чистота, а хранение, применение и передача функций как объектов первого класса это мелочи.

Не просто же так делят functional programming и purely functional.

holuiitipun
() автор топика
Ответ на: комментарий от buddhist

Отличительные признаки ФП: функции как объекты первого класса и две операции: применение функции и композиция функций.

Бредятина.

Отличительные признаки ФП: Иммутабельность. Ссылочная прозрачность. Возможно, call-by-need

Все остальное может присутствовать в over1000000 !ФП ЯП

dkstra
()
Ответ на: комментарий от Debasher

а при чем тут замена? Допустим

object.fun(arg) --> 1
fun(object, arg) --> 1

change(object)

object.fun(arg) --> 2
fun(object, arg) --> 2
Это что функционально что ли?

anonymous
()
Ответ на: комментарий от anonymous
object.fun(arg) --> 1
object.fun(arg) --> 2
object.fun(arg) --> 3
object.fun(arg) --> 4

Такое возможно, ведь мы не знаем что там внутри object.

Такое конечно возможно и в случае fun(object, arg), но тогда в текущем контексте «видно» что меняется что-то.

Debasher ★★★★★
()
Ответ на: комментарий от Debasher

но тогда в текущем контексте «видно» что меняется что-то.

Что это значит? Ты в одном месте вызвал функцию, она тебе вернула 1, в другом месте вызвал, с теми же параметрами, она вернула 2. Что тебе видно? В каком месте программы изменен object? Так это и без ФП видно, только искать запаришься. И, опять же непонятно, как это сочетается с

that treats computation as the evaluation of mathematical functions and avoids changing-state and mutable data

Явно ты что-то путаешь.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.