Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

allow default arguments at any place in a function #22460

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

rfourquet
Copy link
Member

This is more a feature idea, with a proof of concept via a macro @defaults, rather than a PR.

In Julia, it's not possible to get a default argument before a non-default, so to simulate that functionality, one usually has duplicate the methods signatures by hand. But in the docstrings, we specify a default arg at any position with the use of brackets, e.g.:

rand([rng::AbstractRNG=GLOBAL_RNG], T::Type) = ...

I propose to allow that syntax in real code: Julia will automatically duplicate the signature (and forward the default argument when it's not supplied, similarly to what happens with regular default args) for each argument with a bracket (this means 2^n methods if n args have a bracket). It's up to the user to handle ambiguities (e.g. with f([a=0], [b=0])=..., the call f(0) is ambiguous).

This would not cover all our docstring uses (where sometimes the default is not shown), but could be a good step forward.

For the cons, I see that 1) it makes the language a bit more complicated (but anyway the user has to face this syntax in docstrings), and 2) it prevents using this syntax in the future for destructuring arguments (a la Haskell, e.g. defining f([a, b], c=>d) = a+c and being able to call f([1, 2], 3=>4), where a will take value 1, etc.), but I didn't notice such a proposition yet.

This PR shows how the rand methods could be updated with this syntax: basically the number of methods is halved (or even decreased from 8 to 2 for randn/randexp).

If in base, I believe it would be nicer without a macro, but a package with this macro is likely to be sufficient (the impact on Base itself doesn't seem so big).

(For reference, this issue has some related comments).

@rfourquet rfourquet changed the title allow default arguments an any place in a function allow default arguments at any place in a function Jun 21, 2017
@rfourquet rfourquet added the kind:speculative Whether the change will be implemented is speculative label Jun 21, 2017
@martinholters
Copy link
Member

Why the brackets?

@rfourquet
Copy link
Member Author

rfourquet commented Jun 21, 2017

Why the brackets?

Currently, f(a=1, b=2) generates 3 methods, i.e. the number of generated methods is equal to n+1 for n default values. With brackets, this would be 2^n generated methods, so the rules are slighly different.

EDIT: it is possible with the macro to mix bracketed defaults (doubles the number of generated methods) and regular defaults (generates one more method).

@tkelman
Copy link
Contributor

tkelman commented Jun 21, 2017

-1 on this syntax, square brackets are for array literals, they shouldn't have a different meaning in function definitions

the user has to face this syntax in docstrings

Not if we remove this non-syntax from the docstrings.

@nalimilan
Copy link
Member

Couldn't we allow rand(rng::AbstractRNG=GLOBAL_RNG, T::Type) = ... (i.e. without brackets) instead?

@rfourquet
Copy link
Member Author

square brackets are for array literals

It would not be the first time that Julia has overloaded meaning for syntax, but I'm not particularly attached to this bracket syntax here. Another possibility I see is f(x:=1, y) = ..., or @default 1 f(x=1, y) = ... (1 for first arg), instead of f([x=1], y) = ....

Couldn't we allow rand(rng::AbstractRNG=GLOBAL_RNG, T::Type) = ... (i.e. without brackets) instead?

I think it would be difficult without changing the current rules to the ones proposed here (i.e. 2^n generated methods vs. n+1), and I think it is out of question to change the current rules. For example how many methods would be generated for rand(rng::AbstractRNG=GLOBAL_RNG, T::Type=Float64) ? I.e. how to determine which argument can be omitted no matter whether subsequent argument are omitted?

@omus
Copy link
Member

omus commented Jun 22, 2017

As part of the TimeZones.jl package I implemented a version of this for my needs. It doesn't generalize perfectly but it's another implementation of allowing optionals parameters before required parameters:

@rfourquet rfourquet mentioned this pull request Jul 29, 2017
@rfourquet rfourquet mentioned this pull request Aug 25, 2017
19 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind:speculative Whether the change will be implemented is speculative
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants