Hacker News new | ask | show | jobs
by brintnc 2330 days ago
anyone mind explaining the /# to me? like `Application.get_env/3`. been wanting to learn Elixir for awhile now, but didn't even know what do Google for that one.
3 comments

It’s the literal identifier for a function pointer. Module.function/arity. (“Arity” = “number of arguments.”)

If you’re wondering “why add the arity”: Functions in BEAM are polymorphic on their arity, but not their argument types; i.e. multiple functions can share the same name but have different arity, but all definitions in a module of a function with the same name and arity are actually the same function.

When you see Erlang/Elixir code with multiple definitions of a function of the same name and arity, those are called “clause heads”, and are defining the function “by parts”; code like the following gets compiled into one function that branches internally depending on the arguments passed:

    def fact(0), do: 1
    def fact(1), do: 1
    def fact(n), do: n * fact(n - 1)
That out of the way: `Foo.bar/N` in Elixir code is a function-pointer literal, which you can pass around just like you're passing around a closure. These three lines are all equivalent in semantics:

    # remote function pointer
    f = Foo.bar/1

    # closure
    f = fn x -> Foo.bar(x) end

    # closure with anonymous parameters
    f = &Foo.bar(&1)
...in terms of what happens when you use `f` in your code; but the function-pointer version has lower overhead to call, and costs less memory to keep around, because it's not capturing anything from the environment. It's literally just a pointer.

Oh, and this also exists:

    f = &bar/1
...which is a function-pointer referencing a local function in the current module. This distinction is important, because you can get local function pointers that point to private functions; whereas you can't get remote function pointers (the fully-qualified kind that include a module name) to private functions. It's kinda like C++ with private fields—you have to not use `this.` when accessing them.

Oh, and one more variant:

    f = some_mod.foo/2
This isn't a function-pointer literal, but rather a function-pointer expression. `some_mod` here is a variable; this expression will give you a function-pointer to the function `foo/2` on whatever module is named by the atom in the `some_mod` variable. (This can only be resolved at runtime; your code will throw an error here when it executes this expression, if it finds out that `some_mod` doesn’t contain an atom, or that atom has no corresponding module, or that module doesn’t have a foo/2 function on it. You can catch this error, though; and the runtime itself catches this error to implement just-in-time module loading.)
not sure how i made it through my entire CS degree without learning this term. either that or i just don't remember it. anyways, thank you! this is really useful even outside of Elixir.
I've honestly never heard anyone who isn't an Elixir programmer use it. I wouldn't worry about not having heard it before.
It's much more common than just Elixir programmers. It's a common concept in computer science, particularly in functional programming or languages which permit function overloading on arguments.

https://en.wikipedia.org/wiki/Arity

Edit to add: I've heard and used arity for at least 10 years, in particular in the Clojure community. I've heard of Elixir and understand it shares some common ideas with Clojure and Ruby, but never been a part of its community.

In functional programming classes at the uni you probably wouldn't hear this because if they teach Haskell which I assume most do, every function always takes just one argument. That's because functions are curried by default.

I personally haven't really heard this mentioned anywhere outside of the Erlang/Elixir sphere.

This thread really surprised me - I learned about arity when learning about ternary operators, which are pretty universal - you can find ?: in all sorts of languages. I think I was learning about C when I first got a detailed explanation on the subject.
Even if every function is curried by default (and "currying" is yet another concept that may be alien to users of some languages), it is probably still useful to know with what number of arguments a function can evaluate to a value that is not just another function
I learned about it in the Ruby world.

Also, interestingly, it was available from Javascript 1.2 to 1.4: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...

I think it's a useful name for a useful concept, not sure why they'd take it out, "Function.prototype.length" is a much poorer replacement semantically (but hey, Javascript isn't known for its correctness or well-thought-out design...)

I had never heard of "arity" either until I started reading about functional programming concepts. It seems to be used a lot within the functional programming world, but not so much outside of that.
This is Erlang function notation that Elixir inherited. The format is: `{ModuleName}.{function_name}/{arity}`