Help please Undefined Method error

Hi and thank you for reading this
well im new at programming and ruby is the first language I'm trying to
learn so I'm really a newbie, I have this code wich I attached that
gives me this error

"C:/sort.rb:13:in `sort': undefined method `<' for ["hello", "loop",
"array", "teeth", "wave", "new"]:Array (NoMethodError)
        from C:/sort.rb:29:in `<main>'

So my question is: is there a way to make the main methods or ruby
premade methods like "<" "<=" ">" ">=" to work inside mi own method or
to call them or to define them again???

cause if I take it out of my metod "sort" it runs perfectly

Please anwer my question even if the code can be done in some other way
I whould really apreciate it it's not just for this code but to know for
further use
Thanks and sorry if i'm bothering you with this newbie
question

Attachments:
http://www.ruby-forum.com/attachment/6938/sort.rb

···

--
Posted via http://www.ruby-forum.com/.

words is an array, but you put it inside another array when you call sort
just pass words
same for sorted

cheers

But there is another error in this code that is basically the same but
corrected in some things
so this is the error
[code]
sort_cor.rb:13:in `<': comparison of String with nil failed
(ArgumentError)
from C:/sort_cor.rb:13:in `sort'
from C:/sort_cor.rb:30:in `<main>'
[code]
and I don't understand why is giving me nil

Attachments:
http://www.ruby-forum.com/attachment/6939/sort_cor.rb

···

--
Posted via http://www.ruby-forum.com/.

The program is done !!!! i was only checking it for the last time
before going to do something else and I found the solution well the
problem and the solution.
the program now looks like this one
Thank you for your help it was really usefull

Attachments:
http://www.ruby-forum.com/attachment/6949/sort_cor.rb

···

--
Posted via http://www.ruby-forum.com/.

I suspect you're var is getting incremented past the size of the array

You should add some puts statements around lines 14-15
and see how the value of var changes, and how it compares to the length
of unsorted.

cheers

Hi Andes,

I took the liberty to propose an alternative to the
first block of your program. I am afraid some
aspects of your program are not really Ruby idiomatic.

This is meant as "constructive criticism", I hope you
can appreciate it. If not, sorry upfront.

<alternative>
def get_words
  .tap do |a|
    while !(input = gets.chomp).empty?
       a << input
    end
  end
end

puts "Hello, enter all the words you want, finish with empty line"
words = get_words
puts "The words you entered are:"
puts words
</alternative>

Some highlights:

* put that functionality to read the words in a separate function
  and test it separately. Then you can also reuse it more easily.

* Use .tap{|a| a<< stuff} so you do not have to return the
  result array explicitly (I am not having a variable "words"
  or "array" in the function, it is returned as the final result but
  not stored in an explicit local variable; so I can impossibly
  forget to return the built up array at the end, because "tap"
  returns it automatically

* don't do "while true ... break ... end"
  use "while (data is valid) ... do something with the data ... end"
  the "break" in your version burns in my eyes.

* take note of the special 'while !(input = gets.chomp)' construct
  with a _single_ '=' (not a double '==') in the condition for while.
  Some people may find it not optimal to make an assignment,
  but it is the style I prefer for that use case. I am open to alternatives
  for that ...

* don't store the data that is not valid (the empty string) in the array
  and then delete it afterwards. Evaluate the validity of the data
  _before_ storing it in the array.

* a more advanced aspect is that inside the block of "tap", there
  is no variable used that comes from the outside of the block.
  That makes for safer code as there is less chance for accidental
  dependency of a variable that is set higher-up in the code.
  This is also the main reason for short functions, less chance for
  unintended dependencies on far-away variables.

Sorry for being critical, but I honestly hope you can take the time
to analyze my comments and learn some neat "Ruby" tricks from it.

Success with Ruby and welcome :slight_smile:

Peter

···

On Fri, Feb 3, 2012 at 2:58 AM, andres d. <apolo-andres@hotmail.com> wrote:

The program is done !!!! i was only checking it for the last time
before going to do something else and I found the solution well the
problem and the solution.
the program now looks like this one
Thank you for your help it was really usefull

Attachments:
http://www.ruby-forum.com/attachment/6949/sort_cor.rb

I see now that I misread your name (it should be Andres if I see
correctly).

Sorry for that,

Peter

···

On Fri, Feb 3, 2012 at 12:25 PM, Peter Vandenabeele <peter@vandenabeele.com>wrote:

On Fri, Feb 3, 2012 at 2:58 AM, andres d. <apolo-andres@hotmail.com>wrote:

The program is done !!!! i was only checking it for the last time
before going to do something else and I found the solution well the
problem and the solution.
the program now looks like this one
Thank you for your help it was really usefull

Attachments:
http://www.ruby-forum.com/attachment/6949/sort_cor.rb

Hi Andes,

<alternative>
def get_words
.tap do |a|
while !(input = gets.chomp).empty?
a << input
end
end
end

Aw. Do not abuse #tap, please. It's extremely unreadable, especially
to a beginner.

* Use .tap{|a| a<< stuff} so you do not have to return the
result array explicitly (I am not having a variable "words"
or "array" in the function, it is returned as the final result but
not stored in an explicit local variable; so I can impossibly
forget to return the built up array at the end, because "tap"
returns it automatically

There is no advantage to using constructs with tap over regular
variable I know of. IMO #tap should only be used to "inject" debugging
or other side-effects into a long method chain. (Although, if you have
a method chain so long, you probably have other problems...)

-- Matma Rex

···

2012/2/3 Peter Vandenabeele <peter@vandenabeele.com>:

> <alternative>
> def get_words
> .tap do |a|
> while !(input = gets.chomp).empty?
> a << input
> end
> end
> end

Aw. Do not abuse #tap, please. It's extremely unreadable, especially
to a beginner.

Thanks for the feedback.

<subjective>
I find it quite readable, because it take the recipient (an empty array
here),
"augments" it, and then just returns it back. At least for me, I love it,
because
otherwise there is always a chance I forget the
(return) <accumulator> as last line of the function.

But, my argument is subjective ...
</subjective>

> * Use .tap{|a| a<< stuff} so you do not have to return the
> result array explicitly (I am not having a variable "words"
> or "array" in the function, it is returned as the final result but
> not stored in an explicit local variable; so I can impossibly
> forget to return the built up array at the end, because "tap"
> returns it automatically

There is no advantage to using constructs with tap over regular
variable I know of. IMO #tap should only be used to "inject" debugging
or other side-effects into a long method chain. (Although, if you have
a method chain so long, you probably have other problems...)

Could you kindly provide a clearer alternative for this functionality then?

Interested,

Peter

···

On Fri, Feb 3, 2012 at 6:46 PM, Bartosz Dziewoński <matma.rex@gmail.com>wrote:

2012/2/3 Peter Vandenabeele <peter@vandenabeele.com>:

Personally I have no problems using:

def get_words
  ret = []
  while !(input = gets.chomp).empty?
    ret << input
  end
  return ret
end

I think that what I also dislike about using #tap in this scenario is
that you have to scan the entire function to see what it returns. In
my example, it clearly returns a variable named ret, and you can
easily look for this name in the code, see it defined and filled. In
your, it returns a value of the block inside, which might return
anything = so you scroll to the top, only then see it's a #tap, then
looks for the variable name it uses inside the block, and only now you
see what is this array filled with.

Obviously which one you prefer is subjective; just my two cents. But
I'm pretty sure that the "declare accumulator, fill it, return it" is
easily recognizable for anyone - complete beginner and a convert from
any other language - while #tap is Ruby-specific and a cryptic for
newbies.

(I don't know Python well, but what the yield keyword does in it in an
interesting way to solve this problem.)

-- Matma Rex

Thank you for the clarification :slight_smile:

Agree to disagree?

Peter

···

On Fri, Feb 3, 2012 at 7:16 PM, Bartosz Dziewoński <matma.rex@gmail.com>wrote:

Personally I have no problems using:

def get_words
ret =
while !(input = gets.chomp).empty?
   ret << input
end
return ret
end

I think that what I also dislike about using #tap in this scenario is
that you have to scan the entire function to see what it returns. In
my example, it clearly returns a variable named ret, and you can
easily look for this name in the code, see it defined and filled. In
your, it returns a value of the block inside, which might return
anything = so you scroll to the top, only then see it's a #tap, then
looks for the variable name it uses inside the block, and only now you
see what is this array filled with.

Obviously which one you prefer is subjective; just my two cents. But
I'm pretty sure that the "declare accumulator, fill it, return it" is
easily recognizable for anyone - complete beginner and a convert from
any other language - while #tap is Ruby-specific and a cryptic for
newbies.

Haha, yeah, I guess :slight_smile:

-- Matma Rex

···

2012/2/3 Peter Vandenabeele <peter@vandenabeele.com>:

Thank you for the clarification :slight_smile:

Agree to disagree?

Peter