How each class splats

Discussion in 'Ruby' started by Trans, Sep 26, 2005.

  1. Trans

    Trans Guest

    First I'll just ask it there's a way to do this WITHOUT redefining
    #each in Array.

    class A
    def initialize(i,v)
    @i,@v=i,v
    end
    end

    arrayofA = [ A.new:)a,1), A.new:)b,2) ]

    arrayofA.each { |e| p e }
    => #<A @i=:a,@v=1>
    #<A @i=:b,@v=2>

    arrayofA.each { |i,v| p i,v }
    => :a
    1
    :b
    2

    If thsi is not possible, what do people think of allowing a class to
    define a #splat method to determine how it will splat into an each
    block (and perhaps other things).

    class A
    def initialize(i,v)
    @i,@v=i,v
    end
    def splat( arity )
    case arity
    when 1 then self
    when 2 then [@i,@v]
    else
    [@i,@v].concat( [nil]*(arity-2) )
    end
    end
    end

    Or something to that effect.

    Thanks,
    T.
     
    Trans, Sep 26, 2005
    #1
    1. Advertisements

  2. Well, you could do this:

    class B < Array
    def initialize(i,v)
    self[0] = @i = i
    self[1] = @v = v
    end
    end

    But I think your best bet is define your own Collection object with its
    own #each.

    Devin

    Interesting sidenote (endnote?): Operator precedence causes this:
    self[0], self[1] = @i, @v = i, v
    To set self[1] = @i, and @v = i, and to return the Array containing
    self[0], self[1], @v, and v. If you want to do a silly thing like chain
    parallel assignments, you have to add parens:
    self[0], self[1] = (@i, @v = i, v)
    But then again, that's what you get for trying to write code that's
    painful to read.
     
    Devin Mullins, Sep 26, 2005
    #2
    1. Advertisements

  3. I though so, too, but it doesn't help:

    13:13:33 [~]: irbs
    1
    2
    #<struct A i=1, v=2>
    nil
    #<struct A i=3, v=4>
    nil
    #<struct A i=1, v=2>
    nil
    #<struct A i=3, v=4>
    nil
    [#<struct A i=1, v=2>]
    [#<struct A i=3, v=4>]
    [/QUOTE]
    => 2

    In other words, it's not sufficient to be Enumerable to automatically be
    assigned to individual variables in this scenario. You must have an
    Array. Maybe to change this is worth an RCR?

    While I would find this convenient it's really not too hard to access
    members explicitely.
    :)

    Kind regards

    robert
     
    Robert Klemme, Sep 26, 2005
    #3
  4. Try this:
    In theory .each { |(i, v)| ... } should also work, but it seems that
    Ruby doesn't call .to_a there. (I think it should do so.)
     
    Florian Groß, Sep 26, 2005
    #4
  5. Hi --

    You could probably get a similar result by doing something with
    A#inspect, though probably not exactly what you've got here.
    I'd want a better name, and more rationale. My instinct is to prefer
    to know how scalar and/or container objects will behave, and plan for
    that, rather than have different objects do arbitrarily different
    things in the face of argument assignment.


    David
     
    David A. Black, Sep 26, 2005
    #5
  6. Oooh... not what I meant. :) I meant something like this:

    class B
    attr_reader :i, :v
    def initialize(i,v)
    @i, @v = i, v
    end
    end

    class ArrayOfB < DelegateClass(Array)
    def each
    super { |b| yield b.i, b.v }
    end
    end

    a = ArrayOfB.new [B.new:)a, 1), B.new:)b, 2)]
    a.each { |i, v| puts "i = #{i.inspect}, v = #{v.inspect}" }
    Definitely not .include? Enumerable, since not all Enumerable methods
    require finity (finiteness? finition? finality?)*. Maybe against .to_a,
    though, but its deprecatedness (deprecatedity? deprecatality?
    deprecation? aha! deprecation!) on Object makes me wonder if we aren't
    heading down a path matz & friends already scoped out and nixed..
    Ditto.

    Devin.

    *Point in case:

    class Fibs
    extend Enumerable
    def self.each
    i, j = 0, 1
    loop do
    yield i
    i, j = j, i + j
    end
    end
    end

    #find the first Fibonacci number with two nines in a row
    Fibs.find { |i| i.to_s =~ /99/ }
     
    Devin Mullins, Sep 26, 2005
    #6
  7. Trans

    Trans Guest

    Nah, that ruins the whole point. In my case I'm tryinig to create a
    general pupose "association" class. So I can do:

    a >> b

    Same as

    Assoc.new(a,b)

    Please ignore that I'm overridding '>>' ;)

    So then I do:

    [ a0 >> b0, a1 >> b1, a2 >> b2 ]

    And have an object much like an ordered hash. But I also can create a
    mixed collection if I so need:

    [ a0 >> b0, c0, a1 >> b1, c1, a2 >> b2, c2 ]

    But I'm more interested in the ordered-hashish at this point. I want to
    use it as one normally would use a hash, but alas I don't see any way
    to do that expect to overide certain methods in Array, especailly
    #each.

    So I started thinking how a class might have some generalizing methods
    to allow this to work.

    T.
     
    Trans, Sep 26, 2005
    #7
  8. Trans

    Trans Guest

    Ah, that would be an acceptable solution. I wish it did so too.

    T.
     
    Trans, Sep 26, 2005
    #8
  9. Interesting. Why does it work? Which method does the trick here?
    => false

    Hm...

    Kind regards

    robert
     
    Robert Klemme, Sep 27, 2005
    #9
  10. Mrh? ArrayOfB#each does the trick. You understand DelegateClass, no?
    (Probably much better than I do...)
    Yes, that's the downside, but it's not necessarily much of one, is it?

    Devin
     
    Devin Mullins, Sep 27, 2005
    #10
  11. Can't be:
    #<Foo:0x1018b6c0>
    nil
    #<Foo:0x1018b6a8>
    nil
    => [#<Foo:0x1018b6c0>, #<Foo:0x1018b6a8>]

    It must be something different.

    Ah! I remember: it's #to_ary:
    1
    2
    1
    2
    I know and understand it. I dunno whether better or worse than you. :)

    Kind regards

    robert
     
    Robert Klemme, Sep 27, 2005
    #11
  12. Trans

    Trans Guest

    Sweet!

    T.
     
    Trans, Sep 27, 2005
    #12
    1. Advertisements

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.