Forum: Ruby Difference answers from Terminal, TextMate, and BBEdit

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Greg (Guest)
on 2007-05-08 04:36
(Received via mailing list)
A newbie here trying to develop one of Pine's tutorial scripts. Ruby
v1.8.6

I get different results from my script in Terminal, TextMate, and
BBEdit. How is this possible?

TextMate seems to be the closest to what I'd expect. I'd buy it if the
undo's were better. Plus I already own BBEdit. I realize BBEdit doesn't
profess to support Ruby script running that much, but I expected
Terminal to be consistent.

I've driven myself crazy trying to debug my script, stalled in BBEdit,
so went to Terminal, but after putting in all kinds of puts to figure
out what was going on, tried my demo TextMate and it ran better. In all
cases exactly the same file.

Thanks for any clues.
Tim H. (Guest)
on 2007-05-08 05:17
(Received via mailing list)
Greg wrote:
>
> I've driven myself crazy trying to debug my script, stalled in BBEdit,
> so went to Terminal, but after putting in all kinds of puts to figure
> out what was going on, tried my demo TextMate and it ran better. In
> all cases exactly the same file.
>
> Thanks for any clues.
>
>
It would help if you'd post your script, what answers you expected, and
what answers you got.
Greg (Guest)
on 2007-05-08 06:05
(Received via mailing list)
On 2007-05-07 18:16:38 -0700, Tim H. <removed_email_address@domain.invalid> 
said:

>>
>> I've driven myself crazy trying to debug my script, stalled in BBEdit,
>> so went to Terminal, but after putting in all kinds of puts to figure
>> out what was going on, tried my demo TextMate and it ran better. In all
>> cases exactly the same file.
>>
>> Thanks for any clues.
>>
>>
> It would help if you'd post your script, what answers you expected, and
> what answers you got.

Thanks for answering. Here it goes:

#!/usr/bin/env ruby

class OrangeTree

MSG_GROW = "Type \"year\" to grow your tree."
MSG_PICK = "Type a number to pick some more fruit. "
EXIT_TXT = "Something went wrong."

def initialize # we have one tree, does it need a name?
  @heightInches = 0 # at year zero
  @age = 0
  @fruit = 0 # inches, work out feet and inches later
  puts "Congratulations, you planted an orange tree. In a few years it
will start bearing fruit. #{@age} " # Age only for debugging. Can take
it out.
  puts MSG_GROW
end

  def ageOneYear
     @heightInches = @heightInches +1
     puts 'Height: ' + @height.to_s
  @age += 1
    # @age = @age + 1
     puts "Got to ageOneYear. Age: #{@age}"
       case( @age )
        when (1..3) :  puts("Your #{@age} year old tree is too young to
bear fruit yet. #{MSG_GROW}" )
        when (4..29) : puts(" Age: #{@age}. Place holder until get 1..3
working." )
         when (30) :    puts("Your tree was very fruitful, but it
reached
old age and died.")
        else puts( " Something went wrong. #{EXIT_TXT}" )
      end
  end # def ageOneYear

  def height
    # returns the height
  end

  def pick_an_orange
   puts 'Got to pick_an_orange, but haven\'t defined yet'
    # reduce this year count by one
  end

end # class OrangeTree

# here we go
countLoop = 0
tree = OrangeTree.new # assume we need to initialize it. Does it need a
name?

while countLoop < 100
  countLoop += 1
  puts "countLoop = #{countLoop}"  # debugging.
  if gets.to_s=='year'
      puts 'In the gets.to_s if clause' # debugging.
      tree.ageOneYear
  end

  gets case
    when 'year' : tree.ageOneYear # , y as shortcut?
    when (1..100) : tree.pick_an_orange
    else puts('Don\'t be greedy, don\'t try to pick more than 100
oranges')
  end

end # while

TextMate response. I answered 'year' to each request for input:
RubyMate r6354 running Ruby r1.8.6 (/usr/local/bin/ruby)
>>> OrangeTree.post.rb

Congratulations, you planted an orange tree. In a few years it will
start bearing fruit. 0
Type "year" to grow your tree.
countLoop = 1
Height:
Got to ageOneYear. Age: 1
Your 1 year old tree is too young to bear fruit yet. Type "year" to
grow your tree.
countLoop = 2
Height:
Got to ageOneYear. Age: 2
Your 2 year old tree is too young to bear fruit yet. Type "year" to
grow your tree.
countLoop = 3
Height:
Got to ageOneYear. Age: 3
Your 3 year old tree is too young to bear fruit yet. Type "year" to
grow your tree.
countLoop = 4
Height:
Got to ageOneYear. Age: 4
 Age: 4. Place holder until get 1..3 working.
NoMethodError: undefined method `+' for nil:NilClass
method gets
in stdin_dialog.rb at line 6
method gets
in stdin_dialog.rb at line 13
at top level
in OrangeTree.post.rb at line 58
==END TextMate response

Terminal response. All 'year' are my responses. I stopped after two
none reponses.
new-host-2:~ xxxxxx$ ruby -v
ruby 1.8.6 (2007-03-13 patchlevel 0) [powerpc-darwin8.9.0]
new-host-2:~ xxxxxx$ ruby
"/Volumes/share/Greg/Ruby++/OrangeTree.post.rb"
Congratulations, you planted an orange tree. In a few years it will
start bearing fruit. 0
Type "year" to grow your tree.
countLoop = 1
year
Height:
Got to ageOneYear. Age: 1
Your 1 year old tree is too young to bear fruit yet. Type "year" to
grow your tree.
year
year
===End Terminal

BBEdit output. I only Cmd-R to run the script. I was never asked for
input.

Congratulations, you planted an orange tree. In a few years it will
start bearing fruit. 0
Type "year" to grow your tree.
countLoop = 1
Height:
Got to ageOneYear. Age: 1
Your 1 year old tree is too young to bear fruit yet. Type "year" to
grow your tree.
countLoop = 2
Height:
Got to ageOneYear. Age: 2
Your 2 year old tree is too young to bear fruit yet. Type "year" to
grow your tree.
countLoop = 3
Height:
Got to ageOneYear. Age: 3
Your 3 year old tree is too young to bear fruit yet. Type "year" to
grow your tree.
countLoop = 4
Height:
Got to ageOneYear. Age: 4
 Age: 4. Place holder until get 1..3 working.
countLoop = 5
Height:
Got to ageOneYear. Age: 5
 Age: 5. Place holder until get 1..3 working.
<SNIP-SNIP>
countLoop = 100
Height:
Got to ageOneYear. Age: 100
 Something went wrong. Something went wrong.
 ===END BBEdit

 TextMate was close, but I expected values for @heightInches to
increase with each iteration.

 I would like it to work in BBEdit, but realize BareBones support for
this is weak. But at least Terminal should get it right. I own BBEdit,
so am reluctant to buy TextMate, particularly since it has significant
features I would like missing.

 Thanks for any help.

 I hope this isn't a double posting. My original was via Usenet, then I
found the Google G. and tried to post there, but I am not sure I am
a member there. This version may be somewhat different as I had to
recreate it after realizing Google G. wasn't working for me.
Dan Z. (Guest)
on 2007-05-08 07:13
(Received via mailing list)
Greg wrote:
>>> the undo's were better. Plus I already own BBEdit. I realize BBEdit
>>>
> MSG_PICK = "Type a number to pick some more fruit. "
> end
>                 when (4..29) : puts(" Age: #{@age}. Place holder until
>     def pick_an_orange
> while countLoop < 100
>     end
> Height: Got to ageOneYear. Age: 1
> countLoop = 4
>
> Your 1 year old tree is too young to bear fruit yet. Type "year" to grow
> Height: Got to ageOneYear. Age: 1
> countLoop = 4
>
> I hope this isn't a double posting. My original was via Usenet, then I
> found the Google G. and tried to post there, but I am not sure I am
> a member there. This version may be somewhat different as I had to
> recreate it after realizing Google G. wasn't working for me.
>
>
>

Greg,

I saw two clear mistakes. First, you didn't end height().

Second, your later "case" statement should be:
case gets.chomp

because gets() usually includes a newline. Perhaps that is the root of
your problem--different methods of input may or may not have a newline
at the end. calling chomp() removes any present newlines at the end. (I
also removed the "if gets.to_s=='year'" line because it didn't seem
helpful.)

I didn't test it that much after seeing those, but I hope this helps.
Good luck,

Dan
Morton G. (Guest)
on 2007-05-08 07:39
(Received via mailing list)
On May 7, 2007, at 10:05 PM, Greg wrote:

>>> but I expected Terminal to be consistent.
> #!/usr/bin/env ruby
>   @fruit = 0 # inches, work out feet and inches later
>     # @age = @age + 1
>   end # def ageOneYear
>
>
>>>> OrangeTree.post.rb
> grow your tree.
> method gets
> OrangeTree.post.rb"
>
> Height: Got to ageOneYear. Age: 2
> Height: Got to ageOneYear. Age: 5
> BBEdit, so am reluctant to buy TextMate, particularly since it has
> significant features I would like missing.
> Thanks for any help.
> I hope this isn't a double posting. My original was via Usenet,
> then I found the Google G. and tried to post there, but I am
> not sure I am a member there. This version may be somewhat
> different as I had to recreate it after realizing Google G.
> wasn't working for me.

There seems to be too problems with your code.

1. You use @height in one place where really want @heightInches.
2. Your case statement in the your while loop just doesn't do what
you think it should. And actually it would be hard make a case work
in the situation you have set up.

Here is a modification of your code that I think will do what you
were trying to achieve:

<code>
#!/usr/bin/env ruby

class OrangeTree

    MSG_GROW = "Type \"year\" to grow your tree."
    MSG_PICK = "Type a number to pick some more fruit. "
    EXIT_TXT = "Something went wrong."

    def initialize
       @heightInches = 0
       @age = 0
       @fruit = 0
       puts MSG_GROW
    end

    def ageOneYear
       @heightInches = @heightInches +1
       puts 'Height: ' + @heightInches.to_s # <= not '@height'
       @age += 1
       # @age = @age + 1
       puts "Got to ageOneYear. Age: #{@age}"
       case @age
       when (1..3) :  puts("Your #{@age} year old tree is too young
to bear fruit yet. #{MSG_GROW}" )
       when (4..29) : puts(" Age: #{@age}. Place holder until get
1..3 working." )
       when (30) :    puts("Your tree was very fruitful, but it
reached old age and died.")
       else puts( " Something went wrong. #{EXIT_TXT}" )
       end
    end

    def height
       # returns the height
    end

    def pick_an_orange
       puts 'Got to pick_an_orange, but haven\'t defined yet'
       # reduce this year count by one
    end

end

countLoop = 0
tree = OrangeTree.new

while countLoop < 100
    countLoop += 1
    puts "countLoop = #{countLoop}"
    # case statement not really appropriate for this loop.
    # Note: gets always returns a string terminated with a newline.
    user_input = gets.chomp
    if user_input == 'year'
       tree.ageOneYear
    elsif (1..100).include?(user_input.to_i) # need to convert string
to integer
       tree.pick_an_orange
    else puts('Don\'t be greedy, don\'t try to pick more than 100
oranges')
    end
end
</code>

Regards, Morton
Greg (Guest)
on 2007-05-08 07:45
(Received via mailing list)
Thank you Dan and Morton

I knew about chomp, but forgot (typical beginners mistake). That helped
the script. BTW the end was there in height, but got lost in the
posting (actually it's tacked to the end of the previous line).

I haven't tried Morton's suggestions, but sure they'll help as putting
in the chomp brought up some other problems.

The chomp addition eliminates one "problem" as BBEdit can't handle
chomp. (And BareBones has no  plans to add the feature.)

Thanks again.
Greg (Guest)
on 2007-05-08 08:30
(Received via mailing list)
On 2007-05-07 20:37:31 -0700, Morton G. <removed_email_address@domain.invalid>
said:

>>>> doesn't profess to support Ruby script running that much,  but I
>> def initialize # we have one tree, does it need a name?
>>      @heightInches = @heightInches +1
>> old age and died.")
>>   end
>> debugging.       tree.ageOneYear
> There seems to be two problems with your code.
>
> 1. You use @height in one place where really want @heightInches.

Duh. Thanks.

> class OrangeTree
>     end
>        when (4..29) : puts(" Age: #{@age}. Place holder until get  1..3
>
> while countLoop < 100
>     else puts('Don\'t be greedy, don\'t try to pick more than 100  oranges')
>     end
> end
> </code>
>
> Regards, Morton

No it's not working like I want. But I don't understand why case isn't
appropriate. But your method works right and mine doesn't, so I don't
think I'll worry about it now.

One question. How is
>  elsif (1..100).include?(user_input.to_i)
working? I understand it up through "elsif(1..100)" Is the user_input
changed to integer before the elsif is evaluated. What does the
include? do? (The don't be greedy part was just placeholder until I
worked out the whole orange picking and growing logic.)

BTW, the while loop seemed like a crude work around to keep asking for
inputs. I would like it to stop at 30 in the class (at least that seems
more elegant as that is where the age decisions are made).

Thanks again. Lots to learn (and remember).
Sebastian H. (Guest)
on 2007-05-08 10:04
(Received via mailing list)
Greg wrote:
> One question. How is
>
> >  elsif (1..100).include?(user_input.to_i)
>
> working? I understand it up through "elsif(1..100)" Is the user_input
> changed to integer before the elsif is evaluated.

Yes. The to_i method is called on user_input, its result is passed as an
argument to the include? methods of (1..100) and the result of that is
used for the elsif.


> What does the include? do?

blubb.include?(bla) returns true if bla can be found inside blubb and
false
otherwise. In this case it returns true if user_input.to_i is inside the
range
1..100, i.e. if it's a number between one and one hundred (inclusive).
Morton G. (Guest)
on 2007-05-08 14:22
(Received via mailing list)
On May 8, 2007, at 12:30 AM, Greg wrote:

>> class OrangeTree
>>        @heightInches = @heightInches +1
>> reached old age and died.")
>> end
>>     elsif (1..100).include?(user_input.to_i) # need to convert
> isn't appropriate. But your method works right and mine doesn't, so
> I don't think I'll worry about it now.

You _could_ use a case here, but it would have to be considerably
more complicated than the simple case form you wrote. I thought (and
still think) an if-elsif-else statement is better for sorting out the
user input in this case. A case statement like

<code>
case
when 'year' : tree.ageOneYear # , y as shortcut?
when (1..100) : tree.pick_an_orange
else puts('Don\'t be greedy, don\'t try to pick more than 100  oranges')
end
</code>

just looks for the first true when-clause. In this case that will
always be 'year' because everything but false and nil is true in Ruby.

> One question. How is
>>  elsif (1..100).include?(user_input.to_i)
> working? I understand it up through "elsif(1..100)" Is the
> user_input changed to integer before the elsif is evaluated. What
> does the include? do? (The don't be greedy part was just
> placeholder until I worked out the whole orange picking and growing
> logic.)

user_input is converted to a integer during the evaluation of the
elsif. This code is roughly equivalent to:

num = user_input.to_i
in_range = (1..100).include?(num)
elsif in_range
    ...

> BTW, the while loop seemed like a crude work around to keep asking
> for inputs. I would like it to stop at 30 in the class (at least
> that seems more elegant as that is where the age decisions are made).

Do you want to stop after 30 loops (that's easy) or when @age reaches
30 (that's just a little harder)? For the first:

<code>
tree = OrangeTree.new
30.times do
    user_input = gets.chomp
    if user_input == 'year'
       tree.ageOneYear
    elsif (1..100).include?(user_input.to_i) # need to convert string
to integer
       tree.pick_an_orange
    else puts('Don\'t be greedy, don\'t try to pick more than 100
oranges')
    end
end
</code>

For the second:

<code>
class OrangeTree
    attr_reader :age # <= add this to OrangeTree so @age can be
queried outside of class def
end
tree = OrangeTree.new
loop do
    user_input = gets.chomp
    if user_input == 'year'
       tree.ageOneYear
       break if tree.age >= 30
    elsif (1..100).include?(user_input.to_i) # need to convert string
to integer
       tree.pick_an_orange
    else puts('Don\'t be greedy, don\'t try to pick more than 100
oranges')
    end
end
</code>

Regards, Morton
Morton G. (Guest)
on 2007-05-08 14:33
(Received via mailing list)
On May 7, 2007, at 11:45 PM, Greg wrote:

> The chomp addition eliminates one "problem" as BBEdit can't handle
> chomp. (And BareBones has no  plans to add the feature.)

That's really strange. But I checked it and it's true. However, you
can still test your code by saving it to a file and choosing Run in
Terminal from the #! menu.

I must admit that after using TextMate for Ruby coding for sometime
now, going back to BBEdit seems clunky. But one thing BBEdit does
better than TextMate is printing out source code with a printer.

Regards, Morton
Brian C. (Guest)
on 2007-05-08 16:35
(Received via mailing list)
On Tue, May 08, 2007 at 07:22:39PM +0900, Morton G. wrote:
> just looks for the first true when-clause. In this case that will
> always be 'year' because everything but false and nil is true in Ruby.

That's incorrect. Case doesn't check if 'year' is true; it checks
whether
'year' === obj is true.

Try this:

foo = "Hello"
case foo
when "year"
  puts "xxx"
when /ell/
  puts "yyy"   # this line is run
end
Morton G. (Guest)
on 2007-05-08 18:48
(Received via mailing list)
On May 8, 2007, at 8:34 AM, Brian C. wrote:

>> </code>
>
> foo = "Hello"
> case foo
> when "year"
>   puts "xxx"
> when /ell/
>   puts "yyy"   # this line is run
> end

Beg to differ with you. This is a case with no argument. It doesn't
have any obj to do a 'year' === obj on.

Regards, Morton
Brian C. (Guest)
on 2007-05-08 20:53
(Received via mailing list)
On Tue, May 08, 2007 at 11:47:28PM +0900, Morton G. wrote:
> >></code>
> >
> >foo = "Hello"
> >case foo
> >when "year"
> >  puts "xxx"
> >when /ell/
> >  puts "yyy"   # this line is run
> >end
>
> Beg to differ with you. This is a case with no argument. It doesn't
> have any obj to do a 'year' === obj on.

Ugh, you're right. It doesn't even compare against $_.
That seems rather pointless, as it's just the same as if .. elsif .. end

And what about

  case
  when (1..100)
    # whatever
  end

That would be the flipflop operator borrowed from Perl? But with both
ends
true as well?
Greg (Guest)
on 2007-05-08 21:06
(Received via mailing list)
Thanks all for your answers. Much to learn.
Morton G. (Guest)
on 2007-05-09 01:35
(Received via mailing list)
On May 8, 2007, at 12:52 PM, Brian C. wrote:

> Ugh, you're right. It doesn't even compare against $_.
> That seems rather pointless, as it's just the same as if ..
> elsif .. end

AFAIK, a case statement without a target can always be rewritten as a
if-elsif-else statement, but I don't think that makes a target-less
case pointless. When there are many conditions to be handled, I find
the target-less case more readable. A matter of taste, I suppose.

OTOH, the point I wanted to make with the OP was, in his case, with
only two conditions to be  handled, an if-elsif-else statement would
be more readable and the better way to go.

> And what about
>
>   case
>   when (1..100)
>     # whatever
>   end
>
> That would be the flipflop operator borrowed from Perl? But with
> both ends
> true as well?

I think it would work exactly the same as

    if (1..100)
       # whatever
    end

But I haven't tried it. And probably never will -- the flip-flop
behavior of ranges in a boolean expression is something I avoid as a
little too tricky.

Regards, Morton
This topic is locked and can not be replied to.