# A method that doesn't change its arguments

**URL:** <https://www.ruby-forum.com/t/a-method-that-doesnt-change-its-arguments/178631>\
**Category:** Ruby\
**Created:** [November 8, 2009, 11:40am UTC](https://www.ruby-forum.com/t/a-method-that-doesnt-change-its-arguments/178631 "2009-11-08T11:40:43Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Timo\_J](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/d07c76/32.png) [@Timo\_J](https://www.ruby-forum.com/u/Timo_J)\
**Post date:** [November 8, 2009, 11:40am UTC](https://www.ruby-forum.com/t/a-method-that-doesnt-change-its-arguments/178631/1 "2009-11-08T11:40:43Z")

</div>

At the moment I’m doing something like this:

def some\_method(array1)  
…  
array2 = array1.clone  
…  
array2.delete\_at(i)  
…  
return array2  
…  
end

I would like array1 to remain unchanged. It seems a little inefficient  
to clone array1 every time some\_method is called. Is there a more  
elegant solution?

---

<div class="post-metadata">

**Author:** ![Timo\_J](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/d07c76/32.png) [@Timo\_J](https://www.ruby-forum.com/u/Timo_J)\
**Post date:** [November 8, 2009, 12:45pm UTC](https://www.ruby-forum.com/t/a-method-that-doesnt-change-its-arguments/178631/2 "2009-11-08T12:45:41Z")

</div>

> I would like array1 to remain unchanged. It seems a little inefficient  
> to clone array1 every time some\_method is called.

If your code is slow, it’s not because of this use of clone. If your  
code isn’t, don’t bother.

---

<div class="post-metadata">

**Author:** ![Timo\_J](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/d07c76/32.png) [@Timo\_J](https://www.ruby-forum.com/u/Timo_J)\
**Post date:** [November 8, 2009, 1:03pm UTC](https://www.ruby-forum.com/t/a-method-that-doesnt-change-its-arguments/178631/3 "2009-11-08T13:03:14Z")

</div>

lith wrote:

> > I would like array1 to remain unchanged. It seems a little inefficient  
> > to clone array1 every time some\_method is called.
> 
> If your code is slow, it’s not because of this use of clone. If your  
> code isn’t, don’t bother.

“Inefficient” can also refer to memory. If the array has 4 million  
entries, to copy it 100 times might be considered inefficient in that  
sense.

How about something like this:

class MyArray  
include Enumerable

def MyArray.init(arr)  
@@arr = arr  
end

def initialize  
@deleted = {}  
end

def delete\_at(i)  
@deleted[i] = true  
end

def each  
@@arr.each\_with\_index do |elmt, i|  
next if @deleted[i]  
yield elmt  
end  
end

def get\_arr  
out = []

```
@@arr.each_with_index do |elmt, i|
  next if @deleted[i]
  out << elmt
end

out

```

end  
end

MyArray.init [“banana”, “strawberry”, “apple”]  
data1 = MyArray.new  
data2 = MyArray.new

data1.delete\_at(0)  
data2.delete\_at(1)

p data1.get\_arr  
puts “------”  
p data2.get\_arr  
puts

search1 = data1.select do |elmt|  
elmt.length \> 5  
end  
p search1

puts “Found apple.” if data2.include? “apple”

## –output:– [“strawberry”, “apple”]

[“banana”, “apple”]

[“strawberry”]  
Found apple.

---

<div class="post-metadata">

**Author:** ![Timo\_J](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/d07c76/32.png) [@Timo\_J](https://www.ruby-forum.com/u/Timo_J)\
**Post date:** [November 8, 2009, 1:39pm UTC](https://www.ruby-forum.com/t/a-method-that-doesnt-change-its-arguments/178631/4 "2009-11-08T13:39:32Z")

</div>

> “Inefficient” can also refer to memory. If the array has 4 million  
> entries, to copy it 100 times might be considered inefficient in that  
> sense.

Well, maybe you shouldn’t use an array then anyway – which is more or  
less what you’re doing by introducing a layer of indirection.

BTW how does your approach behave if you delete 4 million from  
MyArray? I’d rather go for something tree-like and exchange selected  
branches, I guess.

---

<div class="post-metadata">

**Author:** ![Timo\_J](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/d07c76/32.png) [@Timo\_J](https://www.ruby-forum.com/u/Timo_J)\
**Post date:** [November 8, 2009, 1:20pm UTC](https://www.ruby-forum.com/t/a-method-that-doesnt-change-its-arguments/178631/5 "2009-11-08T13:20:13Z")

</div>

On Sun, Nov 8, 2009 at 7:40 PM, Timo J. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> end
> 
> I would like array1 to remain unchanged. It seems a little inefficient  
> to clone array1 every time some\_method is called. Is there a more  
> elegant solution?

Couldn’t you do something like this?

arr1 = (“a”…“j”).to\_a  
i = 3  
p arr1[0…i]+arr1[i+1…-1] #\> [“a”, “b”, “c”, “e”, “f”, “g”, “h”,  
“i”, “j”]

Harry

---

<div class="post-metadata">

**Author:** ![Timo\_J](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/d07c76/32.png) [@Timo\_J](https://www.ruby-forum.com/u/Timo_J)\
**Post date:** [November 8, 2009, 3:25pm UTC](https://www.ruby-forum.com/t/a-method-that-doesnt-change-its-arguments/178631/6 "2009-11-08T15:25:27Z")

</div>

On Nov 8, 3:38Â am, Timo J. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> end
> 
> I would like array1 to remain unchanged. It seems a little inefficient  
> to clone array1 every time some\_method is called. Â Is there a more  
> elegant solution?

Could you clarify what you’re trying to do? What you’ve shown is a  
method that takes an array and then returns a slightly modified  
version. If you don’t want the original to be modified, what’s your  
other option?

Are you aware that array duplication is a ‘shallow’ operation? All  
you’re doing is (efficiently) copying a list of references to objects,  
not the objects themselves. As lith â‰ˆwrote, avoid premature  
optimization. You may be spending your time and ours on a complete non-  
issue.

---

<div class="post-metadata">

**Author:** ![Timo\_J](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/d07c76/32.png) [@Timo\_J](https://www.ruby-forum.com/u/Timo_J)\
**Post date:** [November 9, 2009, 2:09am UTC](https://www.ruby-forum.com/t/a-method-that-doesnt-change-its-arguments/178631/7 "2009-11-09T02:09:19Z")

</div>

On Sun, 08 Nov 2009 19:40:08 +0900, Timo J. wrote:

> end
> 
> I would like array1 to remain unchanged. It seems a little inefficient  
> to clone array1 every time some\_method is called. Is there a more  
> elegant solution?

If you’re comfortable with the idea of using completely immutable lists,  
and not changing any of the elements of the list, an implementation of  
efficiently catenable lists (such as that described in “Purely  
Functional  
Data Structures”) might be in order.

---

<div class="post-metadata">

**Author:** ![Timo\_J](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/d07c76/32.png) [@Timo\_J](https://www.ruby-forum.com/u/Timo_J)\
**Post date:** [November 8, 2009, 5:46pm UTC](https://www.ruby-forum.com/t/a-method-that-doesnt-change-its-arguments/178631/8 "2009-11-08T17:46:31Z")

</div>

On Sun, Nov 8, 2009 at 6:38 AM, lith [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> 

Arrays in Ruby get unbearably slow when you get into the millions, it  
would  
definitely be worth considering alternative implementations at that  
point.

require ‘benchmark’

def remove\_1millionth\_index(old\_ary)  
new\_ary = old\_ary.clone  
new\_ary.delete\_at 1\_000\_000  
new\_ary  
end

ary = Array(1…4\_000\_000)

Benchmark.bm do |b|  
b.report {  
100.times do  
remove\_1millionth\_index ary  
end  
}  
end

# ================= output =================

# user system total real

# 7.875000 0.938000 8.813000 ( 8.984000)
