Feature #7299
closedRuby should not completely ignore blocks.
Description
Ruby should not completely ignore blocks.
const_set :Example, Class.new do
p "Hello, world"
end
Doesn't print anything, generate any warning nor error.¶
To minimize any impact, Ruby should issue a warning, and in future version could even raise an error.
Even unused variables provide warnings in verbose mode, and they have their use.
I can't think of a case where passing a block to a builtin method that doesn't accept a block is not a programming error though.
If this is approved, I volunteer to implement this.
Updated by matz (Yukihiro Matsumoto) about 12 years ago
- Status changed from Open to Feedback
I considered this issue before, and had problem with how to detect non block calling block.
Things go easier if & block argument is mandatory for block taking methods, but I am not doing so in near future.
Do you have any good idea?
Matz.
Updated by marcandre (Marc-Andre Lafortune) about 12 years ago
- Status changed from Feedback to Open
matz (Yukihiro Matsumoto) wrote:
I ... had problem with how to detect non block calling block.
Sorry, I am not sure I understand completely.
To avoid case like the example I gave, we could modify "rb_mod_const_set" by adding "WARN_IF_BLOCK_GIVEN", for example, or create a more advanced version of "rb_check_arity" like "rb_check_arity_and_block" that accepts a parameter to warn if there is a block given.
What I would really like to do is create an improved "rb_define_method" with arguments to specify:
- mininum arity
- maximum arity
- if block is accepted
- and ideally parameter names, at least for methods with simple interfaces
This way:
- easier to warn if block is accepted
- improved result for
"".method(:gsub).arity
- much improved result for
"".method(:gsub).parameters
- possible to implement
arity_max
orarity_range
with good result if ever it is accepted - improved behavior when using
curry
Also, this would simplify many method that would not have to call rb_check_arity
like we do now.
Updated by matz (Yukihiro Matsumoto) about 12 years ago
- Status changed from Open to Rejected
So you think of changing introducing new functions. I see.
In that case, it's better to submit a new issue for the idea, with API proposal.
Matz.
Updated by Anonymous about 12 years ago
On Wed, Nov 07, 2012 at 01:06:34PM +0900, marcandre (Marc-Andre Lafortune) wrote:
Issue #7299 has been reported by marcandre (Marc-Andre Lafortune).
Feature #7299: Ruby should not completely ignore blocks.
https://bugs.ruby-lang.org/issues/7299Author: marcandre (Marc-Andre Lafortune)
Status: Open
Priority: Normal
Assignee:
Category: core
Target version:Ruby should not completely ignore blocks.
const_set :Example, Class.new do
p "Hello, world"
endDoesn't print anything, generate any warning nor error.¶
To minimize any impact, Ruby should issue a warning, and in future version could even raise an error.
Even unused variables provide warnings in verbose mode, and they have their use.
I can't think of a case where passing a block to a builtin method that doesn't accept a block is not a programming error though.
This happens with normal ruby code:
ruby -w -e'def foo; 10; end; p foo { raise };'
Why would "builtin" methods be special?
--
Aaron Patterson
http://tenderlovemaking.com/
Updated by rosenfeld (Rodrigo Rosenfeld Rosas) about 12 years ago
Em 07-11-2012 11:00, Aaron Patterson escreveu:
On Wed, Nov 07, 2012 at 01:06:34PM +0900, marcandre (Marc-Andre Lafortune) wrote:
Issue #7299 has been reported by marcandre (Marc-Andre Lafortune).
Feature #7299: Ruby should not completely ignore blocks.
https://bugs.ruby-lang.org/issues/7299Author: marcandre (Marc-Andre Lafortune)
Status: Open
Priority: Normal
Assignee:
Category: core
Target version:Ruby should not completely ignore blocks.
const_set :Example, Class.new do
p "Hello, world"
endDoesn't print anything, generate any warning nor error.¶
To minimize any impact, Ruby should issue a warning, and in future version could even raise an error.
Even unused variables provide warnings in verbose mode, and they have their use.
I can't think of a case where passing a block to a builtin method that doesn't accept a block is not a programming error though.
This happens with normal ruby code:ruby -w -e'def foo; 10; end; p foo { raise };'
Why would "builtin" methods be special?
I agree. I'd prefer to just raise an exception when a block is passed
and no block_given? or yield is called for the method.
I was bitten some times by bugs hard to detect because of this behavior
where I thought the block was being given to a method while it was being
given to another one that didn't even expect any block.
Updated by marcandre (Marc-Andre Lafortune) about 12 years ago
matz (Yukihiro Matsumoto) wrote:
So you think of changing introducing new functions. I see.
In that case, it's better to submit a new issue for the idea, with API proposal.
Of course, but first I wanted to validate you were positive with the idea of warning for unused block
tenderlove wrote:
This happens with normal ruby code:
Why would "builtin" methods be special?
Agreed, it would be best if user methods also warned. I was just lacking ambition by suggesting it only for builtin methods :-)
Rodrigo's suggestion of flagging block_given?
, yield
, (as well as Proc.new, super and &capture_block) would work.
Updated by matz (Yukihiro Matsumoto) about 12 years ago
I am positive as long as there's rational way to declare methods as 'non-block taking'.
Last time I tried, I couldn't think any good idea to do so (without adding new API).
New API (alternative version of rb_define_method, I suppose) is a good idea.
The remaining problem should be how to declare Ruby-define methods to be 'non-block taking'.
Under the current language spec, absence of '& argument' may or may not mean the method would take a block.
Matz.
Updated by ko1 (Koichi Sasada) about 12 years ago
(2012/11/08 5:48), matz (Yukihiro Matsumoto) wrote:
Under the current language spec, absence of '& argument' may or may not mean the method would take a block.
I agree that such checking is very useful.
example code¶
p 'str'.gsub('x') do
end
One idea:
If compiled method does not contain
- `yield' statement
- super statement
- block argument
then the method is marked as "block is not needed" method.
This approach introduce incompatibility because we can call block in `eval'.
example¶
def foo str
eval str
end
foo('yield') do
...
end
And maybe there are other issues.
--
// SASADA Koichi at atdot dot net
Updated by shyouhei (Shyouhei Urabe) about 12 years ago
On 11/07/2012 03:23 PM, SASADA Koichi wrote:
This approach introduce incompatibility because we can call block in `eval'.
So you are proposing to deprecate eval? :p
Updated by marcandre (Marc-Andre Lafortune) about 12 years ago
ko1 (Koichi Sasada) wrote:
If compiled method does not contain
- `yield' statement
- super statement
- block argument
then the method is marked as "block is not needed" method.This approach introduce incompatibility because we can call block in `eval'.
And maybe there are other issues.
There is also Proc.new
...
def foo
Proc.new.call
end
foo{ p 42 } # => prints 42
Both eval and Proc.new are strange cornercases though. The only valid uses I can think of for Proc.new
also imply use of super
. If we only issue a warning, the incompatibility would be very minimal.
So I'll make a proposal for an expanded API for rb_define_method
. OTOH, marking ruby methods as {non-}block taking would seriously challenge my cruby skills
Updated by nobu (Nobuyoshi Nakada) about 12 years ago
(12/11/09 1:53), marcandre (Marc-Andre Lafortune) wrote:
ko1 (Koichi Sasada) wrote:
If compiled method does not contain
- `yield' statement
- super statement
- block argument
then the method is marked as "block is not needed" method.There is also
Proc.new
...
Also proc, lambda, and defined?(yield).
--
Nobu Nakada
Updated by headius (Charles Nutter) about 12 years ago
Perhaps methods that want to ensure nobody accidentally passes in a block should just check for it? fail if block_given?
for example?
An option for a syntactic check in Ruby code: def foo(&nil) => raise error on call if a block is given.
I don't think magic checks should be put in place for Ruby code that doesn't have an explicit block parameter. There are a lot of edge cases where the block is used and we don't know about it until later. eval/binding has been brought up, Proc.new (which should be deprecated) has been brought up, and so on.