🦋 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:00
reportable6 left
00:01
reportable6 joined
01:01
statisfiable6 left,
unicodable6 left,
committable6 left,
coverable6 left,
releasable6 left,
reportable6 left
01:02
releasable6 joined,
statisfiable6 joined,
committable6 joined,
reportable6 joined,
unicodable6 joined
01:03
coverable6 joined
01:04
xinming left
01:06
xinming joined
01:19
deoac joined
02:15
teatwo joined
02:19
teatime left
|
|||
Voldenet | ><Nemokosch> just imagine if it even was a well-designed language in addition… | 03:00 | |
I believe that perl5 is fast precisely because it was created with specific tasks in mind | |||
in comparison languages like python, ruby or raku are too general to optimize for those specific tasks (and specific-task optimizations will end up as pure C) | 03:04 | ||
03:19
evalable6 left,
linkable6 left,
evalable6 joined,
linkable6 joined
03:58
rf left
03:59
gabiruh left
04:03
gabiruh joined
04:55
deoac left
05:01
derpydoo joined
|
|||
avuserow | tonight I released (yet another) module for making SQL called SQL::Builder - and wrote a small blogpost on why: dev.to/avuserow/sqlbuilder-making-...-raku-4mgn | 05:01 | |
Voldenet | avuserow: that's cool, does it support some sort of `$sql.from('songs', 's').where("s.name = sandstorm")`?` | 05:12 | |
using aliases is fairly important | |||
also, `["a", "=", 1]` for predicates is fairly awkward, you could accept something like `*.a == 1` by creating infix ops for basic operators and executing that WhateverCode using some operator that'd capture this state | 05:14 | ||
avuserow | yes, `from` can take a Pair to determine the alias: `$sql.from(:s<songs>).where(["s.name", "=", "sandstorm"])` | ||
Voldenet | iirc Red does something like that | 05:15 | |
avuserow | The most likely path forward is to have a lightweight Table/Column type, then have methods/operators on the column | 05:17 | |
Voldenet | yeah, something like that | ||
I'd mention something about CTEs but I don't think I've ever seen a query builder supporting it | 05:18 | ||
On mssql some queries can have their performance altered through the use of CTEs | 05:19 | ||
avuserow | though RakuAST may open other options. If I can know that I'm within a where clause, then I can possibly rewrite things into the three-tuple versions at compile time | ||
Voldenet | Possibly macros would add some cool features without that much pain | 05:20 | |
avuserow | then I don't need to make a ton of runtime things, and it could look even more like SQL | ||
Voldenet | currently evaluating contents of WhateverCode is a thorny path | ||
in fact, the only lib I've seen handling CTEs is linq2db for csharp (linq2db.github.io/articles/sql/CTE.html) | 05:21 | ||
avuserow | I don't have a particular use for CTEs but I don't think they'd be that hard to support | 05:22 | |
Voldenet | Well, the only really important use is recursive CTEs | 05:23 | |
avuserow | since the SelectBuilder object exists, you could have something like... `my $q = $sql.with($with-def, $inner-q).from(...).select(...)` | ||
it would be kind of syntactically like the subquery support with FROM/JOIN clauses | 05:24 | ||
Voldenet | Mssql likes to build parallel queries when you use that, which allocate tons of memory | ||
with CTE you could (not sure about current versions, so I'm using past tense) tell it to not do that | 05:25 | ||
avuserow | linq was a very very vague inspiration, mostly with `from` being the constructor for SelectBuilder | ||
that's kind of interesting | |||
I actually haven't used this with anything but postgres and sqlite. There's definitely some postgres bias in the syntax, especially casting. I may add some compatibility options there | 05:27 | ||
is mssql generally available to test out and use? | 05:28 | ||
Voldenet | development edition is free as long as you're not using it in prod | ||
which contains all the features | 05:29 | ||
erm, developer edition | 05:32 | ||
avuserow | okay, good to know | 05:33 | |
I'm going to call it a night. thanks for reading! | 05:34 | ||
Voldenet | np, thanks for good library to use :) | 05:36 | |
06:00
reportable6 left
06:01
reportable6 joined
06:44
jpn joined
06:51
jpn left
|
|||
Nemokosch | Voldenet: I doubt Perl5 is fast because of the magic variables, the concept of different "contexts" that can mess up the return value you are trying to use, the lack of proper function signatures (weee, got added in 5.36 or something) and so on | 06:56 | |
06:56
jpn joined
|
|||
Voldenet | wantarray is definitely the killer performance feature | 06:58 | |
:> | |||
But honestly, I don't mean the language design at all, just what was the end goal | 06:59 | ||
If you start with things to do and ignore things like syntax, you end up working only on performance while skipping crucial things | 07:00 | ||
I know because I've built a few for-specific-purpose "languages" that were hideous to use outside of very specific task, but fast and easy for one thing | 07:02 | ||
("languages" because they used json/tsv for commands) | 07:04 | ||
Nemokosch | well endless bikeshedding about mundane things like syntax does no good either, that's for sure | 07:05 | |
Voldenet | that's how you end up without multiline lambdas (python) or no signatures (perl) | 07:06 | |
or generics (golang for a long while) | |||
Nemokosch | From what I know, the lack of multiline lambdas was a very deliberate choice in Python | ||
Voldenet | because "it would increase complexity of parsing" | 07:07 | |
Nemokosch | not only that | ||
On the other hand, I don't think there is any reason to protect the lack of function signatures in Perl | |||
Voldenet | you could say that no signatures for a long while was a deliberate choice for perl, because it would significantly increase complexity… ;) | ||
Nemokosch | yeah yeah, it's so complex that even C had them from the beginning and without explicit variable definition since like 1990 | 07:08 | |
Voldenet | it used to have some amazing syntax `int foo(bar, baz) char* bar; int baz; { … }` | 07:10 | |
iirc | |||
Nemokosch | yep, that's what I was referring to as "explicit variable definition" | ||
Voldenet | still, working on performance instead of the language isn't bad tradeoff | 07:12 | |
Nemokosch | as long as it doesn't lead to decisions (or lack of decisions) like this, it's not | ||
Voldenet | perl has Keyword::Declare now, so it's fairly easy to add missing features | ||
Nemokosch | At the end of the day, I don't think you can revert trends just by the virtue of making good design decisions so there's also that | 07:14 | |
07:14
jpn left
|
|||
However, that's not to say that the broader Perl community shouldn't think about what they keep getting constantly wrong, that even JS and PHP managed to fix themselves over time | 07:15 | ||
Voldenet | *cough* | ||
Nemokosch | PHP basically started off as "Perl, the bad parts" | 07:16 | |
and now it's a hundred times better language | |||
Voldenet | "was it strparse, parsestr, str_parse, or parse_str" | 07:17 | |
imo php keeps thinking about performance more than syntax | 07:18 | ||
Nemokosch | which should REALLY make everyone think who obsesses over eternal backwards compatibility | ||
they managed to improve the language significantly, DESPITE not even focusing on that | 07:19 | ||
Voldenet | I do love seeing C++20 codebase with some ancient C++ headers ;) | ||
Nemokosch | you meant to say C headers 😼 | 07:20 | |
Voldenet | "good C headers (k&r style)" won't compile in C++ fortunately | 07:21 | |
:P | |||
Nemokosch | well they don't have to compile 😛 | ||
07:21
sena_kun joined
|
|||
Voldenet | tbh. there's healthy balance between language features and performance and I consider perl to not strike that balance well, but it explains why it's fast :P | 07:21 | |
otoh you could argue that raku doesn't in the other direction, but while improving performance is measurable, improving syntax isn't | 07:23 | ||
Nemokosch | For Python - I do think that lack of fully blown lambdas was mostly a "social" decision, just like Guido forced reduce out of the core language | ||
Voldenet | so it's better to have better syntax first | ||
Nemokosch | Python is most definitely not a "design by committee" language. Whatever GvR set his mind on, had to be that way; in return it has always had a consistent vision | 07:24 | |
07:45
sena_kun left
08:00
xkr47 left,
jpn joined
08:05
jpn left
08:09
jpn joined
08:14
xkr47 joined
08:15
jpn left
08:17
MoC joined
08:37
lizmat left
08:38
lizmat joined
09:08
jpn joined
09:13
jpn left
09:56
jpn joined
10:02
jpn left
10:09
Sgeo left
10:33
kurahaupo joined
10:35
kurahaupo left
10:36
kurahaupo joined
10:49
frost joined
10:58
kurahaupo left,
kurahaupo joined
10:59
sftp left
11:02
sftp joined
11:26
kurahaupo left,
kurahaupo joined
11:47
MoC left
12:00
reportable6 left,
reportable6 joined
12:17
MoC joined
12:35
sena_kun joined
|
|||
Anton Antonov | Which produced a deceptively simplistic programming language. | 13:14 | |
13:14
derpydoo left
|
|||
Nemokosch | "A new BASIC", as some would say | 13:36 | |
14:14
linkable6 left,
evalable6 left,
teatwo left
14:15
evalable6 joined,
teatwo joined
14:16
linkable6 joined
|
|||
Anton Antonov | My attitude is kind of reflected here: resources.wolframcloud.com/PacletR...alParsers/ | 14:20 | |
14:42
jpn joined
|
|||
lucs | gfldex: No luck when adding 'compose', but here are a few more interesting (I think) observations: gist.github.com/lucs/4d5fe5e3c6fbd...66da677df1 | 14:51 | |
gfldex | It is a well known fact that the REPL mostly works. Raku is less dynamic as it looks at first. | 14:52 | |
14:58
MoC left
|
|||
lucs | By "mostly works", do you mean "sometimes fails"? | 15:01 | |
gfldex | yes | ||
lucs | Fair enough :) | ||
Do you have an opinion on how safe or should-avoid using 'augment' is? | 15:04 | ||
15:04
derpydoo joined
|
|||
moritz | you should avoid augment | 15:08 | |
lucs | Yeah, a few people have mentioned that, but I'm not clear on when it can be thought of a legitimate thing to do. | 15:09 | |
*thought of as | 15:10 | ||
15:11
jpn left
|
|||
gfldex | That the REPL doesn't always work is a bug that very difficult to stomp out. | 15:11 | |
lucs | In my case, it's no big deal, because I was using the REPL just to try out stuff as I develop my module, but the 'augment' on Match is kind of important (avoidable, but would be nice). | 15:12 | |
gfldex | In retrospective `use MONEY-*;` was the wrong term. `use YOU-WILL-BREAK-ASSUMPTIONS;` would have been better. | 15:15 | |
lucs | :-) | 15:16 | |
gfldex | But then, the word assumptions contains the word ass. And we don't want to be that either. It's the old dilemma of balancing freedom with predictability. | 15:17 | |
timo | i have heard "when you assume you make an ass out of u and me" | 15:27 | |
Anton Antonov | "When you presume, you make a press out of u and me." -- Does not work that well, but it is something ChatGPT can come up with. | 15:43 | |
@avuserow I am experimenting with "SQL::Builder" -- you might be hearing from me. 🙂 | 15:44 | ||
avuserow | Sounds good. Looks like you found a rough edge already, sorry about that. I'll take a look soon | 15:53 | |
gfldex | lolibloggedalittle: gfldex.wordpress.com/2023/05/07/ha...algorithm/ | 16:00 | |
m: say $*lizmat++ for Empty; | |||
camelia | ( no output ) | ||
gfldex | This line of code is a trueism, because lizmat invented Empty but got very little praise for it. More prais for lizmat, please. tyvm | 16:01 | |
Voldenet | using LAST in map is scary | 16:07 | |
16:10
derpydoo left
|
|||
Voldenet | but since map is described as gather - Empty is guaranteed to work, next will also work | 16:11 | |
Anton Antonov | @Voldenet Good to know. | 16:13 | |
gfldex | Voldenet: In the old days, `for` just called `.map`, `do for` still does. That's why LAST must work in `.map`. | 16:14 | |
Voldenet | iirc for loop will be converted to map as well | 16:15 | |
m: (for ^3 { $_ * 42 }).say | |||
camelia | (0 42 84) | ||
gfldex | Not anymore, I believe lizmat added that optimisation. | 16:16 | |
Voldenet | Oh, it behaves like map, but is not actually map | ||
gfldex | And I don't like it. If `for` would always call `.map` we would not need custom iterators for simple iteration. Providing `method grep` and `method map` would do. | 16:17 | |
Voldenet | funny that most developers would use .map where they intended to use >>. | ||
gfldex | ». was meant to autothread but then we got hyper/race. It would be tricky to set degree and batch-size otherwise. | 16:19 | |
And I don't think loop phasers would work in `».&{ your-code-here() }`. | 16:20 | ||
Nemokosch | don't forget that >>. has deepmap semantics anyway | 16:21 | |
Voldenet | well LAST is scary and also not impleemented | 16:23 | |
fully | |||
m: (^42).hyper.map({ LAST { say ":(" } }) | |||
camelia | Phasers in hyper/race not yet implemented. Sorry. in block <unit> at <tmp> line 1 |
||
Voldenet | Empty and next are implemented though | ||
I wouldn't use phasers outside pure for loops either way, it simply doesn't look right | 16:25 | ||
Nemokosch | there is problematically much non-structured behavior | 16:26 | |
have we talked about next actually skipping through the stack, looking for a loop to step? | 16:27 | ||
Voldenet | I do wonder how is `next` implemented in context of hypermap | 16:28 | |
gfldex | Empty in map is not in Roast (or I can't find the spot). But it really is emergent behaviour, because how binding to a positional container works. And Empty is specced quite a lot. | ||
I believe it does not work. | |||
At least the last time I checked no control exceptions worked in a HyperSeq. In react blocks most of the bugs are fixed tho. | 16:29 | ||
Voldenet | m: (^40000).hyper(:10batch :10degree).map({ next unless $_ > 39980; $_ }).say | 16:30 | |
camelia | (39981 39982 39983 39984 39985 39986 39987 39988 39989 39990 39991 39992 39993 39994 39995 39996 39997 39998 39999) | ||
Voldenet | but it does seem to work | ||
Nemokosch | of course documentation and specification could have improved; documentation has improved a lot, it has a quasi workflow. Specification doesn't. | ||
sometimes I wonder how I picked up this language; ngl I think most people wouldn't have that amount of time and freedom | 16:31 | ||
however, I believe that Empty in particular can be deduced solely from the documentation | 16:32 | ||
Voldenet | one could reason that Empty works differently than next | 16:33 | |
next "skips" the element during the loop | 16:34 | ||
16:34
jpn joined
|
|||
Voldenet | Empty gets emplaced into the resulting data structure which flattens it | 16:34 | |
Nemokosch | yep, that's quite sure | 16:35 | |
btw I think the use of Empty in map even appeared in the Rakudo weeklies, as an alternate implementation to grep | 16:36 | ||
gfldex | next acutally stops execution of the block, while Empty works its magic after the fact. | ||
Voldenet | In practice Empty seems faster | 16:37 | |
Nemokosch | what really strikes me without syntax highlighting is that [before] .item is confusing | 16:38 | |
in theory, I did know about &infix:<before> but not enough to think that while reading the code | |||
gfldex | Aye, control exceptions are still pretty slow. One reason for RakuAST. | ||
Voldenet | either way, Empty seems like something what _should_ be returned from map conceptually | 16:41 | |
gfldex | ofc it does. Empty is the Slip of (). | 16:44 | |
And a Slip is just a value, unless it is bound to a positional container. | |||
Voldenet | fortunately redo doesn't work in map | 16:46 | |
actually maybe it does, but there's no way to return a value | 16:47 | ||
gfldex | Indeed, for doesn't want to be gather/take . | 16:48 | |
Voldenet | m: (^10).map({ redo if (state @x).push($_).elems < 2; |@x }).say | 16:49 | |
camelia | (0 0 0 0 1 0 0 1 2 0 0 1 2 3 0 0 1 2 3 4 0 0 1 2 3 4 5 0 0 1 2 3 4 5 6 0 0 1 2 3 4 5 6 7 0 0 1 2 3 4 5 6 7 8 0 0 1 2 3 4 5 6 7 8 9) | ||
Voldenet | this example makes my head hurt | ||
I don't know any sane use case for this | 16:50 | ||
gfldex | Hold my beer! :D | ||
No wait, you where asking for "sane". :-> | |||
Voldenet | when drunk coding, you may consider more things sane, so take your beer back ;) | 16:51 | |
16:52
rf joined
17:05
Altai-man joined
17:07
lizmat_ joined
17:09
vrurg left
|
|||
Nemokosch | how did you come up with this though | 17:10 | |
there are more serious problems with this than redo, to be honest xD | |||
17:10
vrurg joined
17:14
sena_kun left,
kurahaupo left,
lizmat left
17:38
jpn left
17:48
abraxxa-home joined
17:49
jpn joined
17:53
abraxxa-home left
17:57
abraxxa-home joined
18:00
reportable6 left,
reportable6 joined
18:18
deoac joined
18:35
jpn left
18:50
jpn joined
18:52
lizmat_ left,
lizmat joined
19:14
xinming left
19:39
jpn left,
jpn joined
19:44
Sgeo joined
20:07
euandreh left
20:13
derpydoo joined
21:09
sftp left
21:10
euandreh joined
21:22
abraxxa-home left
|
|||
[Coke] | m: dd 1..10; Range.new(:from(1), :to(10); | 21:28 | |
camelia | ===SORRY!=== Error while compiling <tmp> Unable to parse expression in argument list; couldn't find final ')' (corresponding starter was at line 1) at <tmp>:1 ------> dd 1..10; Range.new(:from(1), :to(10);⏏<EOL> expecting an… |
||
[Coke] | m: dd 1..10; Range.new(:from(1), :to(10)); | ||
camelia | 1..10 Cannot resolve caller new(Range:U: :to(Int), :from(Int)); none of these signatures matches: (Range: Range $min, \max, :$excludes-min, :$excludes-max, *%_) (Range: \min, Range $max, :$excludes-min, :$excludes-max, *%_) (Range:… |
||
[Coke] | m: dd 1..10; Range.new(1, *); | 21:29 | |
camelia | 1..10 | ||
[Coke] | ok, that explains github.com/Raku/doc/issues/4301 | ||
someone used :from :to but it's positional | |||
Anton Antonov | @avuserow I am trying to include "SQL::Builder" as a target in my data wrangling DSL. Here is an example: | 21:31 | |
cdn.discordapp.com/attachments/633...uilder.png | |||
@avuserow I have implemented the where statements generation to be in accordance to "SQL::Builder" (documentation) yet. But where statements are also handled. (Currently Raku code is placed.) | 21:33 | ||
21:33
Altai-man left
|
|||
avuserow | That's awesome | 21:34 | |
Anton Antonov | @avuserow Now, I might have a bunch of implementation requests : distinct , count, semi-join, anti-join, long- and wide form transformations, etc. | 21:35 | |
@avuserow Should make issues at GitHub? Or you prefer to be emailed a list? Other ways? | 21:36 | ||
avuserow | GitHub Issues are great, preferably with some example output | 21:37 | |
Anton Antonov | @avuserow BTW, you can try the code generation yourself here: antononcube.shinyapps.io/DSL-evaluations/ . | ||
I understand you mean SQL code. But would you "accept" Raku code too / instead? | 21:39 | ||
avuserow | DISTINCT is on my list already. I've been treating COUNT as a function (via Fn.new('COUNT', 'column')), but maybe there's something else in mind? | 21:40 | |
PRs are welcome too 👍 | |||
Anton Antonov | Agh, you are asking me to do the work.... 🙂 | 21:41 | |
avuserow | oh, I would accept Raku examples too | ||
I have not heard of semi-joins or anti-joins, and I'm a very example driven learner, so that's the easiest way for me to wrap my head around the request | 21:42 | ||
Anton Antonov | If there is an existing "count feature" I will implemented the code generation for it. It seems I can easily include it in the constructed pipeline. | ||
You can see Raku examples here : github.com/antononcube/Raku-Data-R...s.rakutest | 21:44 | ||
avuserow | I currently write count as: $sql.from("table").select(Fn.new("COUNT", "artists")) => SELECT COUNT(artists) FROM table . TBD whether this deserves a better syntax, since this is 0.0.1 and syntax is easier to add than remove | 21:45 | |
Anton Antonov | That is probably good enough. I have to experiment with it. | 21:47 | |
21:48
n1to__ left
|
|||
@avuserow So, you run the generated SQL code in Raku sessions, or you also use separate SQL sessions? | 21:49 | ||
avuserow | I run it in Raku. I have a Cro webapp that uses this to make the SQL for e.g. search queries | 21:53 | |
Anton Antonov | I see. I use both Cro webapp (the service linked above) and a CLI script that copies the generated code in the clipboard. | 21:54 | |
avuserow | I have an experimental wrapper class for my main project that adds methods like .one, .all to actually run the queries. I'll eventually release that. | 21:56 | |
Anton Antonov | BTW, currently I "only" construct the Raku code for "SQL::Builder" (in "DSL::English::DataQueryWorkflows") -- I am not executing it order to get the SQL code itself. (I plan to do that later today.) I might suggest that your builder know how to deal with wrong arguments. | 21:58 | |
@avuserow For example, this DSL spec: DSL MODULE DataQuery; DSL TARGET Raku::SQL::Builder; load data "songs"; join with ratings by song-id; filter by title is like "Am"; sort by title; generates the Raku code: $sql.from('songs').join(:inner, ratings, :on(["song-id"])).where(title ~~ "Am").order-by("title") | 21:59 | ||
@avuserow Idially, where can just dump the given argument, e.g. select * from songs join ... where <<title ~~ "Am">> order by title. Or something like that... | 22:02 | ||
avuserow | Hm. Maybe. I have a lot of thoughts on the where clause syntax. I need to write a blog article (or two) about it at some point | 22:05 | |
it seems like you would get what you want if you emitted .where(["title", "~~", "Am"]) . It's kind of like an abstract syntax tree way of writing SQL | 22:08 | ||
but there's still some exploration and refinement to do. That's v0.0.1 for you 🙂 | 22:09 | ||
22:48
linkable6 left,
evalable6 left
22:50
linkable6 joined,
evalable6 joined
23:43
jpn left
|