import a function having default values: we must specify each arity used

102 views
Skip to first unread message

thojan...@gmail.com

unread,
Dec 25, 2020, 5:36:03 PM12/25/20
to elixir-lang-core
Say function `foo` has multiple default values (two required args, two with defaults). When importing, we must specify each arity that is used in the calling code, e.g.

```
import Foo, only: [foo: 2, foo: 3, foo: 4]

foo(1, 2)
foo(1, 2, 3)
foo(1, 2, 3, 4)
```

I expected that I could only import `foo/4`, and be able to call `foo` with only two arguments and three arguments. Why? Because there is no use case to force an imported function to be used only with a specific arity. That would even be a code smell.

Could we "generate" [foo: 2, foo: 3]` in addition to `[foo: 4]` to support the call using its default values?

Zach Daniel

unread,
Dec 25, 2020, 5:42:18 PM12/25/20
to elixir-l...@googlegroups.com
There are theoretical name conflicts from not being able to say “only import this story”  (e.g if you have a function with the same name but one less argument) what about import Mod, only: [func: 1..3]?

--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-co...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/28497895-3278-4de0-8423-99f9b9230597n%40googlegroups.com.

Zach Daniel

unread,
Dec 25, 2020, 5:43:03 PM12/25/20
to elixir-l...@googlegroups.com
Sorry, meant to say “in being able to say only import this *function*”, not story :)

thojan...@gmail.com

unread,
Dec 25, 2020, 5:52:17 PM12/25/20
to elixir-lang-core
>  e.g if you have a function with the same name but one less argument 

That can actually also be considered as a function with default values (and in the end, default values generate such functions with different arities). If not then I think it's a code smell and the function needs to be renamed.

José Valim

unread,
Dec 26, 2020, 3:30:32 AM12/26/20
to elixir-l...@googlegroups.com
I believe this was proposed a long time ago but I rejected it because of name conflicts. For example, imagine you import all of "foo" and on v1 it means adding both foo/2 and foo/3. However, on v2 the module also defines a foo/1. There is a chance this new arity will conflict with a local foo/1.

On the other hand, I would say having a function with the same name and different arity as an import is something that should be avoided in general (either by using a different name or not importing it), so I think it is worth this addition. The only complexity I foresee in implementing this is skipping the warning if one of the arities is invoked - but that's an implementation detail.

Therefore, I propose we do support this feature. My suggestion is to represent said names with naked atoms, such as:

import Enum, only: [:at, :map]

Specific arities go at the end as any keyword list:

import Enum, only: [:at, map: 2]

Thoughts?

Zach Daniel

unread,
Dec 26, 2020, 3:34:42 AM12/26/20
to elixir-l...@googlegroups.com
I could get behind that, although having to shuffle the specific arity imports to the end is a bit annoying. What about `import Enum, only: [at: :all, map: 2]`?

José Valim

unread,
Dec 26, 2020, 3:37:22 AM12/26/20
to elixir-l...@googlegroups.com
Thanks!

The reason I proposed naked atoms is because I can see it becoming the main mechanism to import functions, so I would go for the leaner format possible.

Devon Estes

unread,
Dec 26, 2020, 3:43:18 AM12/26/20
to elixir-l...@googlegroups.com
This seems like a source of potentially confusing issues to me, as mentioned earlier. I do admit that this would be a very rare occurrence, but in general it seems to go against what I see as one of the common patterns in Elixir, which is that things are often explicit rather than implicit. This explicitness does come at the cost of more typing when writing the code, but it also comes with the benefit of stability and clarity when reading or changing code, which I (personally) see as an overall benefit.

That said, if this does get implemented, using the :* atom for the arity would be explicit and would also keep the list passed to import/2 a keyword list. Bare atoms would be fine, too, but I see some value in the consistency of a keyword list for that argument as it removes the need for specific ordering.

--

_________________
Devon Estes
+49 176 2356 4717
www.devonestes.com

Wojtek Mach

unread,
Dec 26, 2020, 5:11:50 AM12/26/20
to elixir-l...@googlegroups.com
This addition would be nice for importing record macros, defrecord defines 3 different arities: 0, 1, and 2.

On 26 Dec 2020, at 09:43, Devon Estes <devon....@gmail.com> wrote:



José Valim

unread,
Dec 26, 2020, 5:19:21 AM12/26/20
to elixir-l...@googlegroups.com
Good points Devon. Do you think using :* makes it explicit and consistent enough, or still not worth it in your opinion?

Andrea Leopardi

unread,
Dec 26, 2020, 6:28:12 AM12/26/20
to elixir-l...@googlegroups.com
:* has precedents in Elixir for formatter stuff for example, so I say stick with it 🙃

Devon Estes

unread,
Dec 27, 2020, 3:59:26 AM12/27/20
to elixir-l...@googlegroups.com
If you’re asking just my opinion then I wouldn’t add this feature as it seems to me the case this is solving for happens so rarely that this wouldn’t be worth it. If folks have a bunch of imports and don’t want to specify which functions they’re importing specifically, they can still import the whole module which is even _less_ to type.

But, that said, many folks have a tendency to disagree with me on these cases, so I can see how this might be a desirable feature for some folks, and in that case :* seems like a reasonable way to go.

Wiebe-Marten Wijnja

unread,
Dec 27, 2020, 5:55:47 AM12/27/20
to elixir-l...@googlegroups.com
I very much _do_ agree with you, Devon!
I think this use case is too rare to merit adding built-in support for.
In general importing lots or functions into the local context seems like an antipattern and therefore I do not think we should make this easier, because it will encourage people to do it more often.

~Marten/Qqwy
--
Sent from my Android device with K-9 Mail. Please excuse my brevity.

Christopher Keele

unread,
Dec 28, 2020, 5:12:54 PM12/28/20
to elixir-lang-core
> Do you think using :* makes it explicit and consistent enough, or still not worth it in your opinion?

I think :all is even more explicit, and a little more consistent with the import only/except DSL: import Foo, only: [bar: :all, baz: 3]
Reply all
Reply to author
Forward
0 new messages