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

Already on GitHub? Sign in to your account

support C++ style default arguments? #1817

Closed
stevengj opened this Issue Dec 22, 2012 · 19 comments

Comments

Projects
None yet
8 participants
Owner

stevengj commented Dec 22, 2012

It might be nice to support the C++ default-argument idiom. i.e. defining

f(x, y = 3, z = 0) = .....

would be equivalent to defining

f(x,y,z) = ....
f(x,y) = f(x,y,0)
f(x) = f(x,3,0)

as I find myself doing the latter a lot.

Member

johnmyleswhite commented Dec 22, 2012

Is this different from keyword arguments (e.g. #485) with defaults?

Member

pao commented Dec 22, 2012

Was about to chime on with probable dupe of #485 myself. See also the Options package.

Owner

stevengj commented Dec 22, 2012

Except I'm not suggesting keywords, just the "syntactic sugar" for multiple dispatch that @JeffBezanson mentioned in the thread.

Member

johnmyleswhite commented Dec 22, 2012

Ah. That would be a nice compromise along the road to full keyword arguments.

Owner

JeffBezanson commented Dec 22, 2012

Yep, this is totally separate from keyword arguments. Keyword arguments could coexist with this by using ; as a separator:

f(x, y = 3; key = 0) = ...
Owner

staticfloat commented Dec 22, 2012

I fully support this, this is basically the only reason I use the Options package. Having it be able to be so much less verbose would be awesome.

Owner

StefanKarpinski commented Dec 22, 2012

Keyword arguments strike me as much more important and I'm not at all sure that having a short syntax for default values for positional arguments is worth that additional syntactic complexity.

Member

johnmyleswhite commented Dec 22, 2012

I kind of agree with Stefan that adding a semicolon is a source of confusion. To me this approach could be a nice interim solution, but I would find it confusing to have semicolons have actual semantic content in the language.

Owner

stevengj commented Dec 22, 2012

@johnmyleswhite Don't semicolons already have "actual semantic content" in the language, e.g. for [1 2 3; 4 5 6]? Jeff's suggestion of using a semicolon as a separator between positional and keyword arguments seems reasonable to me---separators are what semicolons are naturally useful for.

Owner

StefanKarpinski commented Dec 22, 2012

My objection is definitely not to using semicolon like that, but more to
the complexity that it introduces into method declarations. But I used to
be really into this idea, so I don't entirely despise it. I've just leaned
very hard towards simplicity over features.

On Sat, Dec 22, 2012 at 6:05 PM, Steven G. Johnson <notifications@github.com

wrote:

@johnmyleswhite https://github.com/johnmyleswhite Don't semicolons
already have "actual semantic content" in the language, e.g. for [1 2 3;
4 5 6]? Jeff's suggestion of using a semicolon as a separator between
positional and keyword arguments seems reasonable to me---separators are
what semicolons are naturally useful for.


Reply to this email directly or view it on GitHubhttps://github.com/JuliaLang/julia/issues/1817#issuecomment-11642325.

Owner

stevengj commented Dec 23, 2012

@StefanKarpinski I definitely sympathize with the instinct to say "no" to new language features. Add too much stuff, and the language turns into C++.

In this particular case, because of Julia's Matlab heritage the use of optional trailing arguments for functions is very idiomatic for Julia (see e.g. sum, round, open, ...). (In Matlab, optional trailing arguments is the oldest and still the easiest form of overloading.) Adding syntactic sugar for this has the advantages that:

  • It makes programming this idiom easier.
  • Because it is easier, it encourages people to adopt the same idiom in their own code and hence a uniform style for optional arguments.
  • It might make documentation writing (and generation) easier. Instead of documenting round(x[, digits[, base]]) and then giving the default values in the text of the description, it would be much clearer to write round(x, digits=0, base=10). (Of course, you could adopt this convention in the documentation even without actually supporting the syntax, but that would be weird.)
Member

johnmyleswhite commented Dec 23, 2012

@stevengj: You're completely right that semicolons do have semantic content already in the language. And, now that I understand the proposal better, I quite like the idea of adding syntactic sugar to make it easier to use optional trailing arguments. But that liking depends on the fact that we don't have keyword arguments yet.

What I worry about is that it becomes very strange to have a mixture of (1) defaults for positional arguments and (2) defaults for keywords separated only by a semicolon. I suspect that will be confusing to new users who wouldn't understand why all of the "optional" arguments aren't keyword arguments. It may just be my lack of familiarity with the C++ idiom, but I'd like all optional arguments to be keyword arguments as soon as that mechanism is in place.

Owner

stevengj commented Dec 23, 2012

@johnmyleswhite So, when (if?) keyword arguments are supported, you would want functions like sum, round, and open in the standard Julia library to switch over to that style for their optional arguments? This would be a fairly extensive change.

Member

johnmyleswhite commented Dec 23, 2012

I would like that, but agree that it's such an extensive change that it may be infeasible. I also am not sure that we'll have keyword arguments anytime soon, which is why I'm now onboard for some sort of interim solution.

Owner

stevengj commented Dec 23, 2012

Remember also that even if keyword arguments are implemented in Julia, optional positional arguments will always be supported because of multiple dispatch, so keywords can never supersede them entirely. That is, optional positional arguments are a feature you already have now, what I am suggesting is just syntactic sugar to make them a bit cleaner to code and document and to encourage them to be used in a consistent way.

My feeling is that optional positional arguments are cleaner for functions like round with one or two optional arguments. Keyword arguments are better for functions like plot with large numbers of arguments. So, it is nice if both will co-exist in the long term (e.g. via a semicolon separator as @JeffBezanson suggested).

@ghost ghost assigned JeffBezanson Mar 16, 2013

Owner

JeffBezanson commented Apr 3, 2013

Feature added.

Contributor

rfourquet commented Dec 24, 2014

Sorry to revive an old thread, but I don't find a discussion on why optional positional arguments are only possible at the end of positional argument list... do they have to?
E.g. print(io::IO=STDOUT, xs...) ?
The next question is probably what to do in:
f(x::X=1, y, z::Z=3) = .... With the current rules, it would define implicitly f(x::X, y, z::Z) = ..., f(x::X, y) = ..., and f(y) = ... : number of methods equals number of defaults plus 1. Why not define implicitly f(x::X, y, z::Z), f(x::X, y), f(y, z::Z), f(y) ? (number of methods equals 2 raised to the number of defaults) I see that the increased complexity for method dispatch may be an obstacle, as well as the complications when the set of generated methods is ambiguous... Are these complications the reason for not implementing optional positionals not at the end?

Contributor

ivarne commented Dec 25, 2014

If you were to use such a feature, you'd have to be really careful to not introduce ambiguous method definitions, or we would need a new sense of method priority so that we can write code like

foo(a=1, b=2) = a*b
foo(3)

Pick the right definition of foo so that the result is 6, not 3. There are probably more complicated cases.

Contributor

rfourquet commented Dec 26, 2014

Yes, maybe it is best left to a macro, or with a different syntax to make it less easy to introduce ambiguity. I'm writing one currently wich uses := instead of = for specifying that two overloaded methods should be defined wrt this argument, e.g @default function print(io::IO:=STDOUT, x, y=1) ... end would literally define function print(io::IO, x, y=1) ... end and print(x, y=1) = print(STDOUT, x, y). What do you think of this API?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment