I am learning ruby from 'Programming ruby 1.9'. I am learning to use the ruby-debug so I can understand what is going on underneath. I use rubymine since it integrates ruby-debug19 or something like that (it says I don't have the gem and installs it). Here is the question, I was able to step through the code and explore the variables and the stack. However, when it reaches a for i in 0...5, the debugger says
stack frame not available
I know that ruby don't use for loops much but I'd still like to know if there debug through for loops.
Code:
raw_text = %{
The problem breaks down into two parts. First, given some text as a
string, return a list of words. That sounds like an array. Then, build a
count for each distinct word. That sounds like a use for a hash---we can
index it with the word and use the corresponding entry to keep a count.}
word_list = words_from_string(raw_text)
counts = count_frequency(word_list)
sorted = counts.sort_by {|word, count| count}
top_five = sorted.last(5)
for i in 0...5 # (this is ugly code--read on
word = top_five[i][0] # for a better version)
count = top_five[i][1]
puts "#{word}: #{count}"
end
If you take a look at the Ruby Language Specification (clause 11.5.2.3.4 on p. 91), you will see that
for i in 0...5
word = top_five[i][0]
count = top_five[i][1]
puts "#{word}: #{count}"
end
is syntactic sugar for
(0...5).each do |i|
word = top_five[i][0]
count = top_five[i][1]
puts "#{word}: #{count}"
end
except that no new variable scope is created for the block. So, the code with for will be translated into the code with each and executed as if it were written that way, except that the variables used in the for loop leak into the surrounding scope.
To put it another way: for actually executes each but without allocating a new stack frame for the block. So, the error message is exactly right: there is a call to a block, but somehow there is no stack frame allocated for that block call. That obviously confuses the debugger.
Now, one might argue that this is a bug and that for loops should get special treatment inside the debugger. I guess that so far nobody has ever bothered to fix that bug, since nobody ever uses for loops, precisely because they leak their variables into the surrounding scope and are exactly equivalent to an idiomatic each which doesn't.
What do I mean by "leaking variables"? See here:
(1..2).each do |i|
t = true
end
i
# NameError: undefined local variable or method `i' for main:Object
t
# NameError: undefined local variable or method `t' for main:Object
for i in 1..2
t = true
end
i
# => 2
t
# => true
Related
Why is each loop preferred over for loop in Ruby? Is there a difference in time complexity or are they just syntactically different?
Yes, these are two different ways of iterating over, But hope this calculation helps.
require 'benchmark'
a = Array( 1..100000000 )
sum = 0
Benchmark.realtime {
a.each { |x| sum += x }
}
This takes 5.866932 sec
a = Array( 1..100000000 )
sum = 0
Benchmark.realtime {
for x in a
sum += x
end
}
This takes 6.146521 sec.
Though its not a right way to do the benchmarking, there are some other constraints too. But on a single machine, each seems to be a bit faster than for.
The variable referencing an item in iteration is temporary and does not have significance outside of the iteration. It is better if it is hidden from outside of the iteration. With external iterators, such variable is located outside of the iteration block. In the following, e is useful only within do ... end, but is separated from the block, and written outside of it; it does not look easy to a programmer:
for e in [:foo, :bar] do
...
end
With internal iterators, the block variable is defined right inside the block, where it is used. It is easier to read:
[:foo, :bar].each do |e|
...
end
This visibility issue is not just for a programmer. With respect to visibility in the sense of scope, the variable for an external iterator is accessible outside of the iteration:
for e in [:foo] do; end
e # => :foo
whereas in internal iterator, a block variable is invisible from outside:
[:foo].each do |e|; end
e # => undefined local variable or method `e'
The latter is better from the point of view of encapsulation.
When you want to nest the loops, the order of variables would be somewhat backwards with external iterators:
for a in [[:foo, :bar]] do
for e in a do
...
end
end
but with internal iterators, the order is more straightforward:
[[:foo, :bar]].each do |a|
a.each do |e|
...
end
end
With external iterators, you can only use hard-coded Ruby syntax, and you also have to remember the matching between the keyword and the method that is internally called (for calls each), but for internal iterators, you can define your own, which gives flexibility.
each is the Ruby Way. Implements the Iterator Pattern that has decoupling benefits.
Check also this: "for" vs "each" in Ruby
An interesting question. There are several ways of looping in Ruby. I have noted that there is a design principle in Ruby, that when there are multiple ways of doing the same, there are usually subtle differences between them, and each case has its own unique use, its own problem that it solves. So in the end you end up needing to be able to write (and not just to read) all of them.
As for the question about for loop, this is similar to my earlier question whethe for loop is a trap.
Basically there are 2 main explicit ways of looping, one is by iterators (or, more generally, blocks), such as
[1, 2, 3].each { |e| puts e * 10 }
[1, 2, 3].map { |e| e * 10 )
# etc., see Array and Enumerable documentation for more iterator methods.
Connected to this way of iterating is the class Enumerator, which you should strive to understand.
The other way is Pascal-ish looping by while, until and for loops.
for y in [1, 2, 3]
puts y
end
x = 0
while x < 3
puts x; x += 1
end
# same for until loop
Like if and unless, while and until have their tail form, such as
a = 'alligator'
a.chop! until a.chars.last == 'g'
#=> 'allig'
The third very important way of looping is implicit looping, or looping by recursion. Ruby is extremely malleable, all classes are modifiable, hooks can be set up for various events, and this can be exploited to produce most unusual ways of looping. The possibilities are so endless that I don't even know where to start talking about them. Perhaps a good place is the blog by Yusuke Endoh, a well known artist working with Ruby code as his artistic material of choice.
To demonstrate what I mean, consider this loop
class Object
def method_missing sym
s = sym.to_s
if s.chars.last == 'g' then s else eval s.chop end
end
end
alligator
#=> "allig"
Aside of readability issues, the for loop iterates in the Ruby land whereas each does it from native code, so in principle each should be more efficient when iterating all elements in an array.
Loop with each:
arr.each {|x| puts x}
Loop with for:
for i in 0..arr.length
puts arr[i]
end
In the each case we are just passing a code block to a method implemented in the machine's native code (fast code), whereas in the for case, all code must be interpreted and run taking into account all the complexity of the Ruby language.
However for is more flexible and lets you iterate in more complex ways than each does, for example, iterating with a given step.
EDIT
I didn't come across that you can step over a range by using the step() method before calling each(), so the flexibility I claimed for the for loop is actually unjustified.
I'm doing a SaaS course with Ruby. On an exercise, I'm asked to calculate the cartesian product of two sequences by using iterators, blocks and yield.
I ended up with this, by pure guess-and-error, and it seems to work. But I'm not sure about how. I seem to understand the basic blocks and yield usage, but this? Not at all.
class CartProd
include Enumerable
def initialize(a,b)
#a = a
#b = b
end
def each
#a.each{|ae|
#b.each{|be|
yield [ae,be]
}
}
end
end
Some explanation for a noob like me, please?
(PS: I changed the required class name to CartProd so people doing the course can't find the response by googling it so easily)
Let's build this up step-by-step. We will simplify things a bit by taking it out of the class context.
For this example it is intuitive to think of an iterator as being a more-powerful replacement for a traditional for-loop.
So first here's a for-loop version:
seq1 = (0..2)
seq2 = (0..2)
for x in seq1
for y in seq2
p [x,y] # shorthand for puts [x, y].inspect
end
end
Now let's replace that with more Ruby-idiomatic iterator style, explicitly supplying blocks to be executed (i.e., the do...end blocks):
seq1.each do |x|
seq2.each do |y|
p [x,y]
end
end
So far, so good, you've printed out your cartesian product. Now your assignment asks you to use yield as well. The point of yield is to "yield execution", i.e., pass control to another block of code temporarily (optionally passing one or more arguments).
So, although it's not really necessary for this toy example, instead of directly printing the value like above, you can yield the value, and let the caller supply a block that accepts that value and prints it instead.
That could look like this:
def prod(seq1, seq2)
seq1.each do |x|
seq2.each do |y|
yield [x,y]
end
end
end
Callable like this:
prod (1..2), (1..2) do |prod| p prod end
The yield supplies the product for each run of the inner loop, and the yielded value is printed by the block supplied by the caller.
What exactly do you not understand here? You've made an iterator that yields all possible pairs of elements. If you pass CartProd#each a block, it will be executed a.length*b.length times. It's like having two different for cycles folded one into another in any other programming language.
yield simply passes (yields) control to a block of code that has been passed in as part of the method call. The values after the yield keyword are passed into the block as arguments. Once the block has finished execution it passes back control.
So, in your example you could call #each like this:
CartProd.new([1, 2], [3, 4]).each do |pair|
# control is yielded to this block
p pair
# control is returned at end of block
end
This would output each pair of values.
I was learning ruby, and i learnt that ruby constants must start with a Upper case letter (e.g. Myconstant). This will make it a constant, but its value is changeable!
If a constant's value is changeable then why do we need constant, what is the difference between variable then?
Constants have lexical scoping, whereas methods have dynamic scoping:
class Super
Constant = "Super::Constant"
def method
'Super#method'
end
def get_constant
Constant
end
def get_method
method
end
end
class Sub < Super
Constant = 'Sub::Constant'
def method
'Sub#method'
end
end
Super.new.get_constant # => "Super::Constant"
Sub.new.get_constant # => "Super::Constant"
Super.new.get_method # => "Super#method"
Sub.new.get_method # => "Sub#method"
And as far as variables, they are inaccessible from the outside. How would you intend to access these?
class Object
Constant = 'constant'
local_var = 'local var'
#instance_var = 'instance var'
##class_var = 'class var' # btw, never use these
end
Also, there's a lot of things you can do in Ruby, but for your own sanity, be wary. I'd recommend against changing constants around, it will likely frustrate your team.
Ruby lets you shoot yourself in the foot (if you really want to). But, at least in this case, it warns you about it.
ONE = 'one'
ONE = 'two' # !> already initialized constant ONE
Some reasons:
1) Convention. It's easy to see just from the name of an identifier that it's not supposed to change.
2) Technical. It (probably; someone more knowledgeable than I will probably answer) makes the interpreter simpler.
3) Dynamism is sometimes helpful; in testing, for example, it's possible to redefine things for testing purposes rather than having to stub/proxy everything…
I use this feature sometimes to test out code without otherwise necessary parameters, eg when i run the script from my editor where it is difficult to provide a parameter.
#ARGV[0] = "c:/test.txt" #in case of testing i remove the first remark sign
In a discussion of Ruby loops, Niklas B. recently talked about for loop 'not introducing a new scope', as compared to each loop. I'd like to see some examples of how does one feel this.
O.K., I expand the question: Where else in Ruby do we see what apears do/end block delimiters, but there is actually no scope inside? Anything else apart from for ... do ... end?
O.K., One more expansion of the question, is there a way to write for loop with curly braces { block } ?
Let's illustrate the point by an example:
results = []
(1..3).each do |i|
results << lambda { i }
end
p results.map(&:call) # => [1,2,3]
Cool, this is what was expected. Now check the following:
results = []
for i in 1..3
results << lambda { i }
end
p results.map(&:call) # => [3,3,3]
Huh, what's going on? Believe me, these kinds of bugs are nasty to track down. Python or JS developers will know what I mean :)
That alone is a reason for me to avoid these loops like the plague, although there are more good arguments in favor of this position. As Ben pointed out correctly, using the proper method from Enumerable almost always leads to better code than using plain old, imperative for loops or the fancier Enumerable#each. For instance, the above example could also be concisely written as
lambdas = 1.upto(3).map { |i| lambda { i } }
p lambdas.map(&:call)
I expand the question: Where else in Ruby do we see what apears do/end block delimiters, but there is actually no scope inside? Anything else apart from for ... do ... end?
Every single one of the looping constructs can be used that way:
while true do
#...
end
until false do
# ...
end
On the other hand, we can write every one of these without the do (which is obviously preferrable):
for i in 1..3
end
while true
end
until false
end
One more expansion of the question, is there a way to write for loop with curly braces { block }
No, there is not. Also note that the term "block" has a special meaning in Ruby.
First, I'll explain why you wouldn't want to use for, and then explain why you might.
The main reason you wouldn't want to use for is that it's un-idiomatic. If you use each, you can easily replace that each with a map or a find or an each_with_index without a major change of your code. But there's no for_map or for_find or for_with_index.
Another reason is that if you create a variable within a block within each, and it hasn't been created before-hand, it'll only stay in existance for as long as that loop exists. Getting rid of variables once you have no use for them is a good thing.
Now I'll mention why you might want to use for. each creates a closure for each loop, and if you repeat that loop too many times, that loop can cause performance problems. In https://stackoverflow.com/a/10325493/38765 , I posted that using a while loop rather than a block made it slower.
RUN_COUNT = 10_000_000
FIRST_STRING = "Woooooha"
SECOND_STRING = "Woooooha"
def times_double_equal_sign
RUN_COUNT.times do |i|
FIRST_STRING == SECOND_STRING
end
end
def loop_double_equal_sign
i = 0
while i < RUN_COUNT
FIRST_STRING == SECOND_STRING
i += 1
end
end
times_double_equal_sign consistently took 2.4 seconds, while loop_double_equal_sign was consistently 0.2 to 0.3 seconds faster.
In https://stackoverflow.com/a/6475413/38765 , I found that executing an empty loop took 1.9 seconds, whereas executing an empty block took 5.7 seconds.
Know why you wouldn't want to use for, know why you would want to use for, and only use the latter when you need to. Unless you feel nostalgic for other languages. :)
Well, even blocks are not perfect in Ruby prior to 1.9. They don't always introduce new scope:
i = 0
results = []
(1..3).each do |i|
results << lambda { i }
end
i = 5
p results.map(&:call) # => [5,5,5]
I'm just starting with Ruby and I personally find the following to be a violation of the "principle of least surprise". And that is, quoting from the documentation, that uniq! "removes duplicate elements from self. Returns nil if no changes are made (that is, no duplicates are found)."
Can anybody explain this, which seems completely counter-intuitive to me? This means that rather than being able to write one line of code below by appending .uniq! to end the first line, I instead have to write the following two lines:
hooks = IO.read(wt_hooks_impl_file).scan(/wt_rt_00\w{2}/)
hooks = hooks.uniq
Or am I missing something, a better way?
EDIT:
I understand that uniq! modifies its operand. Here's the problem illustrated better I hope:
hooks = IO.read(wt_hooks_impl_file).scan(/wt_rt_00\w{2}/)
puts hooks.length #50
puts hooks.uniq!.length #undefined method `length' for nil:NilClass
I contend that the way uniq! works makes it completely senseless and useless. Sure in my case as pointed out I could just append .uniq to the first line. However later in the same program I am pushing elements onto another array inside of a loop. Then, under the loop, I'd like to "de-dupe" the array, but I dare not write 'hooks_tested.uniq!' because it could return nil; instead I must write hooks_tested = hooks_tested.uniq
Indeed I contend this is a particularly egregious mis-feature in that it is a well known principle that, when devising a method that returns an array, one should always at least return an empty array, rather than nil
This is because uniq! modifies self and if uniq! would return a value you wouldn't be able to know whether a change actually occurred in the original object.
var = %w(green green yellow)
if var.uniq!
# the array contained duplicate entries
else
# nothing changed
end
In your code you can simply write
hooks = IO.read(wt_hooks_impl_file).scan(/wt_rt_00\w{2}/)
hooks.uniq!
# here hooks is already changed
If you need to return the value of hook perhaps because it's the last method statement just do
def method
hooks = IO.read(wt_hooks_impl_file).scan(/wt_rt_00\w{2}/)
hooks.uniq
end
or otherwise
def method
hooks = IO.read(wt_hooks_impl_file).scan(/wt_rt_00\w{2}/)
hooks.uniq!
hooks
end
The exclamation point on uniq! indicates that it modifies the array instead of returning a new one. You should do this:
hooks = IO.read(wt_hooks_impl_file).scan(/wt_rt_00\w{2}/).uniq
or this
hooks = IO.read(wt_hooks_impl_file).scan(/wt_rt_00\w{2}/)
hooks.uniq!
puts hooks.length
Since Ruby 1.9, Object#tap is available:
hooks = IO.read(wt_hooks_impl_file).scan(/wt_rt_00\w{2}/).tap do |hooks|
hooks.uniq!
end
puts hooks.length
And perhaps more succinctly (h/t #Aetherus):
hooks = IO.read(wt_hooks_impl_file).scan(/wt_rt_00\w{2}/).tap(&:uniq!)
puts hooks.length
You can append uniq (no exclamation mark at the end) to the end of the first line.
Or, if you insist on using uniq!, use
(hooks = IO.read(wt_hooks_impl_file).scan(/wt_rt_00\w{2}/)).uniq!
This is not an answer to why, but rather, a workaround.
Since uniq doesn't return nil, I use uniq and assign the the result to a new variable instead of using the bang version
original = [1,2,3,4]
new = original.uniq
#=> new is [1,2,3,4]
#=> ... rather than nil
Having a new variable is a small price to pay. It sure as hell beats doing if checks, with repeated complex calls to uniq! and uniq and checking for nil