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

Keyword arguments #805

Closed
wants to merge 1 commit into from
Closed

Keyword arguments #805

wants to merge 1 commit into from

Conversation

iopq
Copy link
Contributor

@iopq iopq commented Feb 3, 2015

Adds keyword arguments as a separate feature in a backwards-compatible way. The current functions are unaffected - only arguments declared as keyword arguments can be called this way. Keyword arguments can be mixed with normal arguments. Adds overloading in the general sense without breaking type inference allowing a later addition of sugar for optional or default arguments if this is desired.

@iopq iopq force-pushed the keyword-arguments branch from c630e04 to 2e41311 Compare February 3, 2015 11:25
```rust
fn slice(&self, from => begin: usize, to => end: usize) -> &'a str
fn slice(&self, from => begin: usize) -> &'a str
fn slice(&self, to => end: usize) -> &'a str
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope. I would vote against this. Why introduce another keyword when we have one? We could use to => usize instead as signature that this is keyword argument or default arguments, so this will be:

fn slice(&self, begin: usize = 0, end: usize = /* something, maybe `self.length()` */) -> &'a str

Anyway syntax need reconsideration.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hauleth: I think it's a little disingenuous to pick on the specific example. I can go one better: why have a slice method at all when we now have overloadable indexing and native range syntax? I agree a better example could be chosen, but that's not really the point of this.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@DanielKeep I could use any example (but this one was poor anyway). Although the meritum was here. Why introduce new keyword when we have one already? We should reuse what we have instead adding some creepy syntax (like Ruby have done).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Default/optional arguments are compatible with this design. They're really sugar for a form of overloading, so they can be added later if keyword arguments are added. Or maybe people will simulate them with macros and it won't be necessary.

The point is that this is outside of the scope of just adding keywords. You can argue merits and syntax for default arguments, but that's not the same concern as the keyword arguments themselves.

@petrochenkov
Copy link
Contributor

First of all, overloading on arity and default arguments are important topics, but they aren't directly related to named arguments.
With regard to passing integral parameters safely, there are enough tools already - newtypes, struct literals (as mentioned in your Javascript example), builders.
The listed benefits are relatively small compared to the existing solutions, and the questionable practice of using functions with lots of arguments is promoted. The arising complexity - namespacing of the argument names, ABI implications - isn't mentioned at all.

Personally, I think it's one of those dangerous proposals which turns a language into a feature creep by adding more and more nonessential bells and whistles.

@BurntSushi
Copy link
Member

I am in violent agreement with @petrochenkov. I agree that there is an ergonomic benefit to keyword arguments as defined here, but I think the added complexity is not worth it.

@Nercury
Copy link

Nercury commented Feb 3, 2015

Maybe we could start simpler at first, for example, work with overloading on arity, then later (if it makes sense) adopt argument defaults, and only then (if it makes sense) work on named arguments. And I still wonder about argument order based on type.

I also think that languages like PHP or JavaScript are bad examples, and history of C# would be a better one, but that is just a personal opinion.

@hauleth
Copy link

hauleth commented Feb 3, 2015

I think (if the "keyword arguments" is so needed) the best solution is to allow just omiting structure name when creating and passing to the function, i.e.:

struct Foo {
  a: u32,
  b: u32
}

fn bar(foo: Foo) {}
fn baz(foo: &Foo) {}

bar(Foo {a: 10, b: 10});
// would be the same as
bar({a: 10, b: 10});

// and

baz(&Foo {a: 4, b: 2});
// equals
baz(&{a: 4, b: 2});

@andrew-d
Copy link

andrew-d commented Feb 3, 2015

I think (if the "keyword arguments" is so needed) the best solution is to allow just omiting structure name when creating and passing to the function

+1 from me - this is a reasonably small change, and has nearly the same ergonomics as "proper" keyword arguments.

@aliblong
Copy link

aliblong commented Feb 3, 2015

Maybe we could start simpler at first, for example, work with overloading on arity, then later (if it makes sense) adopt argument defaults, and only then (if it makes sense) work on named arguments. And I still wonder about argument order based on type.

This seems like a more reasonable course of action than just throwing it all into the language at once; whether it's worthwhile to add even arity overloading and/or arg defaults is debatable.

I think (if the "keyword arguments" is so needed) the best solution is to allow just omiting structure name when creating and passing to the function.

At first glance, this seems to go against the Rust philosophy of no implicit conversion.

@hauleth
Copy link

hauleth commented Feb 4, 2015

@aliblong I wouldn't say that this is implicit conversion. I would rather say that this is type detection based on argument type, like with integers.

@iopq
Copy link
Contributor Author

iopq commented Feb 4, 2015

Or you could start simpler at first and add keyword arguments without overloading. The difference between my proposal and hauleth's proposal is that my struct is anonymous and has extra sugar like => for binding function locals to the members of the struct. I also want to avoid ambiguity about WHERE the struct comes. It should be ONE struct with keyword arguments that always comes in the same position.

I don't care what the syntax is, but if the ergonomics makes it painful to use in any way nobody will bother in reality. If you always have to unpack a struct that seems like unnecessary boilerplate.

@erickt
Copy link

erickt commented Feb 4, 2015

I'm also not ready yet to take a side on this RFC, but I'd like two additions. First to the alternatives is the builder pattern that works incredibly well with movable types. Your example could instead be written as:

window.add_new_control()
  .title("Title")
  .x_position(20)
  .y_position(50)
  .width(100)
  .height(50)
  .drawing_now(true)
  .build()

It does require more boilerplate on the definition of a method though, but that could be addressed with some clever macros. Second, we used to have anonymous record types a few years ago. It would be nice to dig up the arguments for why we removed them in favor of named struct types, see if the argument to remove them applies to your RFC, and finally see if those arguments are still valid today.

@DanielKeep
Copy link

@erickt: I found rust-lang/rust#3089, which mentions that the primary reason for removing structural records was that they didn't play nice with coherence, meaning you couldn't ever implement anything on them.

@iopq
Copy link
Contributor Author

iopq commented Feb 5, 2015

But that's no different from tuples, and tuples are in the language. I don't understand the reasoning here.

@nikomatsakis
Copy link
Contributor

I'm interested in keyword arguments for the future, but I would rather wait to consider them until after 1.0.

@pnkfelix
Copy link
Member

pnkfelix commented Feb 5, 2015

postponing for post 1.0

@pnkfelix pnkfelix closed this Feb 5, 2015
@pnkfelix pnkfelix added the postponed RFCs that have been postponed and may be revisited at a later time. label Feb 5, 2015
@pnkfelix
Copy link
Member

pnkfelix commented Feb 5, 2015

(there is already an issue for this topic in the postponed set, see #323.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
postponed RFCs that have been postponed and may be revisited at a later time.
Projects
None yet
Development

Successfully merging this pull request may close these issues.