[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

x.f! RCR

Greg McIntyre

11/19/2003 12:49:00 PM

It bugs me that some methods have a ! on the end and some don't. It
seems very arbitrary and inconsistent to me. And the same for ?. I'd
like it if ! was a special keyword or operator or something, so that

x.f!

was expanded to this

(x = x.f)

if x#f! was not already defined (so that in-place algorithms retained
their efficiency). Has this already been suggested?

--
Greg McIntyre ======[ greg@puyo.cjb.net ]===[ http://pu... ]===
19 Answers

Greg McIntyre

11/19/2003 1:10:00 PM

0

After thinking more about this, I can see why certain methods have a !
version available and others don't. Or I think I do. It's about data
encapsulation, to some extent. If I have

class Foo
attr :bar

def initialize
@bar = [1,2,3]
end
end
foo = Foo.new

I want to allow

foo.bar.map!{|x| x*2 }

Because it's convenient and it seems legitimate. But I don't want things
which will change@bar's class. Like

foo.bar.join!(', ')

would be bad because then @bar would be something completely different
all of a sudden and the poor Foo object and its clients might not like
that. More generally, I guess this is about repeatable methods. There's
a word for that, I've forgotten. i.e. You can do this:

foo.bar.map!{|x| x*2 }.map!{|x| x*2 }

But you can't do this:

foo.bar.join!(', ').join!(', ')

Hence join! is not defined.

Am I on the right track?


Greg McIntyre <greg@puyo.cjb.net> wrote:
> It bugs me that some methods have a ! on the end and some don't. It
> seems very arbitrary and inconsistent to me. And the same for ?. I'd
> like it if ! was a special keyword or operator or something, so that
>
> x.f!
>
> was expanded to this
>
> (x = x.f)
>
> if x#f! was not already defined (so that in-place algorithms retained
> their efficiency). Has this already been suggested?
>
> --
> Greg McIntyre ======[ greg@puyo.cjb.net ]===[ http://pu... ]===


--
Greg McIntyre ======[ greg@puyo.cjb.net ]===[ http://pu... ]===

Maik Schmidt

11/19/2003 1:29:00 PM

0

Greg McIntyre wrote:
> It bugs me that some methods have a ! on the end and some don't. It
> seems very arbitrary and inconsistent to me. And the same for ?.

Hmm, maybe the whole thing is much simpler than you think:

From matz' "Ruby in a nutshell":

<quote>
You can append ! or ? to the name of a Ruby method. Traditionally,
! is appended to a method that requires more caution than the variant
of the same name without !. A question mark ? is appended to a method
that determines the state of a Boolean value, true or false.
</quote>

That's all.

Cheers,

<maik/>

Greg McIntyre

11/19/2003 1:55:00 PM

0

Maik Schmidt <contact@maik-schmidt.de> wrote:
> Greg McIntyre wrote:
> > It bugs me that some methods have a ! on the end and some don't. It
> > seems very arbitrary and inconsistent to me. And the same for ?.
>
> Hmm, maybe the whole thing is much simpler than you think:
>
> From matz' "Ruby in a nutshell":
>
> <quote>
> You can append ! or ? to the name of a Ruby method. Traditionally,
> ! is appended to a method that requires more caution than the variant
> of the same name without !. A question mark ? is appended to a method
> that determines the state of a Boolean value, true or false.
> </quote>

Yes, but it wasn't until about 15 minutes ago that I understood why, in
the standard library, some methods have ! and some don't. That is, what
the actual rationale is. I'm not talking about capability, I'm talking
about actual practice. Until 15 mintues ago, it just seemed like
inconsistent use. And there is still some inconsistency. I think
Array#delete_if should be Array#delete_if!, for example.

I think it's a subtle issue. Too subtle. If it took me months of being a
Ruby enthusiast to pay enough attention to figure it out, I think it's
probably a bit too tricky... but maybe it's just me being stupid. ?:)

--
Greg McIntyre ======[ greg@puyo.cjb.net ]===[ http://pu... ]===

Maik Schmidt

11/19/2003 1:56:00 PM

0

> I think it's a subtle issue. Too subtle. If it took me months of being a
> Ruby enthusiast to pay enough attention to figure it out, I think it's
> probably a bit too tricky... but maybe it's just me being stupid. ?:)
>

You are absolutely right. My point is much simpler: It is nearly
impossible to enforce the behaviour you expect. Currently, developers
use the ! and ? in arbitrary ways and often they simply forget to use it
(it's the same with 'const' in C++, e.g., it is a really good feature,
but many developers simply forget to use it as often as possible). So,
even if the simple convention to use ! and ? in method names would be
replaced by any other syntactic construct, the problem would remain the
same, but IMHO you would have added another piece of syntactic sugar to
the Ruby language that would be of at least questionable benefit.

Cheers,

<maik/>

Michael Neumann

11/19/2003 2:50:00 PM

0

Greg McIntyre wrote:
> Maik Schmidt <contact@maik-schmidt.de> wrote:
> > Greg McIntyre wrote:
> > > It bugs me that some methods have a ! on the end and some don't. It
> > > seems very arbitrary and inconsistent to me. And the same for ?.
> >
> > Hmm, maybe the whole thing is much simpler than you think:
> >
> > From matz' "Ruby in a nutshell":
> >
> > <quote>
> > You can append ! or ? to the name of a Ruby method. Traditionally,
> > ! is appended to a method that requires more caution than the variant
> > of the same name without !. A question mark ? is appended to a method
> > that determines the state of a Boolean value, true or false.
> > </quote>
>
> Yes, but it wasn't until about 15 minutes ago that I understood why, in
> the standard library, some methods have ! and some don't. That is, what
> the actual rationale is. I'm not talking about capability, I'm talking
> about actual practice. Until 15 mintues ago, it just seemed like
> inconsistent use. And there is still some inconsistency. I think
> Array#delete_if should be Array#delete_if!, for example.

My understanding is, that "delete" is a destructive word itself, so it doesn't
need to be marked explicitly as "dangerous". If you need a non-destructive
delete_if version, better use the Enumerable#reject method, which IMHO
describes better it's internal sematics. Here, it's destructive counterpart,
reject! exists.

Your suggestion is that delete_if does not delete anything (it creates a new
array), where delete_if! would. Principle of Least Surprise? Not for me!


Regards,

Michael


Dan Doel

11/19/2003 5:43:00 PM

0

Michael Neumann wrote:

>Your suggestion is that delete_if does not delete anything (it creates a new
>array), where delete_if! would. Principle of Least Surprise? Not for me!
>
>

That depends on your background, I suppose. If I'm not mistaken, ! and
? probably come from Scheme,
where ! is usually used to denote that it causes a side effect on the
arguments. Since Scheme advocates
functional programming,

(delete_if predicate list)

would return a new list with the proper elements deleted, while

(delete_if! predicate list)

would delete the elements in place (probably returning the list as well).

If you're writing in a functional manner, it's not at all surprising to
expect a delete... or remove... function to
not modify the initial list (in fact it's almost a requirement if you
want to prove certain correctness
requirements for a program). In that case, the fact that there is no
#delete_if that doesn't modify the base
list would be an inconvenience. Not that Ruby's lists are exactly
suited for functional programming, but
food for thought.

Cheers.

- Dan



Michael Neumann

11/19/2003 8:15:00 PM

0

On Thu, Nov 20, 2003 at 02:43:20AM +0900, Dan Doel wrote:
> Michael Neumann wrote:
>
> >Your suggestion is that delete_if does not delete anything (it creates a
> >new
> >array), where delete_if! would. Principle of Least Surprise? Not for me!
> >
> >
>
> That depends on your background, I suppose. If I'm not mistaken, ! and
> ? probably come from Scheme,

I've to admit, I never really used Scheme or Lisp.

> where ! is usually used to denote that it causes a side effect on the
> arguments. Since Scheme advocates
> functional programming,
>
> (delete_if predicate list)
>
> would return a new list with the proper elements deleted, while
>
> (delete_if! predicate list)
>
> would delete the elements in place (probably returning the list as well).
>
> If you're writing in a functional manner, it's not at all surprising to
> expect a delete... or remove... function to
> not modify the initial list (in fact it's almost a requirement if you
> want to prove certain correctness
> requirements for a program). In that case, the fact that there is no
> #delete_if that doesn't modify the base
> list would be an inconvenience. Not that Ruby's lists are exactly
> suited for functional programming, but
> food for thought.

Thanks for the insights into Scheme. Scheme is probably much more
consistent than Ruby. Ruby instead favours 'matz' POLS over consistence
(but it's not that inconsistent at all :-).

Regards,

Michael


Greg McIntyre

11/19/2003 10:42:00 PM

0

Michael Neumann <uu9r@stud.uni-karlsruhe.de> wrote:
> My understanding is, that "delete" is a destructive word itself, so it
> doesn't need to be marked explicitly as "dangerous". If you need a
> non-destructive delete_if version, better use the Enumerable#reject
> method, which IMHO describes better it's internal sematics. Here, it's
> destructive counterpart, reject! exists.
>
> Your suggestion is that delete_if does not delete anything (it creates
> a new array), where delete_if! would. Principle of Least Surprise? Not
> for me!

That isn't my suggestion, but we do have conflicting POLS. :)

My suggestion is that one _should_ be able to do this:

a = [1,2,3]
a.join!

with only Array#join defined.

Basically I see inconsistency. Personally I'd expect delete_if to have
a ! because it modifies the receiver like map! and reject!, regardless
of whether it's clear. Clarity is not just subjective, it's highly
subjective! :)

So _is_ there a rule or mnemonic for ! usage in method names, other than
"danger"? Is there a technical rule? In the standard library it seems to
be that ! is used for in-place transformations to the same class; is
that it?

--
Greg McIntyre ======[ greg@puyo.cjb.net ]===[ http://pu... ]===

Brett H. Williams

11/19/2003 11:02:00 PM

0

On Nov 20, Greg McIntyre wrote:
[snip]
> My suggestion is that one _should_ be able to do this:
>
> a = [1,2,3]
> a.join!
>
> with only Array#join defined.

What would this do? Something like a = a.join ?

irb(main):001:0> a = [1,2,3] # => [1, 2, 3]
irb(main):002:0> a.join! # => "123"
irb(main):003:0> a # => "123"

??

The above is doing a variable assignment with a method. So the receiver is
a different object after the method is called.

This sounds undesirable. I think of ! as either meaning danger OR operate
on an existing object, but not this.

I'm not sure this is even possible in Ruby, but I know it violates my POLS
:|

--
---------------------------------------------- | --------------------------
Brett Williams | (970) 288-0475
Agilent Technologies | brett_williams@agilent.com
---------------------------------------------- | --------------------------

Greg McIntyre

11/19/2003 11:12:00 PM

0

"Brett H. Williams" <brett_williams@agilent.com> wrote:
> The above is doing a variable assignment with a method. So the
> receiver is a different object after the method is called.

That's true...

So that's 1 reason against it so far. However ! does mean danger... :)


> This sounds undesirable. I think of ! as either meaning danger OR
> operate on an existing object, but not this.
>
> I'm not sure this is even possible in Ruby, but I know it violates my
> POLS:|

I must have a non-standard POLS. :) I can see this trend continuing, so
I'll happily stand down my idea. I don't like treading on other people's
POLS. I think really I just needed to understand the reasons behind !.
There's a long road between code being implemented and code being used
and sometimes the rationales get lost along the way.

--
Greg McIntyre ======[ greg@puyo.cjb.net ]===[ http://pu... ]===