[00:21] *** finanalyst joined
[00:26] *** finanalyst left
[00:52] *** finanalyst joined
[00:56] *** finanalyst left
[01:23] *** finanalyst joined
[01:27] *** finanalyst left
[02:24] *** finanalyst joined
[02:25] <[Coke]> I thought dd would give me more detail, and say would give me a gist.

[02:26] <[Coke]> just my initial feeling.

[02:29] *** finanalyst left
[02:55] *** finanalyst joined
[02:58] *** guifa joined
[03:00] *** finanalyst left
[03:00] *** guifa left
[03:26] *** finanalyst joined
[03:30] *** finanalyst left
[03:56] *** finanalyst joined
[04:01] *** finanalyst left
[04:27] *** finanalyst joined
[04:32] *** finanalyst left
[04:58] *** finanalyst joined
[05:03] *** finanalyst left
[05:29] *** finanalyst joined
[05:33] *** finanalyst left
[06:00] *** finanalyst joined
[06:04] *** finanalyst left
[06:30] *** finanalyst joined
[06:35] *** finanalyst left
[07:01] *** finanalyst joined
[07:05] *** finanalyst left
[07:32] *** finanalyst joined
[07:36] *** finanalyst left
[08:03] *** finanalyst joined
[08:07] *** finanalyst left
[08:33] *** finanalyst joined
[08:38] *** finanalyst left
[08:49] <ShimmerFairy> Found an absolutely wild bug today in rakudo (or at least what looks like one). Basically, a .map inside a for loop inside a subroutine call can't modify outside-context variables (originally, a dynvar) without doing something inside the sub to force it.

[08:49] <ShimmerFairy> m: my $x = 42; sub modify() { for 1 { (4,5,6).map({$x += $_}) } }; say $x; modify(); say $x

[08:49] <camelia> rakudo-moar e17a1d43b: OUTPUT: «42␤42␤»

[08:49] <ShimmerFairy> m: my $x = 42; sub modify() { for 1 { (4,5,6).map({$x += $_}).eager } }; say $x; modify(); say $x # using .eager makes it work

[08:49] <camelia> rakudo-moar e17a1d43b: OUTPUT: «42␤57␤»

[08:50] <ShimmerFairy> m: my $x = 42; sub modify() { for 1 { (4,5,6).map({$x += $_}) }; say "(Debug: $x)" }; say $x; modify(); say $x # using debug prints to diagnose the issue also makes it work

[08:50] <camelia> rakudo-moar e17a1d43b: OUTPUT: «42␤(Debug: 57)␤57␤»

[08:51] <ShimmerFairy> I've tried a number of variations that all avoid the issue, whether it's using a second loop instead of a map, or using a 'repeat while False' loop instead of a for loop. There seems to be a very narrow window where the bug appears.

[08:51] <ShimmerFairy> Of course I'll file a bug for this, just had to mention it here first.

[09:57] *** finanalyst joined
[10:43] *** [Tux] left
[10:48] *** [Tux] joined
[11:15] *** finanalyst left
[11:24] <SmokeMachine> m: my @a := ^10 .map: { .say }; say “after”; .say for @a

[11:24] <camelia> rakudo-moar e17a1d43b: OUTPUT: «0␤Type check failed in binding; expected Positional but got Seq ((Bool::True, Bool::T...)␤  in block <unit> at <tmp> line 1␤␤1␤2␤3␤4␤5␤6␤7␤8␤9␤»

[11:25] <SmokeMachine> m: my $a = ^10 .map: { .say }; say “after”; .say for @$a

[11:25] <camelia> rakudo-moar e17a1d43b: OUTPUT: «after␤0␤True␤1␤True␤2␤True␤3␤True␤4␤True␤5␤True␤6␤True␤7␤True␤8␤True␤9␤True␤»

[11:25] <lizmat> ShimmerFairy: the problem is really that the last statement in a scope is not sunk

[11:26] <SmokeMachine> ShimmerFairy: I don’t think that’s a big… but Seqs are lazy… so it will only run when you try to get the data

[11:27] <lizmat> m: class A { method sink() { say "sunk" } }; sub a() { A }; a'

[11:27] <camelia> rakudo-moar e17a1d43b: OUTPUT: «===SORRY!=== Error while compiling <tmp>␤Two terms in a row␤at <tmp>:1␤------> ink() { say "sunk" } }; sub a() { A }; a<HERE>'␤    expecting any of:␤        infix␤        infix stopper␤        statement end␤        statement modifier…»

[11:27] <lizmat> m: class A { method sink() { say "sunk" } }; sub a() { A }; a

[11:27] <camelia> rakudo-moar e17a1d43b: ( no output )

[11:27] <ShimmerFairy> I'd still call it a bug, because it does work in some contexts (like if the map is in a subroutine all on its own)

[11:27] <ShimmerFairy> m: my $x = 42; sub modify() { (4,5,6).map({$x += $_}) }; say $x; modify(); say $x

[11:27] <camelia> rakudo-moar e17a1d43b: OUTPUT: «42␤57␤»

[11:28] <SmokeMachine> m: my $x = 42; sub modify() { (4,5,6).map({$x += $_}) }; say $x; my $a = modify(); say $x

[11:28] <camelia> rakudo-moar e17a1d43b: OUTPUT: «42␤42␤»

[11:29] <lizmat> in any case, I vaguely recall this being reported ~ 8 years ago (I think even by me) and that jnthn had some explanation for it

[11:29] <SmokeMachine> Your worked because the Seq was sunk, so it ran…

[11:31] <ShimmerFairy> OK, so why does the last statement of the for loop not sink? for loops don't appear to return the value of their last statement, so it can't be for that (and even then, I'd expect it to ultimately sink when the calling function does nothing with the value)

[11:32] <lizmat> a .map produces a Seq: that doesn't do anything by itself

[11:33] <SmokeMachine> Because it returns

[11:33] <SmokeMachine> m: Seq.^find_method("sink").wrap: -> | { say "sunk"; callsame }; my $x = 42; sub a { ^10 .map: { $x += $_ } }; a; say $x

[11:33] <camelia> rakudo-moar e17a1d43b: OUTPUT: «sunk␤87␤»

[11:33] <lizmat> a for loop gets something Iterable and a block, and calls the block for each value the iterator of the Iterable produces

[11:34] <SmokeMachine> Seq.^find_method("sink").wrap: -> | { say "sunk"; callsame }; my $x = 42; sub a { ^10 .map: { $x += $_ } }; my $a = a; say $x

[11:34] <evalable6> SmokeMachine, rakudo-moar f571d2fa2: OUTPUT: «42␤»

[11:34] <SmokeMachine> See? No “sunk”

[11:35] <ShimmerFairy> m: sub foo() { for 1,2,3 { $_ } }; say foo()

[11:35] <camelia> rakudo-moar e17a1d43b: OUTPUT: «Nil␤»

[11:35] <ShimmerFairy> If the for loop isn't sinking the last value, and it also isn't returning it up to the outer block, then what exactly is it doing?

[11:35] <lizmat> produces a Seq that doesn't get iterated

[11:36] <lizmat> m: my $a = (1,2,3).map(*.say); $a = 42

[11:36] <camelia> rakudo-moar e17a1d43b: ( no output )

[11:36] <SmokeMachine> Yeah… maybe a for loop (with no `do`) should sink?

[11:39] <ShimmerFairy> You could argue that it was wrong of me to use .map when I wasn't trying to produce a list of transformed values (and instead just using it as a compact way of writing a for loop), but I still think there's something inconsistent and surprising here.

[11:40] <ShimmerFairy> I did make an issue for it, btw, where I was able to simplify the example a bit further: https://github.com/rakudo/rakudo/issues/6912

[11:40] <lizmat> one should really be aware that .map just produces a Seq

[11:41] <lizmat> and that it doesn't run by itself

[11:42] <SmokeMachine> I think the problem here is not map, but the last statement of a for block not sinking…

[11:42] <lizmat> well, the statement of a block cannot be sunk because it can be returned

[11:42] <SmokeMachine> m: Seq.^find_method("sink").wrap: -> | { say "sunk"; callsame }; my $x = 42; sub a { for 1 { ^10 .map: { $x += $_ } } }; a; say $x # this does not sink

[11:42] <camelia> rakudo-moar e17a1d43b: OUTPUT: «42␤»

[11:43] <SmokeMachine> But inside a for (with no `do`) it’s not returned…

[11:43] <SmokeMachine> m: Seq.^find_method("sink").wrap: -> | { say "sunk"; callsame }; my $x = 42; sub a { for 1 { ^10 .map: { $x += $_ }; 42 } }; a; say $x # this sinks

[11:43] <camelia> rakudo-moar e17a1d43b: OUTPUT: «sunk␤87␤»

[11:43] <lizmat> and "for 1,2,3 { foo }"  is basically   (1,2,3).map({ foo }).sink   under the hood

[11:44] <lizmat> m: my $a = (1,2,3).map(*.say); $a.sink

[11:44] <camelia> rakudo-moar e17a1d43b: OUTPUT: «1␤2␤3␤»

[11:44] <lizmat> m: my $a = (1,2,3).map(*.say); say "Seq made"; $a.sink

[11:44] <camelia> rakudo-moar e17a1d43b: OUTPUT: «Seq made␤1␤2␤3␤»

[11:44] <SmokeMachine> But it seems for is not calling that .sink at the end, is it?

[11:45] <lizmat> the for is basically calling the .sink on the Seq that the .map creates

[11:48] <ShimmerFairy> but then why is it *not* doing what Seq sinking does when that for loop is the last statement of a subroutine?

[11:50] <SmokeMachine> If it were calling sink, a and b here should behave the same, no?

[11:50] <SmokeMachine> m: Seq.^find_method("sink").wrap: -> | { say "sunk"; callsame }; my $x = 42; sub a { for 1 { ^10 .map: { $x += $_ } } }; sub b { (1).map({ ^10 .map: { $x += $_ } }).sink }; say "calling a: "; $ = a; say "calling b: "; $ = b

[11:50] <camelia> rakudo-moar e17a1d43b: OUTPUT: «calling a: ␤calling b: ␤sunk␤»

[11:51] <ShimmerFairy> I just don't see the justification for the current behavior. It doesn't sink, and the for loop doesn't "return" anything either, so what is this secret third thing where it disappears entirely?

[11:52] <ShimmerFairy> m: (1,2,3).map({say "outer"; (4,5,6).map({say "inner"})})  # as in my bug report, you also see this with nested maps

[11:52] <camelia> rakudo-moar e17a1d43b: OUTPUT: «outer␤outer␤outer␤»

[11:53] <lizmat> https://github.com/rakudo/rakudo/issues/1571

[11:54] <SmokeMachine> m: (1,2,3).map({say "outer"; (4,5,6).map({say "inner"}).sink })

[11:54] <camelia> rakudo-moar e17a1d43b: OUTPUT: «outer␤inner␤inner␤inner␤outer␤inner␤inner␤inner␤outer␤inner␤inner␤inner␤»

