[Facets] Multiple arguments for Hash#delete

D

Daniel Schierbeck

This may be a Facet:

class Hash
alias_method :__delete__, :delete

def delete(*keys, &block)
if keys.length == 1
__delete__(keys.first, &block)
else
keys.map{|key| __delete__(key, &block) }
end
end
end

Probably somewhat slower, but hey, it lets you do this

a, b, c = hsh.delete :a, :b, :c

which fits in nicely with

hsh[:a, :b, :c] = 1, 2, 3

and

a, b, c = hsh[:a, :b, :c]


Cheers,
Daniel
 
T

Trans

Daniel said:
This may be a Facet:

class Hash
alias_method :__delete__, :delete

def delete(*keys, &block)
if keys.length == 1
__delete__(keys.first, &block)
else
keys.map{|key| __delete__(key, &block) }
end
end
end

Probably somewhat slower, but hey, it lets you do this

a, b, c = hsh.delete :a, :b, :c

which fits in nicely with

hsh[:a, :b, :c] = 1, 2, 3

and

a, b, c = hsh[:a, :b, :c]

Good deal. I'll add it. Looks to be a safe override too.

Perhaps this is a good update for future version of Ruby?

T.
 
D

Daniel Schierbeck

Trans said:
Daniel said:
This may be a Facet:

class Hash
alias_method :__delete__, :delete

def delete(*keys, &block)
if keys.length == 1
__delete__(keys.first, &block)
else
keys.map{|key| __delete__(key, &block) }
end
end
end

Probably somewhat slower, but hey, it lets you do this

a, b, c = hsh.delete :a, :b, :c

which fits in nicely with

hsh[:a, :b, :c] = 1, 2, 3

and

a, b, c = hsh[:a, :b, :c]

Good deal. I'll add it. Looks to be a safe override too.

For once... :)
Perhaps this is a good update for future version of Ruby?

I think the updated #[], #[]= and #delete all deserve to be in core. The
only problem I see is performance-wise, although implementing them in C
might help there.


Cheers,
Daniel
 
N

nobu

Hi,

At Thu, 17 Aug 2006 04:05:08 +0900,
Daniel Schierbeck wrote in [ruby-talk:208833]:
Probably somewhat slower, but hey, it lets you do this

a, b, c = hsh.delete :a, :b, :c

What will be returned from `hsh.delete :a'?
 
D

Daniel Schierbeck

Hi,

At Thu, 17 Aug 2006 04:05:08 +0900,
Daniel Schierbeck wrote in [ruby-talk:208833]:
Probably somewhat slower, but hey, it lets you do this

a, b, c = hsh.delete :a, :b, :c

What will be returned from `hsh.delete :a'?

The value of :a

hsh = {:a => 1, :b => 2, :c => 3}
hsh.delete :a, :b #=> [1, 2]
hsh.delete :c #=> 3

that way, you can do this

a = hsh.delete :a
b, c = hsh.delete :b, :c

Cool, right?


Cheers,
Daniel
 
T

Trans

Daniel said:
Hi,

At Thu, 17 Aug 2006 04:05:08 +0900,
Daniel Schierbeck wrote in [ruby-talk:208833]:
Probably somewhat slower, but hey, it lets you do this

a, b, c = hsh.delete :a, :b, :c

What will be returned from `hsh.delete :a'?

The value of :a

hsh = {:a => 1, :b => 2, :c => 3}
hsh.delete :a, :b #=> [1, 2]
hsh.delete :c #=> 3

that way, you can do this

a = hsh.delete :a
b, c = hsh.delete :b, :c

Cool, right?

Ah, Nobu has a good point. It's beeter to have same kind of output. He
also jogs my memory. Array has #delete_values_at and that's what we
need for Hash too.

def delete_values_at(*keys, &block)
keys.map{|key| delete(key, &block) }
end

Kind of long name though, maybe #delete_at would suffice?

T.
 
N

nobu

Hi,

At Thu, 17 Aug 2006 23:40:18 +0900,
Daniel Schierbeck wrote in [ruby-talk:208980]:
What will be returned from `hsh.delete :a'?

The value of :a

hsh = {:a => 1, :b => 2, :c => 3}
hsh.delete :a, :b #=> [1, 2]
hsh.delete :c #=> 3

The class of returned value varies according to the number of
arguments?
that way, you can do this

a = hsh.delete :a
b, c = hsh.delete :b, :c

a = [:b, :c]
b = hsh.delete(*a)

might be confusing, IMHO.
 
D

Daniel Schierbeck

hsh = {:a => 1, :b => 2, :c => 3}
hsh.delete :a, :b #=> [1, 2]
hsh.delete :c #=> 3

The class of returned value varies according to the number of
arguments?

Yes. I don't see that as a big problem though, especially if there's a
second method that *always* returns an array:

hsh.delete_at :a #=> [1]
hsh.delete_at :b, :c #=> [2, 3]

It may be too much magic for some, but I think it's a very cool feature
that won't interfere with how #delete is being used at the moment.

The main reason for it becoming a Facet is that Hash#[] and Hash#[]=
also work with multiple arguments.


Cheers,
Daniel
 
D

Daniel Schierbeck

Trans said:
Daniel said:
Hi,

At Thu, 17 Aug 2006 04:05:08 +0900,
Daniel Schierbeck wrote in [ruby-talk:208833]:
Probably somewhat slower, but hey, it lets you do this

a, b, c = hsh.delete :a, :b, :c
What will be returned from `hsh.delete :a'?
The value of :a

hsh = {:a => 1, :b => 2, :c => 3}
hsh.delete :a, :b #=> [1, 2]
hsh.delete :c #=> 3

that way, you can do this

a = hsh.delete :a
b, c = hsh.delete :b, :c

Cool, right?

Ah, Nobu has a good point. It's beeter to have same kind of output. He
also jogs my memory. Array has #delete_values_at and that's what we
need for Hash too.

def delete_values_at(*keys, &block)
keys.map{|key| delete(key, &block) }
end

Kind of long name though, maybe #delete_at would suffice?

Read my mind... yes, I think there should be added a #delete_at method
in addition to the new #delete.


Cheers,
Daniel
 
T

Trans

Daniel said:
Read my mind... yes, I think there should be added a #delete_at method
in addition to the new #delete.

Here' is another place in which the interchangeability between Array
andHash is lacking. Array has delete_at(index), while Hash has
delete(key). These two methods should really have the same name. But
array's delete() method is delete(value), which Hash has no equivalent.
Maybe matz will be willing to do a little shuffling to improve this for
2.0, but the only choice I have in the mean time is the long winded
delete_values_at().

Also, it really doesn't work to redefine delete() as you originally
suggested b/c you'd have to use the delete_values_at to ensure you get
an expected result, otherwise you're assuming preknowledge of how many
elemets are in the Hash.

T.
 
D

Daniel Schierbeck

Trans said:
Also, it really doesn't work to redefine delete() as you originally
suggested b/c you'd have to use the delete_values_at to ensure you get
an expected result, otherwise you're assuming preknowledge of how many
elemets are in the Hash.

What do you mean? It would work fine for the purpose I've described. If
you want to be sure you get an array when deleting multiple key-value
pairs, use #delete_values_at, otherwise #delete is just fine. The nifty
thing is that it adjusts its return value according to your need.

If #delete should be altered, why should #[] and #[]= ?


Cheers,
Daniel
 
T

Trans

Daniel said:
What do you mean? It would work fine for the purpose I've described. If
you want to be sure you get an array when deleting multiple key-value
pairs, use #delete_values_at, otherwise #delete is just fine. The nifty
thing is that it adjusts its return value according to your need.

Yea, I'm just saying YAGNI b/c in the end you won't use delete() with
more than one index, you'll use #delete_values_at b/c of the clear
separation of functionality. But...
If #delete should be altered, why should #[] and #[]= ?

You may have a point. Though it doesn't matter as much becuase it's
much less often the anyone depends on the return value of []=. ie. we
just use it to set values. But to be very percise it should probably be
changed to match Array's. Consider that Array's []= method does take
multuiple parameters related to slicing. Facets' deals with that by
allowing it to also take an Array parameter:

a = []
a[[1,2,3]] = :a, :b, :c
a #=> [ :a, :b, :c ]

Hash's can be made to do the same. What do you think?

T.
 
D

Daniel Schierbeck

Trans said:
If #delete should be altered, why should #[] and #[]= ?

You may have a point. Though it doesn't matter as much becuase it's
much less often the anyone depends on the return value of []=. ie. we
just use it to set values.

I only added #[]= because, with Facets, you can do this (as you of
course know)

hsh[:a, :b, :c] = 1, 2, 3

which matches nicely with

a, b, c = hsh[:a, :b, :c]

My point is that #delete is also a retrieval method, in the sense that
it returns the value it has removed from the hash. Therefore it is
natural for it to have the same functionality as #[], which in turn
means that we have to alter #delete in Facets.

a, b, c = hsh.delete:)a, :b, :c)

Simple and elegant.
But to be very percise it should probably be
changed to match Array's. Consider that Array's []= method does take
multuiple parameters related to slicing. Facets' deals with that by
allowing it to also take an Array parameter:

a = []
a[[1,2,3]] = :a, :b, :c
a #=> [ :a, :b, :c ]

Hash's can be made to do the same. What do you think?

Actually, I don't like that solution very much. It doesn't seem very
elegant.


Cheers,
Daniel
 
T

Trans

Daniel said:
Trans said:
If #delete should be altered, why should #[] and #[]= ?

You may have a point. Though it doesn't matter as much becuase it's
much less often the anyone depends on the return value of []=. ie. we
just use it to set values.

I only added #[]= because, with Facets, you can do this (as you of
course know)

hsh[:a, :b, :c] = 1, 2, 3

which matches nicely with

a, b, c = hsh[:a, :b, :c]

My point is that #delete is also a retrieval method, in the sense that
it returns the value it has removed from the hash. Therefore it is
natural for it to have the same functionality as #[], which in turn
means that we have to alter #delete in Facets.

a, b, c = hsh.delete:)a, :b, :c)

Simple and elegant.

Yea, I know what you mean. Believe me I went through the same viewpoint
when working on this for Array. Unfortunately the simplicity and
elegance start to crumble when:

a = hsh.delete(*array)

Which leads to things like:

a = [hsh.delete(*array)].flatten

or

a = hsh.delete(*array)
case a
when Array
...
else
...
end

Which means you'll just opt to use #delete_at anyway.
But to be very percise it should probably be
changed to match Array's. Consider that Array's []= method does take
multuiple parameters related to slicing. Facets' deals with that by
allowing it to also take an Array parameter:

a = []
a[[1,2,3]] = :a, :b, :c
a #=> [ :a, :b, :c ]

Hash's can be made to do the same. What do you think?

Actually, I don't like that solution very much. It doesn't seem very
elegant.

Yes, but sometime simplicity and elegance have to give way to
practicality. I do hope Matz will take some time to address the
"duckability" between Array and Hash for 2.0, though. That would
certainly go a long way toward simplicity and elegance more than
anything.

T.
 
D

Daniel Schierbeck

Trans said:
Daniel said:
Trans said:
If #delete should be altered, why should #[] and #[]= ?
You may have a point. Though it doesn't matter as much becuase it's
much less often the anyone depends on the return value of []=. ie. we
just use it to set values.
I only added #[]= because, with Facets, you can do this (as you of
course know)

hsh[:a, :b, :c] = 1, 2, 3

which matches nicely with

a, b, c = hsh[:a, :b, :c]

My point is that #delete is also a retrieval method, in the sense that
it returns the value it has removed from the hash. Therefore it is
natural for it to have the same functionality as #[], which in turn
means that we have to alter #delete in Facets.

a, b, c = hsh.delete:)a, :b, :c)

Simple and elegant.

Yea, I know what you mean. Believe me I went through the same viewpoint
when working on this for Array. Unfortunately the simplicity and
elegance start to crumble when:

a = hsh.delete(*array)

Which leads to things like:

a = [hsh.delete(*array)].flatten

or

a = hsh.delete(*array)
case a
when Array
...
else
...
end

Which means you'll just opt to use #delete_at anyway.

Of course you will. In this case, #delete_at fits perfectly well with
the intended usage. I just don't see the problem with using #delete_at
in such a case, and #delete in cases where you have a known number of keys.

I propose Facets have *both* an altered #delete *and* a #delete_at method.


Cheers,
Daniel
 
E

Eric Hodel

hsh = {:a => 1, :b => 2, :c => 3}
hsh.delete :a, :b #=> [1, 2]
hsh.delete :c #=> 3
The class of returned value varies according to the number of
arguments?

Yes. I don't see that as a big problem though, especially if
there's a second method that *always* returns an array:

hsh.delete_at :a #=> [1]
hsh.delete_at :b, :c #=> [2, 3]

It may be too much magic for some

Then it probably shouldn't go into Ruby. Especially if you are
proposing two deletion methods that I have to figure out in order to
get the behavior I want.

My brain is full enough, thanks.
 
D

Daniel Schierbeck

Eric said:
hsh = {:a => 1, :b => 2, :c => 3}
hsh.delete :a, :b #=> [1, 2]
hsh.delete :c #=> 3
The class of returned value varies according to the number of
arguments?

Yes. I don't see that as a big problem though, especially if there's a
second method that *always* returns an array:

hsh.delete_at :a #=> [1]
hsh.delete_at :b, :c #=> [2, 3]

It may be too much magic for some

Then it probably shouldn't go into Ruby. Especially if you are
proposing two deletion methods that I have to figure out in order to get
the behavior I want.

Well, I only seriously suggested to add it to Facets.


Cheers,
Daniel
 
N

nobu

Hi,

At Sat, 19 Aug 2006 03:56:56 +0900,
Eric Hodel wrote in [ruby-talk:209285]:
hsh = {:a => 1, :b => 2, :c => 3}
hsh.delete :a, :b #=> [1, 2]
hsh.delete :c #=> 3
The class of returned value varies according to the number of
arguments?

Yes. I don't see that as a big problem though, especially if
there's a second method that *always* returns an array:

hsh.delete_at :a #=> [1]
hsh.delete_at :b, :c #=> [2, 3]

It may be too much magic for some

Then it probably shouldn't go into Ruby. Especially if you are
proposing two deletion methods that I have to figure out in order to
get the behavior I want.

Possiblly, we have to wait until "true multi-value" is
introduced.
 

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. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

Command Line Arguments 0
Facets 2.8.3 released 1
Ruby Hash Keys and Related Questions 6
use of "delete" for hash keys 6
Hash#collate 8
Hash Reverse ? 8
Hash#rekey 11
Hash .each and different action for each key 7

Members online

No members online now.

Forum statistics

Threads
474,209
Messages
2,571,089
Members
47,689
Latest member
kilaocrhtbfnr

Latest Threads

Top