Array.each

a=(1…10)
a.each {| x , y| p x }

1
3
5
7
9

A more general pattern might be:

module Enumerable
def each_group(n=1)
res =
each do |i|
res << i
if res.size >= n
yield res
res =
end
end
yield res if res.size > 0
end
end

By making it part of ‘Enumerable’ and only depending on
‘each’, it works for any enumerable class:

(1…10).each_group(2) { |x,y| puts x } # prints 1,3,5,7,9

cool, but why not use #arity for block’s param count, no? I would then use
the param for the default like…

C:\family\ruby>type a1.rb

#class Array
module Enumerable
def each_group(defval=nil,&block)
n = block.arity
res =
each do |i|
res << i
if res.size >= n
yield res
res =
end
end
if res.size > 0
res << defval until res.size >= n
yield res
end
end
end

what follows are just testing

x = ‘(1…8).to_a.each_group {|x,y,z| p “x = #{x}; y = #{y.inspect}; z =
#{z.inspect}”}’
p “running #{x} using default = nil”
eval x
p ‘-----------’

x = ‘(1…7).to_a.each_group(9999) {|x, y,z| p “x = #{x}; y = #{y.inspect} ;
z= #{z.inspect}”}’
p “running #{x} using default = 9999”
eval x

p ‘-----------’
x = ‘(1…5).to_a.each_group([1,2]) {|x, y,z| p “x = #{x}; y = #{y.inspect}
; z = #{z.inspect}”}’
p “running #{x} using default an array [1,2]”
eval x
p ‘-----------’
x = ‘(1…2).to_a.each_group({“test”=>1}) {|x, y,z| p “x = #{x}; y =
#{y.inspect} ; z = #{z.inspect}”}’
p ‘running #{x} using default a hash {“test”=>1}’
eval x
p ‘-----------’
x = ‘(1…1).to_a.each_group(“hehehe”) {|x, y,z| p “x = #{x}; y =
#{y.inspect} ; z = #{z.inspect}”}’
p "running #{x} using default a string ‘hehehe’ "
eval x

#and outputs…
C:\family\ruby>ruby a1.rb
“running (1…8).to_a.each_group {|x,y,z| p "x = #{x}; y = #{y.inspect};
z =#{z.inspect}"} using default = nil”
“x = 1; y = 2; z = 3”
“x = 4; y = 5; z = 6”
“x = 7; y = 8; z = nil”
“-----------”
“running (1…7).to_a.each_group(9999) {|x, y,z| p "x = #{x}; y =
#{y.inspect}; z = #{z.inspect}"} using default = 9999”
“x = 1; y = 2 ; z = 3”
“x = 4; y = 5 ; z = 6”
“x = 7; y = 9999 ; z = 9999”
“-----------”
“running (1…5).to_a.each_group([1,2]) {|x, y,z| p "x = #{x}; y =
#{y.inspect} ; z = #{z.inspect}"} using default an array [1,2]”
“x = 1; y = 2 ; z = 3”
“x = 4; y = 5 ; z = [1, 2]”
“-----------”
“running #{x} using default a hash {"test"=>1}”
“x = 1; y = 2 ; z = {"test"=>1}”
“-----------”
"running (1…1).to_a.each_group("hehehe") {|x, y,z| p "x = #{x}; y =
#{y.inspect} ; z = #{z.inspect}"} using default a string ‘hehehe’ "
“x = 1; y = "hehehe" ; z = "hehehe"”

Regards,

Brian.

kind regards -botp

···

Brian Candler [mailto:B.Candler@pobox.com] wrote:

That’s cool, and I hadn’t thought of doing it that way. I still don’t trust
“yield” semantics; i.e. the implicit conversion of multiple arguments to an
array or vice versa. I’d be much happier if you had to do
{ |*i| … }
if you wanted multiple arguments amalgamated into an array.

One other point:

what follows are just testing

x = ‘(1…8).to_a.each_group {|x,y,z| p “x = #{x}; y = #{y.inspect}; z =
#{z.inspect}”}’

Why did you include “to_a”? Enumerable works on iterators without having to
convert them to an explicit array first. For example, you could have a file
with a million lines and process it three lines at a time using

File.open(“/name/of/file”).each_group {|l1,l2,l3| puts “<#{l1}:#{l2}>#{l3}”}

If you did “to_a” it would have to read in the whole file into RAM first.

Regards,

Brian.

···

On Wed, Jul 09, 2003 at 05:56:38PM +0900, “Peña, Botp” wrote:

but why not use #arity for block’s param count, no?

array or vice versa. I'd be much happier if you had to do
           { |*i| ... }
if you wanted multiple arguments amalgamated into an array.

I don't understand : do you want something like this ?

svg% ruby -ve '{1 => 1}.each {|i| p i}'
ruby 1.8.0 (2003-07-03) [i686-linux]
-e:1: warning: multiple values for a block parameter (2 for 1)
        from -e:1
[1, 1]
svg%

svg% ruby -ve '{1 => 1}.each {|*i| p i}'
ruby 1.8.0 (2003-07-03) [i686-linux]
[1, 1]
svg%

Guy Decoux

I guess that would do it :slight_smile: As long as I remembered to set -w …

An exception would be better from my point of view though. I’m doing a lot
of things over DRb; exceptions get nicely forwarded to the client side, but
warnings to stderr stay at the server side and I have to remember to look in
different log files for those.

Also, if I want my code to be warning-free, unit testing doesn’t really help
me catch those cases (i.e. even if the code produces the correct answers,
the warning says I should have written |*i| rather than |i| )

Regards,

Brian.

···

On Wed, Jul 09, 2003 at 06:47:45PM +0900, ts wrote:

array or vice versa. I’d be much happier if you had to do
{ |*i| … }
if you wanted multiple arguments amalgamated into an array.

I don’t understand : do you want something like this ?

svg% ruby -ve ‘{1 => 1}.each {|i| p i}’
ruby 1.8.0 (2003-07-03) [i686-linux]
-e:1: warning: multiple values for a block parameter (2 for 1)
from -e:1

I guess that would do it :slight_smile: As long as I remembered to set -w ...

I've used -v just to show the version

svg% ruby -e '{1 => 1}.each {|i| p i}'
-e:1: warning: multiple values for a block parameter (2 for 1)
        from -e:1
[1, 1]
svg%

An exception would be better from my point of view though.

and break old scripts ?

Guy Decoux

No, I wasn’t suggesting that it be changed now - just that this is one of a
couple of things I wish were different.

Cheers,

Brian.

···

On Wed, Jul 09, 2003 at 07:08:11PM +0900, ts wrote:

An exception would be better from my point of view though.

and break old scripts ?

Is there a way to voluntary make the warnings errors. For example, a
switch on the ruby command line.

Something like:

% ruby -e ‘{1 => 1}.each {|i| p i}’
-e:1: warning: multiple values for a block parameter (2 for 1)
from -e:1
[1, 1]

% ruby -W -e ‘{1 => 1}.each {|i| p i}’
WarningError: multiple values for a block parameter (2 for 1)
from -e:1

How hard would it be to implement?
Guillaume.

···

On Wed, 2003-07-09 at 06:08, ts wrote:

An exception would be better from my point of view though.

and break old scripts ?

Is there a way to voluntary make the warnings errors. For example, a
switch on the ruby command line.

I don't think actually : 1.8.0 has a global function #warn but internally
ruby use rb_warn(), rb_warning()

How hard would it be to implement?

What do you have against warning ? :slight_smile:

Guy Decoux

The fact that the error is not trapped at the earliest possible point, but
may result in a failure downstream (possibly a long way downstream)

···

On Wed, Jul 09, 2003 at 11:43:55PM +0900, ts wrote:

How hard would it be to implement?

What do you have against warning ? :slight_smile:

The fact that the error is not trapped at the earliest possible point, but
may result in a failure downstream (possibly a long way downstream)

a warning is not an error.

Guy Decoux

But it could be an indication of one. You can write your code in such a way,
if you choose, that no warnings are generated. I like the idea of being able
to turn warnings into “hard” errors.

Regards,

Brian.

···

On Wed, Jul 09, 2003 at 11:48:39PM +0900, ts wrote:

The fact that the error is not trapped at the earliest possible point, but
may result in a failure downstream (possibly a long way downstream)

a warning is not an error.

Same idea as when I program in C: I do gcc -Wall … Some warnings are
not actual errors, but of them are and it helps me get my program
straight. But I write in such a way that no warnings are display during
compilation.

That’s what I would do with ruby. During my develpment cycle I would
consider warnings as errors and remove them. In production, leave it as
a warning, no need for the application to crash if not needed…

Guillaume.

···

On Wed, 2003-07-09 at 10:48, ts wrote:

The fact that the error is not trapped at the earliest possible point, but
may result in a failure downstream (possibly a long way downstream)

a warning is not an error.

Guy Decoux