Map (collect) not doing what it should

example 1 works, I tried to avoid being repetitive and I got example 2
which doesn't work. I am using Ruby 1.9.3

···

#--------------------------------------------
#example 1

def do_something(x)
  x.upcase
# .upcase is just for this example, I use far more complicated
# function in my code
end

my_array = ["aaa", "bbb", "ccc"]

a, b, c = my_array

a = do_something(a)
b = do_something(b)
c = do_something(c)

puts "a = " + a
puts "b = " + b
puts "c = " + c

#output:
# a = AAA
# b = BBB
# c = CCC
#--------------------------------------------
#example 2

def do_something(x)
  x.upcase
end

my_array = ["aaa", "bbb", "ccc"]

a, b, c = my_array

[a,b,c].map! { |x| x = do_something(x) }

puts "a = " + a
puts "b = " + b
puts "c = " + c

#output:
# a = aaa
# b = bbb
# c = ccc
#--------------------------------------------
#example 3

def do_something(x)
  x.upcase
end

x = ["aaa", "bbb", "ccc"]

x.map! { |n| do_something(n) }

puts x.inspect
#---------------------------------------------

Example 3 also works as expected ... whats wrong with example 2 ?!?

--
Posted via http://www.ruby-forum.com/.

You're mapping the array containing a,b, and c; but you don't keep that
array.

···

--
Posted via http://www.ruby-forum.com/.

what do you know,
a,b,c = [a,b,c].map! { |x| x = do_something(x) }
actually works

I tried:
[a,b,c] = [a,b,c].map! { |x| x = do_something(x) }
but it returned error

There's so many little stuff you gotta know, I wasted whole 2 hours on
this "problem" :frowning:

I thought since I used explicit method map! that it will alter value of
each separate variable that's member of that array, but apparently it
doesn't

a = 5
[a].map! {|x| x*2 }
#=> [10]

puts a
#=> 5

···

--
Posted via http://www.ruby-forum.com/.

I don't want to upcase, that was just example.
What I am trying to do is to make this shorter:

···

#--------------------
a = do_something(a)
b = do_something(b)
c = do_something(c)
.
.
.
z = do_something(z)
#--------------------

So far, the best solution I have is:
#-------------------------------------------------------------
a,b,c ... z = [a,b,c ... z].map {|x| x = do_something(x)}
#-------------------------------------------------------------

I'm not sure if it could be made even more shorter and simple

--
Posted via http://www.ruby-forum.com/.

Are you able to provide an excerpt from your real code? Perhaps a
larger-scale refactoring is in order.

···

--
Posted via http://www.ruby-forum.com/.

haha, I don't really have 26 variables ... I have only three ... but I
sort of wanted to know theoretically, if there is a shorter way to do:

a = do_something(a)
b = do_something(b)
c = do_something(c)

because of DRY principle of programming I've been reading everywhere.

Sorry for being inconclusive when formulating my original post. I'd
gladly post original chunks of my code, but they are not in english, so
I thought I would get better response here if I simplify example with
english names for variables, methods etc

···

--
Posted via http://www.ruby-forum.com/.

fixnum * integer --> numberic_result
#it's mean in this case: map! equal map
#notify: "!" dosen't take effect anywhere,somewhere haven't implements
"!",if u want to use it, u need to implement it by urself first. or
change another way, such as: fixnum << 1

for detail, see the doc about "fixnum"

···

--
Posted via http://www.ruby-forum.com/.

Having that many variables is a design smell, esp when it seems that they don't really mean anything and you have to act across them in a uniform way.

data = {...}

data.each do |key, val|
  data[key] = do_something val
end

···

On Dec 5, 2013, at 11:59, Stu P. D'naim <lists@ruby-forum.com> wrote:

a,b,c ... z = [a,b,c ... z].map {|x| x = do_something(x)}

I thought since I used explicit method map! that it will alter value of
each separate variable that's member of that array, but apparently it
doesn't

a = 5
[a].map! {|x| x*2 }
#=> [10]

puts a
#=> 5

It does, what it should:

a = [5]
puts a.map! {|x| x*2 }
#=> 10

puts a
#=> 10

···

--
Posted via http://www.ruby-forum.com/\.

Fixnum objects are immutable, ie. they never change.
Try with an array of strings:

a = "+"
[a].map {|x| x << "+" }
=> "++"

a
=> "++"

Note that there is no need to use #map!, as you don't
store your array anywhere. If you're not even going to
use the return value of #map you may as well use #each
instead.

The difference between #map and #map! becomes apparent
with this example:

array = [1, 2, 3]

array.map {|x| x + 1 }
=> [2, 3, 4]

array
=> [1, 2, 3] # map hasn't changed the array

array.map! {|x| x + 1 }
=> [2, 3, 4]

array
=> [2, 3, 4] # map! did change the array

···

On Thu, Dec 5, 2013, at 16:11, Stu P. D'naim wrote:

what do you know,
a,b,c = [a,b,c].map! { |x| x = do_something(x) }
actually works

I tried:
[a,b,c] = [a,b,c].map! { |x| x = do_something(x) }
but it returned error

There's so many little stuff you gotta know, I wasted whole 2 hours on
this "problem" :frowning:

I thought since I used explicit method map! that it will alter value of
each separate variable that's member of that array, but apparently it
doesn't

a = 5
[a].map! {|x| x*2 }
#=> [10]

puts a
#=> 5

--
Lars Haugseth

You want String#upcase! and Array#each then, because apparently you
want to change String instances in place:

irb(main):001:0> my_array = ["aaa", "bbb", "ccc"]
=> ["aaa", "bbb", "ccc"]
irb(main):002:0> my_array.each {|s| s.upcase!}
=> ["AAA", "BBB", "CCC"]
irb(main):003:0> my_array
=> ["AAA", "BBB", "CCC"]

Even shorter without a block:

irb(main):004:0> my_array = ["aaa", "bbb", "ccc"]
=> ["aaa", "bbb", "ccc"]
irb(main):005:0> my_array.each(&:upcase!)
=> ["AAA", "BBB", "CCC"]
irb(main):006:0> my_array
=> ["AAA", "BBB", "CCC"]

Kind regards

robert

···

On Thu, Dec 5, 2013 at 4:11 PM, Stu P. D'naim <lists@ruby-forum.com> wrote:

what do you know,
a,b,c = [a,b,c].map! { |x| x = do_something(x) }
actually works

I tried:
[a,b,c] = [a,b,c].map! { |x| x = do_something(x) }
but it returned error

There's so many little stuff you gotta know, I wasted whole 2 hours on
this "problem" :frowning:

I thought since I used explicit method map! that it will alter value of
each separate variable that's member of that array, but apparently it
doesn't

a = 5
[a].map! {|x| x*2 }
#=> [10]

puts a
#=> 5

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

["aaa", "bbb", "ccc"].each do |something|
  /clean your room/
end

=)

···

On Thu, Dec 5, 2013 at 6:40 PM, Stu P. D'naim <lists@ruby-forum.com> wrote:

haha, I don't really have 26 variables ... I have only three ... but I
sort of wanted to know theoretically, if there is a shorter way to do:

a = do_something(a)
b = do_something(b)
c = do_something(c)

because of DRY principle of programming I've been reading everywhere.

Sorry for being inconclusive when formulating my original post. I'd
gladly post original chunks of my code, but they are not in english, so
I thought I would get better response here if I simplify example with
english names for variables, methods etc

--
Posted via http://www.ruby-forum.com/\.

what do you know,
a,b,c = [a,b,c].map! { |x| x = do_something(x) }
actually works

I tried:
[a,b,c] = [a,b,c].map! { |x| x = do_something(x) }
but it returned error

There's so many little stuff you gotta know, I wasted whole 2 hours on
this "problem" :frowning:

I thought since I used explicit method map! that it will alter value of
each separate variable that's member of that array, but apparently it
doesn't

a = 5
[a].map! {|x| x*2 }
#=> [10]

puts a
#=> 5

There is a fundamental misunderstanding here of how Ruby variables work.

> a,b,c = [a,b,c].map! { |x| x = do_something(x) }

^- this is working because you are reassigning to a, b, and c. The "x = ..." does nothing, it's assigning to the local variable "x" inside the block. Coincidentally, the result of an assignment is the value assigned. This value happens to be returned by the block because it is the last expression in the block. After calling #map!, the array contains the results of calling do_something on each variable. As noted elsewhere, though, #map would work just as well in this case because the array is never explicitly stored anywhere.

The contents of the array are assigned back to a, b, and c in the assignment expression. Ruby matches the variables to values in the array by position. In other words, "c, b, a = [a,b,c].map! { ... }" would have a different result.

Each time the block is called, a new local variable "x" is created which refers to the value of an element from the array. It does _not_ refer to the variables "a, b, c". In fact, there is no way to get at those variables from the array, because the array just contains the values referred to by those variables. The values don't know what variables refer to them.

Consider this:

$ irb
2.0.0p247 :001 > a = 1
  => 1
2.0.0p247 :002 > b = a
  => 1
2.0.0p247 :003 > b
  => 1
2.0.0p247 :004 > a = 2
  => 2
2.0.0p247 :005 > b
  => 1

In Ruby assignments, the right-hand side is always a value. The left-hand side is a name/label/variable. Variables refer to values, not other variables. So you cannot hand a variable to a method or block and change the value it refers to. Occasionally you can _modify_ the value itself, but that is not the same as changing which value the variable is referring to.

Hope that clarifies a little bit.

-Justin

···

On 12/05/2013 07:11 AM, Stu P. D'naim wrote: