Delete_if, select and (lack of) delete_if!, self.POLS == false

Hey everyone,

I was looking today for version of Array#select that would mutate the array
by deleting selected elements from it.
I first looked at delete_if, then noticed that it actually mutates original
array and returns mutated array. I wonder would it make sense for delete_if
not to mutate and return new array and delete_if! to mutate and return deleted
elements?

Of course what I want is simple method to implement, it just seems pretty
typical desire for Array#select usage cases and also perhaps mutating
delete_if is as well bit unexpected? Problem is, suggested change would
break many current delete_if usage cases.

Thanks,

···

--
  ++ytti

a non-mutating delete_if is already there:

   array.select{|element| not orginal_condition(element)}

ie

   odds = [0,1,2,3].select{|i| not i.even?}

a @ http://codeforpeople.com/

···

On Apr 11, 2008, at 10:26 AM, Saku Ytti wrote:

Hey everyone,

I was looking today for version of Array#select that would mutate the array
by deleting selected elements from it.
I first looked at delete_if, then noticed that it actually mutates original
array and returns mutated array. I wonder would it make sense for delete_if
not to mutate and return new array and delete_if! to mutate and return deleted
elements?

Of course what I want is simple method to implement, it just seems pretty
typical desire for Array#select usage cases and also perhaps mutating
delete_if is as well bit unexpected? Problem is, suggested change would
break many current delete_if usage cases.

--
we can deny everything, except that we have the possibility of being better. simply reflect on that.
h.h. the 14th dalai lama

Hi --

···

On Sat, 12 Apr 2008, Saku Ytti wrote:

Hey everyone,

I was looking today for version of Array#select that would mutate the array
by deleting selected elements from it.
I first looked at delete_if, then noticed that it actually mutates original
array and returns mutated array. I wonder would it make sense for delete_if
not to mutate and return new array and delete_if! to mutate and return deleted
elements?

Of course what I want is simple method to implement, it just seems pretty
typical desire for Array#select usage cases and also perhaps mutating
delete_if is as well bit unexpected? Problem is, suggested change would
break many current delete_if usage cases.

You should use #reject, which is non-destructive.

David

--
Rails training from David A. Black and Ruby Power and Light:
   ADVANCING WITH RAILS April 14-17 New York City
   INTRO TO RAILS June 9-12 Berlin
   ADVANCING WITH RAILS June 16-19 Berlin
See http://www.rubypal.com for details and updates!

Hi --

···

On Sat, 12 Apr 2008, ara.t.howard wrote:

On Apr 11, 2008, at 10:26 AM, Saku Ytti wrote:

Hey everyone,

I was looking today for version of Array#select that would mutate the array
by deleting selected elements from it.
I first looked at delete_if, then noticed that it actually mutates original
array and returns mutated array. I wonder would it make sense for delete_if
not to mutate and return new array and delete_if! to mutate and return deleted
elements?

Of course what I want is simple method to implement, it just seems pretty
typical desire for Array#select usage cases and also perhaps mutating
delete_if is as well bit unexpected? Problem is, suggested change would
break many current delete_if usage cases.

a non-mutating delete_if is already there:

array.select{|element| not orginal_condition(element)}

ie

odds = [0,1,2,3].select{|i| not i.even?}

Also:

   odds = [0,1,2,3].reject {|i| i.even? }

David

--
Rails training from David A. Black and Ruby Power and Light:
   ADVANCING WITH RAILS April 14-17 New York City
   INTRO TO RAILS June 9-12 Berlin
   ADVANCING WITH RAILS June 16-19 Berlin
See http://www.rubypal.com for details and updates!

Thanks everyone for fast reply.

I first looked at delete_if, then noticed that it actually mutates original
array and returns mutated array. I wonder would it make sense for delete_if
not to mutate and return new array and delete_if! to mutate and return deleted
elements?

You should use #reject, which is non-destructive.

I guess I wasn't being clear, indeed reject removes the need for
non-mutating delete_if, which would make them equal. However, we're still
without method that does select, but mutates the returned elements out from
the original array.
If we'd have it, I guess select! would be bit odd name for it? And if it would
be delete_if! then mutating delete_if would be even more surprising?

Also, I may be biased with my own problem thinking that select that removes
elements from array is typical need. Just feels so at the moment.

···

On (2008-04-12 01:32 +0900), David A. Black wrote:

--
  ++ytti

I guess even I could come up with an odd solution. (t'is 1 funny maybe?)
R.

···

On Fri, Apr 11, 2008 at 6:36 PM, David A. Black <dblack@rubypal.com> wrote:

Hi --

On Sat, 12 Apr 2008, ara.t.howard wrote:

>
> On Apr 11, 2008, at 10:26 AM, Saku Ytti wrote:
>
> > Hey everyone,
> >
> > I was looking today for version of Array#select that would mutate the
array
> > by deleting selected elements from it.
> > I first looked at delete_if, then noticed that it actually mutates
original
> > array and returns mutated array. I wonder would it make sense for
delete_if
> > not to mutate and return new array and delete_if! to mutate and return
deleted
> > elements?
> >
> > Of course what I want is simple method to implement, it just seems
pretty
> > typical desire for Array#select usage cases and also perhaps mutating
> > delete_if is as well bit unexpected? Problem is, suggested change would
> > break many current delete_if usage cases.
> >
>
> a non-mutating delete_if is already there:
>
> array.select{|element| not orginal_condition(element)}
>
> ie
>
> odds = [0,1,2,3].select{|i| not i.even?}
>

Also:

  odds = [0,1,2,3].reject {|i| i.even? }

--
http://ruby-smalltalk.blogspot.com/

---
Whereof one cannot speak, thereof one must be silent.
Ludwig Wittgenstein

Thanks everyone for fast reply.

>> I first looked at delete_if, then noticed that it actually mutates original
>> array and returns mutated array. I wonder would it make sense for delete_if
>> not to mutate and return new array and delete_if! to mutate and return deleted
>> elements?
>

> You should use #reject, which is non-destructive.

I guess I wasn't being clear, indeed reject removes the need for
non-mutating delete_if, which would make them equal. However, we're still
without method that does select, but mutates the returned elements out from
the original array.
If we'd have it, I guess select! would be bit odd name for it? And if it would
be delete_if! then mutating delete_if would be even more surprising?

Also, I may be biased with my own problem thinking that select that removes
elements from array is typical need. Just feels so at the moment.

No, I agree with you but OTOH not many seem to see the need for this
and the community is rather pragmatic about these things.
I would prefer to have a reject and a reject! but I am pragmatic about
democracy ;), and a large majority seems not to see the need for this.
Now I would love to stand corrected of course ;).

Cheers
Robert

···

On Fri, Apr 11, 2008 at 6:46 PM, Saku Ytti <saku@ytti.fi> wrote:

On (2008-04-12 01:32 +0900), David A. Black wrote:

--
  ++ytti

--
http://ruby-smalltalk.blogspot.com/

---
Whereof one cannot speak, thereof one must be silent.
Ludwig Wittgenstein

Hi --

···

On Sat, 12 Apr 2008, Saku Ytti wrote:

On (2008-04-12 01:32 +0900), David A. Black wrote:

Thanks everyone for fast reply.

I first looked at delete_if, then noticed that it actually mutates original
array and returns mutated array. I wonder would it make sense for delete_if
not to mutate and return new array and delete_if! to mutate and return deleted
elements?

You should use #reject, which is non-destructive.

I guess I wasn't being clear, indeed reject removes the need for
non-mutating delete_if, which would make them equal. However, we're still
without method that does select, but mutates the returned elements out from
the original array.
If we'd have it, I guess select! would be bit odd name for it? And if it would
be delete_if! then mutating delete_if would be even more surprising?

Also, I may be biased with my own problem thinking that select that removes
elements from array is typical need. Just feels so at the moment.

So you want a kind of #keep_if ?

David

--
Rails training from David A. Black and Ruby Power and Light:
   ADVANCING WITH RAILS April 14-17 New York City
   INTRO TO RAILS June 9-12 Berlin
   ADVANCING WITH RAILS June 16-19 Berlin
See http://www.rubypal.com for details and updates!

Hmm yeah, so you'd name them something like this?

class Array;def reject!(&blk)
reject(&blk).each{|e|delete e};end
def select!(&blk)
select(&blk).each{|e|delete e};end;end

so reject! does mutating reject and returns non-rejected
and select! does mutating select and returns non-selected.

So if I'd want the 'select' behaviour I was missing, I'd
just call reject!

Upside of this solution is, it wouldn't tinker with
anything existing. But still not sure if people commonly
want something like this.

···

On (2008-04-12 02:08 +0900), Robert Dober wrote:

No, I agree with you but OTOH not many seem to see the need for this
and the community is rather pragmatic about these things.
I would prefer to have a reject and a reject! but I am pragmatic about
democracy ;), and a large majority seems not to see the need for this.
Now I would love to stand corrected of course ;).

--
  ++ytti

Just to implement the previous suggestion correctly(tm) this time.

This is more or less what I want
class Array;def reject!(&blk)
select(&blk).each{|e|delete e};end
def select!(&blk)
reject(&blk).each{|e|delete e};end;end

now if I do array.reject! I actually get array mutated
but it returns the non-rejected.
So kinda destructive/mutating select.

···

On (2008-04-12 02:26 +0900), David A. Black wrote:

So you want a kind of #keep_if ?

--
  ++ytti

Actually just inside out, reject! should be select(&blk)
and select! should be reject(&blk).

···

On (2008-04-12 02:26 +0900), Saku Ytti wrote:

class Array;def reject!(&blk)
reject(&blk).each{|e|delete e};end
def select!(&blk)
select(&blk).each{|e|delete e};end;end

--
  ++ytti

> class Array;def reject!(&blk)
> reject(&blk).each{|e|delete e};end
> def select!(&blk)
> select(&blk).each{|e|delete e};end;end

Actually just inside out, reject! should be select(&blk)
and select! should be reject(&blk).

No, not quite

x=[*0..1]
x.select{|n| n.even?} -> [0]
x -> [0,1]
x.reject!{|n| n.odd?} -> [0]
x -> [0]

Cheers
Robert

···

On Fri, Apr 11, 2008 at 7:31 PM, Saku Ytti <saku@ytti.fi> wrote:

On (2008-04-12 02:26 +0900), Saku Ytti wrote:

--
  ++ytti

--
http://ruby-smalltalk.blogspot.com/

---
Whereof one cannot speak, thereof one must be silent.
Ludwig Wittgenstein

x=[*0..1]
x.select{|n| n.even?} -> [0]
x -> [0,1]
x.reject!{|n| n.odd?} -> [0]
x -> [0]

Not sure what's going on there, but this looks correct to me:

irb(main):001:0> class Array;def reject!(&blk)
irb(main):002:2> select(&blk).each{|e|delete e};end
irb(main):003:1> def select!(&blk)
irb(main):004:2> reject(&blk).each{|e|delete e};end;end
=> nil
irb(main):005:0> x=[*0..1]
=> [0, 1]
irb(main):006:0> x.select{|n| n.even?}
=> [0]
irb(main):007:0> x
=> [0, 1]
irb(main):008:0> x.reject!{|n| n.odd?}
=> [1]
irb(main):009:0> x
=> [0]
irb(main):010:0>

···

On (2008-04-12 04:04 +0900), Robert Dober wrote:

Cheers
Robert

> --
> ++ytti
>
>

--
http://ruby-smalltalk.blogspot.com/

---
Whereof one cannot speak, thereof one must be silent.
Ludwig Wittgenstein

--
  ++ytti

Hi --

x=[*0..1]
x.select{|n| n.even?} -> [0]
x -> [0,1]
x.reject!{|n| n.odd?} -> [0]
x -> [0]

Not sure what's going on there, but this looks correct to me:

select is selecting all the even ones, and reject! is rejecting all
the odd ones, and in both cases, you're seeing the results (the array
with only the even ones; the array without the odd ones). In the case
of reject! you're also seeing that the contents of the array have been
replaced with the results of the reject operation.

I think if you want a reject operation whose return value is the same
as a select operation, you'll probably need to come up with a new
method name :slight_smile:

David

···

On Sat, 12 Apr 2008, Saku Ytti wrote:

On (2008-04-12 04:04 +0900), Robert Dober wrote:

--
Rails training from David A. Black and Ruby Power and Light:
   ADVANCING WITH RAILS April 14-17 New York City
   INTRO TO RAILS June 9-12 Berlin
   ADVANCING WITH RAILS June 16-19 Berlin
See http://www.rubypal.com for details and updates!

select is selecting all the even ones, and reject! is rejecting all
the odd ones, and in both cases, you're seeing the results (the array
with only the even ones; the array without the odd ones). In the case
of reject! you're also seeing that the contents of the array have been
replaced with the results of the reject operation.

Are you talking about your example or my example? They did different thing,
I'm not sure why your did what it did above.

I think if you want a reject operation whose return value is the same
as a select operation, you'll probably need to come up with a new
method name :slight_smile:

The reject! in my example does mutable reject, as one would expect.
But it also returns the non-rejected entries (that is, those entries that
select for same block would return).

Again, I'm not sure if this as typical need for select as I think it is.
But if think of all applications where you need to split array to multiple
arrays in a way where no entry can be ever needed to put to multiple
arrays, it would be lot cheaper to reduce the array size while going
it through. Kinda like select + pop, if you want another way to think
of it.

Thanks,

···

On (2008-04-12 04:20 +0900), David A. Black wrote:
--
  ++ytti

Hi --

···

On Sat, 12 Apr 2008, Saku Ytti wrote:

On (2008-04-12 04:20 +0900), David A. Black wrote:

select is selecting all the even ones, and reject! is rejecting all
the odd ones, and in both cases, you're seeing the results (the array
with only the even ones; the array without the odd ones). In the case
of reject! you're also seeing that the contents of the array have been
replaced with the results of the reject operation.

Are you talking about your example or my example? They did different thing,
I'm not sure why your did what it did above.

I think if you want a reject operation whose return value is the same
as a select operation, you'll probably need to come up with a new
method name :slight_smile:

The reject! in my example does mutable reject, as one would expect.
But it also returns the non-rejected entries (that is, those entries that
select for same block would return).

Having reject return the non-rejected entries is what I was referring
to. That's not how reject (with or without !) works, so if you want a
method that does that you'd want to find a different name for it.

David

--
Rails training from David A. Black and Ruby Power and Light:
   ADVANCING WITH RAILS April 14-17 New York City
   INTRO TO RAILS June 9-12 Berlin
   ADVANCING WITH RAILS June 16-19 Berlin
See http://www.rubypal.com for details and updates!

The reject! in my example does mutable reject, as one would expect.
But it also returns the non-rejected entries (that is, those entries that
select for same block would return).

Having reject return the non-rejected entries is what I was referring
to. That's not how reject (with or without !) works, so if you want a
method that does that you'd want to find a different name for it.

Ok, so your intention with your example was to show how you think
reject! should work, return same array as the destination
would be after? Not an example run of how I wish it would work.
Then we can just agree to disagree :). I don't see any problem
foo! method returning different value than the value of
destination object after the method has finished.

Random core example:

moi.squeeze

=> "moi"

moi.squeeze!

=> nil

moi

=> "moi"

Thanks,

···

On (2008-04-12 04:37 +0900), David A. Black wrote:
--
  ++ytti

Hi --

···

On Sat, 12 Apr 2008, Saku Ytti wrote:

On (2008-04-12 04:37 +0900), David A. Black wrote:

The reject! in my example does mutable reject, as one would expect.
But it also returns the non-rejected entries (that is, those entries that
select for same block would return).

Having reject return the non-rejected entries is what I was referring
to. That's not how reject (with or without !) works, so if you want a
method that does that you'd want to find a different name for it.

Ok, so your intention with your example was to show how you think
reject! should work, return same array as the destination
would be after? Not an example run of how I wish it would work.
Then we can just agree to disagree :). I don't see any problem
foo! method returning different value than the value of
destination object after the method has finished.

Random core example:

moi.squeeze

=> "moi"

moi.squeeze!

=> nil

moi

=> "moi"

There's no general principle at stake; I'm just saying that if you
want a method that behaves like select but performs an in-place
reject, it's better to invent a name than override Enumerable#reject!.

David

--
Rails training from David A. Black and Ruby Power and Light:
   ADVANCING WITH RAILS April 14-17 New York City
   INTRO TO RAILS June 9-12 Berlin
   ADVANCING WITH RAILS June 16-19 Berlin
See http://www.rubypal.com for details and updates!

I see what you mean, and I fully agree that changing existing
methods would cause lot of inconvenience. Kinda just wish this
functionality would be built-in (for performnce reasons), and
select!, reject!, delete_if! might be feasible candidates from
different points of view, if there wasn't history as a burden.
Anyhow than you for your insight.

···

On (2008-04-12 04:54 +0900), David A. Black wrote:

There's no general principle at stake; I'm just saying that if you
want a method that behaves like select but performs an in-place
reject, it's better to invent a name than override Enumerable#reject!.

--
  ++ytti

think about that

   [0, 1, 2, 3].reject!{|i| i.odd}

is going to do mutiple array replacements, so

   [0,2,3]
   [0,3]

shuffling an array like that all the way would KILL performance. you need to build a new array and then replace all at once. of course that is already there

   a.replace a.select{|i| i.odd?}

which reads clearly and doesn't degrade to exponential array shuffling...

food for though

a @ http://codeforpeople.com/

···

On Apr 11, 2008, at 2:07 PM, Saku Ytti wrote:

I see what you mean, and I fully agree that changing existing
methods would cause lot of inconvenience. Kinda just wish this
functionality would be built-in (for performnce reasons), and
select!, reject!, delete_if! might be feasible candidates from
different points of view, if there wasn't history as a burden.
Anyhow than you for your insight.

--
we can deny everything, except that we have the possibility of being better. simply reflect on that.
h.h. the 14th dalai lama