Chomping and stomping

J

John Maclean

Chaps,

Here's a short script to keep requesting for input...

#!/usr/bin/ruby -w
def chomper
xx = gets.chomp!
until $_ == "qq"
puts "hit me with a squirell!"
xx = gets.chomp!
xx
end
end

chomper

# this works but surely there must be a way to incoporate a variable
in there?

#!/usr/bin/ruby -w
def chomper
xx = gets.chomp!
until xx == "qq"
puts "hit me with a squirell!"
xx
end
end

#this don't work.
 
J

Jacob Fugal

#!/usr/bin/ruby -w
def chomper
xx =3D gets.chomp!
until $_ =3D=3D "qq"
puts "hit me with a squirell!"
xx =3D gets.chomp!
xx
end
end

chomper

# this works but surely there must be a way to incoporate a variable
in there?

#!/usr/bin/ruby -w
def chomper
xx =3D gets.chomp!
until xx =3D=3D "qq"
puts "hit me with a squirell!"
xx
end
end

#this don't work.

String#chomp! is a "destructive" operation. This means that it acts in
place on its receiver and, in this case, returns nil. So what's
happening here is that Kernel#gets creates a String object, chomp! is
sent to that object, the object is modified in place and nil returned.
That's why xx is nil. As you discovered in your first example, the
String object returned by Kernel#gets is stored in $_. Accessing it
this way isn't a bset practice however.

What you probably want instead is to use the non-destructive twin (the
Good Twin) of String#chomp!, namely String#chomp. Notice the lack of
the bang (!). The bang is generally (but not always) an indicator that
the method is destructive. String#chomp creates a chomped copy of it's
receiver and returns it. Replacing chomp! with chomp it should work:

#!/usr/bin/ruby -w
def chomper
xx =3D gets.chomp
until xx =3D=3D "qq"
puts "hit me with a squirell!"
xx
end
end

puts chomper

Jacob Fugal
 
W

William James

John said:
Chaps,

Here's a short script to keep requesting for input...

#!/usr/bin/ruby -w
def chomper
xx = gets.chomp!
until $_ == "qq"
puts "hit me with a squirell!"
xx = gets.chomp!
xx
end
end

chomper

# this works but surely there must be a way to incoporate a variable
in there?

#!/usr/bin/ruby -w
def chomper
xx = gets.chomp!
until xx == "qq"
puts "hit me with a squirell!"
xx
end
end

#this don't work.


def chomper
until (xx = gets.chomp) == 'qq'
puts "hit me with a squirell!"
end
xx
end

puts chomper
 
A

ara.t.howard

def chomper
until (xx = gets.chomp) == 'qq'
puts "hit me with a squirell!"
end
xx
end

puts chomper


harp:~ > cat a.rb
def chomper
until (xx = gets.chomp) == 'qq'
puts "hit me with a squirell!"
end
xx
end

puts chomper


harp:~ > ruby a.rb < /dev/null
a.rb:3:in `chomper': private method `chomp' called for nil:NilClass (NoMethodError)
from a.rb:9


nil doesn't like that! ;-)

-a
 
J

Jacob Fugal

harp:~ > ruby a.rb < /dev/null
a.rb:3:in `chomper': private method `chomp' called for nil:NilClass (N= oMethodError)
from a.rb:9

nil doesn't like that! ;-)

Heh, yeah, I glossed over that too. You really need to check the
result of gets before you chomp it. This is the way I'd write John's
original loop (same semantics):

def chomper
while xx =3D gets
xx.chomp!
break if xx =3D=3D 'qq'
puts "hit me with a squirell!"
end
xx
end

and the way I'd write it for myself (different semantics, mostly same inten=
t):

def chomped_gets
(s =3D gets) and s.chomp
end

def chomper
loop do
puts "hit me with a squirell!"
break unless xx =3D chomped_gets
return xx if xx =3D=3D 'qq'
end
end

Jacob Fugal
 
J

John Maclean

Chaps,

Thanks for those speedy replies
Following on from

#thanks to you guyson the list for clearing this up
jayeola@tp20$ cat bin/acid/classes/testing/testchomp.rb
#!/usr/bin/ruby -w
def chomper
xx = gets.chomp
until (xx= gets.chomp) == "qq"
puts "hit me with a squirell!"
end
xx
end


chomper
# ^^ the above works. :)

# This is supposed to do the same as the above but write to a file...

here's version 1
#!/usr/bin/ruby -w

def testwrite
puts "hit me with a squirell!"
until $_ =="qq"
gets.chomp!
if $_ != "qq"
File.open("testfile", "a") { |file| file.write($_) }
end
end
end
testwrite

here's version 1

jayeola@tp20$ cat bin/acid/classes/testing/write_file2.rb
#!/usr/bin/ruby -w

def testwrite
xx = gets.chomp
until (xx.gets.chomp) == "qq"
puts "hit me with a squirell!"
File.open("testfile", "a") { |file| file.write(xx) }
end
end

testwrite
 
J

James Edward Gray II

Heh, yeah, I glossed over that too. You really need to check the
result of gets before you chomp it.

Isn't this why we have iterators in Ruby? We get to avoid all these
messy loop ending tests...
This is the way I'd write John's original loop (same semantics):

def chomper
while xx = gets
xx.chomp!
break if xx == 'qq'
puts "hit me with a squirell!"
end
xx
end

def chomper
$stdin.each do |line|
line.chomp!

return line if line == "qq"

puts "Hit me with a squirrel!"
end
end

James Edward Gray II
 
W

William James

William said:
def chomper
until (xx = gets.chomp) == 'qq'
puts "hit me with a squirell!"
end
xx
end

puts chomper

def chomper
puts "Hit me!" while gets and $_.chomp! != "qq"
$_ if $_
end
 
A

ara.t.howard

Isn't this why we have iterators in Ruby? We get to avoid all these messy
loop ending tests...


def chomper
$stdin.each do |line|
line.chomp!

return line if line == "qq"

puts "Hit me with a squirrel!"
end
end

golfing

def chomper() STDIN.detect{|x| x =~ /^qq/ or puts "hit me"} end

-a
 
W

William James

harp:~ > cat a.rb
def chomper
until (xx = gets.chomp) == 'qq'
puts "hit me with a squirell!"
end
xx
end

puts chomper


harp:~ > ruby a.rb < /dev/null
a.rb:3:in `chomper': private method `chomp' called for nil:NilClass (NoMethodError)
from a.rb:9

The error I get in a dos-box is
The system cannot find the path specified.

To produce the error you gave, I must do it this way:
ruby a.rb < nul:

When you post something that depends upon a particular
operating system, you need to make that dependency clear.

It is reasonable to write a program that requires input.
It is not reasonable to expect a program that requires input to
function properly when you deliberately deprive it of input.
 
J

Jacob Fugal

def chomper
puts "Hit me!" while gets and $_.chomp! !=3D "qq"
$_ if $_
end

This will always loop until EOF and then return nil. $_.chomp! (as
opposed to $_.chomp) returns nil, and nil !=3D "qq".

Jacob Fugal

PS. And let's not golf with this please...
 
W

William James

William said:
def chomper
puts "Hit me!" while gets and $_.chomp! != "qq"
$_ if $_
end

def chomper
puts "Hit me!" while gets and $_.chomp! != "qq"
$_
end
 
J

Jacob Fugal

The error I get in a dos-box is
The system cannot find the path specified.

To produce the error you gave, I must do it this way:
ruby a.rb < nul:

When you post something that depends upon a particular
operating system, you need to make that dependency clear.

Well, in Ara's defense I would claim that prefixing the command with
"harp:~ >" and using "/dev/null" both should be clear indicators that
he's talking about a *nix system.
It is reasonable to write a program that requires input.
It is not reasonable to expect a program that requires input to
function properly when you deliberately deprive it of input.

This problem is not only due to no input. The same error will arise if
you reach EOF before matching the expected line. Try this:
echo "Hello" | ruby a.rb

It *is* reasonable to expect a program that requires input to function
properly when invalid input is provided. Maybe the proper action is to
raise an error, but it should be a contextually appropriate error.

Jacob Fugal
 
A

ara.t.howard

The error I get in a dos-box is The system cannot find the path specified.

To produce the error you gave, I must do it this way: ruby a.rb < nul:

When you post something that depends upon a particular operating system, you
need to make that dependency clear.

indeed. that's what specifying cat and /dev/null does in and least four ways:

cat, the most ubiquitous of unix programs => *nix
/ as file separator => *nix
/dev file system => *nix
/dev/null device => *nix

;-)
It is reasonable to write a program that requires input. It is not
reasonable to expect a program that requires input to function properly when
you deliberately deprive it of input.

that's not what is happening. reading from /dev/null or nul is the same as
reading from an empty file. the key point i was illustrating, and the bug in
the program, is that is fails at eof regardless if input is given.

for example, if i run this from the shell and type 'ctrl-d' to signal end of
input (on unix)

harp:~ > cat a.rb
def chomper
until (xx = gets.chomp) == 'qq'
puts "hit me with a squirell!"
end
xx
end

puts chomper


harp:~ > ruby a.rb
a.rb:2:in `chomper': private method `chomp' called for nil:NilClass (NoMethodError)
from a.rb:8


running on an empty file does the same

harp:~ > touch empty
harp:~ > ruby a.rb < empty
a.rb:2:in `chomper': private method `chomp' called for nil:NilClass (NoMethodError)
from a.rb:8


as does running with some input

harp:~ > echo 42 > input

harp:~ > ruby a.rb < input
hit me with a squirell!
a.rb:2:in `chomper': private method `chomp' called for nil:NilClass (NoMethodError)
from a.rb:8

in fact, it cannot be made to work with any input

it's important, imho only perhaps, to show working code (best done by actually
showing a run) unless that code is noted to be un-tested. i make efforts to do
this for all examples i post:

http://groups.google.com/group/comp.lang.ruby/search?q=howard+cat+a.rb&start=0&scoring=d&

some probably find it anoying but i make too many mistakes otherwise.

kind regards.

-a
 
W

William James

Jacob said:
This will always loop until EOF and then return nil. $_.chomp! (as
opposed to $_.chomp) returns nil, and nil != "qq".

It works under ruby 1.8.2 (2004-05-19) [i386-mswin32].
Did you test it? The code you posted earlier doesn't work:

#!/usr/bin/ruby -w
def chomper
xx = gets.chomp
until xx == "qq"
puts "hit me with a squirell!"
xx
end
end

puts chomper

Always test the code that you post, please.
Jacob Fugal

PS. And let's not golf with this please...

If you don't like golf, why watch it?

def chomper
puts "Hit me!" while gets.chomp! != "qq"
$_
end
 
J

Jacob Fugal

If you don't like golf, why watch it?

Because the original poster was asking for advice on why it wasn't
working, not for a golfing contest.

Jacob Fugal
 
W

William James

Jacob said:
Because the original poster was asking for advice on why it wasn't
working, not for a golfing contest.

The fact that his expectations were modest doesn't mean that
I shouldn't give him a bonus. One never has to ask for a golfing
contest, since those who enjoy programming and who test their
code before they post are always willing to indulge in that pastime.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top