Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

support C++ style default arguments? #1817

Closed
stevengj opened this Issue · 19 comments

8 participants

@stevengj
Collaborator

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.

@johnmyleswhite
Collaborator

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

@pao
Collaborator

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

@stevengj
Collaborator

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

@johnmyleswhite
Collaborator

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

@JeffBezanson

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) = ...
@staticfloat
Owner

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.

@StefanKarpinski

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.

@johnmyleswhite
Collaborator

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.

@stevengj
Collaborator

@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.

@StefanKarpinski
@stevengj
Collaborator

@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.)
@johnmyleswhite
Collaborator

@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.

@stevengj
Collaborator

@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.

@johnmyleswhite
Collaborator

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.

@stevengj
Collaborator

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).

@JeffBezanson JeffBezanson was assigned
@JeffBezanson
Owner

Feature added.

@rfourquet
Collaborator

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?

@ivarne
Collaborator

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.

@rfourquet
Collaborator

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
Something went wrong with that request. Please try again.