Attribute setters for instance variables

Hello,

The Pickaxe book presents the following example:

class Incorrect
  attr_accessor :one, :two
  def initialize
    one = 1
    self.two = 2
  end
end

obj = Incorrect.new

p obj.one
p obj.two

The first thing printed is 'nil' and not '1' since "one = 1" assigns to
a local variable of method initialize instead of the instance variable.
So far it's clear.
Now, they propose a solution: to use self.one instead of just one.
Won't be using @one simpler and also correct ? What am I missing ?

Thanks

eliben@gmail.com wrote:

Hello,

The Pickaxe book presents the following example:

class Incorrect
  attr_accessor :one, :two
  def initialize
    one = 1
    self.two = 2
  end
end

obj = Incorrect.new

p obj.one
p obj.two

The first thing printed is 'nil' and not '1' since "one = 1" assigns to
a local variable of method initialize instead of the instance variable.
So far it's clear.
Now, they propose a solution: to use self.one instead of just one.
Won't be using @one simpler and also correct ? What am I missing ?

Thanks

@one = 1 is setting the instance variable itself, and that's fine for accessors. If you want to do something special on =() then you will want to use the self.one style. e.g.

def Foo
   def one=(n)
     @one = n+42
   end
   def initialize(n)
     self.one = 0 # @one == 42
     @one = 0 # @one == 0
   end
end

def one= arg
     log{ "somthing about one" }
     validate{ arg }
     notify_observers :one, arg
     @one = arg
   end

just a few examples.

this become even more true when the number attribues increases since you can

   class C
     ATTRIBUTES = %w[ one two three four five six seven ]
     def initialize kws = {}
       kws.each{|kw, val| send "#{ kw }=", val}
     end
   end

in one line even if the number of attributes is huge.

i'd also argue that the simplest thing is to simply make the getter take and
optional argument so one can do

   def initialize
     one 1
     two 2
   end

but that's a matter of taste.

hth - cheers.

-a

···

On Sun, 12 Mar 2006 eliben@gmail.com wrote:

Hello,

The Pickaxe book presents the following example:

class Incorrect
attr_accessor :one, :two
def initialize
   one = 1
   self.two = 2
end
end

obj = Incorrect.new

p obj.one
p obj.two

The first thing printed is 'nil' and not '1' since "one = 1" assigns to
a local variable of method initialize instead of the instance variable.
So far it's clear.
Now, they propose a solution: to use self.one instead of just one.
Won't be using @one simpler and also correct ? What am I missing ?

--
share your knowledge. it's a way to achieve immortality.
- h.h. the 14th dali lama

Hans Fugal wrote:

···

eliben@gmail.com wrote:
> Hello,
>
> The Pickaxe book presents the following example:
>
> class Incorrect
> attr_accessor :one, :two
> def initialize
> one = 1
> self.two = 2
> end
> end
>
> obj = Incorrect.new
>
> p obj.one
> p obj.two
>
> The first thing printed is 'nil' and not '1' since "one = 1" assigns to
> a local variable of method initialize instead of the instance variable.
> So far it's clear.
> Now, they propose a solution: to use self.one instead of just one.
> Won't be using @one simpler and also correct ? What am I missing ?
>
> Thanks
>

@one = 1 is setting the instance variable itself, and that's fine for
accessors. If you want to do something special on =() then you will want
to use the self.one style. e.g.

def Foo
   def one=(n)
     @one = n+42
   end
   def initialize(n)
     self.one = 0 # @one == 42
     @one = 0 # @one == 0
   end
end

Thanks for your swift and insightful reply.

Hans Fugal wrote:

Hello,

The Pickaxe book presents the following example:

class Incorrect
  attr_accessor :one, :two
  def initialize
    one = 1
    self.two = 2
  end
end

obj = Incorrect.new

p obj.one
p obj.two

The first thing printed is 'nil' and not '1' since "one = 1" assigns to
a local variable of method initialize instead of the instance variable.
So far it's clear.
Now, they propose a solution: to use self.one instead of just one.
Won't be using @one simpler and also correct ? What am I missing ?

Thanks

@one = 1 is setting the instance variable itself, and that's fine for accessors. If you want to do something special on =() then you will want to use the self.one style. e.g.

def Foo
  def one=(n)
    @one = n+42
  end
  def initialize(n)
    self.one = 0 # @one == 42
    @one = 0 # @one == 0
  end
end

I really wish Ruby required explicit locals declaration. There are many advantages to this, including fix of the problem above, hard to debug spelling mistakes, clearer code, etc. A simple 'var' declaration would be simple:

def Foo
   def one=(n)
     @one = n+42
   end
   def initialize(n)
     var x, y = n * n, 1 / n
     one = 0 # @one == 42
     @one = 0 # @one == 0
     z = 10 # error
   end
end

Regards,
Mike

···

eliben@gmail.com wrote:

Mike Austin wrote:

Hans Fugal wrote:

Hello,

The Pickaxe book presents the following example:

class Incorrect
  attr_accessor :one, :two
  def initialize
    one = 1
    self.two = 2
  end
end

obj = Incorrect.new

p obj.one
p obj.two

The first thing printed is 'nil' and not '1' since "one = 1" assigns to
a local variable of method initialize instead of the instance variable.
So far it's clear.
Now, they propose a solution: to use self.one instead of just one.
Won't be using @one simpler and also correct ? What am I missing ?

Thanks

@one = 1 is setting the instance variable itself, and that's fine for accessors. If you want to do something special on =() then you will want to use the self.one style. e.g.

def Foo
  def one=(n)
    @one = n+42
  end
  def initialize(n)
    self.one = 0 # @one == 42
    @one = 0 # @one == 0
  end
end

I really wish Ruby required explicit locals declaration. There are many advantages to this, including fix of the problem above, hard to debug spelling mistakes, clearer code, etc. A simple 'var' declaration would be simple:

What problem? I don't see any problem, I quite like that behavior. I also like not declaring variables, the inconvenience from spelling errors is minimal, especially when the telltale nil problems are almost as useful as a compiler error most of the time.

···

eliben@gmail.com wrote:

Hans Fugal wrote: [full message below]
>> I really wish Ruby required explicit locals declaration. There are
>> many advantages to this, including fix of the problem above, hard to
>> debug spelling mistakes, clearer code, etc. A simple 'var'
>> declaration would be simple:
>
> What problem? I don't see any problem, I quite like that behavior. I
> also like not declaring variables, the inconvenience from spelling
> errors is minimal, especially when the telltale nil problems are almost
> as useful as a compiler error most of the time.

I can't imagine coding thousands of lines of code without variable declarations. If you catch the nil errors caused by spelling mistakes right away, sure, you can easily track it down. But I'd rather have the compiler tell me that a variable doesn't exist than to give me an nil error who knows where. 'var' is only 4 more letters, and I'm not saying limit them to the beginning of the method or block. The only change would be prepending 'var'.

Mike

Hans Fugal wrote:

···

Mike Austin wrote:

Hans Fugal wrote:

eliben@gmail.com wrote:

Hello,

The Pickaxe book presents the following example:

class Incorrect
  attr_accessor :one, :two
  def initialize
    one = 1
    self.two = 2
  end
end

obj = Incorrect.new

p obj.one
p obj.two

The first thing printed is 'nil' and not '1' since "one = 1" assigns to
a local variable of method initialize instead of the instance variable.
So far it's clear.
Now, they propose a solution: to use self.one instead of just one.
Won't be using @one simpler and also correct ? What am I missing ?

Thanks

@one = 1 is setting the instance variable itself, and that's fine for accessors. If you want to do something special on =() then you will want to use the self.one style. e.g.

def Foo
  def one=(n)
    @one = n+42
  end
  def initialize(n)
    self.one = 0 # @one == 42
    @one = 0 # @one == 0
  end
end

I really wish Ruby required explicit locals declaration. There are many advantages to this, including fix of the problem above, hard to debug spelling mistakes, clearer code, etc. A simple 'var' declaration would be simple:

What problem? I don't see any problem, I quite like that behavior. I also like not declaring variables, the inconvenience from spelling errors is minimal, especially when the telltale nil problems are almost as useful as a compiler error most of the time.