What's wrong with the following code on ruby continuation? - ruby

New to ruby here. Tried to write a simple ruby code to do continuation, but the following code will print non-stopping integers 2,3, 4, 5, 6 ... (one number in each line). There must be an obvious bug here. Thanks.
require "continuation"
def dum ()
i = 1
callcc {|cc| $c = cc}
i += 1
puts i
end
dum() #expect to print 2
$c.call #expect to print 3
$c.call #expect to print 4
My ruby interpreter is 1.9.3p0

$c.call makes a complete jump back to the set execution context, so your script is repeatedly alternating between the call to dum() and the first line invoking $c.call, never reaching the last line. Here's the flow:
The dum() method is defined
dum() #expect to print 2: The script invokes dum() once, which sets an execution context for $c and then prints 2
$c.call #expect to print 3 jumps back into the call to dum() from the previous line -- the top level context of execution literally moves back to the previous line. This time dum() prints 3
The script now reaches the same $c.call #expect to print 3 line AGAIN, and will continue to infinitely alternate between these two lines.
The script will never reach your last line $c.call #expect to print 4.
One way to modify your script so that it produces the expected output:
require "continuation"
def dum ()
i = 1
callcc {|cc| $c = cc}
i += 1
puts i
return i
end
k = dum() #expect to print 2
$c.call unless k >= 4 # reach this line 3 times: print 3, and then 4, and then move on
I hope this helps.

Related

No output produced

Can anyone tell me why this program is not producing an output? The output it should be producing is: Line read: 0
Line read: 1 Line read: 2 Line read: 3 and so on.
So far, I am not getting an output even though I have fixed a number of bugs. Any help or suggestions would be much appreciated.
# takes a number and writes that number to a file then on each line
# increments from zero to the number passed
def write(aFile, number)
# You might need to fix this next line:
aFile.puts(number)
index = 0
while (index < number)
aFile.puts(index.to_s)
index += 1
end
end
# Read the data from the file and print out each line
def read(aFile)
# Defensive programming:
count = aFile.gets
if (is_numeric?(count))
count = count.to_i
index = 0
while (index < count)
line = aFile.gets
puts "line read: " + line
index+=1
end
end
end
# Write data to a file then read it in and print it out
def main
aFile = File.new("mydata.txt", "w") # open for writing
write(aFile, 10)
aFile.close
aFile = File.new("mydata.txt", "r")
read(aFile)
aFile.close
end
# returns true if a string contains only digits
def is_numeric?(obj)
if /[^0-9]/.match(obj) == nil
true
end
false
end
main
Your code isn't written in the Ruby way.
This is how I'd write it if I wanted to closely mimic your code's logic:
# takes a number and writes that number to a file then on each line
# increments from zero to the number passed
def write_data(fname, counter)
File.open(fname, 'w') do |fo|
fo.puts(counter)
counter.times do |n|
fo.puts n
end
end
end
# returns true if a string contains only digits
def is_numeric?(obj)
obj[/^\d+$/]
end
# Read the data from the file and print out each line
def read_data(fname)
File.open(fname) do |fi|
counter = fi.gets.chomp
if is_numeric?(counter)
counter.to_i.times do |n|
line_in = fi.gets
puts 'Line read: %s' % line_in
end
end
end
end
# Write data to a file then read it in and print it out
DATA_FILE = 'mydata.txt'
write_data(DATA_FILE, 10)
read_data(DATA_FILE)
Which outputs:
Line read: 0
Line read: 1
Line read: 2
Line read: 3
Line read: 4
Line read: 5
Line read: 6
Line read: 7
Line read: 8
Line read: 9
Notice these things:
Method (or variable) names are not in camelCase in Ruby, they're snake_case. ItsAReadabiltyThing.
Ruby encourages us to use a block when opening files for reading or writing, to automatically close the file when we're finished with it. Leaving danging file handles opened then not closed, in a loop, in a long-running program, is a great way for your program to crash in a way that's hard to figure out. SO has many questions that resulted from doing that. This is from the IO#open documentation:
With no associated block, ::open is a synonym for ::new. If the optional code block is given, it will be passed io as an argument, and the IO object will automatically be closed when the block terminates. In this instance, ::open returns the value of the block.
Usually you'll see code use File.open instead of IO.open, mostly out of habit in Ruby coders. File inherits from IO and adds some additional file-oriented methods to the class, so it's a little more full-featured.
Ruby has many methods that help us avoid using while loops. Getting the counters wrong or missing a condition that should terminate the loop, is all too common in programming, so Ruby makes it easy to loop "n times" or to iterate over all the elements in an array. The times method accomplishes that nicely.
String's [] method is really powerful and makes it easy to look at the contents of a string and apply a pattern or a slice. Using /^\d+$/ checks the entire string to make sure all characters are digits, so some_string[/^\d+$/] is a shorter version than what you're doing and accomplishes the same thing, returns a "truthy" value.
We don't use a main method. That's old-school Pascal, C or Java and is artificially structured. Ruby's a little more friendly than that.
Instead of using
3.times do |n|
puts n
end
# >> 0
# >> 1
# >> 2
I'd probably use
puts (0..(3 - 1)).to_a * "\n"
# >> 0
# >> 1
# >> 2
just because I tend to think in Perl terms. It's another old habit.
I found 2 errors. Fixing those errors gives you desired output.
Error #1.
Your method is_numeric? always returns false. Even if your condition is true. The last line of the method is false and therefore the whole method ALWAYS returns false.
You can fix it in 2 steps.
Step #1:
if /[^0-9]/.match(obj) == nil
true
else
false
end
It's not a good practice to return booleans within conditional. You can simplify it this way:
def is_numeric?(obj)
/[^0-9]/.match(obj) == nil
end
or even better
def is_numeric?(obj)
/[^0-9]/.match(obj).nil?
end
Error #2 is inside your read method. If you try to output the value of count after you read it from the file it gives you "10\n". That \n at the end messes you up.
To get rid of \n when you read from the file you could possibly use chomp. So then your reading line would be:
count = aFile.gets.chomp
and the rest works like magic

Is there an equivalent of shell scripting's xtrace option for Ruby?

When debugging shell scripts, I find it helpful to run with xtrace on:
-x xtrace Print commands and parameter
assignments when they are exe-
cuted, preceded by the value
of PS4.
For instance:
$ set -x
$ s='Say again?'
+ s='Say again?'
# Other commands that might mess with the value of $s
$ echo $s
+ echo Say 'again?'
Say again?
I know that Ruby has interactive debuggers such as pry and byebug, but I'm looking for something that will be easy to turn on for logging automated scripts.
I did find an xtrace gem, but it has something to do with a PHP format.
I also see there is a Tracer class and a TracePoint class which do seem to provide a way to print statements as they are executed. But I haven't found any way to print the value of variables (rather than just the variable name):
$ ruby -r tracer trace.rb
#0:/usr/local/Cellar/ruby/2.4.1_1/lib/ruby/2.4.0/rubygems/core_ext/kernel_require.rb:55:Kernel:<: return gem_original_require(path)
#0:trace.rb:1::-: s='Say again?'
#0:trace.rb:2::-: puts s
Say again?
I'd like to have the penultimate line read:
#0:trace.rb:2::-: puts 'Say again?'
Is this possible? Or is there a better way with Ruby?
I was able to build a module that more or less does what I'm looking for:
require 'pry'
=begin
We are always one line behind because the value of assignment comes
_after_ the trace is called. Without this, every assignment would look
like:
x = 1 #=> {:x=>nil}
It would be nice if the trace happened after assignment, but what can
you do?
=end
module Xtrace
# Only run the trace on the main file, not on require'd files.
# Possible room for expansion later.
#files = {$0 => Pry::Code.from_file($0)}
def Xtrace.print_trace
if #prev_line then
if #files[#path] then
line = #files[#path].around(#prev_line, 0).chomp
# When calling a method, don't make it look like it's being defined.
line.gsub!(/^\s*def\s*\b/, '') if #event == :call
values = []
#bind.local_variables.each do |v|
values << {v => #bind.local_variable_get(v)} if line =~ /\b#{v}\b/
end
STDERR.printf "%5s: %s", #prev_line, line
STDERR.printf " #=> %s", values.join(', ') unless values.empty?
STDERR.printf "\n"
end
end
end
#xtrace = TracePoint.trace(:line, :call) do |tp|
tp.disable
#bind=tp.binding
Xtrace.print_trace
# Other than the binding, everything we need to print comes from the
# previous trace call.
#prev_line = tp.lineno
#event=tp.event
#path=tp.path
tp.enable
end
# Need to print the trace one last time after the last line of code.
at_exit do
# It doesn't matter what we do in this last line. Any statement works.
# Also, it's a bit inconvenient that the disable command is itself traced.
#xtrace.disable
end
end
If you put it in a file named xtrace.rb and put in in your library load path, you can begin tracing by adding require 'xtrace'. It prints the line number of each line and method call executed, the actual code and the values of any local variable in the line. For a simple factorial function, the output might look like:
3: def factorial(n)
8: puts factorial(3)
3: factorial(n) #=> {:n=>3}
4: return 1 if n <= 1 #=> {:n=>3}
5: return n*factorial(n-1) #=> {:n=>2}
3: factorial(n) #=> {:n=>2}
4: return 1 if n <= 1 #=> {:n=>2}
5: return n*factorial(n-1) #=> {:n=>1}
3: factorial(n) #=> {:n=>1}
4: return 1 if n <= 1
6
For the moment, it only looks at local variables. It also only traces the executed file and not any loaded files. There's no way to enable or disable traces just yet. The trace begins when you require the module and ends when the execution does. Trace output goes to STDERR and the format is hardcoded.
If you use this module, watch out that you don't leak sensitive information such as passwords, API keys or PII.

Create the loading three little dots

Hello how can I make the three dot loading (...), so that it does something like this except without making a new line everytime:
Loading
Loading.
Loading...
Loading..
Loading.
and so on:
This is what I came up with, only problem is that I can't remove the dots one by one if loading continues for more than 1.5 seconds.
puts "Sending"
sleep(0.5)
print "."
sleep(0.5)
print "."
sleep(0.5)
print "."
Hopefully I am clear enough.
Thank you for your help.
10.times do |i|
print "Sending." + ("." * (i % 3)) + " \r"
$stdout.flush
sleep(0.5)
end
So, how does this work?
10.times do |i|
Repeat the following code 10 times, with the variable i indicating the current iteration (0, 1, 2, 3, 4...)
print "Sending." + ("." * (i % 3)) + " \r"
Print the phrase "Sending." followed by a couple of things:
("." * (i % 3)) repeats ("multiplies") the string "." several times, specifically i % 3, which is the remainder of i when it's divided by 3. So when i is 7, i % 3 is 1.
"\r" moves the cursor back to the beginning of the line without making a new line. If you think of a typewriter, it's like returning the carriage (the bit that types) to the beginning of the line so that you can type over the same line again. It's a carriage return.
$stdout.flush
Make sure the data prints.
sleep(0.5)
Sleep for half a sec.
You can try with $stdout.flush:
def loading number_of
number_of.times do |t|
print "Sending#{'.' * (t % 4)} \r"
$stdout.flush
sleep 0.5
end
end
Demonstration

Search and match string, only after a certain point in a file

How do I do scan a file after finding a particular line. The first results do not count.
For example (search for 3s after finding a line that says "begin here"):
Sample file
1
3
3
4
begin here
2
3
3
1
4
The expected output would be two 3s
Ruby's .. operator is your friend:
DATA.each_line do |line|
line.chomp!
next unless (line =~ /^begin here$/) .. false
puts line if line == '3'
end
__END__
1
3
3
4
begin here
2
3
3
1
4
Save that to a file and run it and you'll see:
3
3
.. (and the very much more obscure ...) come from Perl, and are very useful for just this particular kind of use.
What happens is .. is a two-state operator that works with if or unless to look for a first condition which is line =~ /^begin here$/ in this case. When that condition is met, the operator sticks, i.e., returns true until the second test matches, (returns true). Once that happens, the flip-flop then starts returning false again.
In this code, I'm fooling it into always returning true, because what would be the second test is always false. In other words, the code then reads to the end of the data.
.. (and ...) are REALLY useful when you're scanning a file, looking for blocks of data that occur throughout the file. If the second conditional test found the end of the block, .. would reset and the code would skip through the file until it found the next block start, triggered, and started capturing again.
It's also likely that most people haven't seen __END__ or DATA used. __END__ is a way to tell Ruby that there is no additional code to be executed beyond that point. DATA is an internal file handle that points to the lines following __END__ and can be treated similarly to IO and File objects. It's really useful for supplying data you must have with a script, but don't necessarily want to put into a separate file. In this case I'm pretending that the lines after __END__ are a separate file. Easy-peasy.
I would write it like this.
Code
def put3s(fname)
e = IO.foreach(FName)
until e.next.strip == "begin here"; end
loop { puts "3" if e.next.strip == "3" }
end
Note that IO#foreach without a block returns an enumerator. foreach is your best friend.
After the last element of the enumerator has been reached, e.next raises a StopIteration exception. Kernel#loop handles the exception by breaking out of the loop.
Example
We first create a file:
text =<<_
1
3
3
4
begin here
2
3
3
1
4
_
FName = "t"
File.write(FName, text)
and then execute the method
put3s(FName)
# 3
# 3

Equivalent of "continue" in Ruby

In C and many other languages, there is a continue keyword that, when used inside of a loop, jumps to the next iteration of the loop. Is there any equivalent of this continue keyword in Ruby?
Yes, it's called next.
for i in 0..5
if i < 2
next
end
puts "Value of local variable is #{i}"
end
This outputs the following:
Value of local variable is 2
Value of local variable is 3
Value of local variable is 4
Value of local variable is 5
=> 0..5
next
also, look at redo which redoes the current iteration.
Writing Ian Purton's answer in a slightly more idiomatic way:
(1..5).each do |x|
next if x < 2
puts x
end
Prints:
2
3
4
5
Inside for-loops and iterator methods like each and map the next keyword in ruby will have the effect of jumping to the next iteration of the loop (same as continue in C).
However what it actually does is just to return from the current block. So you can use it with any method that takes a block - even if it has nothing to do with iteration.
Ruby has two other loop/iteration control keywords: redo and retry.
Read more about them, and the difference between them, at Ruby QuickTips.
I think it is called next.
Use next, it will bypass that condition and rest of the code will work.
Below i have provided the Full script and out put
class TestBreak
puts " Enter the nmber"
no= gets.to_i
for i in 1..no
if(i==5)
next
else
puts i
end
end
end
obj=TestBreak.new()
Output:
Enter the nmber
10
1
2
3
4
6
7
8
9
10
Use may use next conditionally
before = 0
"0;1;2;3".split(";").each.with_index do |now, i|
next if i < 1
puts "before it was #{before}, now it is #{now}"
before = now
end
output:
before it was 0, now it is 1
before it was 1, now it is 2
before it was 2, now it is 3

Resources