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.
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
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
You can use a block:
def get_score_value value
value.nil? ? "NULL" : yield
end
x = 1
puts get_score_value(x) { x-1 } #=> 0
x = nil
puts get_score_value(x) { x-1 } #=> "NULL"
Related
I am new to ruby and today I found some different behaviour of class_eval for string and block. For example
class A
end
class C
A.class_eval("print Module.nesting") # [A, C]
A.class_eval{print Module.nesting} # [C]
end
As you can see in the case of the string Module.nesting prints [A,C], while in the case of block it prints only C.
Could you please tell me the reason for this?
In the first case, you stuff a string into class_eval, and this class_eval is invoked on the class A. Hence, when the expression is evaluated, Module.nesting - which needs produce its nesting levels - finds itself inside an A, which in turn is evaluated inside a C.
In the second case, you pass a block, which is similar to a proc object. The effect is comparable to have a
class C
p = Proc.new { print Module.nesting }
do_something(p)
end
The Proc represents a closure, i.e. the context is that of creating the Proc. It is clear, that the nesting here is only C, and this does not change, if you evaluate p inside do_something.
This is a good thing. Imagine the following situation:
def f(p)
x = 'f'
p.call
end
def g
x = 'g'
p = Proc.new { puts x }
f(p)
end
Because the binding for p occurs inside method g, the x referenced in the block refers to the local value x inside g, although f has a local variable of the same name. Hence, g is printed here. In the same way, the nesting at the point of block definition is reproduced in your example.
Or rather, how does the determination work?
It takes place with the definition of the base.called_from in /lib/rails/engine.rb:
def inherited(base)
unless base.abstract_railtie?
Rails::Railtie::Configuration.eager_load_namespaces << base
base.called_from = begin
call_stack = caller_locations.map { |l| l.absolute_path || l.path }
File.dirname(call_stack.detect { |p| !p.match?(%r[railties[\w.-]*/lib/rails|rack[\w.-]*/lib/rack]) })
end
end
super
end
The invocation of Kernel#caller_locations returns an Array of Thread::Backtrace::Location-objects, right?
First, I don't understand the idiom in the block passed to map:
l.absolute_path || l.path
Does it want to ensure that if l.absolute_path is nil then at least l.path is element of the result of the map-Enumerator ? But why shouldn't l.absolute_path not exist?
Second, I don't understand the construct composed out of the detect-Enumerator and the regex (-operator).
The detectEnumerator takes the first element for which the expression, here !~, is true. Okay.
But how does the expression, which is true if a path p doesn't match either
railties[\w.-]*/lib/rails
"or" (pipe)
rack[\w.-]*/lib/rack
In other words: Rails.application.root is the first path that doesn't match one of the two regex-patterns. Correct?
But if so, then: why?
(And what method, if I may ask, is super in this context?)
Thanks
von Spotz
I'm trying to implement my first ruby sorting algorithm. This algorithm is based on some specific rules ("always prefer objects of type xxx over objects of types yyy"), and if none of these rules triggered, it uses the ruby <=>-operator. I'm doing this on a ruby-on-rails one-to-many association.
The problem is this algortihm does not return the array itself, it just returns -1 or 1, the result of the comparison..But I actually don't understand why, as my result is only returned in the sort-block.
Here is my current code:
def sort_products!
products.sort! do |p1, p2|
result = 0
# Scalable Products are always the last ones in order
if p1.class.name == "ScalableProduct"
result = -1
elsif p2.class.name == "ScalableProduct"
result = 1
end
if result == 0
# Put products producing electricity and heating down
if p1.can_deliver_electricity?
result = -1
elsif p2.can_deliver_electricity?
result = 1
end
end
# Else: Just compare names
result = p1.name <=> p2.name if result == 0
result
end
end
The best practice here, in my opinion, would be to implement the <=> inside the Product model. You'll need to include the Comparable model in order to achive this:
class Product
include Comparable
def <=>(another_product)
# Compare self with another_product
# Return -1, 0, or 1
end
end
Then your sorting method will be reduced to:
def sort_products!
products.sort!
end
Change the do..end for brackets as delimiters of the block. It is first sorting, and then using the block on the result (because of the precedence of the do..end syntax). Using brackets, it uses the block as a sorting block, which is what you wanted.
Also, in your comparison, if both your products are ScalableProduct then you will not order them in a sensible way. If they are both ScalableProduct at the same time, you might want to keep result as 0 so it falls back to comparing by name. Same deal with can_deliver_electricity?.
My goal is to replace methods in the String class with other methods that do additional work (this is for a research project). This works for many methods by writing code in the String class similar to
alias_method :center_OLD, :center
def center(args*)
r = self.send(*([:center_OLD] + args))
#do some work here
#return something
end
For some methods, I need to handle a Proc as well, which is no problem. However, for the scan method, invoking it has the side effect of setting special global variables from the regular expression match. As documented, these variables are local to the thread and the method.
Unfortunately, some Rails code makes calls to scan which makes use of the $& variable. That variable gets set inside my version of the scan method, but because it's local, it doesn't make it back to the original caller which uses the variable.
Does anyone know a way to work around this? Please let me know if the problem needs clarification.
If it helps at all, all the uses I've seen so far of the $& variable are inside a Proc passed to the scan function, so I can get the binding for that Proc. However, the user doesn't seem to be able to change $& at all, so I don't know how that will help much.
Current Code
class String
alias_method :scan_OLD, :scan
def scan(*args, &b)
begin
sargs = [:scan_OLD] + args
if b.class == Proc
r = self.send(*sargs, &b)
else
r = self.send(*sargs)
end
r
rescue => error
puts error.backtrace.join("\n")
end
end
end
Of course I'll do more things before returning r, but this even is problematic -- so for simplicity we'll stick with this. As a test case, consider:
"hello world".scan(/l./) { |x| puts x }
This works fine both with and without my version of scan. With the "vanilla" String class this produces the same thing as
"hello world".scan(/l./) { puts $&; }
Namely, it prints "ll" and "ld" and returns "hello world". With the modified string class it prints two blank lines (since $& was nil) and then returns "hello world". I'll be happy if we can get that working!
You cannot set $&, because it is derived from $~, the last MatchData.
However, $~ can be set and that actually does what you want.
The trick is to set it in the block binding.
The code is inspired by the old Ruby implementation of Pathname.
(The new code is in C and does not need to care about Ruby frame-local variables)
class String
alias_method :scan_OLD, :scan
def scan(*args, &block)
sargs = [:scan_OLD] + args
if block
self.send(*sargs) do |*bargs|
Thread.current[:string_scan_matchdata] = $~
eval("$~ = Thread.current[:string_scan_matchdata]", block.binding)
yield(*bargs)
end
else
self.send(*sargs)
end
end
end
The saving of the thread-local (well, actually fiber-local) variable seems unnecessary since it is only used to pass the value and the thread never reads any other value than the last one set. It probably is there to restore the original value (most likely nil, because the variable did not exist).
One way to avoid thread-locals at all is to create a setter of $~ as a lambda (but it does create a lambda for each call):
self.send(*sargs) do |*bargs|
eval("lambda { |m| $~ = m }", block.binding).call($~)
yield(*bargs)
end
With any of these, your example works!
I wrote simple code simulating the problem:
"hello world".scan(/l./) { |x| puts x }
"hello world".scan(/l./) { puts $&; }
class String
alias_method :origin_scan, :scan
def scan *args, &b
args.unshift :origin_scan
#mutex ||= Mutex.new
begin
self.send *args do |a|
break if !block_given?
#mutex.synchronize do
p $&
case b.arity
when 0
b.call
when 1
b.call a
end
end
end
rescue => error
p error, error.backtrace.join("\n")
end
end
end
"hello world".scan(/l./) { |x| puts x }
"hello world".scan(/l./) { puts $& }
And found the following. The change of containment of the variable $& became inside a :call function, i.e. on 3-rd step before :call $& contains a valid value, but inside the block it becomes the invalid. I guess this become due to the singularity stack and variable restoration during the change process/thread context, because, probably, :call function can't access the :scan local state.
I see two variants: the first is to avoid to use global variables in the specific function redefinitions, and second, may to dig sources of ruby more deeply.
Given any object in Ruby (on Rails), how can I write a method so that it will display that object's instance variable names and its values, like this:
#x: 1
#y: 2
#link_to_point: #<Point:0x10031b298 #y=20, #x=38>
(Update: inspect will do except for large object it is difficult to break down the variables from the 200 lines of output, like in Rails, when you request.inspect or self.inspect in the ActionView object)
I also want to be able to print <br> to the end of each instance variable's value so as to print them out nicely on a webpage.
the difficulty now seems to be that not every instance variable has an accessor, so it can't be called with obj.send(var_name)
(the var_name has the "#" removed, so "#x" becomes "x")
Update: I suppose using recursion, it can print out a more advanced version:
#<Point:0x10031b462>
#x: 1
#y: 2
#link_to_point: #<Point:0x10031b298>
#x=38
#y=20
I would probably write it like this:
class Object
def all_variables(root=true)
vars = {}
self.instance_variables.each do |var|
ivar = self.instance_variable_get(var)
vars[var] = [ivar, ivar.all_variables(false)]
end
root ? [self, vars] : vars
end
end
def string_variables(vars, lb="\n", indent="\t", current_indent="")
out = "#{vars[0].inspect}#{lb}"
current_indent += indent
out += vars[1].map do |var, ivar|
ivstr = string_variables(ivar, lb, indent, current_indent)
"#{current_indent}#{var}: #{ivstr}"
end.join
return out
end
def inspect_variables(obj, lb="\n", indent="\t", current_indent="")
string_variables(obj.all_variables, lb, indent, current_indent)
end
The Object#all_variables method produces an array containing (0) the given object and (1) a hash mapping instance variable names to arrays containing (0) the instance variable and (1) a hash mapping…. Thus, it gives you a nice recursive structure. The string_variables function prints out that hash nicely; inspect_variables is just a convenience wrapper. Thus, print inspect_variables(foo) gives you a newline-separated option, and print inspect_variables(foo, "<br />\n") gives you the version with HTML line breaks. If you want to specify the indent, you can do that too: print inspect_variables(foo, "\n", "|---") produces a (useless) faux-tree format instead of tab-based indenting.
There ought to be a sensible way to write an each_variable function to which you provide a callback (which wouldn't have to allocate the intermediate storage); I'll edit this answer to include it if I think of something. Edit 1: I thought of something.
Here's another way to write it, which I think is slightly nicer:
class Object
def each_variable(name=nil, depth=0, parent=nil, &block)
yield name, self, depth, parent
self.instance_variables.each do |var|
self.instance_variable_get(var).each_variable(var, depth+1, self, &block)
end
end
end
def inspect_variables(obj, nl="\n", indent="\t", sep=': ')
out = ''
obj.each_variable do |name, var, depth, _parent|
out += [indent*depth, name, name ? sep : '', var.inspect, nl].join
end
return out
end
The Object#each_variable method takes a number of optional arguments, which are not designed to be specified by the user; instead, they are used by the recursion to maintain state. The given block is passed (a) the name of the instance variable, or nil if the variable is the root of the recursion; (b) the variable; (c) the depth to which the recursion has descended; and (d), the parent of the current variable, or nil if said variable is the root of the recursion. The recursion is depth-first. The inspect_variables function uses this to build up a string. The obj argument is the object to iterate through; nl is the line separator; indent is the indentation to be applied at each level; and sep separates the name and the value.
Edit 2: This doesn't really add anything to the answer to your question, but: just to prove that we haven't lost anything in the reimplementation, here's a reimplementation of all_variables in terms of each_variables.
def all_variables(obj)
cur_depth = 0
root = [obj, {}]
tree = root
parents = []
prev = root
obj.each_variable do |name, var, depth, _parent|
next unless name
case depth <=> cur_depth
when -1 # We've gone back up
tree = parents.pop(cur_depth - depth)[0]
when +1 # We've gone down
parents << tree
tree = prev
else # We're at the same level
# Do nothing
end
cur_depth = depth
prev = tree[1][name] = [var, {}]
end
return root
end
I feel like it ought to be shorter, but that may not be possible; because we don't have the recursion now, we have to maintain the stack explicitly (in parents). But it is possible, so the each_variable method works just as well (and I think it's a little nicer).
I see... Antal must be giving the advanced version here...
the short version then probably is:
def p_each(obj)
obj.instance_variables.each do |v|
puts "#{v}: #{obj.instance_variable_get(v)}\n"
end
nil
end
or to return it as a string:
def sp_each(obj)
s = ""
obj.instance_variables.each do |v|
s += "#{v}: #{obj.instance_variable_get(v)}\n"
end
s
end
or shorter:
def sp_each(obj)
obj.instance_variables.map {|v| "#{v}: #{obj.instance_variable_get(v)}\n"}.join
end
This is a quick adaptation of a simple JSON emitter I wrote for another question:
class Object
def inspect!(indent=0)
return inspect if instance_variables.empty?
"#<#{self.class}:0x#{object_id.to_s(16)}\n#{' ' * indent+=1}#{
instance_variables.map {|var|
"#{var}: #{instance_variable_get(var).inspect!(indent)}"
}.join("\n#{' ' * indent}")
}\n#{' ' * indent-=1}>"
end
end
class Array
def inspect!(indent=0)
return '[]' if empty?
"[\n#{' ' * indent+=1}#{
map {|el| el.inspect!(indent) }.join(",\n#{' ' * indent}")
}\n#{' ' * indent-=1}]"
end
end
class Hash
def inspect!(indent=0)
return '{}' if empty?
"{\n#{' ' * indent+=1}#{
map {|k, v|
"#{k.inspect!(indent)} => #{v.inspect!(indent)}"
}.join(",\n#{' ' * indent}")
}\n#{' ' * indent-=1}}"
end
end
That's all the magic, really. Now we only need some simple defaults for some types where a full-on inspect doesn't really make sense (nil, false, true, numbers, etc.):
module InspectBang
def inspect!(indent=0)
inspect
end
end
[Numeric, Symbol, NilClass, TrueClass, FalseClass, String].each do |klass|
klass.send :include, InspectBang
end
Like this?
# Get the instance variables of an object
d = Date.new
d.instance_variables.each{|i| puts i + "<br />"}
Ruby Documentation on instance_variables.
The concept is commonly called "introspection", (to look into oneself).