My personal up until recently underused keyword was (surprise!) "rescue".
I'm not sure how this has been escaping me since 07, but I had no idea you can apply it at the end of an expression, i.e. when you're facing nasty functions that insist on trhowing exceptions, instead of
Careful here: I've seen plenty of "Rubiomatic" bugs that look like this:
value = function_that_nils or "default"
... which results in nil assignment to value. Accidental confusion between || and 'or' is very common in Ruby world IMO, almost like famous == vs = in C.
Agreed. I think one is for statements (or) and the other one is for expressions (||), so they have different operational precedence, even though you could use them interchangeably, as long as you knew what got executed first.
redo, in the Fibonacci example, is still iterative - it's presented as a third way, when it's just a cruftier way of being iterative. If you remove the cruft of the lambda and the redo, you end up with:
def fib(i)
n, result = 1, 0
while i != -1
i, n, result = i - 1, n + result, n
end
result
end
Cleaner, faster (by 10% on Ruby 1.8) and shorter, but certainly iterative.
(Separate to this, the fib routines shown produce incorrect results - my example above maintains this, just for comparison with the original code. fib(10) is 55 not 89 - it's one off in its input.)
You are absolutely right... if you're an interpreter...
From a user's point of view, the redo says "run this block again"; and since the block == the method it's just another way to run acc(). Of course, it's still faking, but I've never claimed anything else :-)
Since we're having the discussion in two places, I'll be quicker here.. ;-)
"run this block again" signifies "loop" to me and "loop" signifies "iteration." If I see a block of code being looped, I don't think (as a coder, not as an interpreter) that it's recursive. Perhaps others would, though. If we got in a time machine back to the 80s, I kinda feel that "redo" would turn into "goto".. :)
(Hey, we should be doing this on RubyFlow as well - you could be earning some serious karma :))
Simplistically, tail call optimisation is an automated way to convert recursion into iteration. You could do that by hand for any tail call recursive function, whether you do so is a function of style and the language you are using.
I'm not sure how this has been escaping me since 07, but I had no idea you can apply it at the end of an expression, i.e. when you're facing nasty functions that insist on trhowing exceptions, instead of
begin
rescue endyou can just write:
value = function_that_throws rescue "default"