Hi all,
It seems writer methods don’t work within blocks, the names are
resolved to new local variable names I guess.
It is funny however the reader method does seem to work fine.
Is it possible to make it work anyway without changing the syntax
within the block?
My example gist: http://gist.github.com/137741
Kind regards,
Wijnand
Hi,
Am Dienstag, 30. Jun 2009, 03:44:48 +0900 schrieb Wijnand W.:
It seems writer methods don’t work within blocks, the names are resolved to
new local variable names I guess.
It is funny however the reader method does seem to work fine.
Is it possible to make it work anyway without changing the syntax within
the block?
My example gist: http://gist.github.com/137741
You don’t even need an instance_eval. It won’t work in a module
definition either:
module M
class <<self
def x= val
puts “Hi, here is C.x=(#{val.inspect}).”
@x = val
end
end
@x = “X0”
x = “X1”
self.x = “X2”
end
Maybe you prefer the self.-construction. I surely don’t.
Bertram
On Mon, Jun 29, 2009 at 2:44 PM, Wijnand W. [email protected]
wrote:
Hi all,
It seems writer methods don’t work within blocks, the names are resolved to
new local variable names I guess.
It is funny however the reader method does seem to work fine.
Is it possible to make it work anyway without changing the syntax within
the block?
My example gist: http://gist.github.com/137741
You can override the getter method for a DSL-ish syntax:
class Foo
attr_accessor :bar
def initialize(&block)
instance_eval(&block)
end
def bar(v=nil)
v ? @bar = v : @bar
end
end
f = Foo.new { bar 2 }
f.bar # => 2
f.bar 3
f.bar # => 3
f.bar = 4
f.bar # => 4
HTH
Mike
Hi –
On Tue, 30 Jun 2009, Wijnand W. wrote:
Hi all,
It seems writer methods don’t work within blocks, the names are resolved to
new local variable names I guess.
It is funny however the reader method does seem to work fine.
Is it possible to make it work anyway without changing the syntax within the
block?
It’s not a block thing. Writer methods always need an explicit
receiver. You always have to write:
obj.x = y
because the parser always sees this:
x = y
as a local variable assignment, even if there’s a method around called
x=.
David
Hi,
Am Dienstag, 30. Jun 2009, 04:37:55 +0900 schrieb Mike S.:
On Mon, Jun 29, 2009 at 2:44 PM, Wijnand W. [email protected] wrote:
def bar(v=nil)
v ? @bar = v : @bar
end
Sorry, but I cannot leave this as it is (untested):
def set_bar v = nil
@bar ||= v
end
Bertram
Thank you for your answers, I was too block focussed to see the
obvious real reason.
Kind regards,
Wijnand
I can only recommend this thread: Attr Methods and object setters - Ruby - Ruby-Forum
We had a nice discussion there on those kind of DSLish attr setters and
what would be the best way to implement them
Greetz,
k
P.S: metaid rocks!
Hi –
On Tue, 30 Jun 2009, Bertram S. wrote:
def set_bar v = nil
@bar ||= v
end
That only sets @bar if @bar hasn’t be set (to a true value) already.
class C
attr_reader :bar
def set_bar(v = nil)
@bar ||= v
end
end
c = C.new
c.set_bar(3)
puts c.bar # 3
c.set_bar(4)
puts c.bar # 3
David
On Monday 29 June 2009 02:21:49 pm Bertram S. wrote:
Maybe you prefer the self.-construction. I surely don’t.
Well, on that note… After using metaid, I hate the class << self
construction.
module M
meta_eval do
def x= val
…
end
end
…
end
For what it’s worth, attr_accessor does work inside meta_eval.
Hi –
On Tue, 30 Jun 2009, Mike S. wrote:
My example gist: http://gist.github.com/137741
You can override the getter method for a DSL-ish syntax:
Assuming your DSL depends on the lack of equal-signs
There’s
nothing inherent in the concept of a DSL that disallows =-terminated
methods or explicit receivers.
class Foo
attr_accessor :bar
No point defining #bar if you don’t want it – just use attr_writer.
def initialize(&block)
instance_eval(&block)
end
def bar(v=nil)
v ? @bar = v : @bar
end
That won’t allow you to (re)set @bar to nil or false, though. You
might want something like:
def bar(*v)
unless v.empty?
@bar, = v
end
@bar
end
David
Hi David,
On Tue, Jun 30, 2009 at 8:01 AM, David A. Black [email protected]
wrote:
to
Assuming your DSL depends on the lack of equal-signs
There’s
nothing inherent in the concept of a DSL that disallows =-terminated
methods or explicit receivers.
Of course! I was thinking of ActiveRecord’s macro method syntax–not the
most apropos when the original question was about variable assignment, I
know. 
@bar, = v
end
@bar
end
Ahh, yes. Thanks for pointing that out. I was really more concerned at
the
time with giving an (admittedly idiosyncratic) example of assignment
without
an explicit receiver as food for the OP’s thought. I’d never thought to
use
@bar, = v in order to grab only the first element of an array though.
Cool!
Thanks again,
Mike
Op 30 jun 2009, om 09:29 heeft Fabian S. het volgende geschreven:
I can only recommend this thread: Attr Methods and object setters - Ruby - Ruby-Forum
We had a nice discussion there on those kind of DSLish attr setters
and
what would be the best way to implement them
I actually like one of the proposed ways in that topic.
Using a method that is both getter and setter.
I decided to create a attr_accessor_special like this:
def attr_accessor_special(*syms)
syms.each do | sym |
name=sym.to_s
send(:define_method, name) do | *args |
value = args[0]
self.instance_variable_set(“@#{name}”, value) if value
self.instance_variable_get(“@#{name}”)
end
end
end
No way to make a value nil again but I don’t think that will be needed
in my case.
Thank you for your replies!
Kind regards,
Wijnand
Hi –
On Thu, 2 Jul 2009, Wijnand W. wrote:
def attr_accessor_special(*syms)
No way to make a value nil again but I don’t think that will be needed in my
case.
You could test to see whether args is empty (see my earlier post).
David
Hi,
Am Dienstag, 30. Jun 2009, 20:48:33 +0900 schrieb David A. Black:
That only sets @bar if @bar hasn’t be set (to a true value) already.
You’re right. Sorry!
Bertram