[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

join_with

Martin DeMello

12/6/2006 10:40:00 AM

While golfing with the hex_ip thread, I realised that map takes no
argument, and join takes no block, leaving a vacuum for a combined
method:

module Enumerable
def join_with(sep, &blk)
map(&blk).join(sep)
end
end

hex_ip.scan(/../).join_with('.') {|i| i.hex}

join_with is still a little clunky - any better name?

martin

29 Answers

Max Muermann

12/6/2006 10:46:00 AM

0

On 12/6/06, Martin DeMello <martindemello@gmail.com> wrote:
> While golfing with the hex_ip thread, I realised that map takes no
> argument, and join takes no block, leaving a vacuum for a combined
> method:
>
> module Enumerable
> def join_with(sep, &blk)
> map(&blk).join(sep)
> end
> end
>
> hex_ip.scan(/../).join_with('.') {|i| i.hex}
>
> join_with is still a little clunky - any better name?
>
> martin
>

join_mapped maybe?

Max

Robert Klemme

12/6/2006 12:45:00 PM

0

On 06.12.2006 11:40, Martin DeMello wrote:
> While golfing with the hex_ip thread, I realised that map takes no
> argument, and join takes no block, leaving a vacuum for a combined
> method:
>
> module Enumerable
> def join_with(sep, &blk)
> map(&blk).join(sep)
> end
> end
>
> hex_ip.scan(/../).join_with('.') {|i| i.hex}
>
> join_with is still a little clunky - any better name?

Hm. I am not convinced this is a good idea at all. Usually the
recommendation is that methods should do one thing - and one thing only.
Combining map with join seems like a clear violation of that principle
as map and join do extremely different things.

Having said that I'd prefer a more efficient implementation:

module Enumerable
def jw( sep )
first = true

inject("") do |s, x|
if first
first = false
else
s << sep
end

s << yield( x )
end
end
end

Kind regards

robert

Logan Capaldo

12/6/2006 2:01:00 PM

0

On Wed, Dec 06, 2006 at 07:40:03PM +0900, Martin DeMello wrote:
> While golfing with the hex_ip thread, I realised that map takes no
> argument, and join takes no block, leaving a vacuum for a combined
> method:
>
> module Enumerable
> def join_with(sep, &blk)
> map(&blk).join(sep)
> end
> end
>
> hex_ip.scan(/../).join_with('.') {|i| i.hex}
hex_ip.scan(/../).map {|i| i.hex}.join('.')
Hey look, the long way is even shorter! Do you just want to conflate
these two because theres room in the interface? That seems like a silly
reason. It would also set a bad precendent. (Well hey, delete doesn't
take a block, lets add one and pass the deleted item in...)
>
> join_with is still a little clunky - any better name?
>
> martin

Martin DeMello

12/6/2006 6:12:00 PM

0

On 12/6/06, Logan Capaldo <logancapaldo@gmail.com> wrote:
> >
> > hex_ip.scan(/../).join_with('.') {|i| i.hex}
> hex_ip.scan(/../).map {|i| i.hex}.join('.')
> Hey look, the long way is even shorter! Do you just want to conflate

I knew someone would say that :)

> these two because theres room in the interface? That seems like a silly
> reason. It would also set a bad precendent. (Well hey, delete doesn't
> take a block, lets add one and pass the deleted item in...)

No, more because map-then-join is a very common pattern, and the
complementary argument lists let us combine them neatly.

html_table = ary.jmap("\n") {|col|
col.jmap {|cell| "<td>#{cell}</td>"}
}

as opposed to

html_table = ary.map {|col|
col.jmap {|cell| "<td>#{cell}</td>"}.join
}.join("\n")

The benefit is that the block is the last argument to what is
conceptually a single operation.

martin

Martin DeMello

12/6/2006 6:17:00 PM

0

On 12/6/06, Robert Klemme <shortcutter@googlemail.com> wrote:
>
> Hm. I am not convinced this is a good idea at all. Usually the
> recommendation is that methods should do one thing - and one thing only.
> Combining map with join seems like a clear violation of that principle
> as map and join do extremely different things.

See my reply to Logan - my argument is that often (particularly when
converting data structures to a textual representation) map-then-join
*is* what you want to be doing, and if you're doing a nested series of
them, it's ugly to scatter joins in between the map blocks.

> Having said that I'd prefer a more efficient implementation:

Definitely - I just posted the code to explain what I wanted the
method to do. Note that an added advantage is that you needn't create
the temporary array for the map step.

martin

Logan Capaldo

12/7/2006 12:15:00 AM

0

On Thu, Dec 07, 2006 at 03:12:23AM +0900, Martin DeMello wrote:
> On 12/6/06, Logan Capaldo <logancapaldo@gmail.com> wrote:
> >>
> >> hex_ip.scan(/../).join_with('.') {|i| i.hex}
> > hex_ip.scan(/../).map {|i| i.hex}.join('.')
> >Hey look, the long way is even shorter! Do you just want to conflate
>
> I knew someone would say that :)
>
> >these two because theres room in the interface? That seems like a silly
> >reason. It would also set a bad precendent. (Well hey, delete doesn't
> >take a block, lets add one and pass the deleted item in...)
>
> No, more because map-then-join is a very common pattern, and the
> complementary argument lists let us combine them neatly.
>
> html_table = ary.jmap("\n") {|col|
> col.jmap {|cell| "<td>#{cell}</td>"}
> }
>
> as opposed to
>
> html_table = ary.map {|col|
> col.jmap {|cell| "<td>#{cell}</td>"}.join
> }.join("\n")
>
> The benefit is that the block is the last argument to what is
> conceptually a single operation.
>
I don't see it personally. As far as I am concerned it's two operations.
At least it wasn't just "Hey, theres room for this, why not put it in."

As for the method name, considered just adding a block to join?

array.join("\n") # Normal join
array.join("\n") { |item| "<td>#{item}</td>" }


Of course theres everybodies favorite iterator:
array.inject("") { |s, cell| "#{s}<td>#{cell}</td>\n" }

> martin

Vincent Fourmond

12/7/2006 11:51:00 AM

0

Martin DeMello wrote:
> On 12/6/06, Robert Klemme <shortcutter@googlemail.com> wrote:
>> Having said that I'd prefer a more efficient implementation:
>
> Definitely - I just posted the code to explain what I wanted the
> method to do. Note that an added advantage is that you needn't create
> the temporary array for the map step.

I vote for this function, although the name, join_with, really isn't
telling what it's doing (it doesn't speak to me, unlike most ruby method
names).

Vince

--
Vincent Fourmond, PhD student
http://vincent.fourmon...

Martin DeMello

12/7/2006 11:56:00 AM

0

On 12/7/06, Vincent Fourmond <vincent.fourmond@9online.fr> wrote:
>
> I vote for this function, although the name, join_with, really isn't
> telling what it's doing (it doesn't speak to me, unlike most ruby method
> names).

I've settled on Enumerable#jmap in my personal code - it fits my
thinking, because I'm focusing on the map, and the join is secondary.

martin

Robert Klemme

12/7/2006 12:14:00 PM

0

On 07.12.2006 12:56, Martin DeMello wrote:
> On 12/7/06, Vincent Fourmond <vincent.fourmond@9online.fr> wrote:
>>
>> I vote for this function, although the name, join_with, really isn't
>> telling what it's doing (it doesn't speak to me, unlike most ruby method
>> names).
>
> I've settled on Enumerable#jmap in my personal code - it fits my
> thinking, because I'm focusing on the map, and the join is secondary.

The I'd spent at least three or four more characters - your current
naming lets me think of some javaism. :-)

robert

Nobuyoshi Nakada

12/13/2006 4:45:00 PM

0

Hi,

At Wed, 6 Dec 2006 19:40:03 +0900,
Martin DeMello wrote in [ruby-talk:228380]:
> While golfing with the hex_ip thread, I realised that map takes no
> argument, and join takes no block, leaving a vacuum for a combined
> method:

Is it what is called "mapconcat" in Emacs Lisp?

--
Nobu Nakada