Inject issue

When I do this:

%w/ap mathn roots facets/.inject :require

whatever is the first item in the list doesn’t get loaded by ‘require’

When I do this:

%w/ap mathn roots facets/.inject 0, :require or .inject(0, :require)

then the first item is also loaded. (the ‘0’ can be essentially
anything)

Is this a bug, or is this the expected operation?

This behavior is consistent across 1.8.7, 1.9.1/2 and jruby using RVM.

On Monday 27 December 2010 17:15:27 jzakiya wrote:

then the first item is also loaded. (the ‘0’ can be essentially
anything)

Is this a bug, or is this the expected operation?

This behavior is consistent across 1.8.7, 1.9.1/2 and jruby using RVM.

This is the expected behaviour. According to the ri documentation for
inject,
the value passed as argument is the initial value used for the
block-local
variable which stores the result and, if you don’t give any, the first
element
of the array will be used as initial value, so the block (or, in your
case,
the method you use instead of the block) is not called on it.

By the way, this is a very strange way to use inject, since you aren’t
actually interested in accumulating the values returned by the block (of
course, assuming this is your actual code). In your case, a simple each
should
work:

%w/ap mathn roots facets/.each{|f| require f}

I hope this helps

Stefano

On Dec 27, 12:10am, jzakiya [email protected] wrote:

When I do this:

%w/ap mathn roots facets/.inject :require

whatever is the first item in the list doesn’t get loaded by ‘require’

Maybe this will help you understand:

%w/ap mathn roots facets/.inject { |memo, i| p memo; p i;
memo.send(:require, i) }

%w/ap mathn roots facets/.inject 0, :require or .inject(0, :require)

then the first item is also loaded. (the ‘0’ can be essentially
anything)

%w/ap mathn roots facets/.inject(0) do |memo, i| p memo; p i;
memo.send(:require, i) }

Is this a bug, or is this the expected operation?

Expected, though it’s an odd way to require libs. Use %/ap
mathn …/.each { |lib| require lib }

On Dec 27, 4:23am, Ryan D. [email protected] wrote:

require “mathn”

…etc…

It REALLY isn’t cleaning anything up to use enumeration there.

I was wondering why these are equivalent:

a=(1…100).inject :+
b=(1…100).inject 0, :+

but these aren’t

%w/lib1 lib2 lib3/.inject :require
%w/lib1 lib2 lib3/.inject 0, :require

On Dec 27, 2:10am, jzakiya [email protected] wrote:

then the first item is also loaded. (the ‘0’ can be essentially
anything)

Is this a bug, or is this the expected operation?

This behavior is consistent across 1.8.7, 1.9.1/2 and jruby using RVM.

It’s clearer to use fences.

%w(ap mathn roots facets).each{|s| require s}

On Dec 27, 2010, at 00:55 , Skye Shaw!@#$ wrote:

Is this a bug, or is this the expected operation?

Expected, though it’s an odd way to require libs. Use %/ap
mathn …/.each { |lib| require lib }

Even better, use simple code for simple problems:

require “ap”
require “mathn”

…etc…

It REALLY isn’t cleaning anything up to use enumeration there.

On Dec 27, 12:46pm, w_a_x_man [email protected] wrote:

When I do this:
anything)

Is this a bug, or is this the expected operation?

This behavior is consistent across 1.8.7, 1.9.1/2 and jruby using RVM.

It’s clearer to use fences.

%w(ap mathn roots facets).each{|s| require s}

Why question is on the operation of ‘inject’.

Are these different:

%w/lib1 lib2 lib3/.inject :require
%w/lib1 lib2 lib3/.inject 0, :require

because ‘require’ operates on one item at a time
whereas these are equivalent:

(1…100).inject :+
(1…100).inject 0, :+

because ‘+’ operates on two items at a time?

Again, my focus in why ‘inject’ behaves differently under these two
examples.

Good Morning,

On Mon, Dec 27, 2010 at 9:25 AM, jzakiya [email protected] wrote:

I was wondering why these are equivalent:

a=(1…100).inject :+
b=(1…100).inject 0, :+

Those are equivalent by luck only. With inject if you fail to provide the
initial “value” (as you do in the first line) then the first element of
the
collection is used (in the first line it would be 1).

So, for example if you used :* or :- instead of :+ for your two rows you
would see a different result for the two rows - using :* would return a
very
large number for the first row and zero for the second row (the second
row
would just keep multiplying numbers by 0 which always equals 0). For :-
you
would have something like -5049 and the second row would be -5050 (or
something close to that).

In the example you provided your second row uses 0 as the initial value
which means after processing the first element of the collection you are
in
the same position as not having provided the value, as the first row
does,
because 1 = 0 + 1.

John

On Dec 27, 2010, at 09:25 , jzakiya wrote:

require “ap”
but these aren’t

%w/lib1 lib2 lib3/.inject :require
%w/lib1 lib2 lib3/.inject 0, :require

1887 % ri Enumerable.inject
= Enumerable.inject

(from ruby core)

enum.inject(initial, sym) => obj
enum.inject(sym) => obj
enum.inject(initial) {| memo, obj | block } => obj
enum.inject {| memo, obj | block } => obj


enum.reduce(initial, sym) => obj
enum.reduce(sym) => obj
enum.reduce(initial) {| memo, obj | block } => obj
enum.reduce {| memo, obj | block } => obj

Combines all elements of enum by applying a binary operation,
specified by a block or a symbol that names a method or operator.

If you specify a block, then for each element in enum
the block is passed an
accumulator value
(memo) and the element. If you specify a symbol instead,
then each element in the collection will be passed to the named method
of
memo. In either case, the result becomes the new value for
memo. At the end of the iteration, the final value of memo is
the return value fo the method.

If you do not explicitly specify an initial value for
memo, then uses the first element of collection is used as the initial
value of memo.

Examples:

Sum some numbers

(5…10).reduce(:+) #=> 45

Same using a block and inject

(5…10).inject {|sum, n| sum + n } #=> 45

Multiply some numbers

(5…10).reduce(1, :*) #=> 151200

Same using a block

(5…10).inject(1) {|product, n| product * n } #=> 151200

find the longest word

longest = %w{ cat sheep bear }.inject do |memo,word|
memo.length > word.length ? memo : word
end
longest #=> “sheep”

jzakiya wrote in post #970917:

because ‘require’ operates on one item at a time
whereas these are equivalent:

(1…100).inject :+
(1…100).inject 0, :+

because ‘+’ operates on two items at a time?

No. The two forms differ as follows:

(1…100).inject 0, :+

starts with accumulator of 0
then calls :+, 1
then calls :+, 2

then calls :+, 100

(1…100).inject :+

starts with accumulator of 1 (i.e. the first element)
then calls :+, 2
then calls :+, 3

then calls :+, 100

Again, my focus in why ‘inject’ behaves differently under these two
examples.

Inject with an initial value applies the given block to each element.
Originally, this was the only form of inject available.

The newer alternative, of inject without an initial value, takes the
first value of the enumeration as the initial value. Hence the block is
only called for the second to last values.

On Mon, Dec 27, 2010 at 11:25 AM, jzakiya [email protected] wrote:

require “ap”
but these aren’t

%w/lib1 lib2 lib3/.inject :require
%w/lib1 lib2 lib3/.inject 0, :require

The point of inject is to push some value through all of the elements.
You
just want to iterate over them, which is the #each method.

Since inject wants to push something through the elements, you have to
give
it the initial value of the object to push through. In your second
example,
you give zero for the initial value. In the one before that, you do not
give
it zero. This causes it to use the first element. Then it invokes the
plus
on that element, and passes the next element. The result is then pushed
through for the next iteration.

So when you try injecting with numbers and plus, you get
(1…3).inject(0,:+) expands to (((0+1)+2)+3)
(1…3).inject(:+) expands to ((1+2)+3)

Which have the same value.

But when you try that with require, you get
%w/lib1 lib2 lib3/.inject(0, :require) expands to (((0.require
‘lib1’).require ‘lib2’).require ‘lib3’)
%w/lib1 lib2 lib3/.inject(:require) expands to ((‘lib1’.require
‘lib2’).require ‘lib3’)

Which doesn’t even make sense. require belongs to Kernel, and we want to
invoke it as if it were a function, not a method on 0 or the string
“lib1”
or the boolean value that would be returned if require were properly
executed. So you can see that inject is about repeatedly passing the
next
element to the result of the previous, using the specified method. Thus
some
value gets “pushed through” (at least that is how I think about it in my
brain), but you are just trying to pass each element to the require
“function”. For that, you would use each, and pass a block instead of a
symbol. %w(lib1 lib2 lib3).each { |lib| require lib }