Is there any way to get the output of the last string sent to output? For instance:
puts "Hello"
puts _+" World"
Would return
Hello
Hello World
The assignment I'm working on involves minimizing code as much as possible. The above example is not the assignment, but if such a variable exists it would certainly help.
Thanks
** EDIT **
#gnibbler has the closest answer to what I'm looking for. This has nothing to do with spacing. I need to reuse the data output on the previous line, not append to it. Another example would be:
puts "foobar" // foobar
puts _.reverse // raboof
Yeah its possible. You need to override the Kernel::puts method likes this
module Kernel
alias_method :old_puts, :puts
def puts arg
old_puts arg
$_=arg # $_ is a global variable, holds the last printed item
end
end
and use it like
>> puts "sample"
=> "sample"
>> _
=> "sample"
>> _.reverse
=> "elpmas"
_ will always holds the last printed value
it means
>> puts "hello"
=> "hello"
>> puts _ + " word"
=> "hello word"
>> _
=> "hello word"
Is there a reason that you want to do this?maybe there is other solutions. If you really wants to do, you can do like this:
module Kernel
alias_method :puts_with_save, :puts
def puts_with_save arg_
puts arg_
$LastPuts = arg_
end
end
puts_with_save "hello"
puts_with_save $LastPuts + " shanison"
This should work as you expected. But I introduce a global $LastPuts to your program.
There is no special variable for that
apart from patching puts (which will conflict with your requirement to minimise the code), you could use a pattern like this
puts w="Hello"
puts w=(w+" World")
puts w=(w.reverse)
etc.
The only thing I can think of is that if you knew you were using puts you could patch it with your own version to give it a "memory" to suit your objective. However, it sounds like in your case you may as well use a separate mechanism rather than overriding the default behavior of puts.
Related
I want to recall the case until user writes a or b. I do not want to use "case"
particularly.
I just want to get input from user but not geting something else. If he writes something else, he should need to write until he writes a or b.
str = gets.chomp.to_s
case str
when "a"
print "nice a"
when "b"
puts "nice b"
else
puts "please do it again"
end
class person
attr_accessor :name , :surname #and other attributes
end
#There will be a method here and it will run when the program is opened.
#The method will create the first object as soon as the program is opened.
#The new object that the user will enter will actually be the 2nd object.
puts "What do you want to do?
add
list
out"
process = gets.chomp.to_s
case process
when "add"
#in here user will add new objects of my class
when "list"
#in here user will show my objects
when "out"
puts "Have a nice day"
else
puts "please do it again"
end
In fact, if you look at it, many actions will be taken as a result of the user entering the correct input. what I want to tell is more detailed in this example. According to the input of the user, there will be actions such as calling methods, adding objects, etc.
I wrote most of the code on my computer. But still I couldn't solve my first problem.
Use Kernel#loop
There are a lot of ways to solve this problem, but let's start with a simple Kernel#loop wrapper around your existing code, as that's probably the easiest path forward for you.
loop do
str = gets.chomp.to_s
case str
when "a"
print "nice a"
when "b"
puts "nice b"
else
puts "please do it again"
# restart your loop when not "a" or "b"
next
end
# exit the loop if else clause wasn't triggered
break
end
Use until Control Expression
The loop construct above is pretty straightforward, but it requires you to think about where you need next and break statements for flow control. My own instinct would be to simply call a block until it's truthy. For example, the core logic could be shortened to:
str = nil; until str =~ /a|b/i do str = gets.chomp end; p str
This is a lot shorter, but it's not particularly user-friendly. To leverage this approach while making the solution more communicative and error-resistant, I'd refactor the original code this way:
# enable single-character input from console
require 'io/console'
# make sure you don't already have a value,
# especially in a REPL like irb
str = nil
until str =~ /a|b/ do
printf "\nLetter (a, b): "
str = STDIN.getch.downcase
end
puts "\nYou entered: #{str}"
While not much shorter than your original code, it handles more edge cases and avoids branching. It also seems less cluttered to me, but that's more a question of style. This approach and its semantic intent also seem more readable to me, but your mileage may legitimately vary.
See Also
IO::Console
Control Expressions
"I just want to do something until something else happens" is when you use some sort of while loop.
You can do this:
while true
str = gets.chomp
break unless str == 'a' || str == 'b'
puts "please do it again"
end
You can also use loop do:
loop do
str = gets.chomp
break unless ['a', 'b'].include?(str)
puts "please do it again"
end
puts "Nice #{str}."
Rubyists tend to prefer loop do over while true. They do pretty much the same thing.
One more thing. There's a simpler way to write out arrays of strings:
loop do
str = gets.chomp
break unless %w(a b).include?(str)
puts "please do it again"
end
puts "Nice #{str}."
It doesn't look a whole lot simpler, but if you have, say, 10 strings, it's definitely quicker to type in when you don't have to use all those quotation marks.
As your intuition was telling you, you don't need to use the case statement at all. Like trying to kill a flea with a sledgehammer. The most concise way to do your check is to check whether the input character is included in an array of the desired characters.
I am learning methods in Ruby and thought that the best way to learn them was to create a method that already exists. However, there are two problems that I am running in to:
I do not know what the capitalize method looks like
My solution (it does more than the original method does) seems like it can be refactored into something more elegant.
This is what I have come up with:
# method that capitalizes a word
def new_capitalize(string)
if string[0].downcase == "m" && string[1].downcase == "c"
puts "#{string[0].upcase}#{string[1].downcase}#{string[2].upcase}#{string[3..-1].downcase}"
else
puts "#{string[0].upcase}#{string[1..-1].downcase}"
end
end
name1 = "ryan"
name2 = "jane"
new_capitalize(name1) # prints "Ryan"
new_capitalize(name2) # prints "Jane"
str = "mCnealy"
puts str.capitalize
# prints "Mcnealy"
new_capitalize(str)
# prints "McNealy"
It seems as if the first part of my if statement could be made much more efficient. It does not need to be even close to my solution as long as it prints the second capital if the name begins with "mc"
Also, if someone could point me to where the built in capitalize method's code could be found that would be great too!
Thank you in advance!
Alright, how about:
module NameRules
refine String do
def capitalize
if self[0..1].downcase == 'mc'
"Mc#{self[2..-1].capitalize}"
else
super
end
end
end
end
Then to use it:
class ThingWithNames
using NameRules
def self.test(string)
string.capitalize
end
end
ThingWithNames.test('mclemon') # => "McLemon"
ThingWithNames.test('lemon') # => "Lemon"
If we were starting from scratch and not using the C implemented code:
module NameRules
refine String do
def capitalize
if self[0..1].downcase == 'mc'
"Mc#{self[2..-1].capitalize}"
else
new_string = self.downcase
new_string[0] = new_string[0].upcase
new_string
end
end
end
end
Reference materials:
String#capitalize source
A really good presentation on refinements
First, in my opinion, doing anything other than capitalizing the first letter of the string should be a different method or an optional arg you pass. Second, if you are trying to mimic the core lib behavior than you could monkey-patch String.
class String
def capitalize
self[0].upcase << self[1..-1].downcase
end
end
The closest to an official ruby implementation is probably Rubinius
https://github.com/rubinius/rubinius/blob/377d5c958bc8239514fb98701b75859c6b51b9d4/core/string.rb#L332
I am new to Ruby.
I need to make this script work:
puts "Do you like cats?"
ask = gets
def ask(n)
if ask == yes
return "I do too"
end
if ask == no
return "Dogs are better"
end
end
puts "#{ask(n)}"
Error message is :
pracif.rb:15:in <main>': undefined local variable or methodn' for
main: Object (NameError)
Here's a script that would work for you :
puts "Do you like cats?"
answer = gets
def ask(n)
if n == 'yes'
return "I do too"
end
if n == 'no'
return "Dogs are better"
end
end
puts ask(answer.downcase.chomp)
Explaination
As the error said you were trying to pass in a variable n which was not defined
Secondly you have a method name ask same as variable name. I've renamed the variable to answer instead
Thirdly, enclose yes and no in quotes
And finally, since you are using gets a \n gets appended like yes\n so none of your conditions would match. So i've used chomp to remove \n. And also used downcase to make input case insensitive.
EDIT
As mentioned by #Jordan in the comments, there is no reason to use string interpolation for the puts statement. So it's enough to call the method directly.
There are a bunch of issues with your code. Try something more like:
def reply(response)
return 'I do too' if response == 'yes'
return 'Dogs are better' if response == 'no'
'Invalid response!'
end
puts 'Do you like cats?'
response = gets().chomp()
puts reply(response)
Pay attention to the variable names. If you keep them descriptive, it is easier to spot mistakes.
Your script has no n local variable defined that you are passing to your ask(n) method at the end.
Rename your ask variable that your script gets from user to answer for example and pass it to your ask method at the end like so:
Updated code to fix other problem I did not see in the first run.
puts "Do you like cats?"
answer = gets.chomp
def ask(n)
(n == 'yes') ? "I do too" : "Dogs are better"
end
puts "#{ask(answer)}"
In ruby, you can append strings using <<:
>> "Hello" << "World"
=> "HelloWorld"
So why can't you prepend them using >>?
>> "Hello" >> "World"
NoMethodError: undefined method `>>' for "Hello":String
I realise String doesn't have the >> method defined, but what's the reasoning behind that?
Ruby 1.9.3 added a String#prepend method.
The proposal about adding prepend[1] also included the ">>" method, and there's some discussion on the thread about that implementation [2]:
Matz says: " >> is interesting notation did not think about it."
sorya says: "This patch is out it had been discussed several times towards the IRC"
However at the end of the thread, the conclusion was to accept String#prepend, and that "other proposals including String # >> are pending."
I couldn't find any other discussion about it though... anyone else?
Personally, I like it, and it's trivial to add:
class String
def >> (s)
s.prepend(self)
end
end
The result:
>> "Hello" >> "World"
=> "HelloWorld"
[1] http://bugs.ruby-lang.org/issues/3675
[2] http://translate.google.com/translate?hl=en&sl=ja&tl=en&u=http%3A%2F%2Fbugs.ruby-lang.org%2Fissues%2F3675
Ruby's syntax wouldn't allow a method like >> to be implemented the way you expect.
<< in "Hello" << "World" is equivalent to the following:
"Hello".<<("World")
If you wanted to create a prepend method >>, I would expect "Hello" in "Hello" >> "World" to be the argument to the string "World":
("Hello")>>."World" which isn't valid Ruby syntax.
If "World" was an argument to "Hello", then you would just be appending a string like fl00r demonstrated. Aliasing >> to mean the same as << would cause confusion.
This is why you have the insert method instead. If you want to insert "Hello" in front of "World" you would call insert on "World":
"World".insert(0, "Hello ")
The takeaway here is to keep in mind that << is a method call just like a string method such as length, so you have to keep the ordering similar to regular method calls.
Ruby always asigns value from the right to the left.
But you can implement it by yourself
class String
def >>(s)
s << self
end
end
"Hello" >> "world"
#=> "worldHello"
I don't think I would do this, but if someone forced me to:
class String
def prepend(string)
insert(0, string)
end
end
I don't think >> is a good idea—the reason << is nice is because it looks like what's going to happen. >> looks like it would have the same result as << to me, except that the calling object is being prepended onto the parameter.
I think this is a good question, and the issue is more general than just the problem with the notation << as suggested in McStretch's answer because there is a same situation with the methods given in an alphabet. Namely, there is String#concat, which appends an argument string to self, but there is no method that prepends an argument string.
I met this when I read ZenTest source code:
Here is the definition of add_mapping method:
def add_mapping(regexp, &proc)
#test_mappings << [regexp, proc]
end
In the Autottest.initailize(), add_method get called to add mapping for implementations.
self.add_mapping(/^lib\/.*\.rb$/) do |filename, _|
possible = File.basename(filename).gsub '_', '_?'
files_matching %r%^test/.*#{possible}$%
end
My question is what "_", the second parameter of the block, means? Seems it is not used in the block.
Thanks
It's an idiom used to indicate the the parameter bound to '_' is not used, even though it's required to be passed to the block/method.
example:
def blah
yield 1,2
end
blah {|a,b|
puts a
# b is never used
}
compare to the identical:
blah {|a,_|
puts a
}
Note that '_' is a perfectly legal variable name in ruby, so the two versions are identical, the following works as well:
blah {|a,_|
puts _
}
Using '_' is nothing more than a convention like using i for counters, 'x' and 'y' or 'foo' and 'bar'.
It means you're cool because you've been dabbling with functional programming, which is, I believe, where this idiom orignates...
def animals
yield "Tiger"
yield "Giraffe"
end
animals { |_| puts "Hello, #{_}" }
Example stolen from http://en.wikibooks.org/wiki/Ruby_Programming/Ruby_Basics
As far as I can see, it's defining _ as a variable which could be referenced later on. This is just forcing ruby's hand and defining _ as to the value of whatever is yielded.
Perhaps the author is using it as a short variable name so that the second parameter can be ignored.