Цепочка функций в Юлии - PullRequest
1 голос
/ 14 мая 2019

Можно ли написать несколько вызовов функций в виде цепочки?

sum(
  map(parseIgFloat, 
    map((row) -> row.PL_Amount, 
      filter((row) -> !ismissing(row.Summary) && row.Summary == "Cash In", 
        collect(ts)
      )
    )
  )
)

Преврати это в нечто вроде:

ts 
  |> collect
  |> filter((row) -> !ismissing(row.Summary) && row.Summary == "Cash In")
  |> map((row) -> row.PL_Amount)
  |> map(parseIgFloat)
  |> sum

Ответы [ 3 ]

3 голосов
/ 15 мая 2019

После поиска это, кажется, лучший вариант из доступных

ts |> 
  collect |> 
  (list -> filter((row) -> !ismissing(row.Summary) && row.Summary == "Cash In", list)) |>
  (list -> map((row) -> row.PL_Amount, list)) |>
  (list -> map(parseIgFloat, list)) |>
  sum

или с пакетом Pipe с макросами

@pipe ts |> 
  collect |> 
  filter((row) -> !ismissing(row.Summary) && row.Summary == "Cash In", _) |>
  map((row) -> row.PL_Amount, _) |>
  map(parseIgFloat, _) |>
  sum
2 голосов
/ 15 мая 2019

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

Однако, что касается map и filter , в частности , создать тривиальные версии этих функций и тривиальноприменить цепочку к ним.Например,

# Create curried versions of map and filter for use in 'chaining'
import Base.map;    function    map(f); return L ->    map(f,L); end;
import Base.filter; function filter(f); return L -> filter(f,L); end;


f  = x -> x ^ 2;
ts = range(1, stop=10);

( ts
  |>  collect          
  |>  map(f)             # square the collection
  |>  filter(iseven)     # keep only even results
  |>  sum              
)

Выходные данные:

220


PS: формирование цепочек в основном связано с удобством чтения и наиболее полезно, если у вас есть последовательность по отдельности простые и визуально простые команды , как указано выше.Если вы будете иметь сложные выражения в вашей «цепочке», такие как в предложенном вами решении, то, на мой взгляд, оно того не стоит.Либо оберните ваши сложные выражения в функции с соответствующими именами, которые делают цепочку читаемой как обычный английский, либо избегайте цепочек, во-первых, и полагайтесь на четкие шаги, используя вместо этого временные переменные.

PS2:Также обратите внимание, что оператор |> является допустимой целью для вещания, как и любая функция.Поэтому |> map(f) выше также можно было бы написать более просто как .|> f.

1 голос
/ 15 мая 2019

Я, вероятно, написал бы это так:

sum(row -> parseIgFloat(row.PL_Amount),
    filter((row) -> !ismissing(row.Summary) && row.Summary == "Cash In", 
            ts)
    )

Если и когда произойдет подчеркивание карри (https://github.com/JuliaLang/julia/pull/24990), вы можете упростить это так:

sum(parseIgFloat(_.PL_Amount)), 
    filter(!ismissing(_.Summary) && _.Summary == "Cash In",  # actually not sure if this line would work
           ts)
    )

В этот момент цепочка может также стать более удобной.

Кстати: не используйте collect, если вам как-то действительно не нужно.

...