Project

General

Profile

Bug #15285

lambda return behavior regression from #14639

Added by nmueller (Nate Mueller) 14 days ago. Updated about 19 hours ago.

Status:
Open
Priority:
Normal
Assignee:
-
Target version:
-
ruby -v:
ruby 2.5.3p105 (2018-10-18 revision 65156) [x86_64-linux]
[ruby-core:89734]

Description

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.

test.rb (118 Bytes) test.rb nmueller (Nate Mueller), 11/06/2018 09:19 PM
test.rb (828 Bytes) test.rb jhawthorn (John Hawthorn), 11/19/2018 10:41 PM

Related issues

Related to Ruby trunk - Bug #14639: Array#map and lambda arity regressionClosed

History

#1 Updated by shyouhei (Shyouhei Urabe) 13 days ago

  • Related to Bug #14639: Array#map and lambda arity regression added

#2 [ruby-core:89748] Updated by shyouhei (Shyouhei Urabe) 13 days ago

ea15ceddbef2cc4c459c1ad5796e43ae9fa2cbf1 is r64996, which is a backport of r63030, which fixes #14639.

nobu (Nobuyoshi Nakada) any idea?

#3 [ruby-core:89888] Updated by jhawthorn (John Hawthorn) about 19 hours ago

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

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

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.

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.

Also available in: Atom PDF