Chomping and stomping

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.

···

--
John Maclean
MSc (DIC)
07739 171 531

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 = gets.chomp
    until xx == "qq"
      puts "hit me with a squirell!"
      xx
    end
  end

  puts chomper

Jacob Fugal

···

On 2/2/06, John Maclean <info@jayeola.org> wrote:

#!/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.

John Maclean wrote:

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

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! :wink:

-a

···

On Fri, 3 Feb 2006, William James wrote:

John Maclean wrote:

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

--
happiness is not something ready-made. it comes from your own actions.
- h.h. the 14th dali lama

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. :slight_smile:

# 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

···

On Fri, 3 Feb 2006 02:16:11 +0900 Jacob Fugal <lukfugl@gmail.com> wrote:

On 2/2/06, John Maclean <info@jayeola.org> wrote:
> #!/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.

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 = gets.chomp
    until xx == "qq"
      puts "hit me with a squirell!"
      xx
    end
  end

  puts chomper

Jacob Fugal

--
John Maclean
MSc (DIC)
07739 171 531

William James wrote:

John Maclean wrote:
> 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

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

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 = gets
      xx.chomp!
      break if xx == 'qq'
      puts "hit me with a squirell!"
    end
    xx
  end

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

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

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

Jacob Fugal

···

On 2/2/06, ara.t.howard@noaa.gov <ara.t.howard@noaa.gov> wrote:

   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! :wink:

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

Jacob Fugal

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

···

On 2/2/06, William James <w_a_x_man@yahoo.com> wrote:

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

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.

···

ara.t.howard@noaa.gov wrote:

On Fri, 3 Feb 2006, William James wrote:

>
> John Maclean wrote:
>> 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

   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

William James wrote:

William James wrote:
> John Maclean wrote:
> > 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

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

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

   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! :wink:

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

···

On Feb 2, 2006, at 11:59 AM, Jacob Fugal wrote:

On 2/2/06, ara.t.howard@noaa.gov <ara.t.howard@noaa.gov> wrote:

> 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.

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

···

On 2/2/06, William James <w_a_x_man@yahoo.com> wrote:

ara.t.howard@noaa.gov wrote:

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

:wink:

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

···

On Fri, 3 Feb 2006, William James wrote:

--
happiness is not something ready-made. it comes from your own actions.
- h.h. the 14th dali lama

Jacob Fugal wrote:

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

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

···

On 2/2/06, William James <w_a_x_man@yahoo.com> wrote:

golfing

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

-a

···

On Fri, 3 Feb 2006, James Edward Gray II wrote:

On Feb 2, 2006, at 11:59 AM, Jacob Fugal wrote:

On 2/2/06, ara.t.howard@noaa.gov <ara.t.howard@noaa.gov> wrote:

   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! :wink:

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

--
happiness is not something ready-made. it comes from your own actions.
- h.h. the 14th dali lama

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

Jacob Fugal

···

On 2/2/06, William James <w_a_x_man@yahoo.com> wrote:

Jacob Fugal wrote:
> PS. And let's not golf with this please...

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

Jacob Fugal wrote:

···

On 2/2/06, William James <w_a_x_man@yahoo.com> wrote:
> Jacob Fugal wrote:
> > PS. And let's not golf with this please...
>
> 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.

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.