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

support C++ style default arguments? #1817

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

support C++ style default arguments? #1817

stevengj opened this issue Dec 22, 2012 · 19 comments
Assignees

Comments

@stevengj
Copy link
Member

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
Copy link
Member

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

@pao
Copy link
Member

pao commented Dec 22, 2012

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

@stevengj
Copy link
Member Author

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

@johnmyleswhite
Copy link
Member

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

@JeffBezanson
Copy link
Member

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
Copy link
Member

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
Copy link
Member

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
Copy link
Member

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
Copy link
Member Author

@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
Copy link
Member

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 <[email protected]

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//issues/1817#issuecomment-11642325.

@stevengj
Copy link
Member Author

@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
Copy link
Member

@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
Copy link
Member Author

@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
Copy link
Member

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
Copy link
Member Author

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
Copy link
Member

Feature added.

@rfourquet
Copy link
Member

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
Copy link
Member

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.

@rfourquet
Copy link
Member

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
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants