Ruby recursion issue - ruby

I wonder why the first approach to factorial does not work (infinite loop) in ruby while the second does.
def fac (x)
if x == 0
return 1
else
return (fac (x-1) * x)
end
end
def fact( num )
return 1 if num == 0
fact(num - 1) * num
end

The difference is the space after the method name, not the way you structured your if-else.
fac (x-1) * x is parsed as fac((x-1) * x). Basically if a method name is followed by a space (or any token that is not an opening parenthesis), ruby assumes you're calling the method without parentheses. So it interprets the parentheses around x-1 as grouping, not a part of the method call syntax.

Related

How to write a recursive factorial function in Ruby?

I just want some help with how to write a recursive factorial function in Ruby. I have the following code which is lisp, but I want to do the same thing in Ruby.
(defun factorial (N)
(if (= N 1) 1
(* N (factorial (- N 1)))))
Here's how to write the your code in ruby:
def factorial(n)
return 1 if n == 1
n * factorial(n - 1)
end
factorial(5)
#=> 120
factorial(7)
#=> 5040
Edit for Stefan's comment:
To avoid a SystemStackError error with large values of n, use the tail-recursive method. Also Ruby's tailcall optimization must be enabled.
# before edit
factorial(100_000).to_s.size
#=> stack level too deep (SystemStackError)
To avoid SystemStackError
RubyVM::InstructionSequence.compile_option = {
tailcall_optimization: true,
trace_instruction: false
}
RubyVM::InstructionSequence.new(<<-CODE).eval
def factorial(n, acc = 1)
return acc if n == 1
factorial(n - 1, n * acc)
end
CODE
puts factorial(100_000).to_s.size
#=> 456574
Resource 1
Resource 2

In Ruby, why doesn't ternary operator work when using a puts function inside an each statement?

Given that you write the code on IRB:
array = [1,2,3]
array.each {|x| x > 2 ? puts "lower" : puts "higher"}
The program doesn't execute the line and it somehow according to the program is an incomplete line. Any help would be appreciated.
This is caused by ambiguous arguments. Ruby, unlike many other languages such as JavaScript, is really lax about requiring brackets puts x and puts(x) are equivalent. Where this breaks down is when it's not clear which are arguments, and which are part of other syntax.
For example, if f is a method that takes 1-3 arguments and x and y are variables, then what is the meaning of:
f x, f x, y
Is that f(x, f(x,y)), f(x), f(x), y or f(x, f(x), y)? Ruby throws an error rather than presume the wrong thing.
Easy fix is to eliminate the duplication of effort here and use a single puts with a ternary used to determine the value:
array = [1,2,3]
array.each { |x| puts x > 2 ? "lower" : "higher"}
Now it works because there's no ambiguity on arguments, there's only one method call so it's easy.
The previous answer explains clearly what is happening. However you may note that this syntax will also work, but here you are duplicating the method call on both sides of the ternary operator:
array.each {|x| x > 2 ? (puts "lower") : (puts "higher")}
By wrapping the duplicate method call on both sides, that code is executed on both sides. But it definitely is better style to do it the more correct way where you are passing the result of ternary to puts
array.each { |x| puts x > 2 ? "lower" : "higher"}
which is the same as:
array.each { |x| puts (x > 2 ? "lower" : "higher") }
The puts method takes a single string argument and that's what we are passing it.

Retrieve method content as an `Expr`ession

I have a function f defined as follows.
f(x, y) = 3x^2 + x*y - 2y + 1
How can I retrieve the following quote block for this method, which includes the function contents?
quote # REPL[0], line 2:
((3 * x ^ 2 + x * y) - 2y) + 1
end
As folks have mentioned in the comments, digging through the fields of the methods like this isn't a stable or officially supported API. Further, your simple example is deceiving. This isn't, in general, representative of the original code you wrote for the method. It's a simplified intermediate AST representation with single-assignment variables and drastically simplified control flow. In general, the AST it returns isn't valid top-level Julia code. It just so happens that for your simple example, it is.
That said, there is a documented way to do this. You can use code_lowered() to get access to this intermediate representation without digging through undocumented fields. This will work across Julia versions, but I don't think there are official guarantees on the stability of the intermediate representation yet. Here's a slightly more complicated example:
julia> f(X) = for elt in X; println(elt); end
f (generic function with 1 method)
julia> code_lowered(f)[1]
LambdaInfo template for f(X) at REPL[17]:1
:(begin
nothing
SSAValue(0) = X
#temp# = (Base.start)(SSAValue(0))
4:
unless !((Base.done)(SSAValue(0),#temp#)) goto 13
SSAValue(1) = (Base.next)(SSAValue(0),#temp#)
elt = (Core.getfield)(SSAValue(1),1)
#temp# = (Core.getfield)(SSAValue(1),2) # line 1:
(Main.println)(elt)
11:
goto 4
13:
return
end)
julia> code_lowered(f)[1] == methods(f).ms[1].lambda_template
true
If you really want to see the code exactly as it was written, the best way is to use the embedded file and line information and refer to the original source. Note that this is precisely the manner in which Gallium.jl (Julia's debugger) finds the source to display as it steps through functions. It's undocumented, but you can even access the REPL history for functions defined interactively. See how Gallium does it through here.
First, retrieve the method using methods(f).
julia> methods(f)
# 1 method for generic function "f":
f(x, y) at REPL[1]:1
julia> methods(f).ms
1-element Array{Method,1}:
f(x, y) at REPL[1]:1
julia> method = methods(f).ms[1]
f(x, y) at REPL[1]:1
From here, retrieving the Expression is straightforward; simply use the lambda_template attribute of the method.
julia> method.lambda_template
LambdaInfo template for f(x, y) at REPL[1]:1
:(begin
nothing
return ((3 * x ^ 2 + x * y) - 2 * y) + 1
end)
Edit: This does not work in Julia v0.6+!

How to write a conditional lambda in Ruby?

I'd like to write a conditional lambda in Ruby. The Python equivalent of what I'd like to write is:
even = (lambda x: x if x % 2 == 0 else 0)
My attempt to write this in Ruby looks like:
even = -> (x) {x if x % 2 == 0 else 0}
Unfortunately, that does not work. Is there any way to fix this?
You have several options here to express this. The long-form is this:
if (x % 2 == 0)
x
else
0
end
Note that a trailing if or unless cannot have a secondary condition like else. You need to use the full form.
If you want a short version, you use the ternary operator:
(x % 2 == 0) ? x : 0
What you could also do is this:
(x % 2 == 0) and x or 0
As others have observed there's a method called even? which does the modulo for you, so that can collapse this further:
x.even? ? x : 0
Ruby's ternary operator has this syntax
x % 2 == 0 ? x : 0
You don't even need a conditional.
p = ->(x) { x*(1-x%2) }
p.call(4) #=> 4
p.call(5) #=> 0
Note procs can be called in multiple ways:
p[4] #=> 4
p.(4) #=> 4
p.yield(4) #=> 4
p === 4 #=> 4
p(4) #=> 4
The last of these may be archaic.
Wrong syntax. You can write it like this:
even = -> (x) {if x % 2 == 0; x; else; 0; end}
However, for such one-liners, it is more common to use the ternary ?: operator, as other have suggested in this thread.
Your syntax is wrong:
The then-block comes after the condition, not before it.
The then-block is separated from the condition by the then keyword, a semicolon, or a newline.
The conditional expression is terminated with an end keyword.
So, any of the following is valid:
# idiomatic:
if x % 2 == 0 then x else 0 end
# idiomatic:
if x % 2 == 0
x
else
0
end
# non-idiomatic:
if x % 2 == 0; x else 0 end
# non-idiomatic:
if x % 2 == 0 then
x
else
0
end
# non-idiomatic:
if x % 2 == 0
x else 0 end
# … and many other non-idiomatic variations
Ruby also has a conditional operator:
x % 2 ? x : 0
But I personally find it ugly and unreadable. It also has different precedence than the conditional expression, which may be surprising to some. (Witness the myriad of variations of the same question about the conditional operator here on StackOverflow.) And it is completely unnecessary: in C, where if is a conditional statement, the conditional operator is required because it is an expression. In Ruby, everything is an expression anyway, there are no statements, so of course if is an expression, too.

Closures in Ruby

I'm having a little trouble with closures and I'd like to know what
the equivalent code for the canonical make-adder procedure would be in
Ruby.
In scheme it would be like:
(define (make-adder n)
(lambda (x) (+ x n))
It's actually very close...
def make_addr n
lambda { |x| x + n }
end
t = make_addr 100
t.call 1
101
In 1.9 you can use...
def make_addr n
->(x) { x + n }
end
One difference is that while Scheme has only one kind of procedure, Ruby has four. Most of the time, they behave similarly enough to your standard lambda, but you should try to understand all the details in depth.
Here's another way to do it in 1.9:
make_adder = -> n, x { n + x }
hundred_adder = make_adder.curry[100]
hundred_adder[4] # => 104
Here is a pretty nice screen-cast explaining blocks and closures in Ruby:
http://www.teachmetocode.com/screencasts/8

Resources