|
00:27
librasteve_ left
08:04
sourceable6 left,
sourceable6 joined,
Geth left,
notable6 left,
sourceable6 left,
sourceable6 joined,
linkable6 left,
greppable6 left
08:05
greppable6 joined,
linkable6 joined,
notable6 joined
|
|||
| lizmat | m: sub b { Promise.kept.then({ return 42 }).result }; say b # guess this is a DIHWIDT ? | 10:36 | |
| camelia | MoarVM panic: Did not find expected unwind target frame. | ||
| timo | shouldn't cause a panic though | 10:45 | |
| lizmat | I seem to recall this is the type of case that fixing would slow down MoarVM generally quite a bit, no ? | 10:49 | |
| timo | not sure, it should be possible at the location of the error happening we could do a bit of extra work to figure out if it was a critical problem (internal bug or whatever) or if we can just throw an exception telling the user that they did an oopsie | 10:54 | |
| Voldenet | it would be best if blocks could have conditional exception handlers | 10:57 | |
| m: sub b { Promise.kept.then(sub { return 42 }).result }; say b # so the above would turn into something like this | |||
| camelia | Tried to get the result of a broken Promise in sub b at <tmp> line 1 in block <unit> at <tmp> line 1 Original exception: Too many positionals passed; expected 0 arguments but got 1 in sub at <tmp> line 1 |
||
| timo | i think the code that runs a "then" may need to have a handler for "return" control exceptions that reacts in this kind of situation | 11:00 | |
| Voldenet | m: sub b { 42.map({ $^a.return }) }; say b # I bet this may be a bit head-scratching | 11:01 | |
| camelia | Attempt to return outside of immediately-enclosing Routine (i.e. `return` execution is outside the dynamic scope of the Routine where `return` was used) in block <unit> at <tmp> line 1 |
||
| Voldenet | otoh | ||
| hm, nah, I can't think of an example where this exception is useful | 11:02 | ||
| timo | the exception from the last execution you mean? | 11:03 | |
| Voldenet | yes | ||
| timo | i'm not sure how you mean "useful" | 11:04 | |
| Voldenet | I mean, I wonder if the situation where you throw return control exception in a block is useful | ||
| I know there is difference, but I can't think of any useful scenario | 11:05 | ||
| timo | recall that if also works with blocks | ||
| and if you're factoring out some code from a sub and the code you're moving has a return in it, if you use blocks rather than subs for the factored out portion you can return from there instead of having to write `return $_ with mysub()` every time you call it | 11:06 | ||
| Voldenet | ah, right, of course | ||
| timo | if and for and other constructs | ||
| that's i think the primary motivation for blocks being transparent to return control exceptions | 11:07 | ||
| also, early return from a sub that uses map is something that can be useful | |||
| Voldenet | m: sub { 42.map({ return $^x }) }().say; # this doesn't work though | 11:08 | |
| camelia | Attempt to return outside of immediately-enclosing Routine (i.e. `return` execution is outside the dynamic scope of the Routine where `return` was used) in block <unit> at <tmp> line 1 |
||
| Voldenet | iirc it works with CX::Last | 11:10 | |
| timo | yeah, map is lazy | 11:11 | |
| last will make the iterator stop generating new values, which is completely fine to do after the enclosing sub has returned | |||
| Voldenet | m: v6.e.PREVIEW; sub { 42.map({ last $^x }) }().say; # …I don't remember, maybe this | ||
| camelia | Cannot resolve caller last(Int:D); none of these signatures matches: ( --> Nil) (Label:D $x --> Nil) in block <unit> at <tmp> line 1 |
||
| timo | m: sub { 42.map({ return $^x }); say "never reached"; }().say | ||
| camelia | 42 | ||
| Voldenet | (nah, it was for grep) | 11:12 | |
| timo | m: sub { <a b c d e>.map({ last when "c"; $_ }) }().say | ||
| camelia | (a b) | ||
| timo | no last-with-value i guess | 11:13 | |
| Voldenet | i mean the form with "last(Bool)" that tells grep whether to include the value or not | ||
| I confused it with map for some reason | |||
| I get the behavior with early return and it is somewhat understandable | 11:14 | ||
| timo | AFKBBL | 11:15 | |
| Voldenet | m: sub { for 42 { return $^x } }().say; # this is something I fully expect in the context | 11:16 | |
| camelia | 42 | ||
| Voldenet | m: sub { 42.map({ return $^x }); 1 }().say; # having to type in that another statement is a bit odd, still | 11:17 | |
| camelia | 42 | ||
| Voldenet | m: sub { 42.map({ return $^x }); }().say; # otherwise this happen | ||
| camelia | Attempt to return outside of immediately-enclosing Routine (i.e. `return` execution is outside the dynamic scope of the Routine where `return` was used) in block <unit> at <tmp> line 1 |
||
| Voldenet | I'm not very strong in this opinion, but maybe "return inside block" should instead let you do this | 11:18 | |
| m: sub { 42.map({ when 42 { .return }; return 1 }); 1; }().say; # the whole sub returns 42, there's no way to escape the block without additional sub… | 11:21 | ||
| camelia | 42 | ||
| Voldenet | m: sub { 42.map(sub { when 42 { .return }; return 1 }); 1; }().say; # so you need that extra handler | 11:22 | |
| camelia | Too many positionals passed; expected 0 arguments but got 1 in sub at <tmp> line 1 in sub at <tmp> line 1 in block <unit> at <tmp> line 1 |
||
| Voldenet | m: sub { 42.map(sub($) { when 42 { .return }; return 1 }); 1; }().say; # so you need that extra handler | ||
| camelia | ===SORRY!=== Error while compiling <tmp> Unable to parse expression in argument list; couldn't find final ')' (corresponding starter was at line 1) at <tmp>:1 ------> sub { 42.map(sub($)<HERE> { when 42 { .return }; return 1 }); 1; expect… |
||
| Voldenet | m: sub { 42.map(sub ($) { when 42 { .return }; return 1 }); 1; }().say; # so you need that extra handler | ||
| camelia | 1 | ||
| Voldenet | in such cases people use ternary op or pattern matching, but often guard statements are more readable, because they don't introduce additional blocks inside a block | 11:24 | |
| e.g. `return Empty if …;` | 11:25 | ||
| lizmat | m: dd do if 0 { } | 11:27 | |
| camelia | Empty | ||
| lizmat | a failed conditional already returns Empty | ||
| m: dd (^10).map({ $_ if $_ %% 2 }) # which is why this works | 11:28 | ||
| camelia | (0, 2, 4, 6, 8).Seq | ||
| Voldenet | yes but I meant code like this `"{ y: 42 }".map({ return Empty unless my $x = .&json_parse; return Empty unless my $n = $x<y>; $n + 5 }` | 11:31 | |
| I have no strong opinion, because one can simply add that "sub ($_)" inside a map(…) and it solves the problem | 11:32 | ||
| it's not the best example though… `sub { return 42.map({ .&json_parse andthen .<y> andthen * + 5 }) }().say;` | 11:35 | ||
| but still, guard statements are useful for handling exceptional cases in .map | 11:36 | ||
|
12:12
Geth joined
|
|||
| timo | sorry i'm not sure what you mean by "extra handler" there | 14:25 | |
| but the oddness happening with "map" is that when you put it as the last statement, it becomes the return value as a value, and if you don't sink or iterate or otherwise consume it, the code in the block you're mapping onto the sequence doesn't run yet | 14:27 | ||
| it's also a footgun when you return a sequence from a block you are using Lock.protect in; the code lexically inside the lock's protection may actually run later | 14:29 | ||
| a future hypothesized linter, or actually the jetbrains plugin, could point something like that out | 14:32 | ||
| am i correctly picking up what you're putting down? | 14:34 | ||
| Voldenet | I just mentioned that as weird as an aside, but I understand the explanation | 16:07 | |
| but by extra handler I mean that if you want to use map({ return … }) you need to use map(sub ($_) { return … }) | |||
| timo | m: .say for <a b c d e f g>.map({ if $_ eq "c" { leave "leave test" }; $_ ~ "+"; }) | 16:09 | |
| camelia | a+ leave not yet implemented. Sorry. in block <unit> at <tmp> line 1 b+ |
||
| Voldenet | :> | ||
| Yes, it would make sense if leave worked, I guess it's specified well | 16:10 | ||
| not having return is a bit visible in Promise.then and in that case return doesn't even make much sense | 16:18 | ||
| unless it's awaited in the same sub where the block originates from | 16:20 | ||
| e.g. `sub x { await fetch("thing").then(sub ($_) { return 0 if .status ~~ Broken; .result })` | 16:22 | ||
| without `sub ($_)` x could return 0 directly without resolving the promise, but that'd be weird | 16:26 | ||
|
21:00
librasteve_ joined
|
|||