Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
730 views
in Technique[技术] by (71.8m points)

undefined method `-' for nil:NilClass (NoMethodError) | ruby / codewars question

    def comp(array1, array2)
  d = array2 - array1.map{|x| x.pow(2)}
  d == [] ? true : false
end

Error exit code:

main.rb:4:in comp': undefined method -' for nil:NilClass (NoMethodError) from main.rb:35:in block in <main>' from /runner/frameworks/ruby/cw-2.rb:55:in block in describe' from /runner/frameworks/ruby/cw-2.rb:46:in measure' from /runner/frameworks/ruby/cw-2.rb:51:in describe' from main.rb:7:in `'

This is my first post here, so sorry if I made any mistake :/

@Edit: Added 'if'

def comp(array1, array2)
  if array1 == nil or array2 == nil
    return false
  else
    d = array2 - array1.map{|x| x.pow(2)}
    d == [] ? true : false
  end
end
question from:https://stackoverflow.com/questions/65937958/undefined-method-for-nilnilclass-nomethoderror-ruby-codewars-question

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

So I read the description of the Kata and thought about just posting it in the comments but I figured why not help a bit.

In the description it states:

a or b might be nil or null or None or nothing (except in C++, Elixir, Haskell, PureScript, Pascal, R, Rust, Shell).

If a or b are nil (or null or None), the problem doesn't make sense so return false.

So your issue right now is that b is nil and thus the error because nil:NilClass does not have a - method.

To guard from this and to complete the Kata we can redesign your method as follows:

def comp(array1, array2)
  return false unless array1 && array2
  d = array2 - array1.map{|x| x.pow(2)}
  d == [] ? true : false
end

This clause return false unless array1 && array2 means that both array1 and array2 must be truthy. In ruby everything is truthy except nil and false. Normally I would write this as return unless array1 && array2 but the Kata explicitly said return false

That being said we can clean up your code a bit more. Let's take a look at this part first d == [] ? true : false. d == [] will return a Boolean (true/false) so logically putting this into words it reads "If d equals empty Array equals true then true OR If d equals empty Array equals false return false".

As you can see based on reading that we can shorten this to "return b equals empty Array" or (d == []). Now that is a bit better however a bit functional. Ruby is an extremely object oriented programming language, literally everything is an Object, and in object oriented programming objects have methods. IF we take a look at the Array object we can see that it has an empty? method so we can simply call d.empty?

So now our code looks like this:

def comp(array1, array2)
  return false unless array1 && array2
  d = array2 - array1.map{|x| x.pow(2)}
  d.empty?
end

There is some additional refactoring that could be done but this should get you headed in the right direction.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...