🦋 Welcome to the MAIN() IRC channel of the Raku Programming Language (raku.org). Log available at irclogs.raku.org/raku/live.html . If you're a beginner, you can also check out the #raku-beginner channel! Set by lizmat on 6 September 2022. |
|||
00:03
yewscion left
00:04
yewscion joined
00:18
librasteve joined
00:23
librasteve left
00:46
librasteve joined
00:51
librasteve left
01:02
yewscion left
01:05
yewscion joined
01:11
jjido left
01:17
librasteve joined
01:22
librasteve left
|
|||
tbrowder | success! | 01:38 | |
ugly, but it serves my needs | |||
01:50
librasteve joined
01:52
hulk joined
01:53
kylese left
01:55
librasteve left
02:03
yewscion left
02:05
yewscion joined
02:12
librasteve joined
02:15
hulk left,
kylese joined
02:17
librasteve left
|
|||
disbot3 | <jubilatious1_98524> @tbrowder I ran into the same issue iterating through lines. What I basically do is declare a my @array and then push the topic as a pair onto the array, with ++$ as key: my @rows; for $fh.lines() { @rows.push: ++$ => $_ }; | 02:19 | |
<jubilatious1_98524> @tbrowder don't know how this translates to Raku OO, though. | |||
02:23
yewscion left
|
|||
Voldenet | the output and stored data of the above snippet would be very similar to `$fh.lines.kv.eager` (except first key would be 0) | 02:24 | |
erm | 02:25 | ||
`$fh.lines.pairs.eager` | |||
02:28
yewscion joined,
librasteve joined
02:31
Aedil joined
|
|||
disbot3 | <jubilatious1_98524> ~$ raku -e 'my %hash = lines.pairs.eager; %hash<3>.put; ' alphabet.txt d | 02:32 | |
02:33
Aedil left,
librasteve left
02:48
apogee_ntv left
02:49
apogee_ntv joined
|
|||
Voldenet | idk if there's any point using hash for that, hashes use string keys and are bound to be slower | 02:51 | |
(i have no idea what the original problem is) | 02:52 | ||
m: sub lines { "a".."z" }; my %hash = lines.pairs.eager; %hash♥>.put; | 02:53 | ||
camelia | ===SORRY!=== Error while compiling <tmp> Bogus postfix at <tmp>:1 ------> " }; my %hash = lines.pairs.eager; %hash<HERE>♥>.put; expecting any of: infix infix stopper statement end statement modif… |
||
Voldenet | erm | ||
m: sub lines { "a".."z" }; my %hash = lines.pairs.eager; %hash<3>.put; | |||
camelia | d | ||
Voldenet | m: sub lines { "a".."z" }; my @hash = lines.eager; @hash[3].put; | ||
camelia | d | ||
03:01
librasteve joined
03:03
yewscion left
03:05
yewscion joined,
librasteve left
03:07
Aedil joined
|
|||
Geth | docker: cd07acf9d9 | AntonOks++ | 4 files Bump to 2025.06.1 [skip workflow] |
03:20 | |
03:36
librasteve joined
03:41
librasteve left
03:45
kylese left
03:47
kylese joined
|
|||
disbot3 | <jubilatious1_98524> Won't hash-lookups be faster than array-lookups, regardless of key? Also Raku enables object keys, so can Int keys be configured? Thx. | 03:52 | |
Voldenet | absolutely not - hash lookups convert key to Str first, then calculate its hash (so they do O(n) operation on the string, so %x<1000> is theoretically going to take longer than %x<1>), then they do op similar to @hashtable[$hash % @hashtable.elems] | 03:55 | |
and when you do index access directly, you pretty much skip a whole lot of ops by simply accessing the table by index | |||
in @a[$n], you add the index (well actually the offset) to the "starting address" of the array, so the lookup is as fast as it can | 03:56 | ||
there's probably no faster way to do that theoretically | |||
in practice there could be performance differences caused by how these are implemented at the moment, but if they were optimized, hash would lose every time | 03:59 | ||
hash is useful in case where you need to do by-key lookup. e.g.: %x<thing> - the only way to implement it without hashing would be to check if every element matches the predicate | 04:00 | ||
so… `@x.first(*.key eq "thing")` | 04:02 | ||
04:02
yewscion left
|
|||
Voldenet | (surprisingly, the latter could be faster for small lists of data, with 3 or 4 elements, but it only matters if you try to squeeze more performance out of hot code path) | 04:04 | |
04:05
yewscion joined
|
|||
disbot3 | <jubilatious1_98524> @Voldenet Hashmap lookup in Java is O(1) i.e. constant-time: stackoverflow.com/questions/154697...stant-time | 04:08 | |
04:08
librasteve joined
|
|||
Voldenet | it's constant when it comes to number of elements in the array, however if your key would be 1GB string, then obviously you have to calculate hash out of it somehow | 04:09 | |
disbot3 | <jubilatious1_98524> @Voldenet also here: stackoverflow.com/questions/277136...ally-be-o1 | 04:10 | |
04:13
librasteve left
|
|||
Voldenet | bottom line - hashes use by-index lookup at the end, so by-index lookup is pretty much guaranteed to win | 04:14 | |
of course the array has to be dense, indexes like `@a[now]` would mess it up | 04:18 | ||
Oh and, to answer the question about Int keys - there's no such thing in nqp::hash: github.com/Raku/nqp/blob/main/docs...down#atkey | 04:20 | ||
04:20
jmcgnh left
04:27
ecocode left
|
|||
Voldenet | ofc Nothing would stop you from implementing Associative role using Int keys, but it isn't typically done | 04:29 | |
m: class IntHash does Associative { has @!x; method AT-KEY(Int \k) is raw { @!x[k] }; method elems { @!x.elems }; method gist { "IntHash" ~ @!x.gist } }; my %x is IntHash; %x{10} = 1; say %x | |||
camelia | IntHash[(Any) (Any) (Any) (Any) (Any) (Any) (Any) (Any) (Any) (Any) 1] | ||
04:30
jmcgnh joined
|
|||
Voldenet | but in such case it could be saner to just use an array | 04:30 | |
04:35
jmcgnh left
04:40
jmcgnh joined
04:42
librasteve joined
04:48
librasteve left
|
|||
Voldenet | ofc people use regular hash as by-default lookup, in fact there are modules that help you making strings out of class for this case especially | 04:49 | |
m: class X { has $.x }; my %n; %n{X.new(x => 42)} = 1; %n{X.new(x => 42)} = 2; say %n # doesn't work | 04:50 | ||
camelia | {X<3144162403440> => 1, X<3144162403520> => 2} | ||
Voldenet | m: use ValueType; class X does ValueType { has $.x }; my %n; %n{X.new(x => 42).WHICH} = 1; %n{X.new(x => 42).WHICH} = 2; say %n # does work, but you need ValueType module | ||
camelia | ===SORRY!=== Error while compiling <tmp> Could not find ValueType in: /home/camelia/.raku /home/camelia/rakudo-m-inst-1/share/perl6/site /home/camelia/rakudo-m-inst-1/share/perl6/vendor /home/camelia/rakudo-m-inst-1/share/per… |
||
Voldenet | but the cost is that it always Str as key and uses Str for hash computation | 04:54 | |
05:03
yewscion left
05:05
yewscion joined
05:15
librasteve joined
05:19
librasteve left
05:51
librasteve joined
05:56
librasteve left
05:57
bisectable6 left,
committable6 left,
bloatable6 left,
bisectable6 joined,
committable6 joined,
bloatable6 joined,
notable6 left,
tellable6 left,
evalable6 left,
notable6 joined
06:00
tellable6 joined,
evalable6 joined
06:02
yewscion left
06:05
yewscion joined
06:23
librasteve joined
06:31
derpydoo joined,
librasteve left
06:32
Sgeo left
06:40
librasteve joined
06:45
librasteve left
07:03
yewscion left
07:05
yewscion joined
|
|||
lizmat | aaah... 15 degrees C cooler than yesterday *phew* | 07:05 | |
07:06
librasteve joined
07:11
librasteve left
|
|||
Voldenet | hot weather is not cool | 07:23 | |
07:28
librasteve joined
07:32
librasteve left
07:45
yewscion left
07:51
yewscion joined
07:54
librasteve joined
07:58
librasteve left
07:59
derpydoo left
08:02
yewscion left
08:04
silug3 joined
08:05
yewscion joined,
silug left,
silug3 is now known as silug
08:13
lucerne left
08:16
librasteve joined,
dakkar joined
08:21
lucerne joined
08:25
librasteve left
08:27
yewscion left
08:32
yewscion joined
08:33
librasteve joined
08:38
librasteve left
08:44
librasteve joined
08:49
librasteve left
08:55
yewscion left
09:02
librasteve joined
09:05
yewscion joined
09:07
librasteve left
09:19
librasteve joined
09:35
jjido joined
|
|||
disbot3 | <jubilatious1_98524> `~$ raku -e 'my %foo2{Int} = 0 => "x"; say %foo2.keys.map( { $_.WHAT } );' ((Int)) | 09:55 | |
09:58
jjido left
10:03
yewscion left
10:05
yewscion joined
|
|||
Voldenet | You are right, it might appear that this is int hash, but let me tell you the sad truth | 10:13 | |
m: use nqp; my %foo2{Int} = 0 => "x"; say nqp::getattr(%foo2, Map, <$!storage>) | |||
camelia | {Int|0 => 0 => x} | ||
Voldenet | it's actually a string | 10:14 | |
but it's a cool syntax, didn't know it existed | 10:16 | ||
`use ValueType; class X does ValueType { has $.x }; my %n{X}; %n{X.new(x => 42)} = 1; %n{X.new(x => 42)} = 2; say %n` # doesn't need .WHICH, because it internally uses key.WHICH | |||
lizmat | Voldenet: the second 0 in your example is *not* a string | 10:17 | |
m: my %foo2{Int} = 0 => "x"; dd %foo.keys.head.^name | |||
camelia | ===SORRY!=== Error while compiling <tmp> Variable '%foo' is not declared. Did you mean '%foo2'? at <tmp>:1 ------> my %foo2{Int} = 0 => "x"; dd <HERE>%foo.keys.head.^name |
||
Voldenet | yes, to clarify, the hash stores pair with original key and value, but the key becomes Str | 10:18 | |
lizmat | m: my %foo2{Int} = 0 => "x"; dd %foo2.keys.head.^name | ||
camelia | "Int" | ||
lizmat | it's called an object hash | ||
Voldenet | I was just pointing out earlier, that in a lot of cases array will be more elegant solution | 10:19 | |
lizmat | could well be :) | ||
Voldenet | so while int hash exists and it could theoretically use array as storage, it doesn't at the moment | 10:20 | |
in fact, if there was nqp::objecthash with HASHCODE (similar to WHICH), then maybe it could skip Str entirely | 10:22 | ||
10:24
yewscion left
|
|||
lizmat | it probably could | 10:25 | |
Voldenet | and then %foo{Int} could check if nqp::can(TKey, "HASHCODE") for more performant implementation | 10:29 | |
10:30
yewscion joined
|
|||
Voldenet | I'm not entirely sure about the nqp-centric design, because it could as well just use a basic array as storage | 10:34 | |
or nqp::list | |||
lizmat | as implementor of object hashes, I decided against using arrays as basic storage, as it would make lookups of keys not scale well | 10:35 | |
Voldenet | Wouldn't index-based hashtable only have to store pairs and have lookups by… well, index? | 10:41 | |
lizmat | how would that work for %h<a> ? | 10:48 | |
how would it find the right pair ? | 10:49 | ||
timo | weather is a lot better now, but yesterday a lightning strike in the area took out the internet ... again | ||
Voldenet | for %h<a> it would first do MVM_string_hash_code | ||
tbrowder | Voldenet: i did come to the same conclusion after sleeping on it: an array of word pairs works fine, and much easier | 10:50 | |
10:52
yewscion left
10:54
jjido joined
|
|||
tbrowder | from looking at discussion above, y'all seem wary of over use of strings, but i rely on them heavily. i know they are "expensive" but my most common use cases are very stringy, so i don't lose any sleep over it. | 10:57 | |
10:58
yewscion joined
|
|||
tbrowder | btw, a friend in idaho send me a picture of his outdoor thermometer reading 118 degreees F. humidity of 37% | 10:59 | |
timo | did we have a discussion yet for a way to get a Uni object out of either utf8-c8, or a buffer of 8 bit integers, or both? | 11:01 | |
lizmat | *i* don't recall, but that's not saying much :) | 11:02 | |
timo | because i've been kind-of wanting that as well :) | ||
i forgot why though | |||
lizmat | the problem is really to get at the synthetics | 11:03 | |
11:03
yewscion left
|
|||
timo | no, synthetics can never make it out of moarvm's internals | 11:04 | |
11:04
yewscion joined
|
|||
timo | or did i misunderstand the question? | 11:05 | |
lizmat | Uni.new takes ints | ||
timo | right | ||
lizmat | how would you repepresent synthetics in that, if you don't want to expose the internal ? | ||
timo | Uni cannot possibly represent synthetics, Uni is about unicode, synthetics are Rakunicode :P | 11:06 | |
Voldenet | m: sub insert(@t, $k, $v) { my $ix = hash($k) % @t.elems; while @t[$ix] { $ix = ($ix + 1) % @t.elems }; @t[$ix] = $k => $v }; sub hash($k) { 42 }; sub lookup(@t, $k) { my $ix = hash($k) % @t.elems; while my \e = @t[$ix] { if e.key eq $k { return e }; $ix = ($ix + 1) % @t.elems } }; my @x = Any xx 4; insert(@x, "a", 42); say @x; lookup(@x, "a").say | ||
camelia | [(Any) (Any) a => 42 (Any)] a => 42 |
||
Voldenet | ^ this is what I exactly had in mind | ||
lizmat | ok, so you have a string with synthetics, would you just want tne use the ords ? | ||
timo | when you get a .Uni from a Str, the Str will be in NFG, so the integers in the Uni object will be NFC and synthetic graphemes will be as close to NFC as they can be | 11:07 | |
lizmat | Voldenet: how would that scale with 1000 keys ? | ||
Voldenet | depends on how good was the hash function | ||
and what was the data | |||
lizmat | timo: so it would be lossy | 11:08 | |
Voldenet: while my \e = @t[$ix] { if e.key eq $k { return e } that doesn't scale | |||
timo | going back from the Uni to a Str will run the NFG algorithm again and end up with the same thing | ||
but at the moment you can not go from bytes that are something encoded in utf8 to a Uni object of the codepoints as the bytes represent them | |||
because we currently force you to go through Str or to do the utf8 decoding by hand in raku with integer arithmetic and stuff | 11:09 | ||
Voldenet | Yes, it's linear, in fact there should be a check if the hash of the key was equal to the key | ||
and memmove would be necessary in insert | |||
timo | ... or does .Uni on a utf8-c8 encoded string do what i want it to already? | ||
Voldenet | lizmat: however, it does scale well if hash is a bit bigger than the collection | 11:10 | |
i believe moarvm hash does exactly this | |||
timo | i don't know the original question, but maybe a lookup structure that's more tree-like, or even a Trie, could be helpful? | ||
Voldenet | the original question was: should one use table as hash, when the key is Int | 11:11 | |
timo | ah, rather than go via Int's WHICH function | 11:12 | |
or Int's Str function | |||
Voldenet | but then you store a lot of strings | ||
timo | right | 11:13 | |
Voldenet | so if you needed to store 1_000_000 Int => Int pairs, array would pretty much not be that tough | ||
hash… would become gigantic | |||
lizmat | possibly related: raku.land/zef:lizmat/Array::Sorted::Util | 11:14 | |
timo | it's true, Int can be a lot smaller than Str, especially when it's a small enough number and it fits into 32 bits | ||
sorted arrays have the drawback that inserting something in the middle forces the rest of the array to have to move one spot | |||
Voldenet | so the following question was, should it be possible to use %foo{Int} in such a way that it really does store Int | ||
timo | it would definitely be possible to implement that for %foo{int} but %foo{Int} has to be able to store Int subclasses and Ints with mixed-in roles | 11:15 | |
lizmat | raku.land/zef:lizmat/Hash::int | ||
timo | lizmatable6++ :) | 11:16 | |
lizmat | well... it may not be as performant as I like after all :-( | ||
Voldenet | so, at the end of the road - should there be nqp-implemented int hash, that'd directly operate on ints | 11:17 | |
or can it be pure rakudo impl using simple array | |||
timo | could be what liz just linked is exactly that | 11:18 | |
Voldenet | nope, it uses nqp::hash | ||
lizmat | this was based on the fact that in nqp, hash access will automatically stringify native int values | ||
timo | haha, ok | 11:19 | |
lizmat | so any performance gain was from needing fewer ops | ||
I think over the years, that performance difference has evaporated | |||
Voldenet | the array-based approach would have different problems, it'd definitely need to allocate more memory for entries table itself, but overall, it wouldn't need to allocate Strings ever | 11:22 | |
in fact nqp::hash has really good implementation, but uses MVMString as key | 11:24 | ||
it could be major improvement to actually use hashCode-esque logic | |||
timo | not sure what you mean by "more memory for entries", a MVMHash has to use memory for that as well | ||
Voldenet | Ah, of course | 11:25 | |
so I was thinking how to close that tiny gap while effectively reusing most of the code in nqp::hash | 11:26 | ||
timo | a simple hash that uses probing and gravestones or even chained buckets wouldn't be too hard to build in raku or nqp i reckon | ||
a bit annoying to write your own hash function in nqp though | |||
Voldenet | Kind of, the modern idea is to give user hashCode only for strings | 11:27 | |
and give users Object.hash(…codes) that would mix codes somehow | |||
> class X { has $.x; has $.y; method HASHCODE { mix-hashcode($.x.HASHCODE, $.y.HASHCODE) }} | 11:28 | ||
ValueType could probably implement this automatically | 11:29 | ||
and default hashcode would be, very java-esque again, address | 11:30 | ||
or MVM_string_hash_code | |||
timo | that's kind of what we have WHICH for, right? but you would prefer integer over string for WHICH? | 11:31 | |
Voldenet | I think WHICH is identity value, hashcode throws away a lot of data | 11:32 | |
and turns into int32 or int64 | |||
so yes, WHICH could be used to implement HASHCODE | 11:33 | ||
if Str had HASHCODE, then `method HASHCODE { WHICH.HASHCODE }` would work | |||
timo | we sometimes put stuff in WHICH through a sha256 i think | 11:34 | |
not entirely sure if it's for true identity or if it's also lossy like hashcode is | 11:35 | ||
Voldenet | but doesn't WHICH imply `$x.WHICH eq $y.WHICH` => `$x eqv $y`? | 11:37 | |
if it doesn't then very likely base64(bytes(hashCode)) could work without any drastic changes | 11:40 | ||
timo | Blob uses sha1 of its contents in its WHICH | ||
i didn't do an exhaustive search though | 11:41 | ||
11:41
jjido left
|
|||
Voldenet | so… WHICH is not a hash, it's an identity | 11:45 | |
m: class X { has $.x; method WHICH { "x" }}; my %foo{X}; %foo{X.new :42x} = 42; %foo{X.new :43x} = 43; say %foo | |||
camelia | {X.new(x => 42) => 43} | ||
Voldenet | has to be | ||
therefore I still think something like .HASHCODE would be useful | |||
in fact, if nqp::hash could recognize int32/int64 as values not needing hash | 11:51 | ||
11:52
jjido joined
|
|||
Voldenet | and then Hash-int would actually be fast, because it wouldn't convert ints to strings | 11:52 | |
btw, interesting fact about WHICH is that it can't even be Int | 11:53 | ||
m: class X { has $.x; method WHICH { 1 }}; my %foo{X}; %foo{X.new :42x} = 42; | |||
camelia | This type cannot unbox to a native string: P6opaque, Int in block <unit> at <tmp> line 1 |
||
lizmat | .WHICH is either an ObjAt or a ValueObjAt the latter indicates a value type, and is used in e.g. Sets | 11:54 | |
12:00
jjido left
|
|||
Voldenet | Hm, using HASHCODE on anything non-string automatically (instead of casting it to Str) would have deadly impact on any code that expected this behavior, I guess that wouldn't work :( | 12:00 | |
so either nqp::objecthash or something similar would have to exist, or nqp would have an op that'd mark hash as "non-autostringable" | 12:02 | ||
12:02
yewscion left
12:05
yewscion joined
12:20
apac joined
12:24
guifa left
12:27
yewscion left
12:33
yewscion joined
12:55
librasteve left
12:56
apac left
13:02
yewscion left
13:04
yewscion joined
13:06
librasteve joined
13:46
yewscion left
14:13
librasteve left
14:24
librasteve joined
14:31
jjido joined
14:33
Sgeo joined
14:34
yewscion joined
14:36
librasteve left
14:43
jjido left
14:52
jjido joined
15:03
librasteve joined
15:07
librasteve left
15:15
jjido left
15:36
librasteve joined
15:41
librasteve left
15:56
librasteve joined
16:04
librasteve left
16:15
librasteve joined
|
|||
SmokeMachine | m: say ValueObjAt.new: 42 | 16:17 | |
camelia | This type cannot unbox to a native string: P6opaque, Int in block <unit> at <tmp> line 1 |
||
16:20
librasteve left
|
|||
lizmat | m: say ValueObjAt.new: "42" | 16:34 | |
camelia | 42 | ||
16:36
dakkar left
16:40
librasteve joined
16:45
librasteve left
17:08
librasteve joined
17:14
librasteve left
|
|||
tonyo | . | 17:31 | |
17:37
librasteve joined
17:47
yewscion_ joined
17:49
yewscion_ left
17:50
yewscion left
17:53
yewscion joined
18:03
jjido joined
18:40
librasteve left
18:48
Guest0 joined
19:08
librasteve joined
19:15
librasteve left
19:26
yewscion_ joined
19:28
yewscion left
19:29
jjido left,
librasteve joined
|
|||
apogee_ntv | lizmat: I opened this as a draft PR: github.com/raku-community-modules/...ble/pull/2 -- adds tExt metadata support to Image::PNG::Portable, will promote to PR once we get the other one merged. | 19:47 | |
lizmat | so PR #1 is good to go? | 19:48 | |
apogee_ntv | We were waiting on feedback because of the Windows fail IIRC | 19:49 | |
lizmat checks if the WIndows CI failure | 19:50 | ||
apogee_ntv | github.com/raku-community-modules/...64485?pr=2 Interestingly... test 2 is passing here but it's failing on unlink. I don't have a windows box to debug on but I assume it's prob solved by a sleep(0.1) or something? | 19:54 | |
failing on unlink on test 3* | |||
No output received, exit-code -16 (38): | 19:55 | ||
Failed to spawn process zef.bat: no such file or directory (error code -4058) | |||
Oh nvm still getting this | |||
lizmat | apogee_ntv: PR1 merged, want me to release this one? | 20:02 | |
or wait for the next one? | |||
too late, released to zef | 20:07 | ||
apogee_ntv | Thats fine, I think releasing separately is fine. I versioned them differently. | ||
lizmat | anyway, if you want to follow progress on raku-community-modules, you can check the #raku-community-modules channel | 20:08 | |
all updates are posted there | |||
apogee_ntv | Thanks, I will | 20:11 | |
I set PR 2 as ready for review and resolved the conflicts. | 20:12 | ||
lizmat | too tired to look at now, will try to look at it tomorrow | 20:13 | |
apogee_ntv | No rush, thanks | 20:16 | |
20:17
jjido joined
20:31
librasteve left
20:51
Guest0 left
20:59
librasteve joined
21:03
librasteve left
21:14
jjido left
21:17
librasteve joined
21:20
yewscion_ left
21:21
librasteve left
|
|||
Geth | vim-raku: 1-1sam++ created pull request #40: Add highlighting for more builtin types |
21:23 | |
21:30
librasteve joined
21:35
librasteve left
21:37
librasteve joined
21:41
librasteve left
22:01
librasteve joined
22:07
yewscion joined,
librasteve left
22:12
yewscion left
22:16
librasteve joined
22:17
jjido joined
22:44
yewscion joined
23:18
librasteve left
23:21
librasteve joined
23:26
librasteve left
23:30
guifa joined
23:47
librasteve joined
23:51
librasteve left
23:56
yewscion left
|