LINUX.ORG.RU

f(f(f(x))) - как записать короче

 


0

1

раньше кажись как-то выражал, теперь не могу вспомнить
количество вложеных вызовов может быть произвольным
конкретно тут речь об ecmascript но меня больше теория интересует, так как в гугле не смог ничего внятного отыскать так же (скорей всего не туда смотрел)

бла, и понимал же что через reduce, старость не радость

> compose = (...fns) => (x) => fns.reduceRight((v, f) => f(v), x)
[Function: compose]
> f = val => val * 2
[Function: f]
> compose(f, f, f)(2)
16
> f(f(f(2)))
16
> 

trashymichael ★★★
() автор топика
function call(...args) {
   let values = args.pop();
   let ret = args.pop()(...values);
   args.reverse().forEach(f=>{
       ret = f(ret); 
   });
   return ret;   
}

//test:
var f = function(v) {return v += "f "};
var f1 = function(v) {return v += "f1 "};
var f2 = function(v) {return v += "f2 "};
var f3 = function(v) {return v += "f3 "};
var x = "Test ";

call(f, f1, f2, f3, [x]) === f(f1(f2(f3(x))))
//true ("test f3 f2 f1 f ")
crutch_master ★★★★★
()
Последнее исправление: crutch_master (всего исправлений: 1)
Ответ на: комментарий от crutch_master

Читается одинаково плохо, но это хотя бы более православный вариант.

Правда как всегда посередине:

function compose(...args) {
   let value = args.pop();
   return args.reduceRight((v, f) => f(v), value);
}

Так и мозг не ломает и по-прежнему элегантно.

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

Такой задачи нет и в твоём варианте всё равно аргументы передаются только в первый вызов, а в остальные его результаты.

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

Такой задачи нет

Сегодня нет, завтра есть.

твоём варианте всё равно аргументы передаются только в первый вызов

Так их все и надо передать в первый вызов.

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

А так не фи?

Так не фи.

где конкретика

Императивщина для compose это не Ъ.

no-such-file ★★★★★
()
Ответ на: комментарий от dave

Haskell, Idris, Agda, PureScript? Который из них?

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

Для этого есть максимально каноничная форма compose из книги «Professor Frisby's Mostly Adequate Guide to Functional Programming»

const compose = (...fns) => (...args) => fns.reduceRight((res, fn) => [fn.call(null, ...res)], args)[0];

А так не фи?

Нет, не фи — это реализация из уже имеющейся из коробки в десятках языков встроенной процедуры, ноги у которой растут из математики. Ты же объявил функцию, название которой идентично существующему методу у Function, которую, встретив в коде, можно принять за реализацию этого метода в виде функции высшего порядка (как, например, тут. Очень неприятно будет обнаружить то, что поведение у неё другое.

И где конкретика?

Конкретика преспокойнейше расположилась в названии функции и её реализации.

Princesska ★★★★
()
Ответ на: комментарий от no-such-file

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

Princesska ★★★★
()

Одноместная функция, определена на том же множестве, в котором у нее и значения? И какая-такая композиция, зачем все переусложнять? Про циклы тут все правильно подсказали.

anonymous
()

std::stack<>

anonymous
()

Вариант 1: написать f2, которая делает f(f(f(x))) - будет шляпа в одном месте Вариант 2 (если набор f динамический): цикл по обратно упорядоченному массиву f()

AlexAT
()

РЕШЕНИЕ

Типичная задача, к примеру, хеш от хеша N раз, конечно в мире после циклов:

const lodash = require("lodash")
    , compose = require("compose-function")
    , sha256 = require("sha256")
    , xsha256 = (times, value) => compose(...lodash.times(times, lodash.constant(sha256)))(String(value))


с зависимости уж сами разберетесь

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

А смысл? Абсолютно любая рекурсия всегда может быть реализована на циклах. Это как бы теорема с формальным доказательством.

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

сам не пойму чего этого нет в lodash и подобном, но есть разные .times f x -> [f(x), f(x), f(x)]

trashymichael ★★★
() автор топика

Правильно такие вещи делать оквадрачиванием функции. Типа как возведение матрицы в степень:

Prelude> let pow f 0 = id; pow f n = if n `mod` 2 == 0 then pow (f . f) (n `div` 2) else pow (f . f) (n `div` 2) . f
Prelude> :t pow
pow :: Integral a => (c -> c) -> a -> c -> c
Prelude> pow (\x -> x * 2 - 1) 3 4
25

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

anonymous
()
Ответ на: комментарий от trashymichael
const sha256 = require("sha256");
xsha256 = (times, value) => {
    while (times--) value = sha256(value);
    return value;
}

Так лучше? Извращенец.

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