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:06
Manifest0 left
|
|||
el gatito (** advocate) | why do you hate using exceptions as iteration sentinels tho | 00:15 | |
Nemokosch | they don't describe the intent well, they are wordy | 00:24 | |
multiple disadvantages for no advantages | |||
el gatito (** advocate) | raku does almost the same thing just returning IterationEnd instead of raising an exception | 00:25 | |
Nemokosch | yes, and that's already slightly better | 00:28 | |
el gatito (** advocate) | how? | 00:33 | |
Nemokosch | it doesn't get mixed with actual exceptions | 00:38 | |
el gatito (** advocate) | you can make an exception subclass that represent fail exceptions and StopIteration wouldn't subclass it | 00:42 | |
Nemokosch | why would you want to drill on the type system, though, in order to indicate the normal behavior of iterators? | 00:45 | |
el gatito (** advocate) | actually python doesn't do that 😭 | 00:46 | |
why not | 00:50 | ||
Nemokosch | because it's inconvenient and error-prone | ||
what is the offer in return? | |||
el gatito (** advocate) | actually ruby does the same thing ruby-doc.org/core-2.6/Enumerator.html | 00:51 | |
Nemokosch | that's sad if anything | 00:52 | |
el gatito (** advocate) | its more convenient if you are iterating multiple times? py with suppress(StopIteration): seq.append(next(it)) other |= next(it) vs py temp = next(it) if not isinstance(temp, StopIteration): seq.append(temp) temp2 = next(it) if not isinstance(temp, StopIteration): other |= temp2 | 00:55 | |
Nemokosch | this rather seems like a hack | ||
even if we ignore that this supressor is some magic function - what value do you get when you were supposed to get an exception? | 01:00 | ||
and if you do get a value that you can recognize - what was the whole exception mumbo jumbo about? we are back to a sentinel value | 01:01 | ||
el gatito (** advocate) | no value also yielding a value and ending the iteration should be different to the consumer, so they do different things (give a value vs raising an exception) | 01:08 | |
Nemokosch | how does "no value" manifest when you are clearly storing something into a variable? | 01:09 | |
also: why would an end user even want to consume an iterator | 01:10 | ||
rather than something iterable | |||
with the proper handling of an iterable | |||
like a foreach loop | |||
el gatito (** advocate) | you don't want to store an "end of iteration" marker to a variable? | ||
by consumer i mean code that consumes iterators bruh | 01:11 | ||
Nemokosch | yes - what would that even be? | ||
that's low-level code | |||
and as such, it clearly never wants to escalate a control exception | |||
and idk how that follows. I just wanted to get an answer | 01:12 | ||
el gatito (** advocate) | also what happens when someone wants to yield StopIteration or IterationEnd you don't want to make assumptions about the data being yielded | 01:15 | |
Nemokosch | yes, you do, if the value happens to be the dedicated sentinel value | 01:17 | |
sorry but that's not some coincidental data, that's part of the interface | |||
you know, this argument is like | |||
el gatito (** advocate) | the exception is raised before something is assigned to the variable so nothing is assigned period | ||
Nemokosch | "what if the processor of the iterator wants to raise StopIteration cause why not?" | ||
"you wouldn't want to make assumptions about the exceptions that can happen..." | 01:18 | ||
yet it's being assigned to something so something just must happen | 01:19 | ||
the universe can't just disappear on this contradiction, lol | |||
el gatito (** advocate) | generators will cause a RuntimeError if they raise that and if class-based iterators raise that it obviously means they want to end | 01:21 | |
Nemokosch | similarly, if you define an iterator that gives you IterationEnd on pulling, that means it's over | 01:23 | |
Actually, IterationEnd isn't even Any; it's really just a unique reference reserved for this purpose | 01:24 | ||
there is literally no other reason to return it than to indicate the exhaustion of the iterator | 01:25 | ||
el gatito (** advocate) | the rhs next(it) raises an exception while evaluating so the assignment doesn't happen same thing when you do a = 1 / 0 there is an exception in 1 / 0, so a is untouched | 01:26 | |
should be pretty easy to reason | 01:27 | ||
Nemokosch | then what did you win with suppress? | ||
el gatito (** advocate) | ignore the exception and exit the block | 01:28 | |
Nemokosch | or you could just do something like | ||
until (my \next := $iterator.pull-next) =:= IterationEnd { ... } | 01:29 | ||
and be in the safe | |||
it didn't need sugar on top of sugar | |||
actually, := is superfluous there, terms always bind on initialization | 01:30 | ||
el gatito (** advocate) | fair 😤 | 01:32 | |
Nemokosch | these wrappers are more or less convertible anyway, if the iterator interface itself achieves the same thing | 01:34 | |
the question is what you'd make the normal way | |||
el gatito (** advocate) | then whats your ideal of an iterator interface you want separate done() method to indicate the end of iterator? | 01:35 | |
01:36
frost joined
|
|||
Nemokosch | Tbh the Java way is not so bad | 01:42 | |
with bare hasNext and next | |||
the C#/Object Pascal way is somewhat more readable to the user imo | |||
a function for moving the cursor (which can return False on "failure"), and another one for reading the current item | 01:43 | ||
the JS interface is fairly interesting and not necessarily in a bad way | 01:44 | ||
that one is more like Python (you can pass a value to next) | |||
however, it doesn't throw an error but returns an object with the value and the completion | 01:45 | ||
if the completion is marked, a final value still might be obtained, which in that case would be the return value of the iterator | 01:46 | ||
el gatito (** advocate) | then there is php php <?php interface Iterator extends Traversable { /* Methods */ public current(): mixed public key(): mixed public next(): void public rewind(): void public valid(): bool } | ||
Nemokosch | well this is a bit harder to actually implement I guess | 01:48 | |
with the rewind | |||
still, I have to say, given the core of the Javascript language, the extensions from ES6 onwards are really gems of shining genius | 01:50 | ||
also unorthodox af | 01:51 | ||
but it seems kinda justified when it comes to a language that has not seen any serious revisions for almost 20 years | |||
and was deliberately designed to be banal | |||
one example that illustrates the desperation, though, is 'use strict' | 01:53 | ||
el gatito (** advocate) | didn't fix the type system tho 😭 | 01:57 | |
which is why typescript is a godsend | 02:05 | ||
Nemokosch | what was wrong with the type system? | 02:08 | |
ngl I also admire TS, mostly because of laziness | |||
el gatito (** advocate) | weak typing 😩 | ||
Nemokosch | Without TS, I basically don't know the API of a random Node module | 02:09 | |
but that's really the biggest use I see for it | |||
el gatito (** advocate) | typescript complains when you give the wrong type so no more weak typing | 02:11 | |
unless you want | |||
Nemokosch | I tend to use == and fortunately the linter won't complain by default | ||
but yeah all of a sudden it's statically known what types can hit that comparison | 02:12 | ||
el gatito (** advocate) | the same with raku too typing will allow me to write strongly typed codebase | 02:14 | |
Nemokosch | I wonder how much static analysis will be possible, and how much it will be just runtime checks, PHP style | 02:21 | |
Also, be warned that the type system demands quite some care to get solid | |||
02:41
rf joined
03:03
rf left
|
|||
el gatito (** advocate) | m:perl my @a = <a b c>; say "this is @a"; | 03:58 | |
Raku eval | this is @a | ||
el gatito (** advocate) | what | ||
m:perl my @a = <a b c>; say "this is @a[]"; | |||
Raku eval | this is a b c | ||
el gatito (** advocate) | why | ||
m:perl my @a = <a b c>; say "this is $@a"; | 03:59 | ||
Raku eval | this is a b c | ||
MasterDuke | because `@` is now a common character to appear in strings where you don't want them to interpolate, i.e., email addresses | 04:08 | |
el gatito (** advocate) | $ is also common? | 04:10 | |
and you can just escape them or use ' strings? | 04:13 | ||
05:23
Heptite left
|
|||
Nemokosch | @ is more common than $ | 08:30 | |
having said that, this is inconsistent, no point in trying to explain it away xD | |||
however, it's also insignificant | 08:31 | ||
09:03
Manifest0 joined
09:10
dakkar joined
|
|||
el gatito (** advocate) | actually {} interpolation most goated | 09:23 | |
m:perl say "1 + 1 = {1 + 1}" | |||
Raku eval | 1 + 1 = 2 | ||
Nemokosch | because it actually creates a block | 09:51 | |
10:09
ab5tract joined
|
|||
el gatito (** advocate) | then invokes it immediately | 10:15 | |
hmm | |||
Nemokosch | m: say "1 + 1 = &{1 + $_}(2)" | 10:33 | |
Raku eval | 1 + 1 = 3 | ||
Nemokosch | needed the ampersand | ||
11:03
frost left
11:16
frost joined,
ab5tract left
11:29
ab5tract joined
11:42
ab5tract left
11:53
ab5tract joined
12:13
frost left
|
|||
Nahita | m: sub f(\n?) { } | 12:28 | |
Raku eval | Exit code: 1 ===SORRY!=== Error while compiling /home/glot/main.raku Malformed parameter at /home/glot/main.raku:1 ------> sub f(\n⏏?) { } expecting any of: constraint | ||
Nahita | m: sub f($n? is raw) { } | ||
Raku eval | |||
13:17
Heptite joined
13:28
saint- left
14:09
QhpAptyj9hj0RQwM joined
14:33
jgaz joined
14:40
habere-et-disper joined
|
|||
habere-et-disper | Hello rakoons o/ :D | 14:44 | |
Is it reasonable that | |||
m: <a b>.join | |||
camelia | ( no output ) | ||
habere-et-disper | m: join <a b> | ||
camelia | ( no output ) | ||
habere-et-disper | give different results? I realize that with the prefix form you have to do: | ||
m: join '', <a b> | |||
camelia | ( no output ) | ||
habere-et-disper | But it seems somewhat irregular that a default value appears supplied in postfix form but not in prefix form. Am I missing something? Thanks! | ||
m: say <a b>.join | |||
camelia | ab | ||
habere-et-disper | m: say join <a b> | ||
camelia | |||
14:53
habere-et-disper left
|
|||
Nemokosch | m: say join (1, 2) | 15:00 | |
Raku eval | |||
Nemokosch | weeeell | ||
oh right | 15:01 | ||
the argument order is different | |||
m: say join '', (1, 2) | |||
Raku eval | 12 | ||
Nemokosch | I think this is regular, in the sense that all array-ish subs have this argument layout | 15:02 | |
map, grep, and so on | |||
the question is rather: why a one-argument call succeeds with whatever result | 15:03 | ||
ab5tract | m: say join |<a b> | 15:52 | |
camelia | b | ||
15:54
habere-et-disper joined
|
|||
ab5tract | seems weird | 15:54 | |
15:54
rf joined
15:55
QhpAptyj9hj0RQwM left
|
|||
Nemokosch | I mean... that's one b, separated by a's | 16:00 | |
😄 | |||
habere-et-disper | The documentation is correct, reading "The method form also allows you to omit the separator", but I'd be interested as to why the prefix form is not afforded it. | 16:54 | |
The join documentation also gives an example of: | |||
m: say join ', ', <a b c>; | |||
camelia | a, b, c | ||
habere-et-disper | Which appears to currently fail !? | ||
I get the following on the REPL (v2022-12): | 16:55 | ||
say join ', ', <a b c>; | |||
===SORRY!=== Error while compiling: | |||
Two terms in a row | |||
------> say join<HERE> ', ', <a b c>; | |||
Nemokosch | can't reproduce on the same version | 17:35 | |
maybe you have actually missed a space between join and ', '? | 17:36 | ||
17:37
dakkar left
|
|||
habere-et-disper | No, and even weirder it appears to work fine again !? | 17:38 | |
17:53
habere-et-disper left
18:02
Heptite left
18:07
Heptite joined
18:16
ab5tract left
18:30
ab5tract joined
|
|||
Nahita | if I have a .rakumod file for common use, what can I do so that use Module from anywhere uses it | 18:57 | |
tried moving the file to some places where it reports it couldn't find it, it still didn't find it | 18:58 | ||
it's a single .rakumod file | |||
i faked a meta6.json and zef installed it but that's perhaps not the way | 19:00 | ||
p6steve | why not zef install https:://github.com/path-to/Module.git ? | 19:03 | |
Nahita | it's a single file locally | ||
p6steve | does zef install /local-path/Module.rakumod work (I never tried it)? | 19:04 | |
Nahita | thanks but that searched for the internet so it did not work | 19:05 | |
by internet i mean it updated mirrors fez, cpan etc. and says No candidates found matching identity | 19:07 | ||
i can make an alias for "raku -Ipath/to/module" i guess... | 19:08 | ||
but there is a better way probably | |||
p6steve | according to the zef README | 19:09 | |
# PATH zef install ./Raku-Net--HTTP | |||
should work ... need to start the local path with / or . | |||
github.com/ugexe/zef#more-cli | 19:10 | ||
Nahita | well i first tried "zef install ." in the folder the module resides in | ||
then i got "Type check failed for return value; expected IO::Path but got Any (Any)" message | |||
then i faked a meta6.json | |||
then "zef install ." worked | |||
now i tried "zef install ./folder" | 19:11 | ||
same message as above | |||
which is not super helpful message but i guess it wants to say it couldn't fine meta6.json or something idk | 19:12 | ||
Nemokosch | I guess you could just copy it to a folder in RAKULIB? | ||
p6steve | yeah I have tried locally on my machine and have the same issue | 19:13 | |
making a mini module (ie spoof the META6.json locally) and then zef install . works for me | 19:14 | ||
as @Nemokosch mentions perhaps you can symlink or append the Module path to RAKULIB | 19:15 | ||
Nahita | in Perl, i put a .pm file in a place mentioned in @INC, it works. in Python, i put a .py file in a place mentioned in sys.path, it works. in Raku, i put a .rakumod file to such place, it doesn't work | 19:22 | |
should i precompile the module or something? | |||
Nemokosch | it should work without | 19:23 | |
Nahita | let me try that maybe | ||
Nemokosch | it definitely works locally by setting -I to the sufficient location | ||
It would only make sense that it works the other way around as well | |||
Nahita | moving the precompiled thing didn't work too | 19:28 | |
19:30
ab5tract left
|
|||
asking in the other place. | 19:35 | ||
19:53
ab5tract joined
|
|||
elcaro | You could to a copy it to a folder, eg. $HOME/.local/lib/raku/Module.rakumod Then export the path to the env var RAKULIB For example, I have a line in my .profile file export RAKULIB=$HOME/.local/lib/raku And now any modules I throw in there are always available to use | 23:09 | |
If you're on windows, replace $HOME with %USERPROFILE%, but really, it doesn't matter where you put them, so long as RAKULIB points to it. Exporting env vars is also annoying in Windows (last I checked). | 23:10 | ||
23:56
Heptite left
|