pro: It's what being used at the caller-level already. It looks cool,
even when the value's a symbol: foo(a => :b).
con: To me, => means "points to", not "is". Therefore it might not be
good as an assignment symbol. No way to specify a named argument
without a default value.
There's no reason you can't leave the value off.
def foo(a=>) # same as foo(a=>nil)
I'm not saying its great. But it would work. And the pros for this are
pretty signifficant.
The 'key: :sym' effect is very unfortunate. I use symbol argument in a
number of places. Whether I will use them with keys much, who knows,
but given the problem I probably just won't and may even end up only
using => so as to avoid it. Then the ':' may as well not exist. I don't
know. But it sure would be nice if there was a simple fix to this.
Perhaps if backticks can become an *additional* way to express a
symbol? I know they are currently used for a type of system call, but
I'm sure a regular method would be okay for that. And I don't think
that's too much to ask of Ruby 2.0. Seems like a reasonble solution.
Of course there's still the question of Evan vs. Matz keyword
arguments. I can go either way. I think we all pretty much can go
either way. We know one works fine for Python, we know the other works
fine for Lisp. Is one truly better than the other? Doesn't seem like it
--at least not by much. Mostly, they're just different. Pick one.
pro: Looks clean and cool, even when the value is a symbol.
con: May be hard to implement. Doesn't specify how you seperate named
and positional arguments (maybe use a keyword like "named"?).
def foo(a, b = "bar", named c = "default", **keys)
It’s impossible to implement without breaking the current semantics of
the assignment operator.
To me, “a = "foobar"” reads very much like an assignment, not as an
argument specifier, but one mans opinion is more or less irrelevant.
If everyone can just get around the fact that passing symbols using
keyword arguments will look a bit awkward, with the two colons in a row
separated by a space, I really don’t see what the problem is. For every
other case, I think that <symbol>':'<ws>+<expr> reads a lot better than
<symbol><ws>*'='<ws>*<expr>, or
⋮
ary.grep(/regex/, start: 5, end: 8)
⋮
over
⋮
ary.grep(/regex/, start = 5, end = 8)
⋮
Reading the latter, I find my brain wondering where start and end are
being used in the code preceding and following the call to
Enumerable#grep. In the earlier I don’t get the feeling that “start”
and “end” are variables that are getting values assigned to them.
nikolai
···
--
Nikolai Weibull: now available free of charge at http://bitwi.se/\!
Born in Chicago, IL USA; currently residing in Gothenburg, Sweden.
main(){printf(&linux["\021%six\012\0"],(linux)["have"]+"fun"-97);}
I don't think this should be an assumption about how named
arguments work (unless you are talking about the final **keys
arg). The easiest initial implementation may be to use hashes
to pass around named arguments, but as we get better VM's and
compilers, that could change.
The main thing I don't like about the current proposal (what
matz presented at rubyconf) is that the *args (remaining
positional args) also contains the named arguments. So this:
def foo(a,b=1,*args,c:,d:2,**keys) ... end
called like this:
foo("a","b","x","y",c:"c",e:"e")
gives:
a = "a"
b = "b"
args = ["x","y",{ :c => "c", :d => 2, :e => "e" }]
c = "c"
d = 2
keys = { :e => "e" }
What use is it to have the named arguments appear twice? I
understand the need if you don't have named arguments in the
definition (compatibility), but as soon as named arguments are
specified, it seems to serve no purpose.
Also, like we have array splatting when you call a method, I
think hash splatting would also be useful. matz said that
hashes would be automatically splatted if they were the last
argument, but this results in ambiguity:
def foo(a,b={},c:2,**keys) ... end
foo("a",{:x => 1,:y => 2})
Does the above result in:
a = "a", b = {:x => 1,:y => 2}, c = 2, keys = {}
or:
a = "a", b = {}, c = 2, keys = {:x => 1,:y => 2}
I would rather see it be the first interpretation and if you
wanted the second, you'd "splat" the hash:
foo("a",**{:x => 1,:y => 2})
which would be the same as:
foo("a", x : 1, y : 2)
I think whether we have something sydney/python like where
positional arguments can automatically be named or whether
there is a clear distinction between positional/named like
lisp, it is OK. Another language comparison to make is just
the shell command-line. One the command-line named arguments
are effectively the "options" and positional are the rest. On
that note, another option would be to specify the named
arguments like command-line options:
def foo(a, b=1, --c=2, --*keys) ... end
foo("a", --c="c", --x=1, --y=2)
Or simply "-" instead of "--" if it could be handled in the
parser (could be confused with a unary - at first). But, I'm
not terribly concerned with syntax.
I'm hoping that we have enough reflection for these named
arguments like #arity. I'm thinking that with named arguments
a potential simple application would be as a spec for handling
command-line options (named arguments). I'd like to see all of
the keywords and defaults accessible from Proc/Method objects.
It'd be nice to have access to defaults of positional args
while wer'e asking.
Since Ruby 2 will also be completely redoing how
multiple-values are handled, why not also consider being able
to name your return values? If a method returns a bunch of
attributes, it would be nice for the caller to be able to pick
what they want.
···
--- Daniel Schierbeck <daniel.schierbeck@gmail.com> wrote:
Furthermore, the named arguments are gathered in a hash in
which the
keys are symbols.
keys[:key] -> value
__________________________________
Yahoo! Mail - PC Magazine Editors' Choice 2005
I can't say I can contribute much to the theoretical discussion. I can
only say what my first impressions are (up until Brian's email I was a
helpless spectator in an incomprehensible discussion).
The :a syntax looks a lot like symbols, which is something I would
avoid, in order to avoid paragraphs in documentation explaining that "in
method declarations :x means keyword", "when calling methods :a=x is a
keyword parameter assignment while :a is a symbol parameter" etc.
I agree. Also, the (a: "foo") syntax looks a lot like Smalltalk's named
arguments, and that gives it instant recognition.
>
> Ruby has always favored implicitness over explicitness. The fact that
> I don't have to do anything explicitly in Sydney makes it the winner
> IMHO.
I don't agree. If I write this:
def meth(a,b,c) ... end
I expect to be "allowed" to rename my parameters at will without
breaking any calling code. I'd even expect to be allowed to change,
say, (a,b,*c) to *args if I felt there was a good reason to.
I don't want my choice of local variable names to be coupled to
calling code. If I offer keywords or hash keys, that means I've
decided that I *do* want to publish those names, and commit to them.
Otherwise I consider them strictly the method's business, not the
caller's.
Amen. As I keep saying, it's a matter of interface. If you allow implicit
keyword arguments, you're suddenly mixing interface and implementation, and
that is *wrong* (in the sense that it is difficult to maintain, and it breaks
the promise of encapsulation). However, if you explicitly decide that some
argument is a keyword argument, you have *consciously* made it part of the
interface (I'd rather say part of the very *name* of the method), so you can
still maintain the separation between interface and implementation to the level
you want as a developer.
And I disagree that Ruby favours implicitness. It favours dynamicity, openness,
reflection, convention above configuration (and that's more a style common to
many Rubyists and well exemplified in Rails). But that doesn't imply
implicitness (pardon the pun, it was unintented). If anything, the fact that
Ruby is strongly typed, even if dynamically typed, and hardly does any implicit
casting (except among numbers, especially between Fixnum and Bignum), should be
indicative that Ruby, if anything, *does not favour implicitness*.
I'm with you on this David. I find myself doing (a,b,*args) => (*args)
quite often.
Regards,
Sean
···
On 10/21/05, David A. Black <dblack@wobblini.net> wrote:
I expect to be "allowed" to rename my parameters at will without
breaking any calling code. I'd even expect to be allowed to change,
say, (a,b,*c) to *args if I felt there was a good reason to.
>Ruby has always favored implicitness over explicitness. The fact that
>I don't have to do anything explicitly in Sydney makes it the winner
>IMHO.
Too much implicitness makes code cryptic. Too much explicitness makes
code verbose. It's a matter of balance.
By the way, how do you delegate the whole arguments (including keyword
arguments) in your style? Using KeywordBehavior?
Besides, what would happen for the following code?
def foo(*args)
# how do you delegate arguments?
bar(*args)
end
def bar(a,b,c)
p [a,b,c]
end
foo(1,a:2,c:3)
Not allowed because redefinition of the same parameter raises an error. Here you're trying to define 'a' twice, once as the first positional argument, once as a named parameter.
For purposes of this argument, though, let's say you did this:
foo(b:1, a:2, c:3)
Then, if we inspect '*args' in foo, it looks like [{:b=>1, :a=>2, :c=>3}]
For now, we're toying with the idea of an explicit behavior call to handle splat args in this case. So, the method definition would look like this:
def foo(*args)
bar(*KeywordBehavior.arguments) # Would pass 2, 1, 3
end
Yes, it's uglier. How does it work in your implementation? I'm curious to know how you preserve argument order.
and
class Foo
def foo(a,b,c)
p [a,b,c]
end
end
class Bar<Foo
# what if argument names differ?
def foo(d,e,f)
super
end
end
Bar.new.foo(d:1,e:2,f:3)
matz.
We discussed this somewhat last night. There are a couple of possible routes to take.
1) Insist that parameter names must match, and raise an error.
2) Pass the arguments positionally.
I think we're still undecided if I recall correctly.
Let me ask you the same thing. What happens here with your implementation?
class Foo
def foo(a:, b:, c:)
p [a,b,c]
end
end
class Bar < Foo
def foo(d:, e:, f:)
super
end
end
Bar.new.foo(f:3, e:2, d:1)
Regards,
Dan
···
In message "Re: A comparison by example of keyword argument styles" > on Fri, 21 Oct 2005 20:12:08 +0900, "Daniel Berger" <djberg96@gmail.com> writes:
Their number is part of the signature (rather than their position(s)).
OK. That's about what I meant .
> Keyword arguments, being just a
> part of the name of a method, must be explicitly marked as such
> by the developer, and shouldn't be allowed to be left out by the
> user, just like you can't leave out the name of a method.
I have always preferred this semantics.
It also means keyword argument names must be available through reflection.
>Matz, are there any patches that implement your proposal yet?
Not yet. The behavior was fixed on a night before the keynote. It is
much easier to implement than one in Sydney though.
matz.
One question. Why this complexity in syntax? Why the strange and
very confusing ':' as the syntax delimiter in both function definition
and, worse, parameter passing? Sorry, but this just feels so
complicated to me and seems more something thought with ruby's parser
in mind, not the user.
What's wrong with '=' and avoiding defining explicit parameters in the
parameter definition.
Compare everything that was proposed with python's simplicity and
elegance:
# this is something akin to ruby's: def f(*args)
def f2(a, b, c, *d):
print a, b, c, d
# and this is akin to ruby's: def f(arg={})
def f(a, b, c='xxx', **d):
print a, b, c, d
There's a lot of things I don't like in python, but how functions are
defined is definitively one of the strongest things in the language.
As you can see above, things are much simpler. No need to use any
special syntax for named parameters in the function definition and the
use of '=' is a heck of a lot more clear than : or =>. Both array and
hash syntaxes for extra parameters are also accounted for.
···
In message "Re: A comparison by example of keyword argument styles" > on Sat, 22 Oct 2005 03:08:19 +0900, Brian Mitchell <binary42@gmail.com> writes:
>1) *Method definition*
> I think named arguments should have the same
> syntax as positional ones, just with a colon
> in front of it.
>
> def foo(a, b, :c, :d = "bar")
Why with a colon in front of it instead of right after it?
>2) *Method calling*
> I think matz' style is preferable in many cases,
> but i still think the :key = value syntax should
> be there.
Why should be?
matz.
Because the keys *are* symbols, and they have colons in front of them.
Cheers,
Daniel
···
In message "Re: A comparison by example of keyword argument styles" > on Fri, 21 Oct 2005 18:46:59 +0900, Daniel Schierbeck <daniel.schierbeck@gmail.com> writes:
I agree. At least both the Sydney and Matz techniques for keyword
arguments use the colon. I do not think using equals will ever be a
valid option. Ruby isn't Python, and thank goodness for that.
Ryan
···
On 10/23/05, Nikolai Weibull <mailing-lists.ruby-talk@rawuncut.elitemail.org> wrote:
⋮
ary.grep(/regex/, start: 5, end: 8)
⋮
over
⋮
ary.grep(/regex/, start = 5, end = 8)
⋮
Reading the latter, I find my brain wondering where start and end are
being used in the code preceding and following the call to
Enumerable#grep. In the earlier I don't get the feeling that "start"
and "end" are variables that are getting values assigned to them.
The 'key: :sym' effect is very unfortunate. I use symbol argument in a
number of places.
Yes, it’s a bit ugly, but to me, using => for key-value pairs is not
visually pleasing either. However, I use them all the time when
creating hashes. How about ‘⇒’?
Whether I will use them with keys much, who knows, but given the
problem I probably just won't and may even end up only using => so as
to avoid it. Then the ':' may as well not exist.
What, we shouldn’t have ‘:’ since you personally will never use it?
If you don’t know how you will be using keyword arguments, then how can
you know if the proposed syntax will cause a visually displeasing
result? As I said in my other mail on this sub-thread, I think that
we’re making too much of the “but symbol arguments to keyword parameters
will look ugly” issue.
I don't know. But it sure would be nice if there was a simple fix to
this. Perhaps if backticks can become an *additional* way to express
a symbol? I know they are currently used for a type of system call,
but I'm sure a regular method would be okay for that. And I don't
think that's too much to ask of Ruby 2.0. Seems like a reasonble
solution.
How about "symbol".to_sym? Personally, I’d love to see Unicode being
used in Ruby’s syntax (OK, I know that it won’t happen, but as long as
we’re on this rather pointless discussion):
• «symbol»
• »symbol«
• »symbol
• ⟨symbol⟩
Of course there's still the question of Evan vs. Matz keyword
arguments.
Named arguments versus keyword arguments, to be more precise, as they
are two different things. Or have I missed something?
I can go either way. I think we all pretty much can go either way. We
know one works fine for Python, we know the other works fine for Lisp.
Is one truly better than the other? Doesn't seem like it --at least
not by much. Mostly, they're just different. Pick one.
They are two different things. Keyword arguments are a cleaner way to
implement methods that take optional parameters. Instead of writing a
method like
def m(a, b, c = 1)
⋮
end
we can write it as
def m(a, b, c: 1)
⋮
end
and then at invocation we write
m(1, 2, c: 3)
instead of
m(1, 2, 3)
to make it clear that we are passing an argument to a parameter that is
usually optional.
Named arguments is just a way of naming the parameter to tie the given
argument to.
They seem to be the same thing, but in reality they aren’t. Personally,
I don’t see the point of naming arguments, as parameters are usually
ordered in a sensible way already (i.e., travel(from, to) is clear
enough; travel(from: from, to: to) doesn’t add anything). I do,
however, see a point of being able to clearly state what optional
(keyword) parameters I do care about, as this allows me to skip defining
those that I don’t care about:
def m(a, b, c: 1, d: 2)
⋮
end
m(1, 2, d: 4)
nikolai
···
--
Nikolai Weibull: now available free of charge at http://bitwi.se/\!
Born in Chicago, IL USA; currently residing in Gothenburg, Sweden.
main(){printf(&linux["\021%six\012\0"],(linux)["have"]+"fun"-97);}
What use is it to have the named arguments appear twice? I
understand the need if you don't have named arguments in the
definition (compatibility), but as soon as named arguments are
specified, it seems to serve no purpose.
It's for method delegation. Currently we do
def foo(*args)
bar(*args)
end
for method delegation. Under my proposal, this delegation would still
work fine, since we have named arguments appear twice, otherwise we
must change the code as
def foo(*args, **keys)
bar(*args, **keys)
end
everywhere, to just do delegation.
Also, like we have array splatting when you call a method, I
think hash splatting would also be useful. matz said that
hashes would be automatically splatted if they were the last
argument, but this results in ambiguity:
def foo(a,b={},c:2,**keys) ... end
foo("a",{:x => 1,:y => 2})
Does the above result in:
a = "a", b = {:x => 1,:y => 2}, c = 2, keys = {}
or:
a = "a", b = {}, c = 2, keys = {:x => 1,:y => 2}
The former. Keyword argument uses the last remaining hash.
I'm hoping that we have enough reflection for these named
arguments like #arity. I'm thinking that with named arguments
a potential simple application would be as a spec for handling
command-line options (named arguments). I'd like to see all of
the keywords and defaults accessible from Proc/Method objects.
It'd be nice to have access to defaults of positional args
while wer'e asking.
Accepting keywords should be obtained from some kind of reflection
API, although the API is not fixed yet. But I'm not sure default
values can be accessed since they are arbitrary expression, and we
have no good way to represent pre-evaluated expression in Ruby (unlike
in Lisp, where we can use S expression).
Since Ruby 2 will also be completely redoing how
multiple-values are handled, why not also consider being able
to name your return values? If a method returns a bunch of
attributes, it would be nice for the caller to be able to pick
what they want.
I have no good idea of multiple value binding for named values
(i.e. syntax). Do you?
matz.
···
In message "Re: A comparison by example of keyword argument styles" on Mon, 24 Oct 2005 05:50:39 +0900, Eric Mahurin <eric_mahurin@yahoo.com> writes:
def foo(*args)
# how do you delegate arguments?
bar(*args)
end
def bar(a,b,c)
p [a,b,c]
end
foo(1,a:2,c:3)
Not allowed because redefinition of the same parameter raises an error. Here
you're trying to define 'a' twice, once as the first positional argument, once
as a named parameter.
Then what if foo(1,b:2,c:3) ?
Yes, it's uglier. How does it work in your implementation? I'm curious to know
how you preserve argument order.
For mine, args in foo becomes [1,{:a=>2,:c=>3}]. And suppose
def bar(a:,b:,c:)
p [a,b,c]
end
since it requires explicit keyword arguments, delegation should be
plain
bar(*args)
and bar prints [1,2,3].
Let me ask you the same thing. What happens here with your implementation?
class Foo
def foo(a:, b:, c:)
p [a,b,c]
end
end
class Bar < Foo
def foo(d:, e:, f:)
super
end
end
Bar.new.foo(f:3, e:2, d:1)
Bar#foo receives [{:f=>3,:e=>2,:d=>1}], then it delegates arguments to
Foo#foo. Foo#foo accepts keyword arguments a, b, c, and no other
keywords (it does not have ** in the list), it raises ArgumentError.
matz.
···
In message "Re: A comparison by example of keyword argument styles" on Sat, 22 Oct 2005 00:44:58 +0900, Daniel Berger <Daniel.Berger@qwest.com> writes: