Tuples/Records/Quicky Objects + Read Only Arrays?

Discussion in 'Ruby' started by Christopher Campbell, Jan 1, 2006.

  1. 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
    Christopher Campbell, Jan 1, 2006
    #1
    1. Advertising

  2. Christopher Campbell 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.

    --
    http://flgr.0x42.net/
    Florian Groß, Jan 1, 2006
    #2
    1. Advertising

  3. On 12/31/05, Christopher Campbell <> 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.
    >
    > 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 =3D 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.
    >
    >


    The Ruby equivalent of a tuple is pretty much an Array, since the
    syntax is so lightweight.
    a =3D [1, 2]
    a.first =3D=3D 1
    a.last =3D=3D 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 =3D {}
    @aliases =3D {}
    end

    def <<(pair)
    @names[pair.first] =3D pair.last
    @aliases[pair.last] =3D 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 =3D FunBox.new
    =3D> #<FunBox:0x2e15f00 @aliases=3D{}, @names=3D{}>
    irb(main):061:0> f<<['joe', 'jim']
    =3D> "joe"
    irb(main):062:0> f.alias_for_name('joe')
    =3D> "jim"
    irb(main):063:0> f.name_for_alias('jim')
    =3D> "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
    Wilson Bilkovich, Jan 1, 2006
    #3
  4. Christopher Campbell <> 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.

    > 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.


    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
    Robert Klemme, Jan 1, 2006
    #4
  5. 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.
    Christopher Campbell, Jan 1, 2006
    #5
  6. Christopher Campbell <> wrote:
    > 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.


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

    robert
    Robert Klemme, Jan 1, 2006
    #6
  7. Robert Klemme wrote:
    > Christopher Campbell <> wrote:
    >> 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.

    >
    > 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
    Christopher Campbell, Jan 1, 2006
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. =?Utf-8?B?anNhbGU=?=

    Session Quicky

    =?Utf-8?B?anNhbGU=?=, Dec 20, 2004, in forum: ASP .Net
    Replies:
    1
    Views:
    311
    Hans Kesting
    Dec 20, 2004
  2. Replies:
    5
    Views:
    534
    Thomas J. Gritzan
    Oct 6, 2006
  3. tuples within tuples

    , Oct 26, 2007, in forum: Python
    Replies:
    12
    Views:
    538
    Dennis Lee Bieber
    Oct 27, 2007
  4. xera121
    Replies:
    8
    Views:
    696
    lolmc
    Sep 30, 2009
  5. Jon Reyes
    Replies:
    18
    Views:
    206
    Mitya Sirenef
    Feb 19, 2013
Loading...

Share This Page