I’m learning Ruby, and trying to grasp the non-declarative concept with
some small difficulties. Specifically, I can’t use a private lvalue
method the way I want. Please excuse me if this is a FAQ, but I
couldn’t find it.
Let’s say I have a class with a private method, say:
private
def dollars=(someDollars)
@cents = someDollars * 100
end
And if I want to use this method from some other method in the class, I
always create a local variable instead. I can’t prepend the method name
with a receiver (“self”) because the method is private.
For exmaple, this assigns to a local variable instead of using the
private method above:
public
def fillWallet
dollars = 100
puts “Wow! You’ve got $” + dollars().to_s
end
How do I call a private lvalue method?
Steve
···
–
Steven Smolinski => http://arbiter.ca/
GnuPG Public Key => http://arbiter.ca/steves_public_key.txt
=> or email me with ‘auto-key’ in the subject.
Key Fingerprint => 08C8 6481 3A7B 2A1C 7C26 A5FC 1A1B 66AB F637 495D
Hmmm… so self.dollars = 100 doesn’t work, eh? Only answer I can
think of is
self.send(:dollars=, 100)
Beautiful, isn’t it? 
Actually, a better answer came to mind. Make :dollars= protected
instead of private. It works.
Gavin
···
On Friday, February 7, 2003, 10:35:08 AM, Steven wrote:
Let’s say I have a class with a private method, say:
private
def dollars=(someDollars)
@cents = someDollars * 100
end
And if I want to use this method from some other method in the class, I
always create a local variable instead. I can’t prepend the method name
with a receiver (“self”) because the method is private.
For exmaple, this assigns to a local variable instead of using the
private method above:
public
def fillWallet
dollars = 100
puts “Wow! You’ve got $” + dollars().to_s
end
How do I call a private lvalue method?
How do I call a private lvalue method?
Hmmm… so self.dollars = 100 doesn’t work, eh? Only answer I can
think of is
self.send(:dollars=, 100)
Beautiful, isn’t it? 
It’s as ugly as sin, but it works as advertised. 
Actually, a better answer came to mind. Make :dollars= protected
instead of private. It works.
That works also, but it changes the spec. So does redefining the method
signature, like so: def dollars(aNumber). That also works, but changes
the spec.
I’ll just have to put this down as a “gotcha” and carry on. Is there a
list of places Ruby doesn’t follow the least surprise principle?
Thanks for the help,
Steve
···
Gavin Sinclair gsinclair@soyabean.com.au wrote:
On Friday, February 7, 2003, 10:35:08 AM, Steven wrote:
–
Steven Smolinski => http://arbiter.ca/
GnuPG Public Key => Webnewswire | Leading newswire service
=> or email me with ‘auto-key’ in the subject.
Key Fingerprint => 08C8 6481 3A7B 2A1C 7C26 A5FC 1A1B 66AB F637 495D
I’m assuming there’s some good reason for this that isn’t apparent to (at
least) me. Would someone care to enlighten me out of interest?
cheers
dim
···
In message “Private lvalue methods unusable?” > on 03/02/07, Steven Smolinski steven.smolinski@sympatico.ca writes:
How do I call a private lvalue method?
No way, except using “send”, e.g.
self.send(:dollars=, 100)
matz.
There’s a newcomers list that documents gotchas, but it doesn’t
include this one. I’ve never seen it mentioned before, actually.
You listening, Bill? 
Gavin
···
On Friday, February 7, 2003, 1:55:40 PM, Steven wrote:
That works also, but it changes the spec. So does redefining the method
signature, like so: def dollars(aNumber). That also works, but changes
the spec.
I’ll just have to put this down as a “gotcha” and carry on. Is there a
list of places Ruby doesn’t follow the least surprise principle?
Private methods can’t have an explicit receiver (i.e., you can’t do
self.method on a private). Calling it directly looks like this:
dollars = 100
So a private lvalue method and assignment to a local variable have the
exact same syntax. Which means ruby had to choose whether it should:
- look for a method and raise an exception if there is none, or
- create a local variable.
It appears ruby does (2).
I suppose there’s always (3), which is to look for a method first and
create a local variable if there’s no method defined. But that’s some
serious semantic gymnastics, and may make things worse rather than
better. I don’t know enough about ruby to comment on that.
Steve
···
Dmitri Colebatch dim@colebatch.com wrote:
In message “Private lvalue methods unusable?” >> on 03/02/07, Steven Smolinski steven.smolinski@sympatico.ca writes:
How do I call a private lvalue method?
No way, except using “send”, e.g.
self.send(:dollars=, 100)
I’m assuming there’s some good reason for this that isn’t apparent to
(at least) me. Would someone care to enlighten me out of interest?
–
Steven Smolinski => http://arbiter.ca/
GnuPG Public Key => Webnewswire | Leading newswire service
=> or email me with ‘auto-key’ in the subject.
Key Fingerprint => 08C8 6481 3A7B 2A1C 7C26 A5FC 1A1B 66AB F637 495D
Hi Gavin,
Are you sure this belongs in the newcomers list? I never use
‘private’ either
(I just put all the “private” methods in the C part.)
Regards,
Bill
···
Gavin Sinclair gsinclair@soyabean.com.au wrote:
There’s a newcomers list that documents gotchas, but it doesn’t
include this one. I’ve never seen it mentioned before, actually.
You listening, Bill? 
Gavin
Hi,
self.send(:dollars=, 100)
I’m assuming there’s some good reason for this that isn’t apparent to (at
least) me. Would someone care to enlighten me out of interest?
“private” does mean “can only be called without explicit receiver”.
This is the reason.
It it a bad idea to relax the restriction, “can only be called
without explicit receiver or with `self’ receiver”?
class C
private
def x=(val)
@x = val
end
public
def set_x(val)
self.x = val # OK
self
end
end
C.new.set_x(1) # OK
C.new.x = 1 # NG
···
At Fri, 7 Feb 2003 13:29:58 +0900, Yukihiro Matsumoto wrote:
–
Nobu Nakada
Not sure, no, since this is the first time it has come up. It is
surprising behaviour though.
After all, dollar= is supposed to be “just another method”, isn’t it?
Gavin
···
On Friday, February 7, 2003, 3:56:14 PM, William wrote:
Gavin Sinclair gsinclair@soyabean.com.au wrote:
There’s a newcomers list that documents gotchas, but it doesn’t
include this one. I’ve never seen it mentioned before, actually.
You listening, Bill? 
Gavin
Hi Gavin,
Are you sure this belongs in the newcomers list? I never use
‘private’ either
(I just put all the “private” methods in the C part.)
Hi,
“private” does mean “can only be called without explicit receiver”.
This is the reason.
It it a bad idea to relax the restriction, “can only be called
without explicit receiver or with `self’ receiver”?
Hmm, interesting. Let me consider this issue.
Forgot an example. Error if the receiver isn’t literally
`self’, even if it actually equals self.
private :x=
def my
self
end
def my_x(val)
my.x = val # NG
end
And patch.
Index: eval.c
···
At Fri, 7 Feb 2003 18:00:35 +0900, Yukihiro Matsumoto wrote:
RCS file: /cvs/ruby/src/ruby/eval.c,v
retrieving revision 1.392
diff -u -2 -p -r1.392 eval.c
— eval.c 7 Feb 2003 06:30:18 -0000 1.392
+++ eval.c 7 Feb 2003 08:14:53 -0000
@@ -1924,6 +1924,7 @@ is_defined(self, node, buf)
goto check_bound;
-
if (node->nd_recv == (NODE *)1) {
-
recv = self;
-
scope = 1;
-
}
-
else {
-
recv = rb_eval(self, node->nd_recv);
-
scope = 0;
-
}
SETUP_ARGS(node->nd_args);
END_CALLARGS;
SET_CURRENT_SOURCE();
-
rb_call(CLASS_OF(recv),recv,node->nd_mid,argc,argv,0);
-
rb_call(CLASS_OF(recv),recv,node->nd_mid,argc,argv,scope);
result = argv[argc-1];
}
@@ -4092,10 +4101,18 @@ assign(self, lhs, val, pcall)
{
VALUE recv;
-
int scope;
-
if (lhs->nd_recv == (NODE *)1) {
-
recv = self;
-
scope = 1;
-
}
-
else {
-
recv = rb_eval(self, lhs->nd_recv);
-
scope = 0;
-
}
if (!lhs->nd_args) {
/* attr set */
ruby_current_node = lhs;
SET_CURRENT_SOURCE();
-
rb_call(CLASS_OF(recv), recv, lhs->nd_mid, 1, &val, 0);
-
rb_call(CLASS_OF(recv), recv, lhs->nd_mid, 1, &val, scope);
}
else {
@@ -4108,5 +4125,5 @@ assign(self, lhs, val, pcall)
SET_CURRENT_SOURCE();
rb_call(CLASS_OF(recv), recv, lhs->nd_mid,
-
if (nd_type($1) == NODE_SELF)
-
$$ = NEW_FCALL(tAREF, $3);
-
else
-
$$ = NEW_CALL($1, tAREF, $3);
}
> tLBRACK aref_args ']'
@@ -4628,7 +4631,13 @@ call_op(recv, id, narg, arg1)
if (narg == 1) {
value_expr(arg1);
- arg1 = NEW_LIST(arg1);
- }
- else {
- arg1 = 0;
}
- return NEW_CALL(recv, id, narg==1?NEW_LIST(arg1):0);
- if (recv && nd_type(recv) == NODE_SELF)
- return NEW_FCALL(id, arg1);
- return NEW_CALL(recv, id, arg1);
}
@@ -4668,4 +4677,6 @@ match_gen(node1, node2)
}
- if (node1 && nd_type(node1) == NODE_SELF)
- return NEW_FCALL(tMATCH, NEW_LIST(node2));
return NEW_CALL(node1, tMATCH, NEW_LIST(node2));
}
@@ -4784,5 +4795,8 @@ aryset(recv, idx)
NODE *recv, *idx;
{
- if (recv && nd_type(recv) == NODE_SELF)
- recv = (NODE *)1;
- else
- value_expr(recv);
return NEW_ATTRASGN(recv, tASET, idx);
}
@@ -4802,5 +4816,8 @@ attrset(recv, id)
ID id;
{
- if (recv && nd_type(recv) == NODE_SELF)
- recv = (NODE *)1;
- else
- value_expr(recv);
return NEW_ATTRASGN(recv, rb_id_attrset(id), 0);
}
@@ -5318,4 +5335,5 @@ new_call(r,m,a)
NODE *a;
{
- if (r && nd_type(r) == NODE_SELF) return new_fcall(m, a);
if (a && nd_type(a) == NODE_BLOCK_PASS) {
a->nd_iter = NEW_CALL(r,m,a->nd_head);
–
Nobu Nakada