ashneyderman

ashneyderman

Compiler tells me anonymous functions can not have default parameters

So something like this fails to compile:

def streamfun_from_string(str) do
  fn(skip_headers \\ true) ->
    ..
  end
end

I am wondering why is this a restriction? I do not quite understand the reason for it. Is there a work-around?

Most Liked

OvermindDL1

OvermindDL1

To sum up:

Functions are named by their atom name and their arity. There is no such thing as an arity-less function. There is such a thing as an atom-less function, those are anonymous functions, notice it still has an arity however. Thus every function always absolutely has an arity. Now considering that a default argument actually creates two function of one with the full arity and one of less that just calls the one with more, and considering function pointers only reference a single function and not multiple, that means it can’t encode both, just not possible.

peerreynders

peerreynders

Google Groups elixir-lang-talk (2014): Default arguments on anonymous functions

i.e.

defmodule Demo do
  def identity(x \\ :ok), # ONE function definition
    do: x

  defp info(fun) do
    fun
    |> Function.info()
    |> IO.inspect()
  end
  def run do
    info(&identity/0)  # TWO functions
    info(&identity/1)  #
  end
end

Demo.run()
$ elixir demo.exs
[
  pid: #PID<0.89.0>,
  module: Demo,
  new_index: 0,
  new_uniq: <<135, 214, 25, 143, 240, 101, 78, 237, 14, 92, 136, 181, 46, 33, 8,
    18>>,
  index: 0,
  uniq: 71217356,
  name: :"-run/0-fun-0-",
  arity: 0,
  env: [],
  type: :local
]
[
  pid: #PID<0.89.0>,
  module: Demo,
  new_index: 1,
  new_uniq: <<135, 214, 25, 143, 240, 101, 78, 237, 14, 92, 136, 181, 46, 33, 8,
    18>>,
  index: 1,
  uniq: 71217356,
  name: :"-run/0-fun-1-",
  arity: 1,
  env: [],
  type: :local
]

An anonymous function is a single function value.

Is there a work-around?

Probably not what you had in mind:

defmodule Demo do
  def makeFun() do
    fn options ->
      {skip_headers, _options} = Keyword.pop_first(options, :skip_headers, true)
      skip_headers
    end
  end

  def run do
    f = makeFun()
    IO.inspect(f.([]))
    IO.inspect(f.(skip_headers: false))
  end
end

Demo.run()
$ elixir demo.exs
true
false
OvermindDL1

OvermindDL1

The common erlang idiom is to do {module, function, [postargs]} where postargs are useful for carrying additional state (I.E. the closure part). So you can do something like {Blah, :blorp, [1, 2, 42]} then call it like {mod, fun, args} = {Blah, :blorp, [1, 2, 42]}; apply(mod, fun, [:prefix, :args | args]).

This is also why you tend to see so many erlang functions designed to take their most useful state at the end (same pattern as piping, which, again, Elixir does backwards), and it fit is so fantastically with Tuple Calls as it basically made this pattern a full callable instead (like anonymous functions)! But that’s gone now *grumble*grumble*

Where Next?

Popular in Questions Top

chrisalley
ExUnit now has describe blocks which is a welcome addition coming from RSpec. In the docs, it states that nested hierarchies of describe ...
New
lucidguppy
I have a super simple question about elixir - how would I take a file like this foo bar baz and output a new file that enumerates th...
New
jononomo
For some reason my phoenix channels are working for me in my local dev environment, but as soon as I deploy via Docker, I get a 403 error...
New
lessless
I believe there are people here who are dealing with CSV files import on the daily basis, and since Excel is a really popular tool there ...
New
mcarvalho
What is the difference between System.get_env and Application.get_env? For example, what are best practices to use one versus another.
New
fireproofsocks
I’m working on defining a simple Ecto schema for a table (in PostGres), but I don’t see where I can define a column as NOT NULL. Conside...
New
shahryarjb
Hello, I get Persian date from my client and convert it to normal calendar like this: def jalali_string_to_miladi_english_number(persi...
New
JDanielMartinez
Hi! May someone helps me, please! I have two apps into an umbrella project: the first one is Database, which manages queries, and the se...
New
dblack
I’ve got an issue with an app and I’ve no idea of how to troubleshoot it. I’m hoping someone here might have seen something similar. I p...
New
jason.o
In the code below, if the create action is not set to accept “extra_key” as an input, it errors out with a message shown above. Is there ...
New

Other popular topics Top

Qqwy
Update: How to use the Blogs &amp; Podcasts section You can post links to your blog posts or podcasts either in one of the Official Blog...
3271 127536 1222
New
JeremM34
Hello, how can I check the Phoenix version ? Thanks !
New
lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
belgoros
I’m not a pro in using Regex and can’t figure out why the following behaviour happens, especially if we take into account the difference ...
New
siddhant3030
Hi, I have to write a raw query for one of my project. But till now I have used ecto queries and don’t have much experience writing raw ...
New
klo
Got a question about when to concat vs. prepending items to list then reversing to achieve appending. So i know lists boil down to [1 | ...
New
malloryerik
Hi, this is for people who, like me, have had some friction using .html.heex templates in VSCode. The solution seems to be, in a hyphena...
New
Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New
senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New

We're in Beta

About us Mission Statement