Forum: Ruby choose parameter to solve for

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
A74096209c78118ff69d50a51129d697?d=identicon&s=25 Jason Lillywhite (jlillywh)
on 2009-02-03 07:10
I'm looking for a clean way to write a function that allows me to choose
which parameter to solve for assuming all others are known. Is it good
design to do something like this: ?

class Foo
  def initialize(x, y, z)
    @x, @y, @z = x, y, z
  end

  def function(var)
    if @x.nil?
      @x = var
    elsif @y.nil?
      @y = var
    else
      @z = var
    end
    @x + @y + @z
  end

end

z = Foo.new(1, 2, nil)
z.function(3)
=> 6
??
9b905791cbdbb1af35b65e02c3217e23?d=identicon&s=25 Tom Link (Guest)
on 2009-02-03 07:22
(Received via mailing list)
>     if @x.nil?
>       @x = var

This could be rewritten as

        @x ||= var

>     elsif @y.nil?

What if @x and @y are nil? You might want to use

        @y ||= var
        @z ||= var

instead -- depending on what you want of course.
3131fcea0a711e5ad89c8d49cc9253b4?d=identicon&s=25 Julian Leviston (Guest)
on 2009-02-03 07:52
(Received via mailing list)
What do you mean?

Blog: http://random8.zenunit.com/
Learn rails: http://sensei.zenunit.com/

On 03/02/2009, at 5:10 PM, Jason Lillywhite
753dcb78b3a3651127665da4bed3c782?d=identicon&s=25 Brian Candler (candlerb)
on 2009-02-03 12:29
Jason Lillywhite wrote:
> I'm looking for a clean way to write a function that allows me to choose
> which parameter to solve for assuming all others are known. Is it good
> design to do something like this: ?
>
> class Foo
>   def initialize(x, y, z)
>     @x, @y, @z = x, y, z
>   end
>
>   def function(var)
>     if @x.nil?
>       @x = var
>     elsif @y.nil?
>       @y = var
>     else
>       @z = var
>     end
>     @x + @y + @z
>   end
>
> end
>
> z = Foo.new(1, 2, nil)
> z.function(3)
> => 6

Hmm, is this some sort of currying?

  adder = lambda { |x,y,z| x+y+z }
  z = lambda { |z| adder[1,2,z] }
  z[3]

You could perhaps factor this out into some sort of fix_args method.

Ruby 1.9 has Proc#curry, but I think this only fixes from the left.
9b905791cbdbb1af35b65e02c3217e23?d=identicon&s=25 Tom Link (Guest)
on 2009-02-03 12:52
(Received via mailing list)
> This could be rewritten as
>
>         @x ||= var

I totally misread the code. Sorry. Brian seems to be on the right
track.
753dcb78b3a3651127665da4bed3c782?d=identicon&s=25 Brian Candler (candlerb)
on 2009-02-03 14:05
Jason Lillywhite wrote:
> class Foo
>   def initialize(x, y, z)
>     @x, @y, @z = x, y, z
>   end
>
>   def function(var)
>     if @x.nil?
>       @x = var
>     elsif @y.nil?
>       @y = var
>     else
>       @z = var
>     end
>     @x + @y + @z
>   end
>
> end
>
> z = Foo.new(1, 2, nil)
> z.function(3)
> => 6

Also, if this is really the pattern you want (an object holding default
values for each of the args), then you probably don't want to modify the
instance variables between invocations. So here is a more general
version:

class Foo
  def initialize(*args)
    @args = args
  end
  def function(*more)
    # for each nil argument, pick one from 'more'
    calculate(*@args.collect { |x| x || more.shift })
  end
  def calculate(x,y,z)
    x + y + z
  end
end
z = Foo.new(1,2,nil)
z.function(3)
q = Foo.new(nil,nil,6)
q.function(4,5)

But I still think some flavour of currying is what you want. Is it
important that arbitrary parameters are fixed, rather than just the
left-most ones?
A74096209c78118ff69d50a51129d697?d=identicon&s=25 Jason Lillywhite (jlillywh)
on 2009-02-03 14:46
  adder = lambda { |x,y,z| x+y+z }
  z = lambda { |z| adder[1,2,z] }
  z[3]
This is what I want: write my equation one time then use that equation
in many different ways - solve for any one variable of my choice without
re-writing the equation. Thank you so much!

>
> But I still think some flavour of currying is what you want. Is it
> important that arbitrary parameters are fixed, rather than just the
> left-most ones?

It is important that arbitrary parameters are fixed as long as only one
parameter is unknown.

Thank you.
753dcb78b3a3651127665da4bed3c782?d=identicon&s=25 Brian Candler (candlerb)
on 2009-02-03 15:09
Jason Lillywhite wrote:
>   adder = lambda { |x,y,z| x+y+z }
>   z = lambda { |z| adder[1,2,z] }
>   z[3]
> This is what I want: write my equation one time then use that equation
> in many different ways - solve for any one variable of my choice without
> re-writing the equation. Thank you so much!
>
>>
>> But I still think some flavour of currying is what you want. Is it
>> important that arbitrary parameters are fixed, rather than just the
>> left-most ones?
>
> It is important that arbitrary parameters are fixed as long as only one
> parameter is unknown.

If the logic is to be hard-coded then maybe

   f2 = lambda { |y| adder[1,y,3] }

is good enough for you. Otherwise, writing a currying function which
fixes arbitrary parameters is left as an exercise :-)
This topic is locked and can not be replied to.