Ruby: What Does STDIN.gets mean? - ruby

Recently, i was reading legacy ruby script and hopefully to convert some of them to python.
I understand the concept of 'STDIN' and done some google search. However, there is no documentation about this stand alone statement: 'STDIN.gets.' What's the return value? Does it secretly get all the input and store it in some default places, or it is simply a piece of unfinished meaningless legacy code i should delete?

If you run p STDIN.method(:gets) you get #<Method: IO#gets>. This means that the gets method if defined in the IO module. Knowing that, you can then read the official documentation of gets here:
http://ruby-doc.org/core-2.3.0/IO.html#method-i-gets
The gets method does not store its data in some default place, it returns it as the return value of the method. If that return value is being ignored, then the data is lost, but it could still be useful to call STDIN.gets for its side effects: gets will pause the execution of your thread and wait for input from the standard input. This would give the user a chance to review what the Ruby script has already done and terminate it early if the user wants to.

When working with Ruby, irb is your friend. irb is the interactive Ruby shell, or REPL. You can try your statement in irb:
2.3.0 :001 > STDIN.gets
hello
=> "hello\n"
After typing STDIN.gets, the system waited for input. I typed hello and then pressed the Enter key. irb indicated that the return value of the expression was "hello\n".
This shows that:
1) gets returns when, and only when, the user presses Enter or equivalent.
2) gets returns the string that was typed, pasted, etc., including the terminating Enter key.
You'll probably see a lot of calls to chomp on strings returned by gets. This is because the trailing "\n" is rarely wanted. chomp returns a string with the "\n" removed.

Related

Which is correct REPL or command-line?

when i write method missing in Object class i'm getting the output different in each interface.
the code is
class Object
def method_missing(hgh)
puts self
end
end
when i use REPL like irb, i get
when i use the command line, i get no error, any reasons would be helpful, thanks in advance
The tl;dr answer is that both are correct. Just more stuff happen in the REPL.
When you run the code from the command line like:
ruby script.rb
All that happens is that it's evaluated.
Whereas REPLs like IRB read your input, evaluate it and print it in a loop.
In this case evaluating your code literally broke the REPL and resulted in the subsequent print failing.
Now you may be a bit confused by this. "There is a print in both cases, I use puts!". The print I'm referring to here is the result that gets visualised after each evaluation. In this case the method definition result (=> :method_missing).
It might not only be the printing itself. It can be the ton of other under the hood code that the REPL has to execute to keep state like "what code was defined on which line" and so on.
Think of what you just did - you made it so that every object has every method possible to return nil. That is not just for the code you write in the REPL. It's for the code of the REPL itself as well.

Ruby iterator yield

I'm wondering why the following tag methods produce different results:
Method 1:
def tag(html)
print "<#{html}>#{yield}</#{html}>"
end
Method 2:
def tag(html)
print "<#{html}>"
print yield
print "</#{html}>"
end
When I ran the following code in terminal using the above methods:
tag(:ul) do
tag(:li) { "It sparkles!" }
tag(:li) { "It shines!" }
tag(:li) { "It mesmerizes!" }
end
The first one gave me:
<li>It sparkles!</li><li>It shines!</li><li>It mesmerizes!</li><ul></ul>
The second one gave me:
<ul><li>It sparkles!</li><li>It shines!</li><li>It mesmerizes!</li></ul>
The second one is the output that I'm looking.
How come the first method prints 'yield' before it prints what comes before 'yield' in the string?
Just to echo #tadman's answer: order of evaluation AND inconsistency of api. Your block sometimes returns strings and sometimes prints strings as a side-effect.
print "<#{html}>"
print yield
print "</#{html}>"
Here you print, then yield. If the block returns a string (one of :li blocks), then it's printed right here. If it's a :ul block, then its side-effects happen (printing of li blocks) and nil is printed after that.
In the other case
print "<#{html}>#{yield}</#{html}>"
Ruby has to assemble one string to print. Which means yielding before any printing. Which means that side-effects happen before printing the opening <ul>. As the ul block returns nil, that's why it's printed empty at the end of the string (<ul></ul>).
Does it make sense?
The main problem is the order of operations. When you call print it will print immediately, there's no delay, which can cause problems.
In Ruby it's often easier to deal with code that returns strings rather than code that causes side-effects like printing. If they return strings you have control over where that output goes. If they print things immediately you need to be very careful about the order you call them in.
The way you're calling that code in the final assembly with the tag(:ul) call is actually going to be trouble. The second version of your method coincidentally orders things correctly.
It's not necessarily easy to fix this. If you return a string, then only the last string from your three tag calls will be used. If you print, you'll have to be sure you're using the second method to make it work.
Within the Rails system there's a way of capturing the output of these things for buffering purposes, but that's a very messy thing to try and do, it can get really confused when you try and handle all cases.
Where possible create some kind of buffer these things can write to, then when everything's done write that out with print or whatever.

Pry (Ruby REPL): How can I turn automatic echo off

Since Ruby supports parallel assignments and automatic value return from functions, almost every assignment and method run ends up creating an output when working on REPLs like IRB and Pry.
Normally I prevent this echo effect by putting a semicolon at the end of each line. For instance:
JSON::parse(very_long_json_string);
This normally prevents REPL echo. But when working with very large enumerables even one mistake can generate enough output to make a mess on the screen and put all my useful command history out of memory before I have the reflex to hit the break.
Is there a way to turn this echo effect off by default in Pry? As mentioned in the comments below (#Stefan), the same can be achieved in IRB by setting conf.echo = false.
In IRB there is:
conf.echo = false
In Pry you could replace the print object with an empty proc:
_pry_.config.print = proc {}
You'll have to store the old print object in order to restore it.
In both cases, the result of the last expression is still available via _

Ruby: "undefined method" error; how to use gsub more effectively?

So I'm trying to find a way to Donald Duck-ify statements inputed by users (judge me later).
This is my code so far:
puts "Wanna get Donald Duck-ified?"
print "Type some text here:"
user_input = gets.chomp
if user_input.gsub!(/s/,"th").gsub!(/ce/,"th").gsub!(/ci/,"th").gsub!(/cy/,"th")
puts "Boop - there go your s's and soft c's!"
else
puts "Dang, you didn't have any s's or soft c's!"
end
puts "#{user_input}"
Upon testing it with some input of my own ("square cycle caesar circle", specifically), I'm getting "undefined method `gsub!' for nil:NilClass" as an error.
How is gsub! undefined? If the code runs with user_input.gsub!(/s/,"th") on it own, without any other methods behind it, it works fine. Once a second method is added, the else code runs and only replacements for "s" are made. All four and I get the error above.
Does there happen to be another way of substituting multiple patterns (as named by the Ruby docs) with a single replacement? I've spent the last hours researching the problem and I still can't totally tell what the issue is.
New to Ruby. Encouraged and motivated.
Many thanks in advance.
Don't use #gsub! chained. (Actually, don't use #gsub! at all for most code.)
[gsub!] Performs the substitutions of String#gsub in place, returning str, or nil if no substitutions were performed.
Switch the code to #gsub which doesn't cause side-effects (yay!) and always returns a string (yay!) - simply compare the result with the original (unmodified) string.
Also, one could use the gsub form that accepts a hash (since Ruby 1.9.something). This has a subtle difference that replaced values will not be themselves replaced, although it doesn't matter here.
user_input.gsub(/s|ce|ci|cy/, { "s"=>"th", "ce"=>"th", "ci"=>"th", "cy"=>"th" })
# or since all are replaced with "th" (which I just noticed =^_^=) ..
user_input.gsub(/s|ce|ci|cy/, "th")
(I still recommend against gsub! because I find side effects upon strings disconcerting. However, it would work reliably when used with the non-chained forms above.)
Ruby's gsub! returns nil if it performs no substitutions. This means you can't reliably chain it like you do. If you want to verify that any of the gsubs have made any change, you can chain non-destructive gsubs (without the bang; return a new string instead of modifying the current one) instead:
input = gets.chomp
replaced = input.gsub(/s/,"th").gsub(/ce/,"th").gsub(/ci/,"th").gsub(/cy/,"th")
if input == replaced
...

ruby cast method input variable as string in ruby irb

How would I coerce the behavior of irb to treat variable identifiers as strings when used in method signatures?
I am trying to create a irb based calculation tool and I want to reduce the typing of users who use this tool in the irb shell. Assume my users are not ruby programmers or know much about the syntax of ruby. The may have some facility with the command line.
I have a file
calculator.rb
inside this file is
def calculate(value, units)
... some logic
end
I instruct the user to fire up irb like so
irb -r path/to/calculator.rb
I instruct the user to type
calculate(10, inches)
get return value in irb
how can I do this without requiring the user to understand that they have to wrap the second parameter in quotation marks. In other words I don't want the user to have to type
calculate(10, "inches")
is it possible to cast the user input as a string instead of a variable identifier before it is passed to my method inside my script? Maybe what I want to do is not possible without fundamentally breaking irb shell?
If this is for non-programmers how about using puts and gets?
def calculate
puts "Which number would you like to convert?"
number = gets.to_i
puts "What do you want to convert it to?"
type = gets
# your conversion logic
puts result
end
You can actually do it the way you requested using method_missing. Any matching units will get converted to strings instead of raising exceptions.
SO_CALC_UNITS = %w[inches feet yards meters parsecs]
def method_missing(method)
if SO_CALC_UNITS.include?(method.to_s)
method.to_s
else
super(method)
end
end

Resources