This channel is intended for people just starting with the Raku Programming Language ( Logs are available at
Set by lizmat on 8 June 2022.
00:01 hudo__ joined 00:04 hudo_ left 01:54 guifa_ left
aruniecrisps Is there a way to use with that allows you to check for two variables at once, kind of like: with $maybe-fail-1 -> $x, $maybe-fail-2 -> { } else { } 02:43
antononcube You can use the method defined instead. 03:41
03:46 discord-raku-bot left, discord-raku-bot joined
aruniecrisps yea, i figured the other option was something like if all($maybe-fail-1, $maybe-fail-2).defined { } else { } 03:47
05:22 discord-raku-bot left, discord-raku-bot joined
@SmokeMachine I'm gonna fork the RedJobber repo and play around with it 05:58
09:43 CIAvash joined 10:32 CIAvash left
gfldex m: my $a; my $b; with $a { with $b {;} } 10:47
Raku eval
ab5tract m: my $a = 1; my $b = 0; with so $a & $b { dd $_ } 11:26
camelia Bool::False
ab5tract mostly defeats the utility of `with`, though 11:30
gfldex Indeed, Rakudo can't optimise that. 11:52
librasteve err - I think that this wil work: 15:07
with ($maybe-fail-1 & $maybe-fai-2) { } else { } 15:08
so you use & to make an all junction and then use that as the argument of with ... 15:09
can even go ... 15:12
with $maybe-fail-1 & $maybe-fail-2 { } else { }
16:07 teatime joined
gfldex m: sub prefix:<///>(\RHS) { RHS.defined ?? True !! Any } my @perms = [X] (42, Any).permutations; for @perms -> [$a, $b] { say [$a, $b, do with /// ($a & $b) { 'Amen!'; }]; } 18:30
Raku eval [42 (Any)] [42 42 Amen!] [(Any) (Any)] [(Any) 42]
gfldex Solved, but way to tricky. 18:31
The problem here is that definedness is not an object. Quite in contrast to True-ness.
.oO( This may deserve a blogpost. ) 18:32
librasteve gfldex: I see that you have a solution and I guess that it is better than mine 19:05
BUT ... I get the same output without the fancy '///' operator 19:06
my @perms = [X] (42, Any).permutations; for @perms -> [$a, $b] { say [$a, $b, do with ($a & $b) { 'Amen!'; }]; }
[42 (Any)] [42 42 Amen!] [(Any) (Any)] [(Any) 42]
Please can you elaborate why my proposal fails? 19:07
My proposition is that with ($a & $b) is similar to ($a & $b).defined where ($a & $b) is an all Junction so maybe there's a flaw in that logic?? 19:23
gfldex with cares about definedness, the &-Junction cares and returns about True-ness. There are objects that are defined but False and one can cunstruct an object that is undefined but True (there may be good reason to do so). 19:44
Sadly, it so not trivial to implent custom Junctions or it would be possible to have one that cares about and returns defined-ness (by cheating, because there is no value for definedness). 19:46
In Raku (and AFAIK no other language) we make a clear distinction between true-ness, defined-ness and DEFINITE-ness. The docs are not good at pointing that out. 19:49
Nahita can you given an example? i think with $a & $b works as librasteve mentions. Junction doesn't return a True immediately unless in a boolean context right? And with doesn't immediately impose that but first subjects definedness, which the junction then seems to evaluate as $a.defined && $b.defined: 19:59
m: my $a = 3 but False; my $b = -2; with $a & $b { say "both defined, ok" } else { say "at least one undefined" }
Raku eval both defined, ok
Nahita m: my $a = 3 but False; my $b = Raku; with $a & $b { say "both defined, ok" } else { say "at least one undefined" } 20:00
Raku eval at least one undefined
gfldex m: my $a = True but role :: { method defined { False } }; my $b = Raku; with $a & $b { say "both defined, ok" } else { say "at least one undefined" } 20:01
Raku eval at least one undefined
Nahita not sure I follow. You mean it should look at .DEFINITE or something? In this example, $a.defined is explicitly made False, so it is the expectation that with $a & $b won't pass through? 20:04
gfldex .DEFINITE is not the same as .defined. The latter is a method under the control of the object in question, .DEFINITE is a grammar-level macro (same as .WHAT) and lastly a call into the VM. (In the VM it's just looking at pointer field in a C-struct). 20:08
Nahita yeah I'm familiar they are not the same. I didn't understand your example, so I was mentioning maybe you were alluding to that or something
I still don't see what your example shows and how it disproves with $a & $b is failing 20:09
gfldex I would not trust a Junction and definedness, because a Junctions always returns Bool. 20:10
m: my $a; my $b; my @perms = [X] (42, Any).permutations; sub infix:</&>(\LHS, \RHS) { constant Defined =; LHS.defined && RHS.defined ?? Defined !! Any } for @perms -> [$a, $b] { say [$a, $b, do with $a /& $b { 'Amen!'; }]; }
Raku eval [42 (Any)] [42 42 Amen!] [(Any) (Any)] [(Any) 42]
gfldex I think this is a clear solution. By defining a defined-and infix, we don't need the Junction anymore. 20:11
Maybe //& would be a better name for defined-and. 20:12
Nahita No this is not clear why extra work is a clear solution. If you changed /& to &, you get the same exact output 20:13
gfldex There is no Roast test for combining Junction and with (or I can't find it). So if that works it is a happy coincidence.
Nahita > because a Junctions always returns Bool. only asked in a boolean context, no?
isn't the superposition of many states their thing 20:14
gfldex No, a Junction always returns a Bool.
Read the Rakudo-code, if you don't trust me.
Nahita m: say (12 & 3) + 1
Raku eval all(13, 4)
gfldex Please not that say is (almost) a debugging utility. 20:15
It will go out of it's way to display something gist-ish.
librasteve m: (-1 & 1).sign 20:17
Raku eval
librasteve m: say (-1 & 1).sign
Raku eval all(-1, 1)
librasteve m: say (-1 & 1).defined
Raku eval True
librasteve so I get from this that .defined caused the Junction to collapse and thus rturn a Bool 20:18
so I guess that gfldex is right about the behaviour (even if it's surprising) 20:19
back to the question, how about
[&&] (-1,1)>>.defined
gfldex For methods-calls. you can find the Rakudo code for what happens. Indeed, it calles .defined an each member of the source-Junction and creates a new Junction object with the returned elements as members (and the same Junction-(sub)-type. 20:21
Please note, that Junctions are internal-ish objects and where meant to be highly optimisable. That Rakudo exposes the values may be a mistakes that will bite us in the future. 20:22
Where by "future" is a value within the next 100 years. :)
librasteve so why dont we get ... 20:23
say (-1 & 1).defined; # all(True, True) 20:24
Nahita so I read the source and concluded it doesn't always return a Bool; only if asked to, directly or indirectly. What do I do next...
no! in this case it returns a Bool method !defined-all() { my \eigenstates := $!eigenstates; my int $i = -1; nqp::while( nqp::islt_i(++$i,nqp::elems(eigenstates)) && nqp::atpos(eigenstates,$i).defined, nqp::null ); nqp::hllbool(nqp::iseq_i($i,nqp::elems(eigenstates))) }
no junction is generated in here 20:25
gfldex Please point me at that code.
Nahita so asks truthfulness and collapses a Junction. defined asks for a parallel concept and collapses a junction, so they specifically implemented .defined method, is my theory 20:27
like they implemented .Bool as well
gfldex !defined-all is called by .defined _on_the_new_Junction_object.
Nahita because if they didn't implement a custom .defined, since Junctions don't evaluate to a Boolean but, well, to a Junction type object, it will do all(True, True) 20:28
sorry, what is the "new" Junction object; don't they evaluate to Bool always as you say?
come on...
gfldex lizmat the be precise, see here:
That is an optimisation and may vanish at some point in the future. 20:29
Nahita with all due respect, "a Junction always returns a Bool." is I think wrong and contrasts the whole existence of Junctions, many states bundled together like a cat, only when you ask, they collapse to a Bool. Otherwise, they are a Junction object... 20:31
m: say (3 & -7) ~~ Bool
Raku eval False
gfldex 1 & 2 forms a Junction object. Any operation on that object creates a new Junction object. Unless the compiler cheats. Such cheats are colled "optimisation". Don't rely on them. They are very internal and can change with every new commit. 20:32
Nahita so can you rephrase for me to better understand what you meant by "a Junction always returns a Bool." please? 20:33
gfldex Please consider Roast the definition of the language, not what Rakudo does. And Roast does not know about the optimisation of the .defined-call case. 20:35
librasteve m: say (Any & Any).defined
Raku eval False
Nahita not talking about .defined, though... If anything, it would support your claim of them being Bools 20:37
librasteve ^^^ this is a quandary - it is a Junction object (which is defined), but it collapses to an undefined state ... so you are going to need a special exception to apply .defined to a Junction
Nahita .defined and .Bool are authors way of providing collapsers to user code
librasteve so we all agree that Junction.defined must be a special cased path, right?
Nahita yes they implemented specifically 20:38
otherwise it would defer to casual method call and return a Junction back, all(False, False) for that last example of yours
librasteve so my guess is that eh implementor of this case made it DWIM (ie made the original with ($a & $b) do what I showed initially)
gfldex This is exactly the special case that lizmat cared about. But if you want to use eigenstates; (a module written by lizmat) you get a surprising result, _in_this_special_case. Because after the operation we should get, True, :type<all>). 20:39
The commit message states otherwise. It is clearly an optimisation. 20:40
Nahita you see that prior to that commit, .defined was returning a Bool still, right? 20:41
and even if it didn't, and returned a Junction (of definedness-es), that Junction will be then tested against truthfulness to collapse a Bool, and it would still work the same 20:42
gfldex I consider the with-block working in conjunction with this optimisation a happy-coincidence. It does DWIM. so this might be an ENOROAST.
Nahita Interesting you don't see it as strangely consistent, though... 20:43
specifically overloading .defined is not an optimization though, it's consistent with .Bool collapsing, so .defined also collapses 20:44
the !defined-all et al. are not of interest to us; implementation detail that someone thankfully did to make it faster
and to repeat, even if they didn't overload .defined, it would return a Junction as yet another casual method call 20:45
librasteve if you are happy with the behaviour of Junction.defined (with and without the optimization), then there is no happy conincidence other than with effectively applies .defined to it's argument
Nahita that Junction would be then collapsed to produce a Bool because that's what with eventually wants being a synonym to if ...defined 20:46
then the observable behaviour here and then would be the same!
librasteve so why not say this is suprisingly consistent and add this test to ROAST
gfldex We may have to do so or use v6.e; may cause more surprises that we would like to. 20:48
However, I'm not sure if a with-block or with-statement makes sense with a Junction. The current behaviour may give the right answer to the wrong question. It feels like a design smell and those tend to hurt in the long run. 20:50
Also, can somebody please add "Sprachgefühl" to the English language. You did steal "schadenfreude" and "zeitgeist" after all. 20:51
librasteve it's certainly fairly "out there" in terms of when you would want it
The first known use of sprachgefühl was in 1894 20:54ühl
just use it!
gfldex Thank you very much indeed!
librasteve (but no capitals and expect everyone to wtf) 20:55
what is the inverse of Sprachgefuehl? 20:56
(in the sense of code smell == poor sprachgefuhl) 20:57
gfldex m: my \a = (42 & 42).defined; dd a; my \b = (42 & 42).Str; dd b; 21:01
Raku eval Bool::True all("42", "42")
gfldex @Nahita Does this ^^^ look consistent to you? 21:02
Nahita yes, as I mentioned, they specifically overloaded .Bool and .defined for us users to collapse the Junctions to Booleans
to work with if and with smoothly
gfldex lizmat: Do you got an opinion on that last example? 21:03
Nahita which it turns out they do very smoothly, as the best answer so far to arun's question was by librasteve and it was with $a & $b
highly readable too
still you didn't answer this, but of course you don't have to... 21:05
gfldex Do you know about the module called eigenstates? 21:06
Nahita exposes the bundled private states of a junction? yes if so 21:07
gfldex Good, you can go a step deeper and do funky stuff with the module. It allows to avoid loops (because that loop is hidden in Junction.rakumod). But that requires the result-Junction to acutally be a Junction. If there is a .defined call in the loop (that can be fairly well hidden, Raku is a functionally-ish language) that will fail. 21:10
This may be the reason why my sprachgefühl is complaining.
This discussion is getting dangerous! I almost crashed my spaceship into a spacestation. :) 21:12
librasteve even the author of eigenstates says we should never use it and that Junctions are a black box 21:13
gfldex here is an example how to (ab)use eigenstates:
librasteve surely the bahaviour of Junctions under a method call is do the call on each member and return a Junction of results (unless it special cased) 21:15
and we all agree that Junction.defined is a special case
gfldex I would support a no-use-nqp-policy of Raku modules. Sadly, that trains has been gone for quite a while now. 21:16
librasteve I do not support a language design policy based on the idea that someone may use eigenstates (there are many health warnings on this module and reliance on such implementation details is a known risk) 21:17
gfldex I do agree that it is a special case. I don't agree it is so for DWIMing. It looks like an optimisation-by-hand. 21:18
librasteve anyway I am keen to hear what lizmat thinks ... since she wrote the code ;-) 21:19
gfldex m: with True && False { say ‘oi‽’ } 21:26
Raku eval oi‽
gfldex Actually, this may be the reason why my sprachgefühl complains so hard.
librasteve & not && 21:27
m: with False {say 'yo'} 21:28
Raku eval yo
lizmat could someone gist me what I should have an opinion about?
gfldex lizmat: 21:29
librasteve m: say "yo" with 1 & Any; 21:30
Raku eval
librasteve m: with 1 & Any {say 'yo'}
Raku eval
librasteve m: with Any & Any {say 'yo'} 21:31
Raku eval
librasteve m: with 1 & 1 {say 'yo'}
Raku eval yo
librasteve ^^ is it supported to use with with a Junction to check that all arguments are .defined?
lizmat so the question is: should Junction.defined return a Junction or a Bool ? 21:32
librasteve no, more like "can with take a Junction a argument" 21:33
aruniecrisps it ultimately spawned from my question on how you would go about assigning multiple variables in a with statement 21:34
lizmat also: I did do but didn't change any semantics
so don't ask me why Junction.defined doesn't return a Junction ;-) 21:35
librasteve here's a longer example (from above)... 21:36
lakmatiol the docs tell me this
.oO(We need to blame deeper!)
librasteve my @perms = [X] (42, Any).permutations; for @perms -> [$a, $b] { say [$a, $b, do with ($a & $b) { 'Amen!'; }]; } 21:37
[42 (Any)] [42 42 Amen!] [(Any) (Any)] [(Any) 42]
gfldex I think I found it. 21:38
librasteve the question is - can a Junction be used reliably as the argument of a with ? (ie can this behaviour be relied on)
lakmatiol if with is specified to call .defined, then it should work fine if .defined works as it says so in the docs for Junction.defined 21:39
librasteve yes, that's the question 21:40
gfldex :D So we conclude: Zoffix just changed he behaviour without any further discussion.
aruniecrisps the question i'm assuming is whether Junction.defined as it is now, is gonna remain that way reliably 21:41
gfldex I don't miss that guy. :)
lizmat A Raku "with" codegens to an nqp::with, and that is documented as: 21:42
gfldex "evaluates to a defined value" is not exactly an explanation what happens. Because Raku does not have a value for defined-ness. 21:43
My guess would be: If it is a native-type, cheat. Otherwise call `.defined`. 21:44
lizmat % nqp -e 'nqp::with(42,nqp::say("foo"))' 21:45
Cannot find method 'defined' on object of type BOOTInt
looks like it tries to execute a .defined
so the doc could be clearer on that 21:46
s/evaluates to a defined value/calls the .defined method/ 21:47
m: class A { method defined(--> False) { } }; with { say "foo" }
camelia ( no output )
gfldex lizmat: does that mean that MoarVM could cheat for BOOTInt (lest there is a mixin)?
21:48 MasterDuke joined
lizmat from Raku, you shouldn't be able to reach the BootInt normally, it would always be boxed 21:48
m: say 42.^find_method("defined").file 21:49
camelia SETTING::src/core.c/Mu.rakumod
lizmat so no cheating is needed 21:50
librasteve ok, so I take it that we can have confidence in: 21:53
with $a & $b {say 'yo'}
lizmat m: with 42 & 666 { say "foo" } 21:54
camelia foo
lizmat m: say "foo" with 42 & 666
camelia foo
librasteve thanks all 21:55
aruniecrisps Is there a way to automatically restart a Cro server when I make changes to the code or no? 22:02
lizmat not sure, maybe ask on #cro ? 22:04
librasteve The cro run command is used to run services. It automatically sets up file watching and restarts services when there are source changes to the services 22:05
aruniecrisps gotcha thanks! 22:06
gfldex Issue issued as: 22:11
aruniecrisps Okay there is one thing I'm not the biggest fan of right now, and it's the install times for Cro 22:22
lizmat you can try installing with --/test 22:23
aruniecrisps Good catch, that's what I was doing wrong, thanks!
lizmat the Cro test suite is pretty elaborate 22:24
aruniecrisps Yea I noticed, looks pretty battle tested as well 22:26
22:53 sivoais left
I'm running into this error when setting up HTTP 2.0 with Cro: 22:56
23:06 sivoais joined 23:11 teatime left, teatime joined