If ruby interpreted your assignment in your last statement as an assignment to self
, you would have no way left to set a local variable.
The way it is leaves no ambiguity for the interpreter to deal with: assignments without self
are always local variables, assignments to self are always trying to use a writer on the object.
If it were the other way around
The interpreter would have to look up the contexts writer methods and assign it via the writer if there is one, which almost certainly would have a negative impact on performance
class A
attr_writer :foo
end
A.new.instance_eval do
# for each of these assignments, the interpreter has to look up if there's
# a writer method defined
foo = 'bar'
bar = 'baz'
fib = 'buz'
end
It would also leave the programmer with the rather stupid task to find out every setter method of the context he's in before assigning local variables to make absolutely sure he does not unintentionally use a setter.
class C
attr_writer :something
end
class B < C
attr_writer :foo
end
class A < B
attr_writer :bar
end
A.new.instance_eval
something = 'something'
#you just (almost certainly with no intention) assigned a value to an attribute
end
Also, your question reads:
setter methods cannot be used without an explicit receiver even when a
local variable with the same name is not assigned prior to the
expression in question:
If it were the other way around, you could not assign a local variable with the same name prior to the expression in question, because the assignment would use the setter (as stated in the first paragraph of this answer)
Concerning the implementation / the access to variables the attribute methods use: Getter and Setters work with instance variables. So, for example attr_accessor
actually defines something like this:
def foo
@foo
end
def foo=(data)
@foo = data
end
So, the attribute is declared as a instance variable and not as a local variable, why should the programmer be able to assign it like a local variable? This would leave the wrong impression that you could assign instance variables of an object via assigning local variables. If ruby would do this, it would almost certainly lead to a serious memory management problem. To make it short: foo = 'bar'
and @foo = 'bar'
are not the same, and exactly because the attr
methods use @foo = 'bar'
, you can not call them via using foo = 'bar'
.