each by arity

Discussion in 'Ruby' started by Trans, Jun 14, 2009.

  1. Trans

    Trans Guest

    I've always wondered, why?

    c = []
    [1,2,3,4].each{ |x,y| c << [x, y] }
    c

    gives us

    [ [1,nil], [2,nil], [3,nil], [4,nil] ]

    why not allow it to look at the arity of the block? And thus produce

    [ [1,2], [3,4] ]

    I don't see how the former is ever of any use, but the later certainly
    is. am i missing something obvious?

    T.
    Trans, Jun 14, 2009
    #1
    1. Advertising

  2. Trans

    Tony Arcieri Guest

    [Note: parts of this message were removed to make it a legal post.]

    On Sun, Jun 14, 2009 at 1:29 PM, Trans <> wrote:

    > I don't see how the former is ever of any use, but the later certainly
    > is. am i missing something obvious?
    >


    The main use I've seen is for iterating hashes, e.g.:

    >> {:a => 1, :b => 2, :c => 3}.map { |k, v| "#{k}=#{v}" }.join(",")

    => "b=2,c=3,a=1"

    Of course you could always massign against an incoming array, so this case
    is also covered by:

    >> {:a => 1, :b => 2, :c => 3}.map { |(k, v)| "#{k}=#{v}" }.join(",")

    => "b=2,c=3,a=1"

    The massign approach is nice with methods where you want to explode an array
    as arguments alongside other arguments:

    >> {:a => 1, :b => 2, :c => 3}.inject(0) { |n, (k, v)| n + v }

    => 6

    Personally I'm not a fan of this mode of arity handling and think massign
    and splats cover all the cases where it's useful.

    --
    Tony Arcieri
    medioh.com
    Tony Arcieri, Jun 14, 2009
    #2
    1. Advertising

  3. Trans wrote:
    > I've always wondered, why?
    >
    > c = []
    > [1,2,3,4].each{ |x,y| c << [x, y] }
    > c
    >
    > gives us
    >
    > [ [1,nil], [2,nil], [3,nil], [4,nil] ]
    >
    > why not allow it to look at the arity of the block? And thus produce
    >
    > [ [1,2], [3,4] ]
    >
    > I don't see how the former is ever of any use, but the later certainly
    > is. am i missing something obvious?


    What would it do with

    [ [1,2], [3,4] ].each {|x,y| ... }

    --
    vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407
    Joel VanderWerf, Jun 14, 2009
    #3
  4. Trans

    Tony Arcieri Guest

    [Note: parts of this message were removed to make it a legal post.]

    On Sun, Jun 14, 2009 at 1:37 PM, Joel VanderWerf <>wrote:

    > What would it do with
    >
    > [ [1,2], [3,4] ].each {|x,y| ... }
    >


    One iteration, with:

    x = [1,2]
    y = [3,4]

    This could be expanded out with:

    [ [1,2], [3,4] ].each {|(a,b),(c,d)| ... }

    and

    [ [1,2], [3,4] ].each {|(x,y)| ... }

    still provides the old behavior.

    This effectively provides the same behavior as each_slice, without the need
    for a separate function, and having the "n" argument of each_slice "implied"
    in the arity of the block.

    These are the cool little bits of syntactic sugar I love to see in Ruby, but
    I often find trying to do things with subtle little idiosyncrasies can make
    code confusing.

    each_slice is a lot clearer.

    --
    Tony Arcieri
    medioh.com
    Tony Arcieri, Jun 14, 2009
    #4
  5. Trans

    trans Guest

    On Jun 14, 4:43=A0pm, Yossef Mendelssohn <> wrote:
    > On Jun 14, 3:32=A0pm, Tony Arcieri <> wrote:
    >
    >
    >
    > > On Sun, Jun 14, 2009 at 1:37 PM, Joel VanderWerf <=

    du>wrote:
    >
    > > > What would it do with

    >
    > > > [ [1,2], [3,4] ].each {|x,y| ... }

    >
    > > One iteration, with:

    >
    > > x =3D [1,2]
    > > y =3D [3,4]

    >
    > > This could be expanded out with:

    >
    > > [ [1,2], [3,4] ].each {|(a,b),(c,d)| ... }

    >
    > > and

    >
    > > [ [1,2], [3,4] ].each {|(x,y)| ... }

    >
    > > still provides the old behavior.

    >
    > And by "the old behavior" I presume you mean two iterations:
    >
    > =A0 x =3D 1
    > =A0 y =3D 2
    >
    > =A0 x =3D 3
    > =A0 y =3D 4
    >
    > And how is that going to happen based on inspecting arity? At least
    > with 1.8.6, Proc.new {|x, y| } and Proc.new {|(x, y)| } both have an
    > arity of 2.


    The underlying systems has to see the difference regardless. In fact
    the current implementation has to do more, b/c it has to look at the
    receiver itself and see that it contains arrays as elements in order
    to know how to treat it, which is rather inefficient. (Also, I think
    one could argue that either this arity is wrong, or the concept of
    arity needs to be expanded with an added dimension.)

    > > each_slice is a lot clearer.

    >
    > Yes. Yes, it is.


    Slice by arity seems pretty clear to me. Moreover, where is
    #map_slice? It starts to look a lot clearer when we think of adding
    "_slice" to every Enumerable method.

    Go ahead and call out the Enumerator now.

    T.
    trans, Jun 15, 2009
    #5
  6. On Jun 14, 2009, at 9:22 PM, trans wrote:

    >
    >
    > On Jun 14, 4:43 pm, Yossef Mendelssohn <> wrote:
    >> On Jun 14, 3:32 pm, Tony Arcieri <> wrote:
    >>
    >>
    >>
    >>> On Sun, Jun 14, 2009 at 1:37 PM, Joel VanderWerf
    >>> <>wrote:

    >>
    >>>> What would it do with

    >>
    >>>> [ [1,2], [3,4] ].each {|x,y| ... }

    >>
    >>> One iteration, with:

    >>
    >>> x = [1,2]
    >>> y = [3,4]

    >>
    >>> This could be expanded out with:

    >>
    >>> [ [1,2], [3,4] ].each {|(a,b),(c,d)| ... }

    >>
    >>> and

    >>
    >>> [ [1,2], [3,4] ].each {|(x,y)| ... }

    >>
    >>> still provides the old behavior.

    >>
    >> And by "the old behavior" I presume you mean two iterations:
    >>
    >> x = 1
    >> y = 2
    >>
    >> x = 3
    >> y = 4
    >>
    >> And how is that going to happen based on inspecting arity? At least
    >> with 1.8.6, Proc.new {|x, y| } and Proc.new {|(x, y)| } both have an
    >> arity of 2.

    >
    > The underlying systems has to see the difference regardless. In fact
    > the current implementation has to do more, b/c it has to look at the
    > receiver itself and see that it contains arrays as elements in order
    > to know how to treat it, which is rather inefficient. (Also, I think
    > one could argue that either this arity is wrong, or the concept of
    > arity needs to be expanded with an added dimension.)


    At this point, it sounds more like we're talking about OCaml style
    pattern matching than proc arity. I, for one, would love to see Ruby
    gain some sort of pattern matching to work with elements, but I fear
    this would be difficult to implement on top of Ruby's dynamism.

    - Josh
    Joshua Ballanco, Jun 15, 2009
    #6
  7. On 15.06.2009 07:44, Joshua Ballanco wrote:
    > On Jun 14, 2009, at 9:22 PM, trans wrote:
    >
    >>
    >> On Jun 14, 4:43 pm, Yossef Mendelssohn <> wrote:
    >>> On Jun 14, 3:32 pm, Tony Arcieri <> wrote:
    >>>
    >>>
    >>>
    >>>> On Sun, Jun 14, 2009 at 1:37 PM, Joel VanderWerf
    >>>> <>wrote:
    >>>>> What would it do with
    >>>>> [ [1,2], [3,4] ].each {|x,y| ... }
    >>>> One iteration, with:
    >>>> x = [1,2]
    >>>> y = [3,4]
    >>>> This could be expanded out with:
    >>>> [ [1,2], [3,4] ].each {|(a,b),(c,d)| ... }
    >>>> and
    >>>> [ [1,2], [3,4] ].each {|(x,y)| ... }
    >>>> still provides the old behavior.
    >>> And by "the old behavior" I presume you mean two iterations:
    >>>
    >>> x = 1
    >>> y = 2
    >>>
    >>> x = 3
    >>> y = 4
    >>>
    >>> And how is that going to happen based on inspecting arity? At least
    >>> with 1.8.6, Proc.new {|x, y| } and Proc.new {|(x, y)| } both have an
    >>> arity of 2.

    >> The underlying systems has to see the difference regardless. In fact
    >> the current implementation has to do more, b/c it has to look at the
    >> receiver itself and see that it contains arrays as elements in order
    >> to know how to treat it, which is rather inefficient. (Also, I think
    >> one could argue that either this arity is wrong, or the concept of
    >> arity needs to be expanded with an added dimension.)


    But the problem is that we have two steps here:
    1. invocation of yield
    2. distributing arguments across block parameters

    If I followed the thread properly then step 1 would have to be
    influenced by knowledge about the block while currently only step 2
    does. The code invoking yield needs to be in charge yet at the moment
    it only has arity as information. I believe more information about the
    block needs to be provided otherwise this cannot work because #each
    needs to know this or else it cannot decide how many elements from the
    current Enumerable must be handed off to the block.

    > At this point, it sounds more like we're talking about OCaml style
    > pattern matching than proc arity. I, for one, would love to see Ruby
    > gain some sort of pattern matching to work with elements, but I fear
    > this would be difficult to implement on top of Ruby's dynamism.


    1.9 is actually moving into that direction:

    irb(main):001:0> f = lambda {|a,*b,c| p a,b,c}
    => #<Proc:0x100d08bc@(irb):1 (lambda)>
    irb(main):002:0> f[1,2]
    1
    []
    2
    => [1, [], 2]
    irb(main):003:0> f[1,2,3]
    1
    [2]
    3
    => [1, [2], 3]
    irb(main):004:0> f[1,2,3,4]
    1
    [2, 3]
    4
    => [1, [2, 3], 4]
    irb(main):005:0>

    And even in 1.8 you had some level of pattern matching, e.g.

    irb(main):001:0> h={1=>2,3=>4}
    => {1=>2, 3=>4}
    irb(main):002:0> h.inject(0) {|s,(k,v)| s + k + v}
    => 10

    Kind regards

    robert

    --
    remember.guy do |as, often| as.you_can - without end
    http://blog.rubybestpractices.com/
    Robert Klemme, Jun 15, 2009
    #7
  8. [Note: parts of this message were removed to make it a legal post.]

    On Sun, Jun 14, 2009 at 11:22 PM, trans <> wrote:

    > On Jun 14, 4:43 pm, Yossef Mendelssohn <> wrote:
    > > And how is that going to happen based on inspecting arity? At least
    > > with 1.8.6, Proc.new {|x, y| } and Proc.new {|(x, y)| } both have an
    > > arity of 2.

    >
    > The underlying systems has to see the difference regardless.



    This is true. I was just pointing out that it's not arity that stores the
    difference, and that makes this at least a little more difficult.


    > (Also, I think one could argue that either this arity is wrong, or the
    > concept of
    > arity needs to be expanded with an added dimension.)



    You can argue a lot of things, and I'm sure you want to. Personally, I have
    yet to find the Ruby concept of block arity lacking, but then again I don't
    try to do anything clever with it.


    > > > each_slice is a lot clearer.

    > >
    > > Yes. Yes, it is.

    >
    > Slice by arity seems pretty clear to me. Moreover, where is
    > #map_slice? It starts to look a lot clearer when we think of adding
    > "_slice" to every Enumerable method.



    Why is map_slice needed? What's the problem with calling each_slice and then
    map on the result? Is it a case of optimization? Are you worried about the
    resources you'll be using? If so, it's quite possible to use each_slice to
    iterate over one collection while appending results to an array. But maybe
    it's not functional enough for you. Or core enough.

    Go ahead and call out the Enumerator now.


    I have no trouble with requiring 'enumerator' and explicitly using exactly
    the methods I want. I'd rather be clear than clever.

    --
    -yossef
    Yossef Mendelssohn, Jun 15, 2009
    #8
  9. On 15.06.2009 20:17, Yossef Mendelssohn wrote:
    > [Note: parts of this message were removed to make it a legal post.]
    >
    > On Sun, Jun 14, 2009 at 11:22 PM, trans <> wrote:


    >> Slice by arity seems pretty clear to me. Moreover, where is
    >> #map_slice? It starts to look a lot clearer when we think of adding
    >> "_slice" to every Enumerable method.

    >
    > Why is map_slice needed? What's the problem with calling each_slice and then
    > map on the result? Is it a case of optimization? Are you worried about the
    > resources you'll be using? If so, it's quite possible to use each_slice to
    > iterate over one collection while appending results to an array. But maybe
    > it's not functional enough for you. Or core enough.
    >
    > Go ahead and call out the Enumerator now.
    >
    > I have no trouble with requiring 'enumerator' and explicitly using exactly
    > the methods I want. I'd rather be clear than clever.


    Question is whether it is clever to duplicate all methods with another
    one that has "_slice" appended to the name. I personally favor the
    approach with Enumerator, e.g. depending on version

    enum.enum_for:)each_slice, 2).map {|a,b| ...}
    enum.each_slice(2).map {|a,b| ...}

    - especially since it works as easy for #each_cons and others. In other
    words: this is much more modular.

    Kind regards

    robert

    --
    remember.guy do |as, often| as.you_can - without end
    http://blog.rubybestpractices.com/
    Robert Klemme, Jun 16, 2009
    #9
  10. Trans

    trans Guest

    On Jun 16, 2:10=A0am, Robert Klemme <> wrote:

    > Question is whether it is clever to duplicate all methods with another
    > one that has "_slice" appended to the name. =A0I personally favor the
    > approach with Enumerator, e.g. depending on version


    Not clever... facetious. Of course Enumerator is useful, and with 1.9
    fairly elegant. But rather, the question is why we must do

    enum.each_slice(2).map {|a,b| ...}

    when

    enum.map {|a,b| ...}

    could be made to work. This is especially interesting b/c it seems the
    underlying implementation stands to be simpler and faster by doing so.

    T.
    trans, Jun 16, 2009
    #10
  11. Trans

    Robert Dober Guest

    On Tue, Jun 16, 2009 at 12:33 PM, trans<> wrote:
    >
    >
    > On Jun 16, 2:10=A0am, Robert Klemme <> wrote:
    >
    >> Question is whether it is clever to duplicate all methods with another
    >> one that has "_slice" appended to the name. =A0I personally favor the
    >> approach with Enumerator, e.g. depending on version

    >
    > Not clever... facetious. Of course Enumerator is useful, and with 1.9
    > fairly elegant. But rather, the question is why we must do
    >
    > =A0enum.each_slice(2).map {|a,b| ...}
    >
    > when
    >
    > =A0enum.map {|a,b| ...}
    >
    > could be made to work. This is especially interesting b/c it seems the
    > underlying implementation stands to be simpler and faster by doing so.

    That is intriguing and I am surprised.

    However, why should

    enum.map{ |a,b| }
    have the semantics of
    enum.each_slice( 2 )....
    and not
    enum.each_cons( 2 ).... ?

    Maybe we need to push the abstraction even higher. Hopefully you
    understand what that sentence means, because I do not, but it felt
    just right to write it. Strange, strange.

    Now I am not so fond of enumerator, because it is really crazy.

    x=3D%w{a b c d}
    y =3D x.enum_for( :rand )
    y.each do | a | p a end
    =3D> 0.680141319345242

    Do you agree with me that enum_for should use #public_send instead of #send=
    ?

    Cheers
    Robert

    Cheers
    Robert
    >
    > T.
    >
    >
    >




    --=20
    Toutes les grandes personnes ont d=92abord =E9t=E9 des enfants, mais peu
    d=92entre elles s=92en souviennent.

    All adults have been children first, but not many remember.

    [Antoine de Saint-Exup=E9ry]
    Robert Dober, Jun 17, 2009
    #11
  12. Trans

    trans Guest

    On Jun 16, 7:43=A0pm, Robert Dober <> wrote:
    > On Tue, Jun 16, 2009 at 12:33 PM, trans<> wrote:
    >
    > > On Jun 16, 2:10=A0am, Robert Klemme <> wrote:

    >
    > >> Question is whether it is clever to duplicate all methods with another
    > >> one that has "_slice" appended to the name. =A0I personally favor the
    > >> approach with Enumerator, e.g. depending on version

    >
    > > Not clever... facetious. Of course Enumerator is useful, and with 1.9
    > > fairly elegant. But rather, the question is why we must do

    >
    > > =A0enum.each_slice(2).map {|a,b| ...}

    >
    > > when

    >
    > > =A0enum.map {|a,b| ...}

    >
    > > could be made to work. This is especially interesting b/c it seems the
    > > underlying implementation stands to be simpler and faster by doing so.

    >
    > That is intriguing and I am surprised.
    >
    > However, why should
    >
    > =A0 enum.map{ |a,b| }
    > have the semantics of
    > =A0 enum.each_slice( 2 )....
    > and not
    > =A0 =A0enum.each_cons( 2 ).... ?
    >
    > Maybe we need to push the abstraction even higher. Hopefully you
    > understand what that sentence means, because I do not, but it felt
    > just right to write it. Strange, strange.


    Simply b/c cons is uncommon. We want to iterate over elements once and
    only once, where as cons hits on the same elements multiple times. Of
    course, I see no reason cons could not look at arity too.

    With this idea, I've been wondering about possibilities for passing
    blocks that might have one, two or more block arguments --the arity
    unknown to the method processing them, and how that might or might
    not be useful. One obvious issue is that arity > 1 produces Array
    elements, whereas arity of 1 would not necessarily.

    > Now I am not so fond of enumerator, because it is really crazy.
    >
    > =A0 x=3D%w{a b c d}
    > =A0 y =3D x.enum_for( :rand )
    > =A0 y.each do | a | p a end
    > =3D> 0.680141319345242
    >
    > Do you agree with me that enum_for should use #public_send instead of #se=

    nd?

    Oh that's nice. I did not think you could use it for anything but
    Enumerable methods. I'm not sure it matters if they are public or not.
    It still can be crazy.

    y =3D x.enum_for:)to_s)
    =3D> #<Enumerable::Enumerator:0x7f64cd403c68>
    >> y.each{ |a| a }

    =3D> "abcd"
    >> y.each{ |a| a+'!' }

    =3D> "abcd"
    >> y.to_a

    =3D> []

    T.
    trans, Jun 17, 2009
    #12
  13. Trans

    Robert Dober Guest

    On Wed, Jun 17, 2009 at 6:49 AM, trans<> wrote:
    >
    >
    > On Jun 16, 7:43=A0pm, Robert Dober <> wrote:
    >> On Tue, Jun 16, 2009 at 12:33 PM, trans<> wrote:
    >>
    >> > On Jun 16, 2:10=A0am, Robert Klemme <> wrote=

    :
    >>
    >> >> Question is whether it is clever to duplicate all methods with anothe=

    r
    >> >> one that has "_slice" appended to the name. =A0I personally favor the
    >> >> approach with Enumerator, e.g. depending on version

    >>
    >> > Not clever... facetious. Of course Enumerator is useful, and with 1.9
    >> > fairly elegant. But rather, the question is why we must do

    >>
    >> > =A0enum.each_slice(2).map {|a,b| ...}

    >>
    >> > when

    >>
    >> > =A0enum.map {|a,b| ...}

    >>
    >> > could be made to work. This is especially interesting b/c it seems the
    >> > underlying implementation stands to be simpler and faster by doing so.

    >>
    >> That is intriguing and I am surprised.
    >>
    >> However, why should
    >>
    >> =A0 enum.map{ |a,b| }
    >> have the semantics of
    >> =A0 enum.each_slice( 2 )....
    >> and not
    >> =A0 =A0enum.each_cons( 2 ).... ?
    >>
    >> Maybe we need to push the abstraction even higher. Hopefully you
    >> understand what that sentence means, because I do not, but it felt
    >> just right to write it. Strange, strange.

    >
    > Simply b/c cons is uncommon. We want to iterate over elements once and
    > only once, where as cons hits on the same elements multiple times. Of
    > course, I see no reason cons could not look at arity too.

    Maybe we should map leave alone and use the enumerable approach

    coll.cons.each{ |a,b| ...
    coll.slice.each { |a,b|...

    I like this because I am used to "waiting" in proxy objects for what
    they are really to be used later, but it might be troubling for
    others.
    Do you think it is a good idea to implement it in Facets first and ask
    for inclusion into the core after having some more feedback from
    users?
    >
    > With this idea, I've been wondering about possibilities for passing
    > blocks that might have one, two or more block arguments --the arity
    > unknown to the method processing them, and how that might or might
    > not =A0be useful. One obvious issue is that arity > 1 produces Array
    > elements, whereas arity of 1 would not necessarily.
    >
    >> Now I am not so fond of enumerator, because it is really crazy.
    >>
    >> =A0 x=3D%w{a b c d}
    >> =A0 y =3D x.enum_for( :rand )
    >> =A0 y.each do | a | p a end
    >> =3D> 0.680141319345242
    >>
    >> Do you agree with me that enum_for should use #public_send instead of #s=

    end?
    >
    > Oh that's nice. I did not think you could use it for anything but
    > Enumerable methods. I'm not sure it matters if they are public or not.
    > It still can be crazy.

    Yeah as long as it justs sends the symbol we cannot avoid that, but I
    guess this is the price to pay for having it flexible or maybe not? I
    am not an expert on Enumerator internals. But I definetely want to
    enumerate over my custom iterators.
    >
    > y =3D x.enum_for:)to_s)
    > =3D> #<Enumerable::Enumerator:0x7f64cd403c68>
    >>> y.each{ |a| a }

    > =3D> "abcd"
    >>> y.each{ |a| a+'!' }

    > =3D> "abcd"
    >>> y.to_a

    > =3D> []
    >
    > T.
    >
    >


    Cheers
    R.

    --=20
    Toutes les grandes personnes ont d=92abord =E9t=E9 des enfants, mais peu
    d=92entre elles s=92en souviennent.

    All adults have been children first, but not many remember.

    [Antoine de Saint-Exup=E9ry]
    Robert Dober, Jun 17, 2009
    #13
  14. Trans

    trans Guest

    On Jun 17, 6:22=A0am, Robert Dober <> wrote:
    > On Wed, Jun 17, 2009 at 6:49 AM, trans<> wrote:
    >
    > > On Jun 16, 7:43=A0pm, Robert Dober <> wrote:
    > >> On Tue, Jun 16, 2009 at 12:33 PM, trans<> wrote:

    >
    > >> > On Jun 16, 2:10=A0am, Robert Klemme <> wro=

    te:
    >
    > >> >> Question is whether it is clever to duplicate all methods with anot=

    her
    > >> >> one that has "_slice" appended to the name. =A0I personally favor t=

    he
    > >> >> approach with Enumerator, e.g. depending on version

    >
    > >> > Not clever... facetious. Of course Enumerator is useful, and with 1.=

    9
    > >> > fairly elegant. But rather, the question is why we must do

    >
    > >> > =A0enum.each_slice(2).map {|a,b| ...}

    >
    > >> > when

    >
    > >> > =A0enum.map {|a,b| ...}

    >
    > >> > could be made to work. This is especially interesting b/c it seems t=

    he
    > >> > underlying implementation stands to be simpler and faster by doing s=

    o.
    >
    > >> That is intriguing and I am surprised.

    >
    > >> However, why should

    >
    > >> =A0 enum.map{ |a,b| }
    > >> have the semantics of
    > >> =A0 enum.each_slice( 2 )....
    > >> and not
    > >> =A0 =A0enum.each_cons( 2 ).... ?

    >
    > >> Maybe we need to push the abstraction even higher. Hopefully you
    > >> understand what that sentence means, because I do not, but it felt
    > >> just right to write it. Strange, strange.

    >
    > > Simply b/c cons is uncommon. We want to iterate over elements once and
    > > only once, where as cons hits on the same elements multiple times. Of
    > > course, I see no reason cons could not look at arity too.

    >
    > Maybe we should map leave alone and use the enumerable approach
    >
    > coll.cons.each{ |a,b| ...
    > coll.slice.each { |a,b|...


    Hmm... I point out the Array#slice is already a method.

    > I like this because I am used to "waiting" in proxy objects for what
    > they are really to be used later, but it might be troubling for
    > others.
    > Do you think it is a good idea to implement it in Facets first and ask
    > for inclusion into the core after having some more feedback from
    > users?


    Perhaps, but I must think about it some more. Presently one would do
    (in 1.9):

    coll.each_slice(n){ ... }
    coll.each_cons(n){ ... }

    If one wanted to map over that:

    coll.map.each_slice(n){ ... }
    coll.map.each_cons(n){ ... }

    correct?

    So how do we best achieve "by arity" without stepping on present toes?
    It would be nice to have a coherent idea about it as well. It would be
    interesting to look at this kind of thing in a variety of languages
    actually. OCaml for instance has already been mentioned. I'll have to
    look that up.

    T.
    trans, Jun 19, 2009
    #14
  15. 2009/6/19 trans <>:

    > Perhaps, but I must think about it some more. Presently one would do
    > (in 1.9):
    >
    > =A0coll.each_slice(n){ ... }
    > =A0coll.each_cons(n){ ... }
    >
    > If one wanted to map over that:
    >
    > =A0coll.map.each_slice(n){ ... }
    > =A0coll.map.each_cons(n){ ... }
    >
    > correct?


    For mapping in 1.9 I would do

    coll.each_slice(n).map{ ... }
    coll.each_cons(n).map{ ... }

    > So how do we best achieve "by arity" without stepping on present toes?


    I would simply stick with the existing behavior. :)

    Kind regards

    robert

    --=20
    remember.guy do |as, often| as.you_can - without end
    http://blog.rubybestpractices.com/
    Robert Klemme, Jun 19, 2009
    #15
  16. Trans

    Robert Dober Guest

    On Fri, Jun 19, 2009 at 8:35 AM, Robert
    Klemme<> wrote:
    > 2009/6/19 trans <>:
    >
    >> Perhaps, but I must think about it some more. Presently one would do
    >> (in 1.9):
    >>
    >> =A0coll.each_slice(n){ ... }
    >> =A0coll.each_cons(n){ ... }


    No It would be
    coll.each_cons # this is the proxy, it does not know about the slice siz=
    e yet
    .map{ |a,b| ... } # the proxy will look at the arity.
    >>
    >> If one wanted to map over that:
    >>
    >> =A0coll.map.each_slice(n){ ... }
    >> =A0coll.map.each_cons(n){ ... }
    >>
    >> correct?

    >
    > For mapping in 1.9 I would do
    >
    > coll.each_slice(n).map{ ... }
    > coll.each_cons(n).map{ ... }
    >
    >> So how do we best achieve "by arity" without stepping on present toes?

    >
    > I would simply stick with the existing behavior. :)


    I will not let the absence of use cases let ruin my work ;) Now I have
    always liked Tom's reach for perfection, but on a practical base I
    agree with Robert it is probably not worth it.

    But on a theoretical ground I find it intriguing that the "proxy"
    would do something similar to what an enumerator does.
    An enumerator prepares a view of an enumerable for an actual method
    delivering the behavior in a block.
    One could say it "waits" for a message with a block.
    The proxy will wait for a message too, and a block too, and will just
    create the Enumerator on the fly with the information of the arity.
    I even wonder if Enumerator could be the proxy with a little monkey
    patch? And that might as well lead to a "default" behavior for map,
    without the "proxy method" which would meet Tom's original requirement
    for Enumerators *only*

    Thus [1,2,3].map{|a,b| [a,b]} would still be [[1, nil]....]
    *but*
    [1,2,3].to_enum.map{|a,b| [a,b]} would be [[1,2],[3,nil]]


    Cheers
    Robert
    Robert Dober, Jun 19, 2009
    #16
  17. 2009/6/19 Robert Dober <>:

    > But on a theoretical ground I find it intriguing that the "proxy"
    > would do something similar to what an enumerator does.
    > An enumerator prepares a view of an enumerable for an actual method
    > delivering the behavior in a block.
    > One could say it "waits" for a message with a block.
    > The proxy will wait for a message too, and a block too, and will just
    > create the Enumerator on the fly with the information of the arity.
    > I even wonder if Enumerator could be the proxy with a little monkey
    > patch?


    ???

    irb(main):002:0> %w{foo bar}.each_cons 2
    => #<Enumerator:0x1016a55c>

    > And that might as well lead to a "default" behavior for map,
    > without the "proxy method" which would meet Tom's original requirement
    > for Enumerators *only*


    Are you mixing up Enumerable and Enumerator?

    Kind regards

    robert

    --
    remember.guy do |as, often| as.you_can - without end
    http://blog.rubybestpractices.com/
    Robert Klemme, Jun 19, 2009
    #17
  18. Trans

    trans Guest

    On Jun 19, 4:57=A0am, Robert Dober <> wrote:
    > On Fri, Jun 19, 2009 at 8:35 AM, Robert
    >
    > Klemme<> wrote:
    > > 2009/6/19 trans <>:

    >
    > >> Perhaps, but I must think about it some more. Presently one would do
    > >> (in 1.9):

    >
    > >> =A0coll.each_slice(n){ ... }
    > >> =A0coll.each_cons(n){ ... }

    >
    > No It would be
    > =A0 =A0coll.each_cons # this is the proxy, it does not know about the sli=

    ce size yet
    > =A0 =A0 =A0.map{ |a,b| =A0... } =A0# the proxy will look at the arity.
    >
    >
    >
    >
    >
    > >> If one wanted to map over that:

    >
    > >> =A0coll.map.each_slice(n){ ... }
    > >> =A0coll.map.each_cons(n){ ... }

    >
    > >> correct?

    >
    > > For mapping in 1.9 I would do

    >
    > > coll.each_slice(n).map{ ... }
    > > coll.each_cons(n).map{ ... }

    >
    > >> So how do we best achieve "by arity" without stepping on present toes?

    >
    > > I would simply stick with the existing behavior. :)

    >
    > I will not let the absence of use cases let ruin my work ;) Now I have
    > always liked Tom's reach for perfection, but on a practical base I
    > agree with Robert it is probably not worth it.


    :) Robert... someone understands me!

    > But on a theoretical ground I find it intriguing that the "proxy"
    > would do something similar to what an enumerator does.
    > An enumerator prepares a view of an enumerable for an actual method
    > delivering the behavior in a block.
    > One could say it "waits" for a message with a block.
    > The proxy will wait for a message too, and a block too, and will just
    > create the Enumerator on the fly with the information of the arity.
    > I even wonder if Enumerator could be the proxy with a little monkey
    > patch? And that might as well lead to a "default" behavior for map,
    > without the "proxy method" which would meet Tom's original requirement
    > for Enumerators *only*
    >
    > Thus =A0[1,2,3].map{|a,b| [a,b]} would still be [[1, nil]....]
    > *but*
    > [1,2,3].to_enum.map{|a,b| [a,b]} would be [[1,2],[3,nil]]


    Though I think that would be kind of confusing, if not problematic.

    As others have pointed out there is no way to query the parenthetical
    patterns, eg. |(a,b)| so this will be somewhat more limited but I was
    thinking of something like:

    [1,2,3].each.by_arity{ |a,b| ... }

    or conversely

    [1,2,3].by_arity.each{ |a,b| ... }

    But we'd still need a way to do #each_cons by arity. To do this I
    think there would need to be an equivalence. #each_slice is to #each
    as #each_cons is to ___ ? So we define a method #cons that normally
    means each_cons(1). Then...

    [1,2,3].cons.by_arity{ |a,b| ... }

    or conversely

    [1,2,3].by_arity.cons{ |a,b| ... }

    Though honestly this makes me wonder why #each just doesn take an
    optional slice number -- why have a completely separate method for
    the special case of n=3D1, when an optional argument would do? Indeed
    Facets has #each_by that does this.

    P.S. I am half tempted to alias #each_by as #air, as in "air your
    arguments", and then name the cons version #conair ;)

    T.
    trans, Jun 19, 2009
    #18
    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. Howard Gardner
    Replies:
    4
    Views:
    342
    Howard Gardner
    Jul 20, 2006
  2. Michael Feathers
    Replies:
    3
    Views:
    281
    Roland Pibinger
    Aug 4, 2006
  3. ðÅÔÒÏ× áÌÅËÓÁÎÄÒ

    Why the expression "(1)" is not an one-arity tuple, but int ?

    ðÅÔÒÏ× áÌÅËÓÁÎÄÒ, Dec 4, 2009, in forum: Python
    Replies:
    0
    Views:
    263
    ðÅÔÒÏ× áÌÅËÓÁÎÄÒ
    Dec 4, 2009
  4. Jeff Mitchell

    getting the arity

    Jeff Mitchell, Aug 28, 2003, in forum: Ruby
    Replies:
    1
    Views:
    83
    Harry Ohlsen
    Aug 28, 2003
  5. DanDiebolt.exe
    Replies:
    4
    Views:
    141
    Robert Klemme
    Sep 15, 2008
Loading...

Share This Page