PHWinfo banniere

Titres
PORTAIL ANNUAIRE ARTICLES COMPARATEUR HÉBERGEURS DEVIS FORUMS RÉDUCTEUR D'URL
Précédent   PHWinfo > Autres forums > Forum Programmation & Conception > comp.lang.ruby > Suprising behaviour with "def property=" method
S'inscrire FAQ Membres Recherche Messages du jour Marquer les forums comme lus
Suprising behaviour with "def property=" method

Réponse
 
LinkBack Outils de la discussion
Vieux 24/02/2008, 22h41   #1
Farrel Lifson
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Suprising behaviour with "def property=" method

I had a bit of a surprise with the following

class Foo
def bar(value)
@bar = value.upcase
end
end

f = Foo.new
my_bar = (f.bar = "bar")

I initially thought that my_bar would == "BAR" but in fact it equals
"bar". It seems no matter what the final value of the bar= method is
the return value is always the parameters. First time I've run into
this so I thought I would share and ask if anyone can think of anyway
to get around this?

Farrel

  Réponse avec citation
Vieux 24/02/2008, 22h42   #2
Farrel Lifson
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Suprising behaviour with "def property=" method

This is on 1.8.6 on Gentoo Linux btw.

  Réponse avec citation
Vieux 24/02/2008, 22h43   #3
Farrel Lifson
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Suprising behaviour with "def property=" method

On 25/02/2008, Farrel Lifson <farrel.lifson@gmail.com> wrote:
> I had a bit of a surprise with the following
>
> class Foo
> def bar(value)
> @bar = value.upcase
> end
> end


And of course the method should be

def bar=(value)
@bar = value.upcase
end

  Réponse avec citation
Vieux 24/02/2008, 22h58   #4
Philipp Hofmann
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Suprising behaviour with "def property=" method

On Mon, Feb 25, 2008 at 07:41:31AM +0900, Farrel Lifson wrote:
> I had a bit of a surprise with the following
>
> class Foo
> def bar(value)
> @bar = value.upcase
> end
> end
>
> f = Foo.new
> my_bar = (f.bar = "bar")
>
> I initially thought that my_bar would == "BAR" but in fact it equals
> "bar". It seems no matter what the final value of the bar= method is
> the return value is always the parameters. First time I've run into
> this so I thought I would share and ask if anyone can think of anyway
> to get around this?
>
> Farrel
>



my_bar = f.send(:bar=, "bar")

g phil

  Réponse avec citation
Vieux 25/02/2008, 00h29   #5
Ezra Zygmuntowicz
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Suprising behaviour with "def property=" method


On Feb 24, 2008, at 2:41 PM, Farrel Lifson wrote:

> I had a bit of a surprise with the following
>
> class Foo
> def bar(value)
> @bar = value.upcase
> end
> end
>
> f = Foo.new
> my_bar = (f.bar = "bar")
>
> I initially thought that my_bar would == "BAR" but in fact it equals
> "bar". It seems no matter what the final value of the bar= method is
> the return value is always the parameters. First time I've run into
> this so I thought I would share and ask if anyone can think of anyway
> to get around this?
>
> Farrel



This is just the way ruby works. It *always* returns the right hand
side of any method call ending in =. This is for consistency sake.
since you can write methods that look like assignment it keeps things
consistent to always return the rhs of any assignment.


Cheers-
- Ezra Zygmuntowicz
-- Founder & Software Architect
-- ezra@engineyard.com
-- EngineYard.com


  Réponse avec citation
Vieux 25/02/2008, 01h03   #6
7stud --
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Suprising behaviour with "def property=" method

Farrel Lifson wrote:
> I had a bit of a surprise with the following
>
> class Foo
> def bar(value)
> @bar = value.upcase
> end
> end
>
> f = Foo.new
> my_bar = (f.bar = "bar")
>
> I initially thought that my_bar would == "BAR" but in fact it equals
> "bar". It seems no matter what the final value of the bar= method is
> the return value is always the parameters. First time I've run into
> this so I thought I would share and ask if anyone can think of anyway
> to get around this?
>
> Farrel


I'm not sure why the return value of calling bar= is the method
argument, but it makes sense to me that the return value is not the
*private* instance variable's value. If the return value were the
private instance variable's value, that would break the encapsulation
that a class is supposed to provide:

class Dog
def secret_code=(seed)
@secret_code = seed * 10 + 2
end
end

d = Dog.new
return_val = (d.secret_code=(3) )
puts return_val #should this reveal the secret code?
--
Posted via http://www.ruby-forum.com/.

  Réponse avec citation
Vieux 25/02/2008, 03h54   #7
James Britt
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Suprising behaviour with "def property=" method

Ezra Zygmuntowicz wrote:

> This is just the way ruby works. It *always* returns the right hand
> side of any method call ending in =. This is for consistency sake.



Except that it is inconsistent with the usually true, "The return value
of a method is the lest expression evaluated."

POLS, yada yada yada. Done deal.

Whatever it's benefits, though, it adds to list of "This is how Ruby
works, except when it doesn't."



--
James Britt

"The greatest obstacle to discovery is not ignorance, but the illusion
of knowledge."
- D. Boorstin

  Réponse avec citation
Vieux 25/02/2008, 10h51   #8
Arlen Cuss
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Suprising behaviour with "def property=" method

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

On Mon, Feb 25, 2008 at 12:03 PM, 7stud -- <bbxx789_05ss@yahoo.com> wrote:

> class Dog
> def secret_code=(seed)
> @secret_code = seed * 10 + 2
> end
> end
>
> d = Dog.new
> return_val = (d.secret_code=(3) )
> puts return_val #should this reveal the secret code?
>


Yes. What would you like it to return? The point is, you're doing
d.secret_code = 3 -- you're saying the secret code *is* 3, so actually
setting it to something else is a bit misleading, don't you think?

class Dog
def generate_secret_code(seed)
@secret_code = seed * 10 + 2
self
end
end

This has the fun of allowing method chaining;
d = Dog.new
d.generate_secret_code(3).some_other_method_that_c hains.yet_another(some,
args)

Arlen

  Réponse avec citation
Vieux 25/02/2008, 10h53   #9
Arlen Cuss
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Suprising behaviour with "def property=" method

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

Hold up a second there;

Yes. What would you like it to return? The point is, you're doing
> d.secret_code = 3 -- you're saying the secret code *is* 3, so actually
> setting it to something else is a bit misleading, don't you think?



I clearly missed the boat here. I didn't know Ruby always returned the rval
of the expression.

You learn something new every day. Sorry for biting.

Arlen

  Réponse avec citation
Vieux 25/02/2008, 12h10   #10
marc
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Suprising behaviour with "def property=" method

7stud -- said...
> Farrel Lifson wrote:
> > I had a bit of a surprise with the following
> >
> > class Foo
> > def bar(value)
> > @bar = value.upcase
> > end
> > end
> >
> > f = Foo.new
> > my_bar = (f.bar = "bar")
> >
> > I initially thought that my_bar would == "BAR" but in fact it equals
> > "bar". It seems no matter what the final value of the bar= method is
> > the return value is always the parameters. First time I've run into
> > this so I thought I would share and ask if anyone can think of anyway
> > to get around this?
> >
> > Farrel

>
> I'm not sure why the return value of calling bar= is the method
> argument, but it makes sense to me that the return value is not the
> *private* instance variable's value. If the return value were the
> private instance variable's value, that would break the encapsulation
> that a class is supposed to provide:
>
> class Dog
> def secret_code=(seed)
> @secret_code = seed * 10 + 2
> end
> end
>
> d = Dog.new
> return_val = (d.secret_code=(3) )
> puts return_val #should this reveal the secret code?
>


I concur; the OP's expected behaviour would break encapsulation.

class Foo
attr_reader :bar
def bar=(value)
@bar = value.upcase
end
end

f = Foo.new
my_bar = (f.bar = "bar")
puts my_bar # "bar"
puts f.bar # "BAR"

g = Foo.new
g.bar = "bar"
puts g.bar # "BAR"

--
Cheers,
Marc


  Réponse avec citation
Vieux 25/02/2008, 17h26   #11
James Britt
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Suprising behaviour with "def property=" method

Arlen Cuss wrote:
> On Mon, Feb 25, 2008 at 12:03 PM, 7stud -- <bbxx789_05ss@yahoo.com> wrote:
>
>> class Dog
>> def secret_code=(seed)
>> @secret_code = seed * 10 + 2
>> end
>> end
>>
>> d = Dog.new
>> return_val = (d.secret_code=(3) )
>> puts return_val #should this reveal the secret code?
>>

>
> Yes. What would you like it to return? The point is, you're doing
> d.secret_code = 3 -- you're saying the secret code *is* 3, so actually
> setting it to something else is a bit misleading, don't you think?


Actually, you're saying "Send the message '.secret_code=(3)' to d"

It's up to d to decide what that means and what happens next.

Suppose secret_code=(x) checks that the given value meets some criteria
(say, is a positive int), and if not, uses the value 0. I might want
the method to then return a valid value, not simply what was passed in.



--
James Britt

"We are using here a powerful strategy of synthesis: wishful thinking."
- H. Abelson and G. Sussman
(in "The Structure and Interpretation of Computer Programs)

  Réponse avec citation
Vieux 25/02/2008, 19h09   #12
Mark Bush
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Suprising behaviour with "def property=" method

James Britt wrote:
> Suppose secret_code=(x) checks that the given value meets some criteria
> (say, is a positive int), and if not, uses the value 0. I might want
> the method to then return a valid value, not simply what was passed in.


If the setter is called in an assignment context, the assignment will
always return the rhs regardless of what the setter returns. This is
for compatibility as Ezra pointed out.

If you do:
a = b = c = 3
what's the value of a? You would expect it to be 3.

What about:
a = b.bar = c = 3
What is a now? Again, wouldn't you still be hoping it would be 3?

Assignment is a syntactic construct. "b.bar = 3" is not a method call,
it's an assignment. Part of evaluating that assignment involves
invoking a method, but, by definition, assignment returns the rhs, so
whatever happens with any method so invoked, its value is lost.
--
Posted via http://www.ruby-forum.com/.

  Réponse avec citation
Vieux 25/02/2008, 19h59   #13
Gary Wright
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Suprising behaviour with "def property=" method


On Feb 25, 2008, at 2:09 PM, Mark Bush wrote:
> Assignment is a syntactic construct. "b.bar = 3" is not a method
> call,
> it's an assignment.


I would modify that a bit and say that

(b.bar = 3)

is an assignment expression with a side-effect
that happens to be a method call. Consider

(a = 3)

which is also an assignment expression but with
a side-effect of changing the binding of 'a'.

So the 'strange' behavior of setter methods
comes about because of the context in which they
are called, not because they behave differently
from other methods.

The return value of any method can be discarded
in the right context:

c = begin
a # return value discarded
b # return value becomes value of begin/end
end

Gary Wright

  Réponse avec citation
Vieux 26/02/2008, 06h31   #14
James Britt
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Suprising behaviour with "def property=" method

Mark Bush wrote:
> James Britt wrote:
>> Suppose secret_code=(x) checks that the given value meets some criteria
>> (say, is a positive int), and if not, uses the value 0. I might want
>> the method to then return a valid value, not simply what was passed in.

>
> If the setter is called in an assignment context, the assignment will
> always return the rhs regardless of what the setter returns. This is
> for compatibility as Ezra pointed out.


Compatibility with *what*? Not with how other methods behave.

It's a cultural thing.

>
> If you do:
> a = b = c = 3
> what's the value of a? You would expect it to be 3.


Perhaps. Depends on the language. But let's assume so.

>
> What about:
> a = b.bar = c = 3
> What is a now? Again, wouldn't you still be hoping it would be 3?



No.

Depends on b. Maybe 3 is not a valid argument for whatever bar does.

I expect that if I'm involving an object then that object may have its
own ideas about how to handle the request. That's sort of their job.


>
> Assignment is a syntactic construct.


Assignment creates or changes a variable binding.

> "b.bar = 3" is not a method call,
> it's an assignment.


b.methods.include?( 'bar=' )


def b.bar=( arg )
exit if arg % 2 == 0
end

Pedantic, sure, but believing that "=" always means a setter method, or
is altering an attribute named in the message, is a mistake. It's
seems mainly to be a convenience for people who like to think in terms
of getters and setters rather than pure messages and private attributes.

It's handy, but a little heavy-handed.

Here's a less churlish example:

def b.bar=(x)
@bar = x.to_i.abs
end

Sadly, this will not return the value of @bar.

Most people don't have a problem with this, and I suspect that was a
reason matz made Ruby behave this way. But it seems to impede a broader
understanding of how Ruby works (and maybe that is part of the reason
some folks misuse, for example, open classes.)

It's a trade-off.

> Part of evaluating that assignment involves
> invoking a method, but, by definition,


The definition comes first, and can be otherwise.

> assignment returns the rhs, so
> whatever happens with any method so invoked, its value is lost.


As so behaviorally defined in Ruby for methods of a certain form. It
breaks the simpler concept of all object interaction being done with
messages, and all methods returning the value of the last executed
expression.

But, again, this is PO(matz)LS. I think I understand why matz choose
it, but it was a matter of taste, not immutable laws of computer science.


--
James Britt

"The use of anthropomorphic terminology when dealing with
computing systems is a symptom of professional immaturity."
- Edsger W. Dijkstra

  Réponse avec citation
Réponse


Outils de la discussion

Règles de messages
Vous ne pouvez pas créer de nouvelles discussions
Vous ne pouvez pas envoyer des réponses
Vous ne pouvez pas envoyer des pièces jointes
Vous ne pouvez pas modifier vos messages

Les balises BB sont activées : oui
Les smileys sont activés : oui
La balise [IMG] est activée : oui
Le code HTML peut être employé : non
Trackbacks are oui
Pingbacks are oui
Refbacks are oui


Fuseau horaire GMT +1. Il est actuellement 20h55.


Édité par : vBulletin® version 3.7.3
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Search Engine Friendly URLs by vBSEO 3.2.0 RC5 Tous droits réservés.
Version française #16 par l'association vBulletin francophone
PHWinfo est un site Éducation Sans Frontières ©2000-2008
Ad Management by RedTyger
©Tous droits réservés par les parties respectives
Page generated in 0,24971 seconds with 22 queries