Issue #9428 has been updated by Tom Wardrop.


Haha. I don't think any programming language exists that does anything even similar to this. Whether it's a good idea or not, it's going to provoke all the feelings that come unfamiliarity. Everything is confusing until you learn it and get use to it. Plenty of things in Ruby confused the hell out of me as there were many new ideas and concepts; those things normally turn out to be the best features mind you.

The first thing to keep in mind that the behaviour is very well defined, and the logic itself is simple. I can't think of any edge cases except if no variable is used in the expression, but this can be picked up by the compiler which could throw an error like: "Expecting local variable in argument expression at position 1".

Really, it's a question of "do we want this in Ruby". I don't think there's any denying the practicality, so really it's only a matter of aesthetics and readability. Keep in mind that just everyone uses code highlighting, so any semi-decent editor would pick up the first local variable in the expression at highlight it some how (make it bold, underline it, etc). If the expression is simple enough like in the examples I've provided, it's very readable in my opinion.

Aesthetically, we must compare the current situation to the proposed. Here's some code I wrote today. Pretty common scenario:

    ordered_values.map { |v|
      v = v.dup
      [v.delete(:media_type), v]
    }.to_h

Rewritten using the proposal, we get it onto one line:

    ordered_values.map { |v.dup| [v.delete(:media_type), v] }.to_h

You tell me which you prefer? Of course, like most features in Ruby, it can be abused, so looking at all the wrong you can do with it isn't relevant. Another use case would be to provide logical defaults. At the moment, default values for arguments are only applicable when that argument isn't supplied at all, but what if we want to set a default if the value is `nil` or `false`. Here's a comparison:

    # Currently
    def article(title, body)
      title = title || 'Unnamed'
      # bleh
    end
    
    # With proposal
    def article(title || 'Unnamed', body)
      # bleh
    end

I find all these examples readable and aesthetically pleasing. Longer expressions with conditions are best avoided in favour of simply doing it within the body of the method or block, but shorter conditions work quite well:

    def article('Unnamed' if title.empty?, body)
      # bleh  
    end

Like in my previous example, this comes in most handy not when defining methods, but when defining proc's where this can in my opinion greatly improve readability.





----------------------------------------
Feature #9428: Inline argument expressions and re-assignment
https://bugs.ruby-lang.org/issues/9428#change-44431

* Author: Tom Wardrop
* Status: Open
* Priority: Normal
* Assignee: 
* Category: core
* Target version: 
----------------------------------------
Just a random idea. Currently, Ruby allows you to use any arbitrary expression for setting default values for arguments, which can be really convenient and makes for clear code, especially handy for documentation, etc. For example:

    def fetch(id, cache = config[:cache])
      # bleh
    end

In the same vein, as well as setting a default value using an arbitrary expression, it's not uncommon to *post-process* an argument, some common examples include:

    arg = arg.upcase
    arg = arg.to_sym
    arg = arg.dup

It would be rather nice in my opinion to be able to do this inline when defining the argument:

    def fetch(id.to_i, cache = config[:cache])
      # bleh
    end

This works well where the argument is the receiver of the method call, but what if you wanted to do `Integer(id)` in the above example instead of using String#to_i? There are two options. One could either fallback to processing the argument within the method/block body, or, you could make the implementation a little bit clever by using inferencing.

Ruby could auto-assign the passed argument to the first variable encountered in the expression. So in the following example, as soon as the virtual machine encounters `id`, it recognises it as a variable and assigns the argument value before continuing. When encountering subsequent variables, Ruby would take the usual action and look for a corresponding method in `self` before throwing an error. You can always disambiguate by qualifying the receiver, e.g. `self.id`

    def fetch(Integer(id), cache = config[:cache])
      # bleh
    end

Whatever the result of the expression, it's assigned as the final argument value. So in the case of `id.to_i`, the argument name of `id` is inferred. `id` is set to the supplied argument for the duration of the expression. The result of the expression is then re-assigned as the value of `id`. This technically allows expressions of arbitrary complexity, but like all things in Ruby, with great power comes great responsibility. One must use common sense when deciding whether to manipulate the argument inline, or within the method body. As long as the expression is of reasonable length and complexity, readability remains perfectly reasonable.

Interested to get some thoughts and opinions on this one. I sense the potential for controversy :)




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