4 ms·
An Elixir convention I've seen is to put the thing you're operating on first, so that you can compose functions using the `|>` operator, which places the previo
by grantjpowell 6y ago
An Elixir convention I've seen is to put the thing you're operating on first, so that you can compose functions using the `|>` operator, which places the previous expression as the first argument of the function to the right.
Maybe something like this?
defmodule Compare do
def clamp(number, minimum, maximum) do
number
|> max(minimum)
|> min(maximum)
end
end
import Compare
clamp(5, 1, 10) # 5
clamp(1, 5, 10) # 5
clamp(10, 1, 5) # 5
some_number
|> clamp(min, max)
As a side note, I think the Elixir |> operator is a stroke of genius that other languages should take a look at. Making the pipe operator append the _first_ argument has the following benefits
1.) It makes the most "important" argument of the function the first thing you read in function signatures
2.) If you need to add more arguments to a function signature later, they tend to be less important the original args, so they tend to make sense at the end
3.) It creates a convention for all libraries to follow so they can leverage the pipe operator. Its really jarring when the thing you want to put in a pipeline isn't the first argument (looking at you `Regex`[0] which puts the regular expression as the first arg and not the string)
[0] https://hexdocs.pm/elixir/Regex.html#replace/4 https://hexdocs.pm/elixir/Regex.html#replace/4
- spapas82 6y agoYes you are right! Puting the number in the first parameter is even more idiomatic Elixir.
- LandR 6y ago> It makes the most "important" argument of the function the first thing you read in function signatures Doesn't that make writing functions that can use partial application harder? e.g. If I was writing clamp i would want the signature to be (defn clamp [min max n] ,,,) Then I can do: (map (partial clamp 1 11) [-14 2 5 8 11 15 18]) I know when I use Clojures threading macros I use thread last way more than any of the others. My next most common would be piping it into arbitrary locations, e.g.: ; pipe into an arbitrary spot (specified here as o) (as-> (range 1 10) o (map inc o) (filter even? o) (reduce + o)) I rarely use thread-first.
- grantjpowell 6y agoElixir has an anonymous function short hand that makes the "partial application" use case pretty easy for me. &Compare.clamp(&1, some_min, some_max) The above creates an arity one function which puts the arg into the first position in the original function. I've never felt pain around partial application because I use the anonymous function short hand a good deal