Fun with setter functions

I have a setter function in a class that I would like to pass additional
arguments to, so I can do some addtional calculations if required.

My first crack at this was to do something like...

....
def variable=(value, options=nil)
  @variable = value
  do_something_cool if options == :flag
end

Here's the only problem, how do you pass the options?

object.variable = value, :flag
results in
[value, :flag] being passed to the function.

I see a couple of work arounds.
1. send works, but is ugly object.send('variable=',value,:flag)
2. rewrite variable so that it expects an array and just unpack stuff
from the array

Any other solutions I may have overlooked?

_Kevin
www.sciwerks.com

···

--
Posted with http://DevLists.com. Sign up and save your mailbox.

Try

def variable=(*args)
  @variable = args.shift
  do_something_cool if args.shift == :flag
end

*args will receive array of arguments passed in either case (i.e. both
when one and two parameters are passed)

The latter args.shift will return nil if there are no more parameters.

Another possibility could be using hash parameters, as rails often does:

def variable=(value, options ={})
   @variable = value
   do_something_cool if options[:options] == :flag
end

Call as: variable = value, :options => :flag

···

On 8/26/06, Kevin Olbrich <devlists-ruby-talk@devlists.com> wrote:

I have a setter function in a class that I would like to pass additional
arguments to, so I can do some addtional calculations if required.

My first crack at this was to do something like...

....
def variable=(value, options=nil)
  @variable = value
  do_something_cool if options == :flag
end

Here's the only problem, how do you pass the options?

object.variable = value, :flag
results in
[value, :flag] being passed to the function.

I see a couple of work arounds.
1. send works, but is ugly object.send('variable=',value,:flag)
2. rewrite variable so that it expects an array and just unpack stuff
from the array

Any other solutions I may have overlooked?

Both approaches won't work as Ruby does allow only exactly one argument to an assignment:

11:06:12 [Temp]: cat -n var.rb
      1
      2 class Foo
      3 def var=(val,*opts)
      4 p opts
      5 @var = val
      6 end
      7
      8 def var() @var end
      9 end
     10
     11 f=Foo.new
     12 p f.var
     13 f.var = 10
     14 p f.var
     15 f.var = 10, 20
11:06:18 [Temp]: ruby var.rb
nil

10

You can get it to work with send but then you're loosing the clean syntax:

11:07:03 [Temp]: cat -n var.rb
      1
      2 class Foo
      3 def var=(val,*opts)
      4 p opts
      5 @var = val
      6 end
      7
      8 def var() @var end
      9 end
     10
     11 f=Foo.new
     12 p f.var
     13 f.var = 10
     14 p f.var
     15 f.var = 10, 20
     16 p f.var
     17 f.send(:var=, 10, :opt => 20)
11:08:08 [Temp]: ruby var.rb
nil

10

[10, 20]
[{:opt=>20}]
11:08:08 [Temp]:

Kind regards

  robert

···

On 26.08.2006 16:42, Jan Svitok wrote:

On 8/26/06, Kevin Olbrich <devlists-ruby-talk@devlists.com> wrote:

I have a setter function in a class that I would like to pass additional
arguments to, so I can do some addtional calculations if required.

My first crack at this was to do something like...

....
def variable=(value, options=nil)
  @variable = value
  do_something_cool if options == :flag
end

Here's the only problem, how do you pass the options?

object.variable = value, :flag
results in
[value, :flag] being passed to the function.

I see a couple of work arounds.
1. send works, but is ugly object.send('variable=',value,:flag)
2. rewrite variable so that it expects an array and just unpack stuff
from the array

Any other solutions I may have overlooked?

Try

def variable=(*args)
@variable = args.shift
do_something_cool if args.shift == :flag
end

*args will receive array of arguments passed in either case (i.e. both
when one and two parameters are passed)

The latter args.shift will return nil if there are no more parameters.

Another possibility could be using hash parameters, as rails often does:

def variable=(value, options ={})
  @variable = value
  do_something_cool if options[:options] == :flag
end

Call as: variable = value, :options => :flag