Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to do lazy evaluation of Ruby arguments

I have a code to do a check of nil in ruby. So what I want to achieve is this: for example, if I call get_score_value(nil,(nil-1)). I want ruby to delay the evaluation of nil-1 till it reaches the get_score_value function, instead of evaluate it before it got passed in the function. In another word, I want to pass a mathematical expression as an argument into a method. What is the most elegant way to do this in ruby? Thanks very much

def get_score_value(value,value2)
    value.nil? ? "NULL" : value2.round(2)
end

UPDATE:

I just realized this question is actually related to the topic of lazy and strict evaluation. ( the following is from this great site: http://www.khelll.com/blog/ruby/ruby-and-functional-programming/

Strict versus lazy evaluation

Strict evaluation always fully evaluates function arguments before invoking the function. Lazy evaluation does not evaluate function arguments unless their values are required to be evaluated. One use of Lazy evaluation is the performance increases due to avoiding unnecessary calculations.

However as the following example shows, Ruby use Strict evaluation strategy:

print length([2+1, 3*2, 1/0, 5-4]) =>ZeroDivisionError: divided by 0

The third parameter of the passed array contains a division by zero operation and as Ruby is doing strict evaluation, the above snippet of code will raise an exception.

like image 592
zsljulius Avatar asked Aug 11 '11 19:08

zsljulius


People also ask

What is lazy evaluation in Ruby?

Lazy enumeration means that an expression is only processed when we are working with the result. There are languages that are lazy by default, like Haskell, and many others are implementing a way to lazily evaluate expressions.

What is lazy evaluation in C++?

The story about lazy evaluation in C++ is quite short. That will change in C++20 with the ranges library from Eric Niebler. Lazy evaluation is the default in Haskell. Lazy evaluation means that an expression is only evaluated when needed.

What is lazy evaluation of function in R?

Lazy evaluation is a programming strategy that allows a symbol to be evaluated only when needed. In other words, a symbol can be defined (e.g in a function), and it will only be evaluated when it is needed (and that moment can be never). This is why you can do: plop <- function(a, b){ a * 10.

What is lazy evaluation in Javascript?

Lazy evaluation means to delay the evaluation of an expression until it's needed. Lazy evaluation is sometimes referred to as call-by-need. The opposite of lazy evaluation is an eager evaluation.


2 Answers

You might be interested in using a Proc...

func = Proc.new {|n| n -1 }

def get_score_value(value, proc)
  if value.nil?
    return proc.call(0)
  end
end

p get_score_value(nil, func)

Your proc is like a normal method, it can still test for nil and things like that.

Or, it allows you to provide separate functions to handle those situations:

func1 = Proc.new {|n| n -1 }
func2 = Proc.new { "was nil" }

def check_for_nil(value, funcNil, funcNotNil)
  if value.nil?
    return funcNil.call()
  else
    return funcNotNil.call(value)
  end
end

p check_for_nil(nil, func2, func1)
p check_for_nil(1, func2, func1)

Also note the potential use of the or keyword in cases when you simply want to convert it to an empty or default type of the input (i.e. use 0 for numbers, [] for arrays, etc.)

def get_score_value(value)
  (value or 0).round(2)
end
like image 88
drharris Avatar answered Sep 18 '22 14:09

drharris


The Ruby-ish way to do this is to put your expression in your method's block and have the method execute a conditional yield.

def f x
  yield if x
end

x = nil
f x do 
  x - 1
end
like image 25
DigitalRoss Avatar answered Sep 20 '22 14:09

DigitalRoss