Named paramters again

Ok, last recommendation for named parameters was:

obj.my_method( height: 10, width: 20, name: “foo” )

The problem I’ve got with this is that you can alter the parameter order and
I suspect that this calling convention incurs extra runtime cost.

I was having look at another language called ElastiC, which is a pretty cool
language. As far as I can tell its named method calls are similar to
Smalltalks and especially similar (identical?) to Objective-C.

[obj height: 20 width: 40 name: “foo” ]

But the interesting thing to note is that there is no method name specified.
The method is selected based on the argument names.

It’s like having a method defined as:

def height: width: name:
p height
p width
p name
end

But how would we call the method?

obj( height: 10, width: 20, name: “foo” )

or

obj height: 10, width: 20, name: “foo”

Normally, such a call would look for a method called ‘obj’ at the top level.
The parser would need to be altered to treat ‘obj’ as an object if the
arguments are named parameters.

Interestingly, most of this implementation of named parameters exists within
the parser and need not affect the runtime greatly. Example:

def height: width: name:

can convert to:

def height_width_name( height, width, name )

and

obj height: 10, width: 20, name: “foo”

can convert to:

obj.height_width_name( 10, 20, “foo” )

Benefits:

  1. I don’t see the benefit of the Python implementation where you can
    optionally define named parameters in the call. Example:

    obj.set( 10, y=20, 30 )
    obj.set( x=10, 50, z=20 )
    obj.set( y=10, z=20, x=50 ) --blah, please tell me why?

Being able to supply the parameters in any order just means that the
programmer can make the program harder to read. I think that’s bad. I also
suspect performance overhead for this feature.

Better:

obj( x: 10, y: 20, z: 30 )
  1. No performance hit. It’s exactly the same lookup strategy as for other
    methods.

Thoughts anyone? Like how to handle default values for arguments? :wink:

···


Justin Johnson

Ok, last recommendation for named parameters was:

obj.my_method( height: 10, width: 20, name: “foo” )

The problem I’ve got with this is that you can alter the parameter order
and
I suspect that this calling convention incurs extra runtime cost.

AFAIC, the point of allowing (not enforcing) named parameters is so that
the programmer can alter the parameter order. That way, if a method has
several parameters, you don’t have to remember the order. This is really
only suited to those situations where a class or method is data-heavy. In
these situations, there is generally nothing special about parameter order.

I can’t think of any method of the built-in classes that would benefit from
named parameters.

Nobody should be forced to use named parameters, so who cares about runtime
cost?

I was having look at another language called ElastiC, which is a pretty
cool
language. As far as I can tell its named method calls are similar to
Smalltalks and especially similar (identical?) to Objective-C.

[obj height: 20 width: 40 name: “foo” ]

But the interesting thing to note is that there is no method name
specified.
The method is selected based on the argument names.

A nice experiment, perhaps, but methods have names for a reason: to indicate
what they do.

It’s like having a method defined as:

def height: width: name:
p height
p width
p name
end

But how would we call the method?

obj( height: 10, width: 20, name: “foo” )

or

obj height: 10, width: 20, name: “foo”

Normally, such a call would look for a method called ‘obj’ at the top
level.
The parser would need to be altered to treat ‘obj’ as an object if the
arguments are named parameters.

Interestingly, most of this implementation of named parameters exists
within
the parser and need not affect the runtime greatly. Example:

def height: width: name:

can convert to:

def height_width_name( height, width, name )

and

obj height: 10, width: 20, name: “foo”

can convert to:

obj.height_width_name( 10, 20, “foo” )

Benefits:

  1. I don’t see the benefit of the Python implementation where you can
    optionally define named parameters in the call. Example:

    obj.set( 10, y=20, 30 )
    obj.set( x=10, 50, z=20 )
    obj.set( y=10, z=20, x=50 ) --blah, please tell me why?

Why not? If x, y and z are simply properties of the object that need to be
set, the programmer’s intention couldn’t be more explicit than the third
line above. Apart from their alphabetical order, which does not generalise,
there is nothing suggesting anything special about the order they are
specified in.

Being able to supply the parameters in any order just means that the
programmer can make the program harder to read. I think that’s bad. I
also
suspect performance overhead for this feature.

Imagine the following method:

def calculate_maintenance(bulls, sheep, chickens)

Which is clearer:
calculate_maintenance(400, 251, 49)
or
calculate_maintenance(chickens:49, bulls:400, sheep:251)
?

There is no significance to the order of the parameters, so its easy to get
the arguments around the wrong way.

Better:

obj( x: 10, y: 20, z: 30 )

What’s the difference? No method name (surely that makes the program
harder to read), and using : instead of =. Big deal.

  1. No performance hit. It’s exactly the same lookup strategy as for
    other
    methods.

Performance shmerformance. Clear, maintainable solutions are more expensive
than faster equipment. Ruby is not likely to be a performance gun anytime
soon, and a named parameters strategy won’t change that much either way.

Thoughts anyone? Like how to handle default values for arguments? :wink:

My thoughts on named parameters:

  1. They are a useful convenience in a limited set of cases, not a magic
    bullet or killer gimmick for a language.

  2. If used widely, they will make code difficult to read.

  3. They should not be mandatory. (Shouldn’t need stating, should it?)

  4. (1) & (2) → One can only provide named arguments if the method was
    defined to receive them. (This could be bothersome to specify and may not
    meet with agreement.)

  5. Even for methods that have named parameters, anonymous arguments are
    allowed. Mixing anonymous and named parameters in a method call is
    prohibited.

  6. When someone writes a method that takes named parameters, they should
    stop and think whether they can make it unnecessary (by reducing the number
    of parameters, for instance).

Just my 14c.


Justin Johnson

Gavin

···

----- Original Message -----
From: “Justin Johnson” justinj@mobiusent.com

I was having look at another language called ElastiC, which is a pretty
cool language. As far as I can tell its named method calls are similar
to Smalltalks and especially similar (identical?) to Objective-C.
[obj height: 20 width: 40 name: “foo” ]
But the interesting thing to note is that there is no method name
specified. The method is selected based on the argument names.

This is not totally true: in the example you made above, there is a method
name and it’s “height:width:name:”. Actually, I should say that the
method signature is “height:width:name:”. The method is selected
based on this signature, not on the “argument names” (even if, from
a reader’s point of view, this is equivalent to having named arguments).

obj( height: 10, width: 20, name: “foo” )
or
obj height: 10, width: 20, name: “foo”

As I proposed in another post:

obj.height:10 width:20 name:“foo”

I don’t know what changes to the parser this would require, though.
Objective-C’s and Smalltalk’s syntax could be used, but it would
interfere with Array literals.

Being able to supply the parameters in any order just means that the
programmer can make the program harder to read. I think that’s bad.

I think that’s EXTREMELY bad.

Better:
obj( x: 10, y: 20, z: 30 )

In my view, commas and parenthesis could be eliminated and replaced
with dot and spaces, as I said above.

···

On Wed, 07 Aug 2002 02:37:30 +0200, Justin Johnson wrote:


ste

From: Gavin Sinclair [mailto:gsinclair@soyabean.com.au]
Sent: Wednesday, August 07, 2002 12:00 PM
To: ruby-talk ML
Subject: Re: Named paramters again

AFAIC, the point of allowing (not enforcing) named parameters is
so
that
the programmer can alter the parameter order. That way, if a method
has
several parameters, you don’t have to remember the order. This is
really
only suited to those situations where a class or method is data-heavy.
In
these situations, there is generally nothing special about parameter
order.

Named parameters can also be used to allow for methods where default
values are supplied for specific parameters:

def foo(x, y=2, z=3)

end

If you want to call this and set ‘z’ but leave ‘y’ is default value,
named parameters are your friend.

foo(2, z: 4)

Where this is used a lot in python are constructors in GUI widgets were
lots
of default values can be set and you only need to provide those you wish
to
‘override’…and yes…order independence becomes relevant here too
because you will have a hard time maintaining the order in your head for
20 or 30 parameters. Granted, you could just implement this as
subsequent calls to attribute getter/setters, but it’s nice to be able
to do it in widget construction.

-rich

···

-----Original Message-----

Gavin Sinclair wrote:
[ lots of clever stuff I agree with ]

  1. Even for methods that have named parameters, anonymous arguments are
    allowed. Mixing anonymous and named parameters in a method call is
    prohibited.

Does this imply that a method call must either use anonymous or named
parameters exclusively? I’d like to be able to specify the first X of
the arguments sequentially by position (as normal) and tag on the
remaining named parameters in any old order. (This seems to be the
current practice, with the Hash hack way of pseudo named parameters)

I think this could make some things more readable, e.g.:
anArray.insert(“new element”, at_index: 5) # reads nicely
anArray.insert(element: “new element”, at_index: 5) # tad too verbose

Now, a tangent thought: The name given to a parameter which makes the
method call readable is not necessarily a name that makes the method
code readable. Now, we could reassing them to more suiting local
variables inside the method, but this is akin to using a hash and
pulling them out of it.

class Array
def insert( element:, at: )
# in here, ‘at’ is just plain ugly
insertion_index = at
end
end
anArray = Array.new
anArray.insert(“new element”, at: 5 ) # but here ‘at’ is more readable

So I’ll toss out the wild & crazy idea that… drumroll
Named parameters can have aliases. Yep, you read that right. So that at:
would be an alias of insertion_index:, instead of us having to
compromise in the choice of variable names inside. And also, we could go
a little nuts, and allow:
anArray.insert( “new element”, at: 5 )
anArray.insert( “new element”, at_index: 5 )
anArray.insert( “new element”, insertion_index: 5 )

Now, before you call me utterly mad, keep in mind that with named
parameters, the names you choose in your API will be cast in stone. No
way of changing these later w/o breaking code that uses them, nor
refactor the names to something more readable. But if you could alias
them, it would be no problem. Old code would work, new code would use
more sensible named parameter names w/o having to use a method postfixed
with a version number. Besides, alot of things are already aliasable(?)
in Ruby, why not parameter names? :stuck_out_tongue_winking_eye:

Ok, you can start flaming now.

(Note that I don’t want changes to Array, I just use it as an example.)

  1. When someone writes a method that takes named parameters, they should
    stop and think whether they can make it unnecessary (by reducing the number
    of parameters, for instance).

goes back to nodding

···


([ Kent Dahl ]/)_ ~ [ http://www.stud.ntnu.no/~kentda/ ]/~
))_student
/(( _d L b_/ NTNU - graduate engineering - 5. year )
( __õ|õ// ) )Industrial economics and technological management(
_
/ö____/ (_engineering.discipline=Computer::Technology)

Where this is used a lot in python are constructors in GUI widgets were
lots
of default values can be set and you only need to provide those you wish
to
‘override’…and yes…order independence becomes relevant here too
because you will have a hard time maintaining the order in your head for
20 or 30 parameters. Granted, you could just implement this as
subsequent calls to attribute getter/setters, but it’s nice to be able
to do it in widget construction.

I see your point.

I think that the named argument method that I outlined serves a slightly
different purpose to the one above. The one I outlined gives the language a
way of calling methods based on set named parameters in a way similar to
Smalltalk and Objective-C. The Python style call allows flexible
specification of named arguments and seems particularly useful in the
presence of default argument values.

The main thing for me is that the Python style named arguments must require
extra processing when calling a method with named arguments.

But there again, maybe that’s the price you pay for flexibility.

···


Justin Johnson

aliasing the paramters seems like a good idea. how would you implement
that?

you know i can’t help but return to my earlier thoughts on this subject.
the difference between passing unnamed/ordered-arguments versus
named/unordered arguments is so very similiar to array vs. hash. so
using both “types” as method arguments is similar to what i was
attempting by making array and hash a single entity. of course for
arguments theres less to worry about, as you don’t pass them around and
manipulate them. BUT that’s where it gets me. why arn’t arguments, being
a list of things, array-like or hash-like, not just arrays and/or hashes
to begin with?

here’s an off-the-cuff notation for visual conception:

f:[1, 2]

f:{a=>1, b=>2}   

which is equivalent to the generally discussed:

f(1,2)

f(a: 1, b: 2)

now by making arguments bonified objects in themselves as either arrays
or hashes, we can do things like this:

a = [1, 2]
f:a

h = {a=>1, b=>2}
f:h

ruby currently lets us do similar things, although more limited, by
offering us terse tricks and defaults, like *a for example.

i’d be interested to hear what others might concieve of doing with this
notation, that perhaps can’t readily be done with ruby currently.

now, as for bringing the two together, we get a unification of array and
hash such that we might write a “mix”: (note: i use <: and :> for a lack
of unused brackets)

m = <: 1, b=>2 :>

this mixture of array and hash necessarily combines all the
characteristics of the two, such that each parameter/element has an
index-number, a value, and optionally an index-name.

so thats my breif take on all this. the upshot being that i do think
named parameters are a good idea. but it would be nice to do it very
cleanly, with the conceptions as i have basically presented them,
although i am uncertain of exact implementation. it also indicates that,
as i have suspected, an array and a hash are not so distinct and that
they may indeed make for a more powerful entity if combined.

by seeing the equivalent nature of things and utilizing then as such, we
are blessed with a much cleaner and more powerful dialect with which to
code. but such ideas may be outside the scope of what can be improved
upon in ruby.

···

On Wed, 2002-08-07 at 11:24, Kent Dahl wrote:

So I’ll toss out the wild & crazy idea that… drumroll
Named parameters can have aliases. Yep, you read that right. So that at:
would be an alias of insertion_index:, instead of us having to
compromise in the choice of variable names inside. And also, we could go
a little nuts, and allow:
anArray.insert( “new element”, at: 5 )
anArray.insert( “new element”, at_index: 5 )
anArray.insert( “new element”, insertion_index: 5 )


~transami

Hi –

Named parameters can also be used to allow for methods where default
values are supplied for specific parameters:

def foo(x, y=2, z=3)

end

If you want to call this and set ‘z’ but leave ‘y’ is default value,
named parameters are your friend.

foo(2, z: 4)

Where this is used a lot in python are constructors in GUI widgets were
lots
of default values can be set and you only need to provide those you wish
to
‘override’…and yes…order independence becomes relevant here too
because you will have a hard time maintaining the order in your head for
20 or 30 parameters. Granted, you could just implement this as
subsequent calls to attribute getter/setters, but it’s nice to be able
to do it in widget construction.

I’m completely GUI-programming ignorance, but I’ll accept on faith
that the interface authors have good reason to do it this way (rather
than wrapping the arguments up in an object). But I’m still not sure
this should be taken as a model for language-level change. Isn’t it
sort of good that the language doesn’t make 20-parameter methods
convenient? :slight_smile:

David

···

On Thu, 8 Aug 2002, Rich Kilmer wrote:


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

What about:

class Array
def insertElement:element at:position

end
end
anArray = Array.new
anArray.insertElement:“new element” at:5

Just like Objective-C (or Smalltalk)

···

On Wed, 07 Aug 2002 19:11:25 +0200, Kent Dahl wrote:

class Array
def insert( element:, at: )
# in here, ‘at’ is just plain ugly
insertion_index = at
end
end
anArray = Array.new
anArray.insert(“new element”, at: 5 ) # but here ‘at’ is more readable


ste

Where this is used a lot in python are constructors in GUI widgets were
lots
of default values can be set and you only need to provide those you wish
to
‘override’…and yes…order independence becomes relevant here too
because you will have a hard time maintaining the order in your head for
20 or 30 parameters. Granted, you could just implement this as
subsequent calls to attribute getter/setters, but it’s nice to be able
to do it in widget construction.

I see your point.

I think that the named argument method that I outlined serves a slightly
different purpose to the one above. The one I outlined gives the language a
way of calling methods based on set named parameters in a way similar to
Smalltalk and Objective-C. The Python style call allows flexible
specification of named arguments and seems particularly useful in the
presence of default argument values.

The main thing for me is that the Python style named arguments must require
extra processing when calling a method with named arguments.

But there again, maybe that’s the price you pay for flexibility.

···


Justin Johnson

Where this is used a lot in python are constructors in GUI widgets were
lots
of default values can be set and you only need to provide those you wish
to
‘override’…and yes…order independence becomes relevant here too
because you will have a hard time maintaining the order in your head for
20 or 30 parameters. Granted, you could just implement this as
subsequent calls to attribute getter/setters, but it’s nice to be able
to do it in widget construction.

I see your point.

I think that the named argument method that I outlined serves a slightly
different purpose to the one above. The one I outlined gives the language a
way of calling methods based on set named parameters in a way similar to
Smalltalk and Objective-C. The Python style call allows flexible
specification of named arguments and seems particularly useful in the
presence of default argument values.

The main thing for me is that the Python style named arguments must require
extra processing when calling a method with named arguments.

But there again, maybe that’s the price you pay for flexibility.

···


Justin Johnson

Where this is used a lot in python are constructors in GUI widgets were
lots
of default values can be set and you only need to provide those you wish
to
‘override’…and yes…order independence becomes relevant here too
because you will have a hard time maintaining the order in your head for
20 or 30 parameters. Granted, you could just implement this as
subsequent calls to attribute getter/setters, but it’s nice to be able
to do it in widget construction.

I see your point.

I think that the named argument method that I outlined serves a slightly
different purpose to the one above. The one I outlined gives the language a
way of calling methods based on set named parameters in a way similar to
Smalltalk and Objective-C. The Python style call allows flexible
specification of named arguments and seems particularly useful in the
presence of default argument values.

The main thing for me is that the Python style named arguments must require
extra processing when calling a method with named arguments.

But there again, maybe that’s the price you pay for flexibility.

···


Justin Johnson

I apologize for the multiple postings again.

Outlook seems to keep my responses in the outbox sometimes and gets stuck in
a loop of sending. I have to go in and manually delete it.

I’ll try to spot it earler next time.

Sorry.

···


Justin Johnson

I apologize for the multiple postings again.

Outlook seems to keep my responses in the outbox sometimes and gets stuck in
a loop of sending. I have to go in and manually delete it.

I’ll try to spot it earler next time.

Sorry.

···


Justin Johnson

I apologize for the multiple postings again.

Outlook seems to keep my responses in the outbox sometimes and gets stuck in
a loop of sending. I have to go in and manually delete it.

I’ll try to spot it earler next time.

Sorry.

···


Justin Johnson

I remember from Amiga days so called TagList It was an array of pais NAME,
VALUE, followed by end of list tag, it made GUI programming very easy.

I think it would be easy to write function putting values from TagList in
right places in a string containing parameter values, and giving default
values where required name value pair is missing. And then calling it with
eval

···


Jacek Podkanski

Response at bottom

From: David Alan Black [mailto:dblack@candle.superlink.net]
Sent: Wednesday, August 07, 2002 6:57 PM
To: ruby-talk ML
Subject: RE: Named paramters again

Hi –

Named parameters can also be used to allow for methods where default
values are supplied for specific parameters:

def foo(x, y=2, z=3)

end

If you want to call this and set ‘z’ but leave ‘y’ is default value,
named parameters are your friend.

foo(2, z: 4)

Where this is used a lot in python are constructors in GUI widgets
were
lots
of default values can be set and you only need to provide those you
wish
to
‘override’…and yes…order independence becomes relevant here too
because you will have a hard time maintaining the order in your head
for
20 or 30 parameters. Granted, you could just implement this as
subsequent calls to attribute getter/setters, but it’s nice to be
able
to do it in widget construction.

I’m completely GUI-programming ignorance, but I’ll accept on faith
that the interface authors have good reason to do it this way (rather
than wrapping the arguments up in an object). But I’m still not sure
this should be taken as a model for language-level change. Isn’t it
sort of good that the language doesn’t make 20-parameter methods
convenient? :slight_smile:

Well, I agree that it’s a code smell to accept 20 params in a
constructor, but named parameters are still useful in the above
mentioned (3 param) method call. Where the first param is required, the
other two have a default value, and you want to change the value of the
third param.

In Ruby you could (as easily) do this instead of the 20 param thing.

class Widget
attr_accessor :x, :y, :z
def initialize(&block)
@x=0
@y=0
@align=:center
# … lots of other params
instance_eval &block if block_given?
end
end

Widget.new {@align=:left}

Which is how I solved it for my GUI abstraction layer.

···

-----Original Message-----
On Thu, 8 Aug 2002, Rich Kilmer wrote:

From Stephano:

What about:

class Array
def insertElement:element at:position

end
end
anArray = Array.new
anArray.insertElement:“new element” at:5

Just like Objective-C (or Smalltalk)


ste

Sorry if I’m being closed-minded, but why is “insertElement” preferable to
“insert”, and why is “f:arg1 arg2” preferable to “f(arg1, arg2)”?

–Gavin

did a little wondering about the internet, found this quote:

Viewing Hash and Array as instances of “Container” leads
to easy implementation of “Sparse Array” and “Sorted Hash”
and “Real Array”

of course, what i’m suggesting is perhaps a bit more radical: unifying
array and hash --well, perhaps just making a new type of object which is
this unification (but given this, i can’t exactly see why you’d still
need the other two, but no matter)

this new “MixedContainer” class could have a literal representation
denoted by parantheticals:

( 'one', :opkey=>'two' )

then a subclass of Container could be made called Arguments, where
Arguments has some added features that give it some of the reminaing
applicaple characteristics of Ruby’s current argument behavior, ie.
*array, &block and the like.

thus, calling any method simply boils down to passing a single Arguments
object.

f ('one', :opkey=>'two')

which then could also be done like this:

args = ('one', :opkey=>'two')
f args

the end result? we get a new powerful class and named parameters in one
shot.

neat/clean/interestig idea?

~transami

p.s. found a nice pitch page for ruby:

http://www.cse.unsw.edu.au/~gjmc469/

···

On Thu, 2002-08-08 at 04:05, Justin Johnson wrote:

Where this is used a lot in python are constructors in GUI widgets were
lots
of default values can be set and you only need to provide those you wish
to
‘override’…and yes…order independence becomes relevant here too
because you will have a hard time maintaining the order in your head for
20 or 30 parameters. Granted, you could just implement this as
subsequent calls to attribute getter/setters, but it’s nice to be able
to do it in widget construction.

I see your point.

I think that the named argument method that I outlined serves a slightly
different purpose to the one above. The one I outlined gives the language a
way of calling methods based on set named parameters in a way similar to
Smalltalk and Objective-C. The Python style call allows flexible
specification of named arguments and seems particularly useful in the
presence of default argument values.

The main thing for me is that the Python style named arguments must require
extra processing when calling a method with named arguments.

But there again, maybe that’s the price you pay for flexibility.


Justin Johnson


~transami

Hi,

In Ruby you could (as easily) do this instead of the 20 param thing.

class Widget
attr_accessor :x, :y, :z
def initialize(&block)
@x=0
@y=0
@align=:center
# … lots of other params
instance_eval &block if block_given?
end
end

Widget.new {@align=:left}

Which is how I solved it for my GUI abstraction layer.

I don’t guess that it’s good habit to instance_eval block
created in other scope, since changing the receiver in
invisible place from the definition point often causes
confusion. Rather, I’ll suggest yielding with “self”.

class Widget
attr_accessor :x, :y, :z, :align
def initialize()
# same as above…
yield self if block_given?
end
end

Widget.new {|w| w.align = :left}

···

At Thu, 8 Aug 2002 08:49:56 +0900, Rich Kilmer wrote:


Nobu Nakada