[ruby-core:89888] [Ruby trunk Bug#15285] lambda return behavior regression from #14639

From: john.hawthorn@...
Date: 2018-11-19 22:41:35 UTC
List: ruby-core #89888
Issue #15285 has been updated by jhawthorn (John Hawthorn).

File test.rb added

I also ran into this problem in ruby 2.5.3.

This is a little confusing because there are two things being changed here:
1. How arguments are handled in a passed &lambda, which was asked for in #14639
2. How return is handled in a passed &lambda

I attached a test script to help demonstrate

In ruby 2.3, the passed lambda will **always** splat the arguments (the lambda treats arguments like a block), but return only returns from the lambda

~~~ text
2.3.7
Array#map
  args    ✅
  return  ✅ lambda return semantics
Enumerable#map
  args    ✅
  return  ✅ lambda return semantics
Array#each
  args    ✅
  return  ✅ lambda return semantics
Array#map!
  args    ✅
  return  ✅ lambda return semantics
~~~



In ruby 2.4, the passed lambda now treats arguments like a normal lambda (it won't splat them). I think this is a good change (but that could be a debate). This is the complaint in #14639

~~~ text
2.4.4
Array#map
  args    💣 wrong number of arguments (given 1, expected 2)
  return  ✅ lambda return semantics
Enumerable#map
  args    💣 wrong number of arguments (given 1, expected 2)
  return  ✅ lambda return semantics
Array#each
  args    💣 wrong number of arguments (given 1, expected 2)
  return  ✅ lambda return semantics
Array#map!
  args    💣 wrong number of arguments (given 1, expected 2)
  return  ✅ lambda return semantics
~~~

In ruby 2.5.3 and in 2.6.0-preview3, `Array#map` was changed to always treat the passed lambda as a block. This changed both how it treats arguments (the desired change) and how it treats return (this bug).

In addition, it only made this change to `Array#map` aka `Array#collect`, which now doesn't match similar methods like `Enumerable#map` or `Array#each` or `Array#map!`. It's also a weird behaviour to have since it would be hard to write a custom `MyClass#map` in ruby which behaved the same way.

~~~ text
2.6.0
Array#map
  args    ✅
  return  ❌ block return semantics
Enumerable#map
  args    💣 wrong number of arguments (given 1, expected 2)
  return  ✅ lambda return semantics
Array#each
  args    💣 wrong number of arguments (given 1, expected 2)
  return  ✅ lambda return semantics
Array#map!
  args    💣 wrong number of arguments (given 1, expected 2)
  return  ✅ lambda return semantics
~~~


I think both r64996 (for 2.5.x) and r63030 should be reverted.


----------------------------------------
Bug #15285: lambda return behavior regression from #14639
https://bugs.ruby-lang.org/issues/15285#change-74961

* Author: nmueller (Nate Mueller)
* Status: Open
* Priority: Normal
* Assignee: 
* Target version: 
* ruby -v: ruby 2.5.3p105 (2018-10-18 revision 65156) [x86_64-linux]
* Backport: 2.3: UNKNOWN, 2.4: UNKNOWN, 2.5: UNKNOWN
----------------------------------------
The change in ea15ceddbef2cc4c459c1ad5796e43ae9fa2cbf1 to use rb_yield_force_blockarg changes the behavior of returns called inside a passed lambda function.  In 2.5.1 and below, including before the enum.c change, the attached script would print `true`.  In 2.5.3 it prints `false`.

---Files--------------------------------
test.rb (118 Bytes)
test.rb (828 Bytes)


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

Unsubscribe: <mailto:ruby-core-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>

In This Thread

Prev Next