Some questions on ruby - case1

It's this: "tools_info.slice!"

The clue is in the "!". It's a "bang" method, which means it modifies
the receiver.

···

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

You could always use tap if you don't want a local variable hanging
around.

tools_info.slice(3..-1).tap { |tools_info_tmp| other_stuff }

···

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

You can duplicate objects with the #dup method. This creates a copy without introducing a temporary variable. The normal assignment operation just copies a reference, so in your code tools_info refers to the same object instance and not a copy. (Also, I think #clone is an alias of #dup.)

tools_info = tools_info_array[toolName].dup

···

-----Original Message-----
From: ruby-talk [mailto:ruby-talk-bounces@ruby-lang.org] On Behalf Of Previn Lin
Sent: Thursday, October 24, 2013 4:25 AM
To: ruby-talk@ruby-lang.org
Subject: some questions on ruby - case1

##############################
# Case 1
##############################
cat case_1.rb
#!/usr/bin/env ruby

tools_info_array = {
                        'tool_a' => ['tool_a_home', '2009.12-17', 'bin',
{'LD_LIBRARY_PATH' => 'lib'}]
                   }

toolName = 'tool_a'

tools_info = tools_info_array[toolName]

if tools_info.size > 3
        print "\nbefore delete:\n"
        puts "tools_info_array:\n", tools_info_array
        tools_info.slice!(0..2)
        print "\nafter delete:\n"
        puts "tools_info_array:\n", tools_info_array
end

tools_info.each do |xsub|
......
end

run case1.rb get results below:

before delete:
tools_info_array:
{"tool_a"=>["tool_a_home", "2009.12-17", "bin",
{"LD_LIBRARY_PATH"=>"lib"}]}

after delete:
tools_info_array:
{"tool_a"=>[{"LD_LIBRARY_PATH"=>"lib"}]}

Question:
Why modify 'tools_info' cause 'tools_info_array' changed?
Define a temp variable to save tools_info as below, is there other
method can avoid using temp variable, that get 'tools_info' modified but
without influence on 'tools_info_array'?

tools_info_tmp = tools_info.slice(3..-1)
tools_info_tmp.each do |xsub|
......
end

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

Hi WILLS,

Thanks for your help check this issue, now I understand, in ruby, the
default behavior of the array variable is a reference(or name it as a
pointer) to the array(even slice of array), so any change on the contect
of slice will cause the original array value changed, the safe way is
dupicate the slice, or just move the pointer to the start of the slice
data, am I right?

Thanks a lot,
Previn

···

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

Joel Pearson wrote in post #1125477:

It's this: "tools_info.slice!"

The clue is in the "!". It's a "bang" method, which means it modifies
the receiver.

I know this, so I use "!", what I want is modify 'tools_info' but don't
change 'tools_info_array'.

···

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

Another way to handle it is to use #slice instead of #slice! as follows:

  tools_info = tools_info.slice(0..2)

This allows the slice method to do the duplication as well as the slicing.

One way to define bang and non-bang method pairs is to make the safe method duplicate the arguments of the unsafe (bang!) method:

  def some_method!(some_object)
    # do something dangerous to some_object here
  end

  def some_method(some_object)
    some_method!(some_object.dup)
  end

As you can see, some_method does the exact same thing as some_method!, but on a duplicate of the original object. This is an implicit way of the explicit #dup I described before:

  tools_info = tools_info_array[toolName].dup

I suppose it depends on the desired level of code, memory, and processing complexity desired.

Jamal Wills

WILLS, JAMAL A wrote in post #1125494:

Another way to handle it is to use #slice instead of #slice! as follows:

  tools_info = tools_info.slice(0..2)

This doesn't do the same thing as #slice!, the return value is what is
removed, not the remainder.

···

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

Sorry, I'm less familiar with that particular method. In that case, this may work better:

  tools_info = tools_info.dup.slice!(0..2)

Or this:

  tools_info = tools_info.slice(3..-1)

Jamal Wills

···

-----Original Message-----
From: ruby-talk [mailto:ruby-talk-bounces@ruby-lang.org] On Behalf Of Joel Pearson
Sent: Thursday, October 24, 2013 8:38 AM
To: ruby-talk@ruby-lang.org
Subject: Re: RE: some questions on ruby - case1

WILLS, JAMAL A wrote in post #1125494:

Another way to handle it is to use #slice instead of #slice! as follows:

  tools_info = tools_info.slice(0..2)

This doesn't do the same thing as #slice!, the return value is what is
removed, not the remainder.