marick

marick

I confess I don’t use Function.identity because &(&1) comes to mind faster. However, there’s another function that seems commonly used in functional languages, which is a function that makes a function that always returns the same value:

  def constantly(value) do
    fn _ -> value end
  end

Given there’s no shorter version than fn _ -> value end (is there?) would it be worth adding Function.constantly?

First 7 of 7 Posts Switch mode

marciol

marciol

I think that the best place to suggest this kind of thing is on Elixir Lang Core Mailing List

@ericmj @fishcakez @fertapric @lexmag @whatyouhide and @josevalim can confirm.

benwilson512

benwilson512

Author of Craft GraphQL APIs in Elixir with Absinthe

I think this proposal is tricky because, unlike identity/1, there isn’t an obvious arity that your return function should have. Should it be:

fn -> value end
or
fn _ -> value end
or
fn _, _ -> value end
... etc

Each of those has real scenarios where they’d be useful.

The other issue is that these two things do not have the same semantics: Function.constantly(code) and fn -> code end will behave differently depending on what code is. If code is DateTime.utc_now() then Function.constantly will return the same date time over and over, but fn -> DateTime.utc_now() end will return a new datetime each time it is invoked.

dorgan

dorgan

If we take maths as our source of truth(since most constructs of this kind come from there), then I’d argue the arity should be 1, based on notions from lambda calculus.

If we consider the expression λx.λy.x, giving it an x will result in an abstraction that, no matter what y we feed it, it will always return x. The resulting abstraction would be λx.y which is the constant function x↦y. The abstraction that produces such constant functions is the constant combinator K = λx.λy.x.

The identity combinator I is already incarnated in Function.identity, if the K combinator is implemented, we would only need to add the S combinator λfgx.fx(gx):

def substitution(f) do
  fn g ->
    fn x ->
      (f.(x)).(g.(x))
    end
  end
end

And this would complete the three combinators needed for SKI combinator calculus.

The other argument for K’s returned function to have an arity of 1, is that a lot of this work involves giving one argument at a time to partially apply those functions, and it just makes no sense to have more arguments. Having zero arguments also goes against the definition of x↦y.

Another observation is that such constant function is the return value, what’s being proposed is the combinator that produces it. Function.constantly(code) and fn -> code end will behave differently because the former is an invocation to the combinator, and the latter is the produced function. Moreover, if you give a function to Function.constantly/1, then expect the constant function to return the same function, not to evaluate it.


I don’t know what was the motivation behind the addition of Function.identity/1, but I’m not sure if it’s worth it to implement these combinators in elixir itself, or it’s best to leave it for userland code. I think that once you add one you’ll be tempted to add the others, and I don’t know if that’s the goal of the Function module.
I also understand that Elixir is a pragmatic language and academic purity is not it’s goal, but if we are going to implement these abstractions then we need to pick something that’s already been generalized and well understood, otherwise we would end up discussing which arity the function should have considering x, y and z practical examples, and for such cases I believe ad-hoc functions are the best.

marick

marick OP

Other languages have this function. I think it’s always arity 1, with the argument being ignored.

al2o3cr

al2o3cr

Nitpick: Function.constantly(value) is also not a shorter version, since it’s literally nine characters longer.

OvermindDL1

OvermindDL1

“Other languages” have this function also seem to be the same languages where every function is arity 1 (what you’d think of as an arity 3 function is just an arity 1 that returns a function that is arity 1 that returns a function that is arity 1 that return the result), and no language on the BEAM can work quite like that without a huge amount of preprocessing to ‘pack’ arity’s together if you want to work with the rest of the beam.

marick

marick OP

Clojure has a constantly, and it has functions that aren’t just syntactic sugar for arity-1 functions.

— All posts loaded —

Where Next? Top

Trending in Discussions Top

AstonJ
As the title says, please share what you’ve been up to with Elixir. Whether that’s been learning it, looking into it, making stuff with i...
2977 91898 914
New
AstonJ
The obligatory hello world thread! Who are you and where are you from? :stuck_out_tongue:
4616 55835 594
New
byu
@chrismccord : I just saw the Extract AGENTS.md from Phoenix.new into phx.new generator commit to the phoenix project. My initial shotgu...
New
arcanemachine
I was working on an Ecto migration and I needed a timestamp. So, for the nth time, I looked up the different data types for timestamps, a...
New
alexslade
Fly’s CEO posted this recently - Turn And Face The Strange · The Fly Blog It says that Fly is going all-in on sprites, which is a worry ...
New
Herve37
We’re evaluating API mocking tools for OpenAPI-based projects and would love to hear what other teams are using. We’re particularly inte...
New
matt-savvy
Is there a word for the ~> symbol used in Version strings? Do you also just call it a Squiggle Arrow™ ?!
New

Other Trending Topics Top

JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
mcass19
ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applicatio...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge & Solve. They are GUI (Emerge) and State management (S...
New
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
ausimian
Emily is an Elixir library that runs Nx computations on Apple’s MLX. Install it as the default Nx backend and Nx, defn, Axon, Nx.Serving,...
New

We're in Beta

About us Mission Statement