|
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
|
|||
| [Coke] | I thought dd would give me more detail, and say would give me a gist. | 02:25 | |
| just my initial feeling. | 02:26 | ||
|
02:29
finanalyst left
02:55
finanalyst joined
02:58
guifa joined
03:00
finanalyst left,
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
|
|||
| 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 | |
| m: my $x = 42; sub modify() { for 1 { (4,5,6).map({$x += $_}) } }; say $x; modify(); say $x | |||
| camelia | 42 42 |
||
| 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 | ||
| camelia | 42 57 |
||
| 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 | 42 (Debug: 57) 57 |
||
| 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 | |
| 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
|
|||
| SmokeMachine | m: my @a := ^10 .map: { .say }; say “after”; .say for @a | 11:24 | |
| camelia | 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 |
||
| SmokeMachine | m: my $a = ^10 .map: { .say }; say “after”; .say for @$a | 11:25 | |
| camelia | after 0 True 1 True 2 True 3 True 4 True 5 True 6 True 7 True 8 True 9 True |
||
| lizmat | ShimmerFairy: the problem is really that the last statement in a scope is not sunk | ||
| 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:26 | |
| lizmat | m: class A { method sink() { say "sunk" } }; sub a() { A }; a' | 11:27 | |
| camelia | ===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… |
||
| lizmat | m: class A { method sink() { say "sunk" } }; sub a() { A }; a | ||
| camelia | ( no output ) | ||
| 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) | ||
| m: my $x = 42; sub modify() { (4,5,6).map({$x += $_}) }; say $x; modify(); say $x | |||
| camelia | 42 57 |
||
| SmokeMachine | m: my $x = 42; sub modify() { (4,5,6).map({$x += $_}) }; say $x; my $a = modify(); say $x | 11:28 | |
| camelia | 42 42 |
||
| 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… | ||
| 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:31 | |
| lizmat | a .map produces a Seq: that doesn't do anything by itself | 11:32 | |
| SmokeMachine | Because it returns | 11:33 | |
| m: Seq.^find_method("sink").wrap: -> | { say "sunk"; callsame }; my $x = 42; sub a { ^10 .map: { $x += $_ } }; a; say $x | |||
| camelia | sunk 87 |
||
| lizmat | a for loop gets something Iterable and a block, and calls the block for each value the iterator of the Iterable produces | ||
| 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 | 42 | ||
| SmokeMachine | See? No “sunk” | ||
| ShimmerFairy | m: sub foo() { for 1,2,3 { $_ } }; say foo() | 11:35 | |
| camelia | Nil | ||
| 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? | ||
| lizmat | produces a Seq that doesn't get iterated | ||
| m: my $a = (1,2,3).map(*.say); $a = 42 | 11:36 | ||
| camelia | ( no output ) | ||
| SmokeMachine | Yeah… maybe a for loop (with no `do`) should sink? | ||
| 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:39 | |
| I did make an issue for it, btw, where I was able to simplify the example a bit further: github.com/rakudo/rakudo/issues/6912 | 11:40 | ||
| lizmat | one should really be aware that .map just produces a Seq | ||
| and that it doesn't run by itself | 11:41 | ||
| 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 | ||
| 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 | ||
| camelia | 42 | ||
| SmokeMachine | But inside a for (with no `do`) it’s not returned… | 11:43 | |
| 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 | |||
| camelia | sunk 87 |
||
| lizmat | and "for 1,2,3 { foo }" is basically (1,2,3).map({ foo }).sink under the hood | ||
| m: my $a = (1,2,3).map(*.say); $a.sink | 11:44 | ||
| camelia | 1 2 3 |
||
| lizmat | m: my $a = (1,2,3).map(*.say); say "Seq made"; $a.sink | ||
| camelia | Seq made 1 2 3 |
||
| SmokeMachine | But it seems for is not calling that .sink at the end, is it? | ||
| lizmat | the for is basically calling the .sink on the Seq that the .map creates | 11:45 | |
| ShimmerFairy | but then why is it *not* doing what Seq sinking does when that for loop is the last statement of a subroutine? | 11:48 | |
| SmokeMachine | If it were calling sink, a and b here should behave the same, no? | 11:50 | |
| 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 | |||
| camelia | calling a: calling b: sunk |
||
| 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:51 | |
| 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 | outer outer outer |
||
| lizmat | github.com/rakudo/rakudo/issues/1571 | 11:53 | |
| SmokeMachine | m: (1,2,3).map({say "outer"; (4,5,6).map({say "inner"}).sink }) | 11:54 | |
| camelia | outer inner inner inner outer inner inner inner outer inner inner inner |
||