Project

General

Profile

Feature #10499

Eliminate implicit magic in Proc.new and Kernel#proc

Added by headius (Charles Nutter) about 6 years ago. Updated 16 days ago.

Status:
Closed
Priority:
Normal
Target version:
-
[ruby-core:66225]

Description

Proc.new and Kernel#proc have a little known feature: if called without a block, they capture whatever block was passed to the current method.

I propose that this feature should be removed, finally, since it:

  • Doesn't enhance readability (where is this block coming from?)
  • Doesn't reflect any other behavior in Ruby
  • Can lead to bugs (call either without a block accidentally and you aren't sure what you'll get)

I believe this was an implementation artifact in MRI, since the most recently-pushed block would still be on global stacks, which is where the logic for proc and Proc.new looked for it.

All argument syntaxes now support &block, which I believe is the correct way to clearly, explicitly capture the incoming block into an object.

Thoughts?


Related issues

Copied to Ruby master - Feature #15554: warn/error passing a block to a method which never use a blockClosedmatz (Yukihiro Matsumoto)Actions

Updated by marcandre (Marc-Andre Lafortune) about 6 years ago

  • Category set to core
  • Assignee set to matz (Yukihiro Matsumoto)

I agree.

Deprecate first (2.2?), remove afterwards.

This would also simplify things if and when we want to warn/raise on unused blocks when calling user methods.

Updated by headius (Charles Nutter) about 6 years ago

Adding a deprecation warning would be easy if we can get buy-in from matz.

matz: ball's in your court, I think!

#3

Updated by k0kubun (Takashi Kokubun) over 1 year ago

  • Copied to Feature #15554: warn/error passing a block to a method which never use a block added
#4

Updated by naruse (Yui NARUSE) about 1 month ago

  • Target version deleted (3.0)

Updated by dazuma (Daniel Azuma) 17 days ago

Was this change implemented in Ruby 3.0.0?

It looks to me like it was. (And this is causing test failures on libraries that depend on this behavior.)

Ruby 2.7.2:

def foo
  Proc.new
end

foo          # => ArgumentError
foo { :hi }  # => Proc

Ruby 3.0.0:

def foo
  Proc.new
end

foo          # => ArgumentError
foo { :hi }  # => ArgumentError

Updated by dazuma (Daniel Azuma) 16 days ago

Note that the documentation still specifies the old behavior in 3.0.0.

Creates a new Proc object, bound to the current context. ::new may be called without a block only within a method with an attached block, in which case that block is converted to the Proc object.

https://ruby-doc.org/core-3.0.0/Proc.html#method-c-new
https://github.com/ruby/ruby/blob/95aff214687a5e12c3eb57d056665741e734c188/proc.c#L800-L813

#7

Updated by nobu (Nobuyoshi Nakada) 16 days ago

  • Status changed from Open to Closed

Applied in changeset git|8da7f4abc779c6549833d718336d75aac98494b8.


[DOC] Update Proc.new without a block [ci skip]

[Feature #10499]
[Feature #15554]

Updated by nobu (Nobuyoshi Nakada) 16 days ago

Thank you, updated.

Also available in: Atom PDF