Project

General

Profile

Feature #15192

Updated by jjyr (Jinyang Jiang) over 5 years ago

Motivation: 

 Introduce a new syntax for convenient setup instance variables for objects. 

 The problem: 

 Currently, setup instance variables in Ruby is too verbose.  
 Basically, we need to write the meaningless assigning code again and again to assign variables 

 ``` ruby 
 class Person 
   def initialize(name:, age:, gender:, country:) 
     @name = name 
     @age = age 
     @gender = gender 
     @country = country 
   end 
 end 


 # we can use Struct to avoiding this 

 Person = Struct.new(:name, :age, :gender, :country, keyword_init: true) 

 # let's see a real-world case, which can't use Struct to describe an initializing process, from https://github.com/ciri-ethereum/ciri/blob/748985ccf7a620a2e480706a5a6b38f56409d487/lib/ciri/devp2p/server.rb#L54 
 # Because we want to do something more than just assigning instance variables 

 class Server 
       def initialize(private_key:, protocol_manage:, bootstrap_nodes: [], 
                      node_name: 'Ciri', tcp_host: '127.0.0.1', tcp_port: 33033) 
         @private_key = private_key 
         @node_name = node_name 
         @bootstrap_nodes = bootstrap_nodes 
         @protocol_manage = protocol_manage 
         server_node_id = NodeID.new(@private_key) 
         caps = [Cap.new(name: 'eth', version: 63)] 
         @handshake = ProtocolHandshake.new(version: BASE_PROTOCOL_VERSION, name: @node_name, id: server_node_id.id, caps: caps) 
         @tcp_host = tcp_host 
         @tcp_port = tcp_port 
         @dial = Dial.new(bootstrap_nodes: bootstrap_nodes, private_key: private_key, handshake: @handshake) 
         @network_state = NetworkState.new(protocol_manage) 
         @dial_scheduler = DialScheduler.new(@network_state, @dial) 
       end 
 end 


 # Introduce a new "shortcut assigning" syntax for convenient setup 

 class Person 
   # use @ prefix to describe instance variables. 
   def initialize(@name:, @age:, @gender:, @country:) 
   end 

   # equal to 
   def initialize2(name:, age:, gender:, country:) 
     @name = name 
     @age = age 
     @gender = gender 
     @country = country 
   end 

   # it should also work on position style arguments 
   def initialize2(@name, @age, @gender, @country) 
   end 
 end 

 # Our real-world case can be rewritten as below 
 class Server 
       def initialize(@private_key:, @protocol_manage:, @bootstrap_nodes: [], 
                      @node_name: 'Ciri', @tcp_host: '127.0.0.1', @tcp_port: 33033) 
         server_node_id = NodeID.new(@private_key) 
         caps = [Cap.new(name: 'eth', version: 63)] 
         @handshake = ProtocolHandshake.new(version: BASE_PROTOCOL_VERSION, name: @node_name, id: server_node_id.id, caps: caps) 
         @dial = Dial.new(bootstrap_nodes: @bootstrap_nodes, private_key: @private_key, handshake: @handshake) 
         @network_state = NetworkState.new(@protocol_manage) 
         @dial_scheduler = DialScheduler.new(@network_state, @dial) 
       end 
 end 

 # consider to keep consistency, insistence, this "shortcut assigning" syntax should work for non-initialize methods 
 class Foo 
   def bar(@still_works) 
     p @still_works 
   end 
 end 
 ```

Back