ruby picture

RCR 159: Default arg names for closures

Submitted by legacy (Mon Oct 20 01:10:56 UTC 2003)

Abstract

This is a legacy RCR from Ruby Garden, submitted by volty. Matz has declared these RCRs obsolete, and asked that their authors resubmit them in the new format.

an_array.map { _1 * 2 }
an_enum.each_with_index { p "at #{_2} we have #{_1}" }

or at least the usual $_ (when mult params) - an array prefixed with '_' or whatever else.
I do like readable code, but in short code it's just boring to type these.

What about using '{' '}' pair for defs too?

Problem

(RCR imported from old format)

Proposal

Analysis

(RCR imported from old format)

Implementation

(RCR imported from old format)
ruby picture
Comments Current voting

it's not *that* boring :-) (dblack, 2003-10-21 20:19:27)

Hi --

I don't think typing |x| is that much more boring than typing _1 -- and besides, then in your block you get to just type x, which saves you one character :-) In any case, the gain in readability, consistency, and generally nice looking-ness is pretty considerable.

As for $_, it really isn't very "usual" in Ruby. The Perl/shell-derived special variables in general are kind of semi-deprecated; search for "discourage use of" in the ToDo file in the source :-)

David Black

agreed (, 2003-10-26 18:52:17)

I too like concise code.

another suggestion could be to allow the yield method call to accept an associated parameter list, such as:

class Array # ...
def each_with_index
  (0...length).each do |i|
    yield(:i => i, :value => self[i])
  end
end
end
%w( one, two, three ).each_with_index do
  puts "#{value} is #{i}"
end

I do not think this is good idea (ch00k, 2003-10-30 12:18:16)

1. Omitting implicit block parameter declaration yields to serious problems of name clashes... what if I have a 'value' variable outside of block and want (or do not want) to use (or even modify) it's contents inside of a block?

2. Hard-coding paramater names a into method definition (such as shown in your example) is also not very good.
If you think of block as an anonymous method, that is defined the _user_ of class Array, not by it's _developer_, than it seems strange, that parameter names for _user's_ method are specified by class _developer_

All of this is IMHO.

counter (, 2003-11-01 19:02:55)

You bring up two good points.

1. I think this is more of an implementation issue. It should be possible that implicit yield variables could have special scope only to the block (ie a closure), so that when the block is done, all pre-existing variable bindings have not been altered by the block. For example the 'value' variable outside of the block would not have be modified. Of course there is still the possibility that you want to use the outer scoped variable inside the block, which would result in a variable name collision, which leads to my next point ...

2. Class developers specify class and method names, and they could easily be allowed to specify block parameter names too. Just like class and method names are part of the interface (or protocol) for a class, implicit block parameters could belong to this interface as well. The ideal situation would be to use anaphoric terms, for example 'it', 'value', or perhaps 'the_value'. For example, 'it' could be the default name for the each method, which would result in easy to read code like:

orders.each { it.do_something }

maybe the variables could be $-prefixed to show that their scope and life time are special, and not normal variables. The important thing is for the class developer to choose generic anaphoric variable names, like the ones I previously mentioned because they are best for dealing with collection elements (or otherwise back-referenced identifiers). Ideally, my code wouldn't use variable names like 'value' except in collection related code and only in small cohesive sections of code that refer to some variable that is inherant to the collection traversal. I generally try not to use generic variable identifiers like 'value' because there is hopefully a more domain specific terminology available to be used. In the case where a variable name collision would result, simply allow the client code to specify the parameter names as the currently do, and even allow the block code to use some default parameter names, while specify others. For example:

matrix.each do |it => row|
  # work with 'row'
  row.each_with_index do
    # work with i and/or value
  end
end

I don't expect to see this added to Ruby, but I think it does actually have some literary value for making readable code.

Another way (ch00k, 2003-11-05 08:49:32)

Maybe we should treat anonymous parameter names as a new keyword like "this" in C++?


Strongly opposed 0
Opposed 0
Neutral 0
In favor 0
Strongly advocate 0
ruby picture
If you have registered at RCRchive, you may now sign in below. If you have not registered, you may sign up for a username and password. Registering enables you to submit new RCRs, and vote and leave comments on existing RCRs.
Your username:
Your password:

ruby picture

Powered by .