This channel is intended for people just starting with the Raku Programming Language (raku.org). Logs are available at irclogs.raku.org/raku-beginner/live.html
Set by lizmat on 8 June 2022.
00:44 archenoth left 01:17 frost joined 01:46 chikega joined
chikega Hi everyone, are there any video tutorials about learning the Raku language? 01:47
01:51 chikega left 02:46 jetchisel left 02:49 jetchisel joined 03:06 MasterDuke left 03:09 razetime joined 03:27 razetime left 04:06 razetime joined 08:03 razetime left 08:20 razetime joined 08:34 frost left
lizmat there are: www.youtube.com/results?search_que...23rakulang is a good starting point ? 08:44
09:00 crystalfrost[m] left
Nemokosch Do you think a tematic Raku series would help? I used to love making tutorial series 09:00
09:00 crystalfrost[m] joined, crystalfrost[m] left
lizmat I think it would, if you feel up to it :) 09:04
Nemokosch The main question is if I should try to aim for a "first language" approach or an "nth language" assumption will do 09:06
lizmat fwiw, personally I would love to see a "first language" approach, because there are quite a few tutorials already coming from other languages 09:07
09:31 razetime left, razetime_ joined
zacque Why is my `@pascal` has different values from calling the `pascal-sequence` directly? paste.debian.net/1255512/ 09:41
What's going on with the assignment?
gfldex <@511826957558611968> you don't reset @k and the result-array @pascal contains referenced to @k. So the last change to @k will end up x times in @pascal. 09:46
m:``` 09:50
sub pascal-sequence(Int:D $number) {
my @k;
gather {
for 1..$number {
@k = 1, | @k >>+>> (| @k[1..*], 0);
take @k.clone;
}
}
}
sub MAIN(Int:D $rows where $rows >= 3) {
my @pascal = (pascal-sequence $rows);
say @pascal; # OUTPUT: [[1 4 6 4 1] [1 4 6 4 1] [1 4 6 4 1] [1 4 6 4 1] [1 4 6 4 1]]
say (pascal-sequence $rows); # OUTPUT: ([1] [1 1] [1 2 1] [1 3 3 1] [1 4 6 4 1])
}
MAIN(5);
```
m:```
sub pascal-sequence(Int:D $number) {
my @k;
gather {
for 1..$number {
@k = 1, | @k >>+>> (| @k[1..*], 0);
take @k.clone;
} 09:51
}
}
sub AIN(Int:D $rows where $rows >= 3) {
my @pascal = (pascal-sequence $rows);
say @pascal; # OUTPUT: [[1 4 6 4 1] [1 4 6 4 1] [1 4 6 4 1] [1 4 6 4 1] [1 4 6 4 1]]
say (pascal-sequence $rows); # OUTPUT: ([1] [1 1] [1 2 1] [1 3 3 1] [1 4 6 4 1])
}
AIN(5);
```
I got the feeling that there is a sequence operator waiting to be used for this problem. :) 09:52
zacque Hmm, I don't get it, but `say (pascal-sequence $rows);` does give the correct result? 09:53
I hope it does! ๐Ÿ˜„ 09:54
Nemokosch it is seriously weird that one works and the other doesn't
but what you are doing was clearly a bad idea 09:55
ie modifying it in-place and taking it multiple times 09:56
actually, I have an idea why it's so weird
@vars are eager by default
so it fetched your whole sequence, and the inner list reached the last element
so you got the last element multiple times
on the other hand, the sequence was lazy so the mutation happened on the fly, giving the correct results
if my hypothesis is correct, it would work correctly with ` my @pascal = lazy (pascal-sequence $rows);` 09:57
zacque Ok, so `take` always return a reference to the variable? 10:16
I don't see how lazy and eager play a role here, because it doesn't say that `gather/take` is always lazy 10:17
Putting `lazy` in front of `pascal-sequence` doesn't help either 10:18
Nemokosch pretty much everything is always lazy
it would be easier to collect the counterexamples
zacque Oh, that's new to me. But I don't see it stated in the docs =X 10:19
Hmmm, I mean why do you say that everything is always lazy? 10:21
Nemokosch ~~because it's quite accurate~~
it's a general design principle that everything that can return Seq over List, will return Seq over List
X, Z, map, grep, in fact gather and take is rather obvious in this list
because it's like the Raku version of generators and generators are lazy by concept 10:23
zacque Huh? But Seq is only potentially lazy, from the doc "class Seq: An iterable, potentially lazy sequence of values"
I guess it meant that some functions taking Seq should be able to handle lazy list?
Nemokosch I'd say there is no big difference between "lazy" and "potentially lazy" 10:24
the implications come with the potential 10:25
it's rather a semantic argument, if we mean "lazy" as implementation or "lazy" as interface
"potentially lazy" is about the interface
zacque I don't think it matters if that's an implementation detail
Nemokosch you shall not assume that it's not lazy
zacque From the user perspective, I guess I can safely assume all are not lazy unless declared otherwise?
Nemokosch it's rather the opposite 10:27
zacque I meant if I work with the built-in lists and operators
Nemokosch yeah no
almost everything is "potentially lazy", unless you ask otherwise
zacque Hmmm, okay, I'll keep it in mind while learning more about Raku
Thanks
Nemokosch this is really good when working with loads (potentially infinite) of data
zacque But in the case, I think the laziness doesn't matter? Cause I've put `lazy` keyword and it gives the same result 10:28
Yup, agree 10:29
Nemokosch for me it didn't
zacque Huh? Can you elaborate further? You've got a different result with `lazy`?
gfldex m:```
my \pascal = (1,), (1,1), -> @a { 1, |(@a ยซ+ยป (|@a[1..*], 0)) } โ€ฆ *;
say pascal[^10];
```
Nemokosch yep 10:30
I did this 10:31
zacque Ah, I see. Thanks for showing your code
Mine still not working even with `lazy`. paste.debian.net/1255516/
Guess I should use your approach 10:32
Nemokosch [^4] seems to be too eager 10:33
zacque I think it works with `@pascal` as well, is there a specific reason that you use `\pascal`?
What do you mean?
Nemokosch tbh I don't know how to properly use this lazy mess but if you iterate it, you can see the results popping out one after the other 10:34
I replaced your @pascal[^4] line to 10:35
```perl
.say for @pascal;
```
and then the right results were indeed popping out
zacque Yes indeed, together with the `lazy` keyword 10:37
Nemokosch yep
docs.raku.org/language/list#index-...le_objects I'm reading this rn
zacque Hmmm, that's so confusing right now 10:38
I don't think it helps? 10:39
Nemokosch not detailed enough...
right
There is one thing I feel we need to know
zacque What's it?
Nemokosch are the elements of the lazy list still the very same element multiple times, or not
because if they are, it's inevitable that once we fetch more at once, it will always have the same value 10:40
zacque I guess it is the same variable? If not, it won't be lazy ๐Ÿ˜‚ 10:41
gfldex `lazy` sneaks another `Seq` in that decontainerises the values in `@k`. When assigned to the Array, fresh containers are being filled with values.
Nemokosch <@511826957558611968>
```perl 10:42
my @pascal = lazy (pascal-sequence $rows);
say @pascal[0];
say @pascal[0].WHERE;
say @pascal[1];
say @pascal[1].WHERE;
say (pascal-sequence $rows); # OUTPUT: ([1] [1 1] [1 2 1] [1 3 3 1] [1 4 6 4 1])
```
so yes
it's the very same variable retrieved in multiple states 10:43
okay, now, this makes it fairly obvious why retrieving a part of the list will contain the same value
as gfldex pointed out with his very first code example (calling .clone), your array doesn't have copies 10:44
it has the same variable over and over
zacque Can I know why does it matter? 10:45
This is a bit over my head right now
I see, didn't know about `WHERE` before this
Let me see what if without the `lazy` keyword?
Nemokosch it will be the same pretty sure, except the values will match 10:46
gfldex `return @k` doesn't return the values in `@k` but `@k` itself. You keep overwriting the values in `@k`, so you end up with the values of the very last overwriting. 10:47
Nemokosch okay, thankfully we are saying the same thing with different words
zacque Okay, I see, I've tried it out myself
Nemokosch so you don't have to understand two things at once but one thing twice ๐Ÿ˜„
zacque Okay, so `take @k` here behaves similarly to `return @k`? 10:48
Does it apply to all container variables? Or is it a special case? 10:49
So, when I'm passing a `@var` around, I'm passing the reference around?
Kaiepi `take` behaves like `return` wrt containers
Nemokosch From what I know, something that has an Array _container_ (like @-sigilled vars by default), cannot just drop that container 10:50
gfldex `take @k[]:v;` works too and might be faster as a `.clone`. The zen slice with `:v` also removes any holes.
Nemokosch I noticed a gotcha 10:52
m: my @k = <blah foo bar>; @k =:= @k[]:v andthen .say;
weird parsing as I clearly meant (@k[]:v)
my @k = <blah foo bar>; @k =:= (@k[]:v) andthen .say; 10:53
<@511826957558611968> =:= will be useful, trust me 10:54
it's the container equivalence
zacque I'll pass `:v` for now, thanks you for your time and effort ๐Ÿ˜„
It looks weird... ๐Ÿ˜„
Nemokosch ie "are these two things the same one thing"
m: my @k = <blah foo bar>; @k =:= (@k[]:v) andthen .say;
no, they aren't - thank heavens, in this case
zacque Ah, it's the container identity operator, so it checks whether two "references" are equal 10:56
Nemokosch yes, basically
zacque I don't think it helps in this case either
But glad to learn about it
Nemokosch it helps to know if you have the "same variable" over and over
let me take your original code again
zacque How is `=:=` different from `===` wrt container? Some experiment shows that they are the same? See: 10:58
```raku
[0] > (1,2,3) =:= (1,2,3)
False
[1] > (1,2,3) === (1,2,3)
False
[2] > my @foo = (1,2,3);
[1 2 3]
[3] > @foo =:= @foo
True
[4] > @foo === @foo
True
[5] > @foo === (1,2,3)
False
```
Nemokosch the difference is that === says true if you drop the container on one side 10:59
while =:= would say false to that 11:00
zacque Erm, is there an example for that? I don't know how to "drop the container"
Nemokosch in fact, I suspect === always drops the container
yes, your code is a perfect example
```perl
sub MAIN(Int:D $rows where $rows >= 3) {
my @pascal = (pascal-sequence $rows);
say [===] @pascal;
say @pascal[^$rows]; # OUTPUT: [[1 4 6 4 1] [1 4 6 4 1] [1 4 6 4 1] [1 4 6 4 1] [1 4 6 4 1]]
say (pascal-sequence $rows); # OUTPUT: ([1] [1 1] [1 2 1] [1 3 3 1] [1 4 6 4 1])
}
```
it will say True
I wish I could phrase what happened here xD 11:02
zacque It's okay! I know about `[]`!
It's the `reduce` operator
Nemokosch that helps
but there is more...
so @pascal wraps the same Array container into different Scalar containers
zacque So, it shows that every element are in fact the same container
Nemokosch if you assign to @pascal[0], that won't be reflected in @pascal[1]
because they are put into different Scalar containers
you can even try that
zacque I don't follow here... 11:03
Nemokosch I mean, understandable, I've been spending more than one year 11:04
zacque What's the deal with Scalar containers?
Nemokosch to kinda sorta understand variables
zacque Ah, scalar container is a catch indeed
Nemokosch let's wait for Kaiepi
zacque The doc says it won't get flatten
But, but, but they have the same value?? 11:06
๐Ÿคฆโ€โ™‚๏ธ
Nemokosch it's like the containers are nested
there is an item of the array, and that item contains an array
the items don't match, the underlying arrays do match
zacque Ya, I get this, `pascal-sequence` returns a (lazy?) array of list
Nemokosch =:= will say false for the items
=== will say true because it drops the scalar container and finds the array 11:07
zacque Then when I assign `pascal-sequence` to `@pascal` it will be coerced to `array` type 11:08
Kaiepi `my @pascal = ...` makes an empty `Array`, then assigns to fresh `Scalar` containers within this for each element in `pascal-sequence`'s `gather` (`Seq`)
it does this eagerly because the `gather` isn't `lazy`
if you assign an array, it copies from the containers within that
zacque Okay, so an array assignment to an array performs an implicit iteration? Makes sense... 11:10
Nemokosch array assignment calls .STORE
zacque If eager I meant
Nemokosch by definition
Kaiepi neat thing is if you assign a lazy iterable to an array, consume some values, then assign that to another array, it preserves any laziness left
zacque But the state remains right? Make sense...
I meant it'll follow from last "consumption" 11:11
Kaiepi yeah
zacque But I still don't get the "different Scalar containers" part
Nemokosch I'm describing it, hold on 11:12
zacque Ok, thanks
Nemokosch pls <@210313526928080896> also hold on in case I mess something up big time ๐Ÿ˜…
Kaiepi ok ๐Ÿ˜›
zacque Please take your time! Gtg, I'll be right back in about an hour... 11:13
Nemokosch 1. `my @pascal = ...` this is an "array assignment, hence calling STORE with the content on the right handside 11:14
2. because the rhs wasn't explicitly marked lazy, the content is traversed eagerly
3. the content is some Iterable that consists of the very same Array container over and over again (let me call this `gathered`
4. STORE allocates Scalar containers, the elements of the @pascal array
5. as it traverses `gathered`, it puts the elements of it (which are the same Array container over and over) into the Scalar containers
1. `my @pascal = ...` this is an "array assignment, hence calling STORE with the content on the right handside
2. because the rhs wasn't explicitly marked lazy, the content is traversed eagerly
3. the content is some Iterable that consists of the very same Array container over and over again (let me call this `gathered`)
4. STORE allocates Scalar containers, the elements of the @pascal array
5. as it traverses `gathered`, it puts the elements of it (which are the same Array container over and over) into the Scalar containers
so you end up with 11:15
@pascal - an Array container on top
the elements of @pascal - Scalar containers that you can mutate
the current contaent of the elements - the same one Array container (for all elements)
so you end up with
@pascal - an Array container on top
the elements of @pascal - Scalar containers that you can mutate
the current content of the elements - the same one Array container (for all elements)
Kaiepi pretty much 11:18
repeated `STORE`s clobber any existing containers within the array, but the wrapper remains
Nemokosch also, from what I understand (and iirc lizmat told me this), Arrays can not be decontainerized 11:21
Kaiepi the `Array` is the container and the value
Nemokosch they are like bundled
a mnemonic/mental aid to it: Scalars do have one identity while Arrays are inherently divided into pieces 11:25
I always imagine something like this for an array:
(array as in the container)
lizmat note you *can* put an Array into a container 11:26
but it will be considered a single object like any other object in a container
m: my $a = [1,2,3]; .say for $a
camelia [1 2 3]
Nemokosch a grid is made a grid by its cells, it's not a thing on its own 11:27
- unless, of course, you put the whole thing into a Scalar container ๐Ÿ˜„
okay, you were faster ๐Ÿ˜›
lizmat :-)
Nemokosch the more time you spend with it, the more logically sound it becomes 11:29
but a thorough demostration of it is still on my wanted list 11:31
yes, I know that article and it did help
but still, "more more more"
zacque Hang on, let me digest your messages ๐Ÿ˜„ 12:15
Okay, so without `lazy`, the RHS (`gathered`) is evaluated eagerly by calling `STORE` on it. `STORE` constructs an `Array` of `Scalar` elements. In this case, the `Scalar` elements are actually `Array` elements (containing other `Scalar` elements), so the result is an `Array` of `Scalar` `Array` of `Scalar` something. Finally, this result is assigned to the variable `@pascal`. 12:29
Ermm, so each of the `Scalar` elements in an `Array` has unique identity? That's why you said it's "different Scalar containers" 12:31
Nemokosch I think you are on the right track
zacque So, that why I got this: ```raku
sub MAIN(Int:D $rows where $rows >= 3) {
my @pascal = (pascal-sequence $rows);
say [===] @pascal; # Output: True
say [=:=] @pascal; # Output: False
} 12:32
```
12:55 saint- joined 13:36 razetime_ left 13:50 razetime joined 14:54 jgaz joined 17:00 razetime left 19:24 jgaz left 20:54 sivoais left, sivoais joined 22:16 MasterDuke joined