Project

General

Profile

Actions

Feature #7314

open

Convert Proc to Lambda doesn't work in MRI

Added by schneems (Richard Schneeman) over 11 years ago. Updated almost 8 years ago.

Status:
Assigned
Target version:
-
[ruby-core:49112]

Description

I have code where I need to convert a proc to a lambda (i need to be able to return out of the block). I would expect that passing a proc into a lambda to return a lambda. When I run this code on MRI i do not get the result I would expect

my_proc = proc { |x| x }
my_lambda = lambda &my_proc
my_lambda.lambda?

The result is false but I would expect it to be true

There is currently a way to turn a proc into a lambda in MRI like this:

def convert_to_lambda &block
  obj = Object.new
  obj.define_singleton_method(:_, &block)
  return obj.method(:_).to_proc
end

But this feels like a hack, and is not supported across other implementations. I would expect that passing a proc into a lambda to return a lambda, I believe it is a bug.


Related issues 2 (0 open2 closed)

Related to Ruby master - Feature #12957: A more OO way to create lambda ProcsFeedbackActions
Related to Ruby master - Feature #15973: Let Kernel#lambda always return a lambdaClosedmatz (Yukihiro Matsumoto)Actions
Actions #1

Updated by shyouhei (Shyouhei Urabe) over 11 years ago

  • Tracker changed from Bug to Feature

Moved this to feature tracker. I think you are feeling this like a hack because, you are in fact doing something hacky (return from a block).

Anyway I'm not against that kind of feature, though I'm not sure if that can be achieved by lambda(&proc). So I feel a needs of discussion.

Updated by schneems (Richard Schneeman) over 11 years ago

I would like a standard way to turn a Proc into a lambda even if it cannot be achieved through lambda(&proc). I don't know if it will affect the outcome, but jRuby correctly returns a lambda from lambda(&proc) in 1.9 mode.

Updated by mame (Yusuke Endoh) over 11 years ago

  • Status changed from Open to Assigned
  • Assignee set to matz (Yukihiro Matsumoto)
  • Target version set to 2.6

Matz will require a use case, I guess.

--
Yusuke Endoh

Updated by avit (Andrew Vit) about 8 years ago

Use case: a stored block gets called with a "target" as first parameter, plus optional arguments. If the target object is an array, then the behaviour is unpredictable:

lm = lambda { |target, *options| puts target.inspect, options.inspect }
pr = proc   { |target, *options| puts target.inspect, options.inspect }

lm.call([1,2], 'a')  #=> [1, 2], ["a"]
pr.call([1,2], 'a')  #=> [1, 2], ["a"]

lm.call([1,2])  #=> [1, 2], []
pr.call([1,2])  #=> 1, [2]

Note how calling the block with only a single array destructures the "target" argument.
If we need to avoid destructuring, a lambda does the right thing, so converting it would be helpful.

Updated by nobu (Nobuyoshi Nakada) almost 8 years ago

  • Description updated (diff)

Updated by shyouhei (Shyouhei Urabe) almost 8 years ago

We looked at this issue in yesterday's developer meeting.

The use case Andrew showed is (in spite of his intention) not unpredictable. Rather, if we allowed proc->lambda transformation, it gets unpredictable for a proc body what to expect for its first argument.

When writing a proc literal, its programmer's intention is clear that they wanted proc-style behaviour in mind. Currently if a block starts with "lambda {", it behaves like a lambda. All others are proc. This is consistent. But if we introduce proc conversion, this intension breaks. You can't predict what would happen when a proc is actually called during you write that proc; because it can be converted later. This is bad.

Updated by headius (Charles Nutter) almost 8 years ago

Maybe this should warn or error when you attempt to turn a proc into a lambda?

The JRuby behavior is not intentional and we'll align with whatever MRI does. I'd also note that next always exits the block exactly like lambda's return, for all of procs, lambdas, and uncaptured blocks.

Updated by shyouhei (Shyouhei Urabe) almost 8 years ago

Shyouhei Urabe wrote:

Currently if a block starts with "lambda {", it behaves like a lambda. All others are proc.

I have to apology that I forgot about stabby lambdas here. They behave like lamndas too.

Anyways this doesn't change the fact that the way a Proc instance behaves, is statically determined when they are literally written. I think it is a good property. I'd like to +1 to Charles' proposal to add warning when people try converting a proc into lambda.

Actions #9

Updated by shyouhei (Shyouhei Urabe) over 7 years ago

  • Related to Feature #12957: A more OO way to create lambda Procs added
Actions #10

Updated by shyouhei (Shyouhei Urabe) over 4 years ago

  • Related to Feature #15973: Let Kernel#lambda always return a lambda added
Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0