2017-01-28 2 views
2

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

, например:

aFunction value1 value2 

эквивалентно:

value2 
    |> aFunction value1 

, но что, если я хочу передать value1 в aFunction через трубу вместо value2?

на данный момент я использую что-то вроде этого:

value1 
    |> (\x y -> aFunction y x) value2 

Однако, это поражает меня как немного клуджем, чтобы быть честным. Есть ли более элегантный способ сделать это?

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

+0

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

ответ

5

Используйте функцию flip (это просто функция, которую вы определяете в линию с лямбда-выражения):

value1 |> (flip aFunction) value2 
+0

Спасибо, чепнер! Я еще не обнаружил функцию флип. Мне все еще интересно, есть ли хороший способ сделать это для функций с более чем двумя параметрами? –

+2

@MTaylor, определяющий 'aFunctionWithMoreConvenientArguments x y z = aFunction z x y', вероятно, является вашим лучшим вариантом. –

+0

@MTaylor Возможно, вы можете начать играть с ужасающими композициями, включающими «флип». 'флип.flip', интересно, но бесполезно, представляется 2-аргументной версией 'id'. '(flip.). flip :: (a -> b -> c -> d) -> b -> c -> a -> d', но вращает аргумент функции с тремя аргументами. Тем не менее, у меня нет никаких советов о том, как создать желаемую перестановку аргументов. – chepner

0

В соответствии с ответом @ chepner, в flip, кажется, лучший способ сделать это для функции с двумя аргументами.

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

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

module RotArgs exposing (..) 

rot3ArgsL1 func = \y z x -> func x y z 

rot3ArgsL2 func = \z x y -> func x y z 

rot4ArgsL1 func = \x y z w -> func w x y z 

rot4ArgsL2 func = \y z w x -> func w x y z 

rot4ArgsL3 func = \z w x y -> func w x y z 

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

Это позволило бы такие вещи, как:

import RotArgs exposing (..) 

someFunction one two three = 
    ...whatever 

... 

one 
    |> (rot3ArgsL1 someFunction) two three 

Очевидно RotArgs может быть легко extemded к функциям более 4-х аргументов, хотя это, кажется, скорее всего, будет более менее полезным добавляются более аргументов.

Смежные вопросы