F #, Первый аргумент переадресации

Совсем похоже на этот вопрос: Первый параметр трубы F #

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

Например, если я хочу переслать последний аргумент, он выглядит очень красивым и чистым:

[4;5;6]
    |> List.append [1;2;3]

// Result: [1;2;3;4;5;6]

Если я хочу перенаправить первый аргумент, я могу использовать функцию "fun x → ", но мне просто интересно, есть ли более чистый способ.

[1;2;3]
    |> fun x -> List.append x [4;5;6]

// Result: [1;2;3;4;5;6] 

Большое спасибо.


P.S. Мой коллега просто помог мне с этой проблемой. Но я был бы признателен за любую помощь, если у вас есть предложения для начинающего F #. Спасибо.

Ответ 1

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

let flip f x y = f y x

[1; 2; 3]
    |> (flip List.append) [4; 5; 6]

Преобразование функций полезно во многих контекстах. Это функциональный программист с хлебом и маслом.

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

let prependTo a b = List.append b a

[1; 2; 3] 
   |> prependTo [4; 5; 6]

Ответ 2

Все существующие ответы обеспечивают хорошее решение проблемы.

Однако, я думаю, что если вы хотите использовать pipe для указания первого аргумента функции, большую часть времени это не очень хорошая идея, и вы должны просто использовать обычный вызов без труб:

List.append [1;2;3] [4;5;6]

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

Если вы переходите к аргументу, который не является последним, это означает, что вы нарушаете эту закономерность, так что вы больше не переносите одну структуру данных через серию преобразований. Это сделает ваш код запутанным, потому что "он выглядит как труба, но на самом деле это не труба".

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

Ответ 3

Просто используйте лямбда:

[1;2;3] |> fun l -> l @ [4;5;6]

или point-free:

[1;2;3] |> (@) <| [4;5;6] // or
([1;2;3], [4;5;6]) ||> (@)

или как нормальная функция:

let foo l = l @ [4;5;6]
let bar = foo [1;2;3]

Ответ 4

После того, как я спросил своего коллегу, он предложил:

[1;2;3]
    |> List.append
    <| [4;5;6]
// Result: [1;2;3;4;5;6]

Если у вас есть другие предложения для начинающего F #, такого как я, я был бы очень признателен за вашу помощь. Спасибо.