# Tuples/Records/Quicky Objects + Read Only Arrays?

**URL:** <https://www.ruby-forum.com/t/tuples-records-quicky-objects-read-only-arrays/55595>\
**Category:** Ruby\
**Created:** [January 1, 2006, 2:45am UTC](https://www.ruby-forum.com/t/tuples-records-quicky-objects-read-only-arrays/55595 "2006-01-01T02:45:39Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![chriscauser](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/65b543/32.png) [@chriscauser](https://www.ruby-forum.com/u/chriscauser)\
**Post date:** [January 1, 2006, 2:45am UTC](https://www.ruby-forum.com/t/tuples-records-quicky-objects-read-only-arrays/55595/1 "2006-01-01T02:45:39Z")

</div>

Hi,

Does Ruby have a tuple or quicky object mechanism? I’m new to Ruby and  
have become stuck on how to solve the following.

I’m testing adding items to a container, where each item is a pair of  
strings. One is a name and another an alias. As they’re added a check  
should be performed to see if they’re in the container, etc.

I’ve been using OCaml for a while, and for this I’d just use a list of  
tuples of strings. What’s the ruby way of doing this? Iterating over  
a container/array is a doddle, that’s not the problem. The problem is  
really can you have quick pairs without making classes and so on?

While I’m at it, is there a read only array like container? Don’t want  
anyone messing with the internal array, they should not know that what’s  
returned is actually the internal representation or fiddle with it.  
Don’t care what they do with the elements in the array, only the array  
itself.

class X  
def initialize  
@elements = Array.new  
end

…

def elements  
@elements.clone  
end  
end

Returning a clone of an array is fine, just wondered if you could  
“write-protect” stuff in general.

Thanks,  
Chris

---

<div class="post-metadata">

**Author:** ![chriscauser](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/65b543/32.png) [@chriscauser](https://www.ruby-forum.com/u/chriscauser)\
**Post date:** [January 1, 2006, 3:15am UTC](https://www.ruby-forum.com/t/tuples-records-quicky-objects-read-only-arrays/55595/2 "2006-01-01T03:15:42Z")

</div>

Christopher C. wrote:

> Returning a clone of an array is fine, just wondered if you could  
> “write-protect” stuff in general.

Just use Object#freeze. Note that you will not usually be able to change  
objects once they have become frozen.

---

<div class="post-metadata">

**Author:** ![chriscauser](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/65b543/32.png) [@chriscauser](https://www.ruby-forum.com/u/chriscauser)\
**Post date:** [January 1, 2006, 5:21am UTC](https://www.ruby-forum.com/t/tuples-records-quicky-objects-read-only-arrays/55595/3 "2006-01-01T05:21:52Z")

</div>

On 12/31/05, Christopher C. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> tuples of strings. What’s the ruby way of doing this? Iterating over  
> def initialize  
> Returning a clone of an array is fine, just wondered if you could  
> “write-protect” stuff in general.

The Ruby equivalent of a tuple is pretty much an Array, since the  
syntax is so lightweight.  
a = [1, 2]  
a.first == 1  
a.last == 2

Possibly due to champagne, I can’t think of a built-in object that  
behaves the way you want… but luckily, a quick implementation of it  
shouldn’t be hard:  
class FunBox  
def initialize  
@names = {}  
@aliases = {}  
end

def \<\<(pair)  
@names[pair.first] = pair.last  
@aliases[pair.last] = pair.first  
end

def alias\_for\_name(n)  
@names[n]  
end

def name\_for\_alias(a)  
@aliases[a]  
end  
end

irb(main):060:0\> f = FunBox.new  
=\> #\<FunBox:0x2e15f00 @aliases={}, @names={}\>  
irb(main):061:0\> f\<\<[‘joe’, ‘jim’]  
=\> “joe”  
irb(main):062:0\> f.alias\_for\_name(‘joe’)  
=\> “jim”  
irb(main):063:0\> f.name\_for\_alias(‘jim’)  
=\> “joe”  
irb(main):064:0\>

Of course, given that you know OCaml, I’m probably telling you exactly  
nothing you don’t know.  
I’m not aware of a way to freeze instance variables, such that you  
couldn’t still change them with Object#instance\_variable\_set

---

<div class="post-metadata">

**Author:** ![chriscauser](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/65b543/32.png) [@chriscauser](https://www.ruby-forum.com/u/chriscauser)\
**Post date:** [January 1, 2006, 6:15pm UTC](https://www.ruby-forum.com/t/tuples-records-quicky-objects-read-only-arrays/55595/4 "2006-01-01T18:15:23Z")

</div>

Christopher C. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Hi,
> 
> Does Ruby have a tuple or quicky object mechanism? I’m new to Ruby  
> and have become stuck on how to solve the following.

Easiest is to use arrays. But you can as well use a Struct:

> > Tuple=Struct.new :name, :alias  
> > =\> Tuple  
> > t1=Tuple.new(“name”, “alias”).freeze  
> > =\> #\<struct Tuple name=“name”, alias=“alias”\>  
> > t2=Tuple.new(“name”, “alias”).freeze  
> > =\> #\<struct Tuple name=“name”, alias=“alias”\>  
> > t1.name = “changed?”  
> > TypeError: can’t modify frozen Struct  
> > from (irb):14:in `name=’  
> > from (irb):14  
> > from ?:0  
> > t1 == t2  
> > =\> true

> I’m testing adding items to a container, where each item is a pair of  
> strings. One is a name and another an alias. As they’re added a  
> check should be performed to see if they’re in the container, etc.

I guess you rather want a Set so no multiple insertions can occur.  
Alternatively you can use a Hash with your tuple as key if there is a  
meaningful value.

> end
> 
> Returning a clone of an array is fine, just wondered if you could  
> “write-protect” stuff in general.

Use #freeze as Florian pointed out.

> > require ‘set’  
> > =\> true  
> > container = Set.new  
> > =\> #\<Set: {}\>  
> > container \<\< [“name”, “alias”].freeze  
> > =\> #\<Set: {[“name”, “alias”]}\>  
> > container \<\< [“name”, “alias”].freeze  
> > =\> #\<Set: {[“name”, “alias”]}\>  
> > container \<\< [“no name”, “alias”].freeze  
> > =\> #\<Set: {[“name”, “alias”], [“no name”, “alias”]}\>  
> > container.each {|nm,al| print “name=”, nm, " alias=“, al,”\n"}  
> > name=name alias=alias  
> > name=no name alias=alias  
> > =\> #\<Set: {[“name”, “alias”], [“no name”, “alias”]}\>  
> > container.each {|a| a \<\< “does not work”}  
> > TypeError: can’t modify frozen array  
> > from (irb):7:in `<<' from (irb):7 from /usr/lib/ruby/1.8/set.rb:189:in `each’  
> > from /usr/lib/ruby/1.8/set.rb:189:in `each’  
> > from (irb):7  
> > from :0

HTH

Kind regards

```
robert

```

---

<div class="post-metadata">

**Author:** ![chriscauser](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/65b543/32.png) [@chriscauser](https://www.ruby-forum.com/u/chriscauser)\
**Post date:** [January 1, 2006, 7:00pm UTC](https://www.ruby-forum.com/t/tuples-records-quicky-objects-read-only-arrays/55595/5 "2006-01-01T19:00:34Z")

</div>

Thanks guys.

I see now we can use arrays and hashes to get

[{‘name’ =\> ‘hi’, ‘c\_alias’ =\> ‘c\_hi’}]

or

[{:name =\> ‘hi’, :c\_alias =\> ‘c\_hi’}]

which works dandy. I think my brain evaporated with the festivities  
last night, heh.

---

<div class="post-metadata">

**Author:** ![chriscauser](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/65b543/32.png) [@chriscauser](https://www.ruby-forum.com/u/chriscauser)\
**Post date:** [January 1, 2006, 7:18pm UTC](https://www.ruby-forum.com/t/tuples-records-quicky-objects-read-only-arrays/55595/6 "2006-01-01T19:18:36Z")

</div>

Christopher C. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> which works dandy. I think my brain evaporated with the festivities  
> last night, heh.

Are you sure you recovered? I mean, what’s the point in stuffing a hash  
into a one element array?

```
robert

```

---

<div class="post-metadata">

**Author:** ![chriscauser](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/65b543/32.png) [@chriscauser](https://www.ruby-forum.com/u/chriscauser)\
**Post date:** [January 1, 2006, 8:00pm UTC](https://www.ruby-forum.com/t/tuples-records-quicky-objects-read-only-arrays/55595/7 "2006-01-01T20:00:44Z")

</div>

Robert K. wrote:

> > which works dandy. I think my brain evaporated with the festivities  
> > last night, heh.
> 
> Are you sure you recovered? I mean, what’s the point in stuffing a hash  
> into a one element array?

Heh… it was just an example, I will be stuffing lots of hashes into an  
array.

def test\_add\_many\_aliased  
sample = [{:name =\> “abc”, :c\_alias =\> “c\_abc”},  
{:name =\> “hoop”, :c\_alias =\> “c\_hoop”},  
{:name =\> “blah”, :c\_alias =\> “c\_blah”}]  
elist = EnumList.new(“many\_aliased”)

```
 sample.each_index {|e| elist.add_alias(sample[e][:name],
                                        sample[e][:c_alias])
                        assert_equal(sample[e][:name], 

```

elist[e].name)  
assert\_equal(sample[e][:c\_alias],  
elist[e].c\_alias)}  
end
