ruby-core@ruby-lang.org archive (unofficial mirror)
 help / color / mirror / Atom feed
From: larskanis@gmail.com
To: ruby-core@ruby-lang.org
Subject: [ruby-core:96908] [Ruby master Feature#16499] define_method(non_lambda) should not change the semantics of the given Proc
Date: Thu, 16 Jan 2020 09:57:31 +0000 (UTC)	[thread overview]
Message-ID: <redmine.journal-83926.20200116095730.20b60c5f1be776d9@ruby-lang.org> (raw)
In-Reply-To: redmine.issue-16499.20200110223629@ruby-lang.org

Issue #16499 has been updated by larskanis (Lars Kanis).


Unfortunately `define_method` is currently the only way to retrieve `Proc#parameters` without information loss. See #15357 and [here](https://github.com/larskanis/eventbox/blob/3bcbc30096c6003e96d41c6496c781dfc90ac36a/lib/eventbox/argument_wrapper.rb#L10-L17) for the workaround per `default_method`. Therefore fixing `default_method` would also require fixing `Proc#parameters`.

----------------------------------------
Feature #16499: define_method(non_lambda) should not change the semantics of the given Proc
https://bugs.ruby-lang.org/issues/16499#change-83926

* Author: Eregon (Benoit Daloze)
* Status: Rejected
* Priority: Normal
* Assignee: 
* Target version: 
----------------------------------------
From https://bugs.ruby-lang.org/issues/15973?next_issue_id=15948&prev_issue_id=15975#note-38

But I think we should change `define_method(&non_lambda)` because that currently confusingly treats the same block body differently (e.g., the same `return` in the code means something different).

This is the only construct in Ruby that can change a non-lambda to a lambda, and it's very inconsistent.
It also forces implementations to have a way to convert a proc to a lambda, which is a non-trivial change.

We could maybe make `define_method(name, non_lambda)` just wrap the Proc in a lambda, automatically,
just like we can do manually with: `define_method(name, -> *args { non_lambda.call(*args) })`.
But it would also preserve `arity`, `parameters`, etc.
Then it wouldn't be any more verbose, but it would avoid the problem of treating the same `return`/`break` in the code differently.

My point is we shall never change the semantics of `return`/`break` somewhere in the code.
It should always mean exactly one thing.
`define_method(name) { literal block }` is fine with that rule, it always behave as a lambda.
But `define_method(&non_lambda)` is problematic as `non_lambda` can be passed to other methods or called directly.

I believe exactly 0 people want `foo { return 42 }` to change its meaning based on whether `foo` calls `define_method` or not.

OTOH, it seems people have repeatedly wanted to convert a proc to a lambda, but for other reasons.
We should look at those reasons and provide better alternatives.

I think sometimes people want to know how many arguments a non-lambda Proc takes.
For example, `proc { |a,b=1| }`.
`proc.arity` gives `1` here which might be helpful but also surprising as that Proc accepts any number of arguments.
They might also look at `proc.parameters` which gives `[[:opt, :a], [:opt, :b]]` which does not differentiate `a` and `b` even though only `b` has a proper default value.
`lambda { |a,b=1| }.parameters` returns the more useful `[[:req, :a], [:opt, :b]]`.

Maybe we should return the same as for a lambda for `non_lambda.parameters`?
`Proc#lambda?` would still tell whether it's strict about arguments and whether it deconstructs them.

cc @zverok



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

      parent reply	other threads:[~2020-01-16  9:57 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <redmine.issue-16499.20200110223629@ruby-lang.org>
2020-01-10 22:36 ` [ruby-core:96768] [Ruby master Feature#16499] define_method(non_lambda) should not the semantics of the given Proc eregontp
2020-01-11 22:44 ` [ruby-core:96793] " ruby-core
2020-01-12 14:20 ` [ruby-core:96802] " zverok.offline
2020-01-12 16:19 ` [ruby-core:96803] " eregontp
2020-01-12 16:24 ` [ruby-core:96804] " eregontp
2020-01-12 16:27 ` [ruby-core:96805] " eregontp
2020-01-16  8:18 ` [ruby-core:96901] [Ruby master Feature#16499] define_method(non_lambda) should not change " matz
2020-01-16  9:57 ` larskanis [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.ruby-lang.org/en/community/mailing-lists/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=redmine.journal-83926.20200116095730.20b60c5f1be776d9@ruby-lang.org \
    --to=ruby-core@ruby-lang.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).