Issue #15192 has been updated by shyouhei (Shyouhei Urabe).


This isn't Matz's but my experience.  When "we want to do something more than just assigning instance variables", that "something" tends to include cancellation of creating new object -- maybe because we are returning a cached instance, or because we are raising an exception.  In order to properly handle such situations #initialize tends to be too late to "do something".  When I write a complex constructor that tends to happen inside of .new directly, and #initialize eventually becomes a series of instance variable assignments.  One of such example is: https://github.com/shyouhei/xmp2assert/blob/master/lib/xmp2assert/quasifile.rb

----------------------------------------
Feature #15192: Introduce a new "shortcut assigning" syntax to convenient setup instance variables
https://bugs.ruby-lang.org/issues/15192#change-74270

* Author: jjyr (Jinyang Jiang)
* Status: Open
* Priority: Normal
* Assignee: 
* Target version: 
----------------------------------------
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, this "shortcut assigning" syntax should work for non-initialize methods
class Foo
  def bar(@still_works)
    p @still_works
  end
end
```



-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request / ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>