Skip to content
This repository has been archived by the owner on Aug 21, 2023. It is now read-only.

Undefined method [] for Nil:Class during compilation #25

Open
elrok123 opened this issue Jul 10, 2017 · 6 comments
Open

Undefined method [] for Nil:Class during compilation #25

elrok123 opened this issue Jul 10, 2017 · 6 comments

Comments

@elrok123
Copy link

elrok123 commented Jul 10, 2017

Getting a problem when trying to create an instance of a collection, I can't get past the compilation as I think the compiler is trying to account for the client instance possibly being 'Nil' and there being no method handlers for '[]' on the object which is very odd, as I have validation expressions outside the object. If someone could give a hand on why this is happening, that'd be great.

Implementation:

 class MxMongo                                                                                       
 -»»»# Initialise everything we need                                                                 
 -»»»def initialize(host : String, username : String, password : String, port : String)              
 -»»»-»»»@client = Nil                                                                               
 -»»»-»»»@database = "aggregation"                                                                   
 -»»»-»»»self.connect(host, username, password, port)                                                
 -»»»end                                                                                             
 -»»»                                                                                                
 -»»»# Connect to the database                                                                       
 -»»»def connect(host : String, username : String, password : String, port : String)                 
 -»»»-»»»@client = Mongo::Client.new "mongodb://#{username}:#{password}@#{host}:#{port}/#{@database}"
 -»»»-»»»return @client                                                                              
 -»»»end                                                                                             
                                                                                                     
 -»»»# Get an instance of the database                                                               
 -»»»def get_instance                                                                                
 -»»»-»»»if @client.not_nil! && db.not_nil!                                                          
 -»»»-»»»-»»»return @client                                                                          
 -»»»-»»»else                                                                                        
 -»»»-»»»-»»»return Nil                                                                              
 -»»»-»»»end                                                                                         
 -»»»end                                                                                             
                                                                                                     
 -»»»def get_collection(collection : String)                                                         
 -»»»-»»»if !@client.nil? && !collection.nil?                                                        
 -»»»-»»»-»»»client = @client                                                                        
 -»»»-»»»-»»»return client.not_nil![collection] if collection.not_nil!                               
 -»»»-»»»else                                                                                        
 -»»»-»»»-»»»return Nil                                                                              
 -»»»-»»»end                                                                                         
 -»»»end                                                                                             
 end                                                                                                 

Error I recieve:

                                                                                                                      
test = mongo_client.get_collection("aggregation")                                                                     
                    ^~~~~~~~~~~~~~                                                                                    
                                                                                                                      
in classes/init_mongo.cr:27: undefined method '[]' for Nil:Class (compile-time type is (Mongo::Client | Nil:Class))   
                                                                                                                      
   return client.not_nil![collection] if collection.not_nil!                                                          
                         ^                                                                                            
                                                                                                                      
================================================================================                                      
                                                                                                                      
Nil:Class trace:                                                                                                      
                                                                                                                      
  /usr/lib/crystal/object.cr:156                                                                                      
                                                                                                                      
      def not_nil!                                                                                                    
          ^~~~~~~~                                                                                                    
                                                                                                                      
  /usr/lib/crystal/object.cr:157                                                                                      
                                                                                                                      
        self                                                                                                          
        ^~~~                                                                                                          


Apologies for the formatting, copied from vim

@elrok123 elrok123 changed the title Undefined method Nil:Class during compilation Undefined method [] for Nil:Class during compilation Jul 10, 2017
@datanoise
Copy link
Owner

i think you meant to write it as @client not just client

@elrok123
Copy link
Author

elrok123 commented Jul 11, 2017

@datanoise Nope, unfortunately not, I offload the @client instance to a local var, due to the read write differences between instance vars and local vars, I've had issues in the past with Crystal not allowing me to set instance vars etc, so tried offloading to a local var just to see if that fixed it.

If you read the code though, you can see here that I definitely define the client var before being used:

-»»»def get_collection(collection : String)                                                         
-»»»-»»»if !@client.nil? && !collection.nil?                                                        
-»»»-»»»-»»»client = @client                                                                        
-»»»-»»»-»»»return client.not_nil![collection] if collection.not_nil!                               
-»»»-»»»else                                                                                        
-»»»-»»»-»»»return Nil                                                                              
-»»»-»»»end                                                                                         
-»»»end

@datanoise
Copy link
Owner

why Nil is uppercased? is it intentional?

@elrok123
Copy link
Author

In this instance they would resolve to the same thing anyway, no? As it's a return value, and Nil is just the class, and nil is an global instance of the Nil class. Correct me if I'm wrong.

@datanoise
Copy link
Owner

No, they are not the same thing. 'Nil' is the class type (in this case struct type) and nil is its singleton instance. Nil.not_nil! == Nil as for any other object, but nil.not_nil! will raise an exception. That means that your @client variable could be either an instance of Mongo::Client class or Nil class type and the compiler correctly detects that Nil class type has no method [] defined.

@elrok123
Copy link
Author

Ah awesome, thanks for the explanation, was curious what was actually going on under the hood, as I've experienced something similar to this I think, and I did not even consider the difference between Nil and nil

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants