ruby-core@ruby-lang.org archive (unofficial mirror)
 help / color / mirror / Atom feed
* [ruby-core:103481] [Ruby master Feature#17808] Feature Request: JS like splat of Object properties as named method parameters
@ 2021-04-16 12:19 brad.krane
  2021-04-16 13:43 ` [ruby-core:103483] " jean.boussier
                   ` (6 more replies)
  0 siblings, 7 replies; 8+ messages in thread
From: brad.krane @ 2021-04-16 12:19 UTC (permalink / raw)
  To: ruby-core

Issue #17808 has been reported by Lithium (Brad Krane).

----------------------------------------
Feature #17808: Feature Request: JS like splat of Object properties as named method parameters
https://bugs.ruby-lang.org/issues/17808

* Author: Lithium (Brad Krane)
* Status: Open
* Priority: Normal
----------------------------------------
I'm pretty sure there is no equivalent Ruby for a very convenient JS way to enter named function parameters as below:

``` javascript
const test = ({param1,
 param2,
 param3 = null,
 param4 = false,
 param5 = null,
 }={}) => {
   console.log(`${param1}, ${param2}, ${param3}, ${param4}, ${param5}\n`)    
 }
let obj = {
 param1: 23,
 param2: 234,
 param3: 235,
 param4: 257
};

test({...obj});

```

which is super convenient and as far as I'm aware there is no standard Ruby equivalent. It can be accomplished in Ruby but the call syntax is far less nice. A couple examples below:

``` ruby
# Implementing such a feature wouldn't be too difficult.
# Ok so here is what you could do it. Patch Kernel with a method splat. (Sorry in advance for formatting)
module Kernel
  def splat obj, method:
    new_hash = method.parameters.reduce({}) do |hash, attrr|
      hash[attrr.last] = obj.send(attrr.last)
      hash
    end
  end
end

# Then you can pass it a list of symbols.
# Then for your method:
def some_method name:, weight: 
    puts "#{name} weighs #{weight}"
end

class Dog
  attr_reader :name, :weight
  def initialize name:,weight: 
    @name = name
    @weight = weight
  end
end

a_dog = Dog.new( name: 'fido', weight: '7kg')
hash_puppy = a_dog.splat(a_dog, method: method(:some_method)  )

some_method(**hash_puppy)
```


or what I think is a bit better:

``` ruby
# Same class as above
a_dog = Dog.new( name: 'fido', weight: '7kg')

def other_splat  obj, method:
  new_hash = method.parameters.reduce({}) do |hash, attrr|
    if obj.class <= Hash
      hash[attrr.last] = obj[attrr.last]      
    else
      hash[attrr.last] = obj.send attrr.last
    end
    hash
  end
  method.call **new_hash
end

other_splat(a_dog, method: method(:some_method))

# above line should be like:
# some_method ...a_dog

```

Source: https://gist.github.com/bradkrane/e051d205024a5313cb4a5b9eb1eae0e3

I'm sure I'm missing a possibly more clever way to accomplish this, but I'm pretty sure something like `other_splat(a_dog, method: method(:some_method))` is about as close as it can get, unless I'm missing something? It would be quite nice to have a similar syntax as JS but in Ruby: `some_method ...a_dog`

Thanks for your time and attention!



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

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [ruby-core:103483] [Ruby master Feature#17808] Feature Request: JS like splat of Object properties as named method parameters
  2021-04-16 12:19 [ruby-core:103481] [Ruby master Feature#17808] Feature Request: JS like splat of Object properties as named method parameters brad.krane
@ 2021-04-16 13:43 ` jean.boussier
  2021-04-16 18:54 ` [ruby-core:103485] " brad.krane
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: jean.boussier @ 2021-04-16 13:43 UTC (permalink / raw)
  To: ruby-core

Issue #17808 has been updated by byroot (Jean Boussier).


Doesn't the implicit `to_hash` answer your demand?

```ruby
def foo(bar:)
  p bar
end

class MyObject
  def initialize(bar)
    @bar = bar
  end

  def to_hash
    { bar: @bar }
  end
end

foo(**MyObject.new(42)) # => 42
```

----------------------------------------
Feature #17808: Feature Request: JS like splat of Object properties as named method parameters
https://bugs.ruby-lang.org/issues/17808#change-91581

* Author: Lithium (Brad Krane)
* Status: Open
* Priority: Normal
----------------------------------------
I'm pretty sure there is no equivalent Ruby for a very convenient JS way to enter named function parameters as below:

``` javascript
const test = ({param1,
 param2,
 param3 = null,
 param4 = false,
 param5 = null,
 }={}) => {
   console.log(`${param1}, ${param2}, ${param3}, ${param4}, ${param5}\n`)    
 }
let obj = {
 param1: 23,
 param2: 234,
 param3: 235,
 param4: 257
};

test({...obj});

```

which is super convenient and as far as I'm aware there is no standard Ruby equivalent. It can be accomplished in Ruby but the call syntax is far less nice. A couple examples below:

``` ruby
# Implementing such a feature wouldn't be too difficult.
# Ok so here is what you could do it. Patch Kernel with a method splat. (Sorry in advance for formatting)
module Kernel
  def splat obj, method:
    new_hash = method.parameters.reduce({}) do |hash, attrr|
      hash[attrr.last] = obj.send(attrr.last)
      hash
    end
  end
end

# Then you can pass it a list of symbols.
# Then for your method:
def some_method name:, weight: 
    puts "#{name} weighs #{weight}"
end

class Dog
  attr_reader :name, :weight
  def initialize name:,weight: 
    @name = name
    @weight = weight
  end
end

a_dog = Dog.new( name: 'fido', weight: '7kg')
hash_puppy = a_dog.splat(a_dog, method: method(:some_method)  )

some_method(**hash_puppy)
```


or what I think is a bit better:

``` ruby
# Same class as above
a_dog = Dog.new( name: 'fido', weight: '7kg')

def other_splat  obj, method:
  new_hash = method.parameters.reduce({}) do |hash, attrr|
    if obj.class <= Hash
      hash[attrr.last] = obj[attrr.last]      
    else
      hash[attrr.last] = obj.send attrr.last
    end
    hash
  end
  method.call **new_hash
end

other_splat(a_dog, method: method(:some_method))

# above line should be like:
# some_method ...a_dog

```

Source: https://gist.github.com/bradkrane/e051d205024a5313cb4a5b9eb1eae0e3

I'm sure I'm missing a possibly more clever way to accomplish this, but I'm pretty sure something like `other_splat(a_dog, method: method(:some_method))` is about as close as it can get, unless I'm missing something? It would be quite nice to have a similar syntax as JS but in Ruby: `some_method ...a_dog`

Thanks for your time and attention!



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

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [ruby-core:103485] [Ruby master Feature#17808] Feature Request: JS like splat of Object properties as named method parameters
  2021-04-16 12:19 [ruby-core:103481] [Ruby master Feature#17808] Feature Request: JS like splat of Object properties as named method parameters brad.krane
  2021-04-16 13:43 ` [ruby-core:103483] " jean.boussier
@ 2021-04-16 18:54 ` brad.krane
  2021-04-16 19:03 ` [ruby-core:103486] " jean.boussier
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: brad.krane @ 2021-04-16 18:54 UTC (permalink / raw)
  To: ruby-core

Issue #17808 has been updated by Lithium (Brad Krane).


Thanks for the quick update. 

That almost works but to automate this the to_hash function needs to be aware of the methods named arguments. The below works in one case and fails in another with an object having more instance variables than the called method and it throws a `[ArgumentError] unknown keyword: :color` as there is now an extra parameter included that is not one of the named method params.

Also would this be dangerous to begin with modifying the Kernel to_hash?  


``` ruby
module Kernel
  def to_hash
    new_hash = self.instance_variables.reduce({}) do |hash, instance_var|
      hash[instance_var.to_s[1..-1].to_sym] = self.instance_variable_get instance_var
      hash
    end
  end
end

# Then you can pass it a list of symbols.
# Then for your method:
def some_method name:, weight: 
    puts "#{name} weighs #{weight}"
end

class Dog
  attr_reader :name, :weight
  def initialize name:,weight: 
    @name = name
    @weight = weight
  end
end

a_dog = Dog.new name: 'fido', weight: '7kg'

some_method(**a_dog)  # Works great!

class CockerSpanel < Dog
  def initialize name:,weight:,color:
    super name: name, weight: weight
    @color = color
  end
end

another_dog = CockerSpanel.new name: 'Jessie', weight: '5kg', color: 'black'

some_method **another_dog

```


NVM on the hash question it is a problem pasting into irb crashes with 


``` shell
C:/Ruby27-x64/lib/ruby/2.7.0/reline/unicode.rb:70: warning: Using the last argument as keyword parameters is deprecated
C:/Ruby27-x64/lib/ruby/2.7.0/reline/unicode.rb:70: warning: Using the last argument as keyword parameters is deprecated
C:/Ruby27-x64/lib/ruby/2.7.0/reline/unicode.rb:70: warning: Using the last argument as keyword parameters is deprecated
C:/Ruby27-x64/lib/ruby/2.7.0/reline/unicode.rb:70: warning: Using the last argument as keyword parameters is deprecated
C:/Ruby27-x64/lib/ruby/2.7.0/reline/unicode.rb:70: warning: Using the last argument as keyword parameters is deprecated
C:/Ruby27-x64/lib/ruby/2.7.0/reline/line_editor.rb:1080: warning: Using the last argument as keyword parameters is deprecated
C:/Ruby27-x64/lib/ruby/2.7.0/reline/line_editor.rb:1063: warning: Using the last argument as keyword parameters is deprecated
C:/Ruby27-x64/lib/ruby/2.7.0/reline/unicode.rb:70: warning: Using the last argument as keyword parameters is deprecated
C:/Ruby27-x64/lib/ruby/2.7.0/reline/unicode.rb:70: warning: Using the last argument as keyword parameters is deprecated
C:/Ruby27-x64/lib/ruby/2.7.0/reline/unicode.rb:70: warning: Using the last argument as keyword parameters is deprecated
C:/Ruby27-x64/lib/ruby/2.7.0/reline/unicode.rb:70: warning: Using the last argument as keyword parameters is deprecated
C:/Ruby27-x64/lib/ruby/2.7.0/reline/unicode.rb:70: warning: Using the last argument as keyword parameters is deprecated
C:/Ruby27-x64/lib/ruby/2.7.0/reline/unicode.rb:70: warning: Using the last argument as keyword parameters is deprecated
C:/Ruby27-x64/lib/ruby/2.7.0/irb/ext/save-history.rb:110: warning: Using the last argument as keyword parameters is deprecated
Traceback (most recent call last):
        13096: from C:/Ruby27-x64/bin/irb.cmd:31:in `<main>'
        13095: from C:/Ruby27-x64/bin/irb.cmd:31:in `load'
        13094: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/irb-1.2.3/exe/irb:11:in `<top (required)>'
        13093: from C:/Ruby27-x64/lib/ruby/2.7.0/irb.rb:399:in `start'
        13092: from C:/Ruby27-x64/lib/ruby/2.7.0/irb.rb:470:in `run'
        13091: from C:/Ruby27-x64/lib/ruby/2.7.0/irb.rb:470:in `catch'
        13090: from C:/Ruby27-x64/lib/ruby/2.7.0/irb.rb:471:in `block in run'
        13089: from C:/Ruby27-x64/lib/ruby/2.7.0/irb.rb:536:in `eval_input'
         ... 13084 levels...
            4: from C:/Ruby27-x64/lib/ruby/2.7.0/reline/line_editor.rb:93:in `block in reset'
            3: from C:/Ruby27-x64/lib/ruby/2.7.0/reline/line_editor.rb:93:in `block in reset'
            2: from C:/Ruby27-x64/lib/ruby/2.7.0/reline/line_editor.rb:93:in `block in reset'
            1: from C:/Ruby27-x64/lib/ruby/2.7.0/reline/line_editor.rb:93:in `block in reset'
C:/Ruby27-x64/lib/ruby/2.7.0/reline/line_editor.rb:93:in `block in reset': stack level too deep (SystemStackError)
```

Running the file itself we get

``` shell
C:\Users\Brad Krane\Documents\src\ruby-splat>ruby ruby-splat.rb
fido weighs 7kg
Traceback (most recent call last):
        1: from james.rb:38:in `<main>'
ruby-splat.rb:13:in `some_method': unknown keyword: :color (ArgumentError)

C:\Users\Brad Krane\Documents\src\ruby-splat>
```


How could I automate the to_hash knowing the method arguments required so as to prevent the `unknown keyword: :color (ArgumentError)` Or should I be specifying my to_hash methods individually and if I did how can I specify the correct parameters?

----------------------------------------
Feature #17808: Feature Request: JS like splat of Object properties as named method parameters
https://bugs.ruby-lang.org/issues/17808#change-91583

* Author: Lithium (Brad Krane)
* Status: Open
* Priority: Normal
----------------------------------------
I'm pretty sure there is no equivalent Ruby for a very convenient JS way to enter named function parameters as below:

``` javascript
const test = ({param1,
 param2,
 param3 = null,
 param4 = false,
 param5 = null,
 }={}) => {
   console.log(`${param1}, ${param2}, ${param3}, ${param4}, ${param5}\n`)    
 }
let obj = {
 param1: 23,
 param2: 234,
 param3: 235,
 param4: 257
};

test({...obj});

```

which is super convenient and as far as I'm aware there is no standard Ruby equivalent. It can be accomplished in Ruby but the call syntax is far less nice. A couple examples below:

``` ruby
# Implementing such a feature wouldn't be too difficult.
# Ok so here is what you could do it. Patch Kernel with a method splat. (Sorry in advance for formatting)
module Kernel
  def splat obj, method:
    new_hash = method.parameters.reduce({}) do |hash, attrr|
      hash[attrr.last] = obj.send(attrr.last)
      hash
    end
  end
end

# Then you can pass it a list of symbols.
# Then for your method:
def some_method name:, weight: 
    puts "#{name} weighs #{weight}"
end

class Dog
  attr_reader :name, :weight
  def initialize name:,weight: 
    @name = name
    @weight = weight
  end
end

a_dog = Dog.new( name: 'fido', weight: '7kg')
hash_puppy = a_dog.splat(a_dog, method: method(:some_method)  )

some_method(**hash_puppy)
```


or what I think is a bit better:

``` ruby
# Same class as above
a_dog = Dog.new( name: 'fido', weight: '7kg')

def other_splat  obj, method:
  new_hash = method.parameters.reduce({}) do |hash, attrr|
    if obj.class <= Hash
      hash[attrr.last] = obj[attrr.last]      
    else
      hash[attrr.last] = obj.send attrr.last
    end
    hash
  end
  method.call **new_hash
end

other_splat(a_dog, method: method(:some_method))

# above line should be like:
# some_method ...a_dog

```

Source: https://gist.github.com/bradkrane/e051d205024a5313cb4a5b9eb1eae0e3

I'm sure I'm missing a possibly more clever way to accomplish this, but I'm pretty sure something like `other_splat(a_dog, method: method(:some_method))` is about as close as it can get, unless I'm missing something? It would be quite nice to have a similar syntax as JS but in Ruby: `some_method ...a_dog`

Thanks for your time and attention!



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

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [ruby-core:103486] [Ruby master Feature#17808] Feature Request: JS like splat of Object properties as named method parameters
  2021-04-16 12:19 [ruby-core:103481] [Ruby master Feature#17808] Feature Request: JS like splat of Object properties as named method parameters brad.krane
  2021-04-16 13:43 ` [ruby-core:103483] " jean.boussier
  2021-04-16 18:54 ` [ruby-core:103485] " brad.krane
@ 2021-04-16 19:03 ` jean.boussier
  2021-04-16 19:24 ` [ruby-core:103487] " brad.krane
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: jean.boussier @ 2021-04-16 19:03 UTC (permalink / raw)
  To: ruby-core

Issue #17808 has been updated by byroot (Jean Boussier).


Well, the ruby equivalent to your example JS function would be:

```ruby
def test(param1: nil, param2: nil, **)
end 
```

The `**` will catch any key that don't match any of the declared keyword arguments.

----------------------------------------
Feature #17808: Feature Request: JS like splat of Object properties as named method parameters
https://bugs.ruby-lang.org/issues/17808#change-91584

* Author: Lithium (Brad Krane)
* Status: Open
* Priority: Normal
----------------------------------------
I'm pretty sure there is no equivalent Ruby for a very convenient JS way to enter named function parameters as below:

``` javascript
const test = ({param1,
 param2,
 param3 = null,
 param4 = false,
 param5 = null,
 }={}) => {
   console.log(`${param1}, ${param2}, ${param3}, ${param4}, ${param5}\n`)    
 }
let obj = {
 param1: 23,
 param2: 234,
 param3: 235,
 param4: 257
};

test({...obj});

```

which is super convenient and as far as I'm aware there is no standard Ruby equivalent. It can be accomplished in Ruby but the call syntax is far less nice. A couple examples below:

``` ruby
# Implementing such a feature wouldn't be too difficult.
# Ok so here is what you could do it. Patch Kernel with a method splat. (Sorry in advance for formatting)
module Kernel
  def splat obj, method:
    new_hash = method.parameters.reduce({}) do |hash, attrr|
      hash[attrr.last] = obj.send(attrr.last)
      hash
    end
  end
end

# Then you can pass it a list of symbols.
# Then for your method:
def some_method name:, weight: 
    puts "#{name} weighs #{weight}"
end

class Dog
  attr_reader :name, :weight
  def initialize name:,weight: 
    @name = name
    @weight = weight
  end
end

a_dog = Dog.new( name: 'fido', weight: '7kg')
hash_puppy = a_dog.splat(a_dog, method: method(:some_method)  )

some_method(**hash_puppy)
```


or what I think is a bit better:

``` ruby
# Same class as above
a_dog = Dog.new( name: 'fido', weight: '7kg')

def other_splat  obj, method:
  new_hash = method.parameters.reduce({}) do |hash, attrr|
    if obj.class <= Hash
      hash[attrr.last] = obj[attrr.last]      
    else
      hash[attrr.last] = obj.send attrr.last
    end
    hash
  end
  method.call **new_hash
end

other_splat(a_dog, method: method(:some_method))

# above line should be like:
# some_method ...a_dog

```

Source: https://gist.github.com/bradkrane/e051d205024a5313cb4a5b9eb1eae0e3

I'm sure I'm missing a possibly more clever way to accomplish this, but I'm pretty sure something like `other_splat(a_dog, method: method(:some_method))` is about as close as it can get, unless I'm missing something? It would be quite nice to have a similar syntax as JS but in Ruby: `some_method ...a_dog`

Thanks for your time and attention!



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

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [ruby-core:103487] [Ruby master Feature#17808] Feature Request: JS like splat of Object properties as named method parameters
  2021-04-16 12:19 [ruby-core:103481] [Ruby master Feature#17808] Feature Request: JS like splat of Object properties as named method parameters brad.krane
                   ` (2 preceding siblings ...)
  2021-04-16 19:03 ` [ruby-core:103486] " jean.boussier
@ 2021-04-16 19:24 ` brad.krane
  2021-04-16 21:00 ` [ruby-core:103488] " jean.boussier
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: brad.krane @ 2021-04-16 19:24 UTC (permalink / raw)
  To: ruby-core

Issue #17808 has been updated by Lithium (Brad Krane).


byroot (Jean Boussier) wrote in #note-3:
> Well, the ruby equivalent to your example JS function would be:
> 
> ```ruby
> def test(param1: nil, param2: nil, **)
> end 
> ```
> 
> The `**` will catch any key that don't match any of the declared keyword arguments.

This does work, but this requires modifying all methods to include this extra parameter to avoid the error. 

Is there a way to modify existing declared methods adding that parameter so as to avoid an error when additional params are provided in error due to the object having more instance_variables for whatever reason?

I can't see how to escape the following syntax for this functionality without heavy lifting: `other_splat(a_dog, method: method(:some_method))` 

With the Kernel.to_hash monkey patching how can one avoid the argument error for 'poorly written methods' that don't have the extra ** that already?

There is also the case an object is passed to many different methods all with different named params selectively grabbing what's needed for the moment, without having to mod all the methods to have a **, or specifying a specific to_hash_some_method for each method or using `other_splat(a_dog, method: method(:some_method))` which does work but is ugly af for Ruby in my opinion.







----------------------------------------
Feature #17808: Feature Request: JS like splat of Object properties as named method parameters
https://bugs.ruby-lang.org/issues/17808#change-91585

* Author: Lithium (Brad Krane)
* Status: Open
* Priority: Normal
----------------------------------------
I'm pretty sure there is no equivalent Ruby for a very convenient JS way to enter named function parameters as below:

``` javascript
const test = ({param1,
 param2,
 param3 = null,
 param4 = false,
 param5 = null,
 }={}) => {
   console.log(`${param1}, ${param2}, ${param3}, ${param4}, ${param5}\n`)    
 }
let obj = {
 param1: 23,
 param2: 234,
 param3: 235,
 param4: 257
};

test({...obj});

```

which is super convenient and as far as I'm aware there is no standard Ruby equivalent. It can be accomplished in Ruby but the call syntax is far less nice. A couple examples below:

``` ruby
# Implementing such a feature wouldn't be too difficult.
# Ok so here is what you could do it. Patch Kernel with a method splat. (Sorry in advance for formatting)
module Kernel
  def splat obj, method:
    new_hash = method.parameters.reduce({}) do |hash, attrr|
      hash[attrr.last] = obj.send(attrr.last)
      hash
    end
  end
end

# Then you can pass it a list of symbols.
# Then for your method:
def some_method name:, weight: 
    puts "#{name} weighs #{weight}"
end

class Dog
  attr_reader :name, :weight
  def initialize name:,weight: 
    @name = name
    @weight = weight
  end
end

a_dog = Dog.new( name: 'fido', weight: '7kg')
hash_puppy = a_dog.splat(a_dog, method: method(:some_method)  )

some_method(**hash_puppy)
```


or what I think is a bit better:

``` ruby
# Same class as above
a_dog = Dog.new( name: 'fido', weight: '7kg')

def other_splat  obj, method:
  new_hash = method.parameters.reduce({}) do |hash, attrr|
    if obj.class <= Hash
      hash[attrr.last] = obj[attrr.last]      
    else
      hash[attrr.last] = obj.send attrr.last
    end
    hash
  end
  method.call **new_hash
end

other_splat(a_dog, method: method(:some_method))

# above line should be like:
# some_method ...a_dog

```

Source: https://gist.github.com/bradkrane/e051d205024a5313cb4a5b9eb1eae0e3

I'm sure I'm missing a possibly more clever way to accomplish this, but I'm pretty sure something like `other_splat(a_dog, method: method(:some_method))` is about as close as it can get, unless I'm missing something? It would be quite nice to have a similar syntax as JS but in Ruby: `some_method ...a_dog`

Thanks for your time and attention!



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

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [ruby-core:103488] [Ruby master Feature#17808] Feature Request: JS like splat of Object properties as named method parameters
  2021-04-16 12:19 [ruby-core:103481] [Ruby master Feature#17808] Feature Request: JS like splat of Object properties as named method parameters brad.krane
                   ` (3 preceding siblings ...)
  2021-04-16 19:24 ` [ruby-core:103487] " brad.krane
@ 2021-04-16 21:00 ` jean.boussier
  2021-04-16 21:05 ` [ruby-core:103489] " marcandre-ruby-core
  2021-04-17 23:43 ` [ruby-core:103503] " brad.krane
  6 siblings, 0 replies; 8+ messages in thread
From: jean.boussier @ 2021-04-16 21:00 UTC (permalink / raw)
  To: ruby-core

Issue #17808 has been updated by byroot (Jean Boussier).


> Is there a way to modify existing declared methods adding that parameter

Well, I suppose you can decorate the methods and filter the extra keywords, a bit tricky but doable:

```ruby
class Module
  def ignore_extra_parameters(method_name)
    method = instance_method(method_name)
    keyword_args = method.parameters.filter_map { |type, name| name if type == :key || type == :keyreq }
    define_method(method_name) do |*args, **kwargs, &block|
      method.bind_call(self, *args, **kwargs.slice(*keyword_args), &block)
    end
  end
end

class MyObject
  def initialize(bar)
    @bar = bar
  end

  def to_hash
    { bar: @bar, plop: 42 }
  end
end

module Test
  extend self
  ignore_extra_parameters def foo(bar:)
    p bar
  end
end

Test.foo(**MyObject.new(42)) # => 42
```


But ultimately your whole feature request rely on a very specific JS "feature" (many people would call it a cruft), that extra arguments are simply ignored.

That's not the case in Ruby, every argument must be accounted for. And while I'm merely an observer of the ruby-core development, I'm pretty sure it isn't acceptable to change. So I doubt there any way such feature would be implemented.

Or you'd need to introduce some new syntax for the caller to specify that the extra parameters should be discarded, but again, not very likely to happen.





----------------------------------------
Feature #17808: Feature Request: JS like splat of Object properties as named method parameters
https://bugs.ruby-lang.org/issues/17808#change-91586

* Author: Lithium (Brad Krane)
* Status: Open
* Priority: Normal
----------------------------------------
I'm pretty sure there is no equivalent Ruby for a very convenient JS way to enter named function parameters as below:

``` javascript
const test = ({param1,
 param2,
 param3 = null,
 param4 = false,
 param5 = null,
 }={}) => {
   console.log(`${param1}, ${param2}, ${param3}, ${param4}, ${param5}\n`)    
 }
let obj = {
 param1: 23,
 param2: 234,
 param3: 235,
 param4: 257
};

test({...obj});

```

which is super convenient and as far as I'm aware there is no standard Ruby equivalent. It can be accomplished in Ruby but the call syntax is far less nice. A couple examples below:

``` ruby
# Implementing such a feature wouldn't be too difficult.
# Ok so here is what you could do it. Patch Kernel with a method splat. (Sorry in advance for formatting)
module Kernel
  def splat obj, method:
    new_hash = method.parameters.reduce({}) do |hash, attrr|
      hash[attrr.last] = obj.send(attrr.last)
      hash
    end
  end
end

# Then you can pass it a list of symbols.
# Then for your method:
def some_method name:, weight: 
    puts "#{name} weighs #{weight}"
end

class Dog
  attr_reader :name, :weight
  def initialize name:,weight: 
    @name = name
    @weight = weight
  end
end

a_dog = Dog.new( name: 'fido', weight: '7kg')
hash_puppy = a_dog.splat(a_dog, method: method(:some_method)  )

some_method(**hash_puppy)
```


or what I think is a bit better:

``` ruby
# Same class as above
a_dog = Dog.new( name: 'fido', weight: '7kg')

def other_splat  obj, method:
  new_hash = method.parameters.reduce({}) do |hash, attrr|
    if obj.class <= Hash
      hash[attrr.last] = obj[attrr.last]      
    else
      hash[attrr.last] = obj.send attrr.last
    end
    hash
  end
  method.call **new_hash
end

other_splat(a_dog, method: method(:some_method))

# above line should be like:
# some_method ...a_dog

```

Source: https://gist.github.com/bradkrane/e051d205024a5313cb4a5b9eb1eae0e3

I'm sure I'm missing a possibly more clever way to accomplish this, but I'm pretty sure something like `other_splat(a_dog, method: method(:some_method))` is about as close as it can get, unless I'm missing something? It would be quite nice to have a similar syntax as JS but in Ruby: `some_method ...a_dog`

Thanks for your time and attention!



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

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [ruby-core:103489] [Ruby master Feature#17808] Feature Request: JS like splat of Object properties as named method parameters
  2021-04-16 12:19 [ruby-core:103481] [Ruby master Feature#17808] Feature Request: JS like splat of Object properties as named method parameters brad.krane
                   ` (4 preceding siblings ...)
  2021-04-16 21:00 ` [ruby-core:103488] " jean.boussier
@ 2021-04-16 21:05 ` marcandre-ruby-core
  2021-04-17 23:43 ` [ruby-core:103503] " brad.krane
  6 siblings, 0 replies; 8+ messages in thread
From: marcandre-ruby-core @ 2021-04-16 21:05 UTC (permalink / raw)
  To: ruby-core

Issue #17808 has been updated by marcandre (Marc-Andre Lafortune).


I believe the answers given so far should help (i.e. `(**rest)` and defining `to_hash`).

Also looks into `Struct` that does some of that for you. I wish `Struct` was better for inheritance though, I'd like to propose a better solution one day.

In the meantime, if this discussion needs to continue, it would be more appropriate on StackOverflow / some code-refactoring site, as there doesn't seem to be a particular feature request.

----------------------------------------
Feature #17808: Feature Request: JS like splat of Object properties as named method parameters
https://bugs.ruby-lang.org/issues/17808#change-91587

* Author: Lithium (Brad Krane)
* Status: Open
* Priority: Normal
----------------------------------------
I'm pretty sure there is no equivalent Ruby for a very convenient JS way to enter named function parameters as below:

``` javascript
const test = ({param1,
 param2,
 param3 = null,
 param4 = false,
 param5 = null,
 }={}) => {
   console.log(`${param1}, ${param2}, ${param3}, ${param4}, ${param5}\n`)    
 }
let obj = {
 param1: 23,
 param2: 234,
 param3: 235,
 param4: 257
};

test({...obj});

```

which is super convenient and as far as I'm aware there is no standard Ruby equivalent. It can be accomplished in Ruby but the call syntax is far less nice. A couple examples below:

``` ruby
# Implementing such a feature wouldn't be too difficult.
# Ok so here is what you could do it. Patch Kernel with a method splat. (Sorry in advance for formatting)
module Kernel
  def splat obj, method:
    new_hash = method.parameters.reduce({}) do |hash, attrr|
      hash[attrr.last] = obj.send(attrr.last)
      hash
    end
  end
end

# Then you can pass it a list of symbols.
# Then for your method:
def some_method name:, weight: 
    puts "#{name} weighs #{weight}"
end

class Dog
  attr_reader :name, :weight
  def initialize name:,weight: 
    @name = name
    @weight = weight
  end
end

a_dog = Dog.new( name: 'fido', weight: '7kg')
hash_puppy = a_dog.splat(a_dog, method: method(:some_method)  )

some_method(**hash_puppy)
```


or what I think is a bit better:

``` ruby
# Same class as above
a_dog = Dog.new( name: 'fido', weight: '7kg')

def other_splat  obj, method:
  new_hash = method.parameters.reduce({}) do |hash, attrr|
    if obj.class <= Hash
      hash[attrr.last] = obj[attrr.last]      
    else
      hash[attrr.last] = obj.send attrr.last
    end
    hash
  end
  method.call **new_hash
end

other_splat(a_dog, method: method(:some_method))

# above line should be like:
# some_method ...a_dog

```

Source: https://gist.github.com/bradkrane/e051d205024a5313cb4a5b9eb1eae0e3

I'm sure I'm missing a possibly more clever way to accomplish this, but I'm pretty sure something like `other_splat(a_dog, method: method(:some_method))` is about as close as it can get, unless I'm missing something? It would be quite nice to have a similar syntax as JS but in Ruby: `some_method ...a_dog`

Thanks for your time and attention!



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

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [ruby-core:103503] [Ruby master Feature#17808] Feature Request: JS like splat of Object properties as named method parameters
  2021-04-16 12:19 [ruby-core:103481] [Ruby master Feature#17808] Feature Request: JS like splat of Object properties as named method parameters brad.krane
                   ` (5 preceding siblings ...)
  2021-04-16 21:05 ` [ruby-core:103489] " marcandre-ruby-core
@ 2021-04-17 23:43 ` brad.krane
  6 siblings, 0 replies; 8+ messages in thread
From: brad.krane @ 2021-04-17 23:43 UTC (permalink / raw)
  To: ruby-core

Issue #17808 has been updated by Lithium (Brad Krane).


 
> But ultimately your whole feature request rely on a very specific JS "feature" (many people would call it a cruft), that extra arguments are simply ignored.

Yes likely but it is very convenient.

> That's not the case in Ruby, every argument must be accounted for. And while I'm merely an observer of the ruby-core development, I'm pretty sure it isn't acceptable to change. So I doubt there any way such feature would be implemented.
> 
> Or you'd need to introduce some new syntax for the caller to specify that the extra parameters should be discarded, but again, not very likely to happen.

I agree with you here. I suppose the ultimate question is if I can't redefine to_hash for everything, verified bad idea, and I don't want to mod all methods like in your `ignore_extra_parameters` example, (which is brilliant btw), how can I call my to_hash method with it knowing if it is a ** reduction and if so what caller is so as to be able to yield the appropriate hash for this to work?

Can a methods parameter identify the function it's in before it's called? and then be able to define itself based on the named params of the method after called into?

For this to work a parameter needs to know it's calling method and then react to it appropriately.

`some_method splat(object)` is the ideal syntax but seems impossible and where

where `some_method splat(object)` is really `some_method splat(object, method: some_method)`

so you could detect and emit the correct params as opposed to spamming them.



Towards Marc-Andre

I will have to study the Struct class as this looks promising but I haven't the time atm.

----------------------------------------
Feature #17808: Feature Request: JS like splat of Object properties as named method parameters
https://bugs.ruby-lang.org/issues/17808#change-91601

* Author: Lithium (Brad Krane)
* Status: Open
* Priority: Normal
----------------------------------------
I'm pretty sure there is no equivalent Ruby for a very convenient JS way to enter named function parameters as below:

``` javascript
const test = ({param1,
 param2,
 param3 = null,
 param4 = false,
 param5 = null,
 }={}) => {
   console.log(`${param1}, ${param2}, ${param3}, ${param4}, ${param5}\n`)    
 }
let obj = {
 param1: 23,
 param2: 234,
 param3: 235,
 param4: 257
};

test({...obj});

```

which is super convenient and as far as I'm aware there is no standard Ruby equivalent. It can be accomplished in Ruby but the call syntax is far less nice. A couple examples below:

``` ruby
# Implementing such a feature wouldn't be too difficult.
# Ok so here is what you could do it. Patch Kernel with a method splat. (Sorry in advance for formatting)
module Kernel
  def splat obj, method:
    new_hash = method.parameters.reduce({}) do |hash, attrr|
      hash[attrr.last] = obj.send(attrr.last)
      hash
    end
  end
end

# Then you can pass it a list of symbols.
# Then for your method:
def some_method name:, weight: 
    puts "#{name} weighs #{weight}"
end

class Dog
  attr_reader :name, :weight
  def initialize name:,weight: 
    @name = name
    @weight = weight
  end
end

a_dog = Dog.new( name: 'fido', weight: '7kg')
hash_puppy = a_dog.splat(a_dog, method: method(:some_method)  )

some_method(**hash_puppy)
```


or what I think is a bit better:

``` ruby
# Same class as above
a_dog = Dog.new( name: 'fido', weight: '7kg')

def other_splat  obj, method:
  new_hash = method.parameters.reduce({}) do |hash, attrr|
    if obj.class <= Hash
      hash[attrr.last] = obj[attrr.last]      
    else
      hash[attrr.last] = obj.send attrr.last
    end
    hash
  end
  method.call **new_hash
end

other_splat(a_dog, method: method(:some_method))

# above line should be like:
# some_method ...a_dog

```

Source: https://gist.github.com/bradkrane/e051d205024a5313cb4a5b9eb1eae0e3

I'm sure I'm missing a possibly more clever way to accomplish this, but I'm pretty sure something like `other_splat(a_dog, method: method(:some_method))` is about as close as it can get, unless I'm missing something? It would be quite nice to have a similar syntax as JS but in Ruby: `some_method ...a_dog`

Thanks for your time and attention!



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

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2021-04-17 23:44 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-04-16 12:19 [ruby-core:103481] [Ruby master Feature#17808] Feature Request: JS like splat of Object properties as named method parameters brad.krane
2021-04-16 13:43 ` [ruby-core:103483] " jean.boussier
2021-04-16 18:54 ` [ruby-core:103485] " brad.krane
2021-04-16 19:03 ` [ruby-core:103486] " jean.boussier
2021-04-16 19:24 ` [ruby-core:103487] " brad.krane
2021-04-16 21:00 ` [ruby-core:103488] " jean.boussier
2021-04-16 21:05 ` [ruby-core:103489] " marcandre-ruby-core
2021-04-17 23:43 ` [ruby-core:103503] " brad.krane

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).