🦋 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