Fork me on GitHub
#clojure
<
2021-03-19
>
didibus06:03:01

What would be nice is also to support :keys for sequential destructuring everywhere (not just on the vararg rest)

(let [{:keys [a b]} [:a 1 :b 2]] [a b])
;;> [1 2]

didibus06:03:48

Then it would make sense that an attempt at associative destructuring also attempts to coerce the seq into a map

didibus06:03:41

I'm imagining any attempt at an associative destructuring of a sequence would be like calling (apply hash-map [:a 1 :b 2]) on it first and then destructuring it as a map.

Alex Miller (Clojure team)06:03:09

it is supported everywhere - you just need (let [[& {:keys [a b]}] [:a 1 :b 2]] [a b])

🤯 16
Alex Miller (Clojure team)06:03:22

could the former be sugar for the latter? dunno, haven't thought about that

didibus06:03:08

Well it would make everything consistent with:

(let [{:keys [a b]}
      (list :a 1 :b 2)]
 [a b])
;;> [1 2]

Alex Miller (Clojure team)06:03:45

vectors though are both associative and sequential so gets tricky

Alex Miller (Clojure team)06:03:51

user=> (let [{a 0} [:hi :there]] a)
:hi

🤯 4
didibus06:03:55

Hum... That's true. Never thought about that, and I guess this kind of makes sense why it works for sequences and not for vectors. Though in practice seems not as useful. But I never thought of doing [& {a :a}] and now that I know, it's not a big deal, and allows both form if.you ever want to destructure the vector by its index or instead as a key/value pair map.

Alex Miller (Clojure team)06:03:26

I mean, that's not new, it's always worked liked that :)

didibus06:03:24

Haha ya, but for some reason I just never really thought about it lol. I think I assumed & was like only for function varargs, but it makes sense since I think function args are just destructured as if they were a vector.

arohner09:03:22

Can anyone recommend any books on designing Erlang systems? I’ve built a large clojure “microservices” system in Kafka+Datomic that is starting to feel very Erlang-y in terms of actors and message passing, so now I’d like to understand how Erlang and Beam handle those kinds of problems

mpenet10:03:26

Designing for Scalability with Erlang/OTP is a good one

mpenet10:03:59

it's full of little insights useful in non erlang contexts. I quite enjoyed reading it

mpenet12:03:48

oh I forgot that one: https://www.erlang-in-anger.com/ Fred Hebert is a good writter and the bits about flow control are excellent

mpenet12:03:53

and it's free...

mpenet12:03:34

but it's way more erlang centric, I guess with that one you could cherry pick parts to read

emccue19:03:06

> It is obvious that due to JVM limitations otplike cannot replace Erlang/OTP and otplike will `NEVER` be seen as Erlang/OTP alternative.

emccue19:03:39

other than the threading model - which might get patched before wet bulb temperatures kill us all - i wonder what else is a limitation

mpenet19:03:29

Per process gc/stack/heap, so isolation is quite extreme and allows some patterns hard to replicate on the jvm

mpenet19:03:17

It's also full of tricks internally to allow this share nothing approach without being wastful when operating on the same host. Also message passing works across the network natively... etc etc. I really like erlang (used it professionally) but I think it might not be a good idea to try to replicate this kind of stuff on the jvm

mpenet19:03:46

At least not now

emccue00:03:48

hmmm - so the message passing part is something that akka solves no?

emccue00:03:21

I'd agree that the ability to share memory is an issue, but you could just choose not to right?

emccue00:03:34

or like, choose not to make use of that

vemv13:03:02

Not a direct answer, but when having a "message-passey" system there's likely a pure-functional system hidden underneath (which is obviously a good thing) Many production clj codebases aren't pure-functional. If yours doesn't happen to be, perhaps you'd have it reasonably easy to make it so. The benefit being: you can create test suites that exercise failure scenarios comprehensively/generatively and instantly. This is very different to hand-crafting failure scenarios that run slowly (because they have to run kafka, datomic, spin up an aws instance, w/e)

kulminaator11:03:41

Can anyone suggest a comfortable lexer or tokenizer to parse sql like syntax?

kulminaator11:03:34

I will add a sample

kulminaator11:03:50

table public."this""is stupid": INSERT: id[integer]:5 sometext[text]:'tere2' somedate[timestamp with time zone]:'2021-03-19 12:13:07.609859+02'

slipset11:03:50

instaparse?

kulminaator11:03:52

This is output from postgres test_decoding plugin and i'm trying to avoid reinventing a lot if wheels when parsing this.

kulminaator11:03:49

It has funny oddities "" meaning an escaped double quote

kulminaator11:03:19

Instaparse looks good, will check it out

kulminaator12:03:39

Calcite probably won't do as the syntax is just similar to sql semantics, not sql itself

viesti13:03:22

I wonder if there's a json plugin for the wal/logical decoding

kulminaator15:03:36

I can not rely on being able to install plugins on source postgres database

kulminaator15:03:55

Source can be hosted postgres like rds, i can not install anything there.

ghadi15:03:36

+1 instaparse

kulminaator20:03:13

instaparse working like a champ, thanks 🙂

NoahTheDuke13:03:15

i have a function that caches the return value (with an atom). I would like to skip the cache during development so I don't have to (reset! cache {}) when I make changes. is there a preferred idiom for this kind of thing?

Jeff Evans14:03:29

I would think just have a *cache-results?* var that gets set to true for prod?

Jeff Evans14:03:47

I’m not super experienced yet but have seen that idiom in a few different projects

nilern14:03:13

Dynamic vars are slow and the thread locality can bite you

nilern14:03:30

You could put the cache or a config flag in an Integrant (or Component or...) system but it might be a bit heavyweight

nilern14:03:50

Also the Reloaded workflow with e.g. Integrant can reset the cache along with everything else

jjttjj19:03:57

I have a library function where I have two things that have a property that is required to be numeric, and I return the absolute value between them, I'm guessing I should avoid Math/abs and copy something like https://github.com/clojure/math.numeric-tower/blob/e8387dfac1757701e842a65c52b2b5596d1c9607/src/main/clojure/clojure/math/numeric_tower.clj#L104 so that it works with bigdec, etc. This question kind of answers itself, but it feels a bit wrong still to bring in that function just to get an absolute value in one spot

seancorfield19:03:43

@jjttjj Would it be a reasonable restriction on your code to only support long/double? Or do you need to support big integer/big decimal?

seancorfield19:03:12

(I suspect there’s a lot of “numeric” code out there that doesn’t work properly with the “big” variants in all cases)

jjttjj19:03:32

Technically it's extensible in a way that it might be need to support the big variants, but I suppose it's probably unlikely they'd be needed so maybe I should add the restriction

quoll19:03:07

Maybe could just use:

(defn abs [n] (if (neg? n) (-' n) n))
That goes through all the appropriate Clojure machinery and captures the edge cases (such as (abs Long/MIN_VALUE)) It’s also reasonably close to what math-tower is doing.

👍 3
didibus20:03:53

So anything else new in 1.11 appart from keyword args accepting a map as well?

jjttjj20:03:30

Personally I'm hoping for any ergonomic improvements to qualified keyword usage (https://clojure.atlassian.net/browse/CLJ-2123?filter=10021)

Alex Miller (Clojure team)20:03:42

that is probably the thing next most farthest along

👏 6
3
borkdude20:03:18

spec2......? 🙏

seancorfield20:03:31

@didibus That’s the only feature in 1.11 Alpha 1.

seancorfield20:03:10

But there are lots of things in JIRA marked for possible inclusion in 1.11 I believe. Including, possibly, map-vals and map-keys? I’ve seen those mentioned a few times.

Max20:03:40

Recently I’ve been hurting for a map-kv. (map (fn [[k v]] (…))) works fine, but it’d be nice to be able to use a #() with %1 == k, %2 == v instead

seancorfield21:03:06

I don’t like #(..) with multiple arguments — I’ll use (fn [..] ..) as soon as there are multiple arguments. I almost never map over a hash map — I use reduce-kv for that.

didibus21:03:09

Hum, seems a bit frivolous compared to just (map + (keys foo))

didibus21:03:26

But why not

imre22:03:45

I no longer wish for these since I got comfortable with transducers and came across cgrand's xforms. They could benefit libraries though

didibus22:03:30

Actually, having more transducers in core would be nice.

lilactown23:03:02

(map + (keys foo)) doesn't return a map; I would appreciate a (map-keys + foo) that produced a new map with the keys updated

didibus23:03:37

Oh, is that the idea of map-keys ? I see I see. Though reduce-kv is pretty damn close, but ya I can see it being a bit more convenient. Then I would actually like a map-kv that returned a map.

didibus23:03:50

I see. Ya, I don't know... I expect every Clojure dev to have their own "my-extra-utils" library, and this seems it could go there, amongst a bunch of other conveniences. I don't know which one are used so often that it makes sense to promote them to core or not. I wouldn't mind anyways. Though the name instinctively made it feel to me like it's mapping over the keys, not that it would become a non-lazy type preserving function.

seancorfield00:03:45

Naming is hard. But functions like this are common in “util” libraries out there. I haven’t felt a need for them in core.

seancorfield00:03:05

I’ve always just used reduce-kv for any transformation over a hash map. Well, since it was added to Clojure in 1.4 🙂

didibus00:03:25

I feel I rarely need to apply the same transform to all values in a map. Generally my maps model compound types, so the keys are specifically to distinguish the kind of values. And so I rarely need to make the same value change to all of them. With reduce-kv I can switch on the key to apply the appropriate transformation to the value.

borkdude20:03:29

btw, alpha1 does simplify function specs for kwarg functions, you can now just spec them as a map I guess. or was this just as easy before? can't remember.

Alex Miller (Clojure team)20:03:08

we still have a pending enhancement to extend keys*

seancorfield20:03:49

Looks like 31 vetted tickets marked for consideration in 1.11… including tap-> (yay!), java.util.functions interface support, #clojure/var tagged literal, lighter-weight aliasing on keywords (to help with qualified Spec names), DCL for prepl (yay!)… those are my “favorites”…

didibus21:03:27

Java.util.functions support that would be really great

borkdude21:03:27

What is DCL?

seancorfield21:03:43

DynamicClassLoader. Needed for add-libs.

borkdude21:03:02

oh I thought Dead Code ... but what does the L stand for? ;)

Alex Miller (Clojure team)20:03:01

you should not put any belief that those are meaningful

Alex Miller (Clojure team)20:03:51

consider things marked 1.11 as "top of mind" for one reason or another (some are really things possibly for 1.11, some are "important", some just had been in late consideration in the past and have been dragged along)

seancorfield20:03:31

I don’t think that list includes https://clojure.atlassian.net/browse/CLJ-1959 which has been mentioned a couple of times? map-keys/`map-vals`

Alex Miller (Clojure team)20:03:52

like I said that list likely bears little relation to what will end up in 1.11

seancorfield20:03:58

I have no expectations that all of those 31 would make 1.11. I do hope tap-> makes it in though.

Alex Miller (Clojure team)20:03:42

feature-ish wise, we've done design and some impl work on new thing related to keyword aliasing, don't really want to get into details, would rather do that when it's ready

Alex Miller (Clojure team)20:03:11

and have done more looking at java function interop, no conclusion yet on where that will end up

seancorfield20:03:24

I would guess 1.11 is 6-12 months out still at this point?

seancorfield20:03:49

Haha… You’re a lot of help! 😆

Alex Miller (Clojure team)20:03:02

we haven't decided what's in it so ... hard to estimate

seancorfield20:03:27

Fair enough. I was a bit surprised to get an alpha so soon. Esp. with a single feature in it.

seancorfield20:03:26

For now I’m using (doto tap>) anywhere I would otherwise want tap-> so I guess that’s not really “important”.

Alex Miller (Clojure team)20:03:01

generally, we prefer to do bigger things first (alphas), more bug/small things next (betas), then clean up

Alex Miller (Clojure team)20:03:27

so while tap-> is likely, you may not see it till later

seancorfield20:03:41

DCL for socket REPL and prepl would mean I could clean up my dot-clojure deps.edn file, although I take care of that in my dev.clj file now. I’m more excited about tools.build TBH than 1.11 overall 🙂

dpsutton20:03:58

what's DCL?

Alex Miller (Clojure team)20:03:14

I have a patch for that but on first review it raised more questions and got a bit bigger

Alex Miller (Clojure team)20:03:20

but yes, of interest for sure

seancorfield20:03:26

DynamicClassLoader @dpsutton

👍 6
seancorfield20:03:43

A normal REPL has that context, but socket REPL and prepl don’t.

seancorfield20:03:04

Which means you can’t use add-libs in them unless you do a little DCL dance at startup…

dpsutton20:03:39

ah fair. i stay away from that kind of stuff and just restart my repl. in practice i don't add deps very often so the invitation to classloader issues is a problem without a large payoff for its complexity

6
didibus22:03:04

I always have a case where I started a repo and forgot some lib

didibus22:03:20

I think it be an awesome feature for exploration and experimentation

seancorfield20:03:06

@alexmiller Yeah, that comment from Stu makes perfect sense. Not sure what to suggest. I took that approach in my dev.clj file — setting up the DCL before I start Socket/Rebel/Reveal etc: https://github.com/seancorfield/dot-clojure/blob/develop/dev.clj#L182-L188

andy.fingerhut20:03:18

That comment from Stu? On https://clojure.atlassian.net/browse/CLJ-2540 or somewhere else?

seancorfield21:03:00

Yes, on that issue.

seancorfield20:03:04

@dpsutton My HoneySQL REPL has been running since Jan 31st. I just restarted my work REPL today to switch from JDK 15 / Clojure 1.10.3 to JDK 16 / Clojure 1.11.0 Alpha 1 but it had been running since Feb 26th.

didibus22:03:21

I can't really think of anything major I would want from 1.11, honestly pretty content with most of Clojure 1.10. But I didn't know I wanted keyword args to work on maps before and now I really want it 😂 Definitely interested in spec2, function interface interop, and I'm intrigued by tools.build though I also don't feel I'm not getting what I need from current build tooling. Other then that I'm more into the upcoming JVM changes, project loom would be big, native image to support more code, value objects (the Jep for it even mentions Rich Hickey haha), etc. I think the overarching themes the survey often asks for, better error messages, faster startup, better performance, well I'd never say no to that. But can't really think of much beyond that in the language itself, the ergonomics, like it's all pretty damn good already 😂 Oh... I do hope one day to see a form of HEREDOC support.

didibus22:03:04

I'll keep dreaming 😁

vlaaad22:03:19

I want more runtime introspection, e.g. metrics/watchers for stuff like core.async, multimethods, namespaces

Alex Miller (Clojure team)22:03:48

A great place to describe a problem you are trying to solve and see if others have it too is on https://ask.clojure.org

Alex Miller (Clojure team)22:03:25

If many people have the same problem, then the core team becomes interested :)

didibus22:03:26

I see why keyword alias and function interface are being looked at for 1.11 then haha. https://ask.clojure.org/index.php/questions?sort=votes

didibus22:03:27

On that topic, I have found it harder since the move to ask.clojure to vote on things, because feature requests and bug fixes are hidden in the noise of generic questions.

borkdude23:03:22

@didibus what's HEREDOC support, you mean multiline strings?

3
didibus23:03:31

Multiline string that doesn't need to be escaped.

didibus23:03:14

#text DELIMITER
Here I can now write whatever I want including with " : \ \ / / (foo)
All kind of error character.
DELIMITER

seancorfield23:03:26

That would be horrible syntax in Clojure tho’…

jjttjj23:03:42

How about

#__ 
Multi
Line
Comments!
__#
🙂

didibus23:03:52

Well I don't want it for comments 😂, it's basically for embedding other languages into Clojure or for templating.

jjttjj23:03:31

Ohhh I see

henrik4212:03:41

I once did this https://github.com/henrik42/extended-lisp-reader as an experiment. Won't run anymore I guess.

danielneal14:03:56

like the js template literals

borkdude23:03:01

Just sexprs and pr-str can get you pretty far ;)

seancorfield23:03:25

One of the problems with heredoc as typically implemented is that this is currently legal Clojure:

dev=> (def foo ["""
 #_=> this is a heredoc
 #_=> """])
#'dev/foo
dev=> foo
["" "\nthis is a heredoc\n" ""]
(edited to be a better example)

didibus23:03:04

When I last thought of it, I thought a new tag reader would be best:

#text end
Whatever multiline string here.
end
So after the reader #text is encountered, you'd give a symbol which is the delimeter for the string that follows.

seancorfield23:03:36

Reader tags still require legal Clojure forms though.

didibus23:03:08

Sorry, not a tagged literal, like an additional reader form

didibus23:03:12

More like #()

didibus23:03:39

Which lets you pick the delimiter the reader will use on the next form for strings.

borkdude23:03:42

reader dispatch

didibus23:03:14

Ya, so you tell the reader the following string is delimited by this symbol.

seancorfield23:03:50

I would suggest you try actually implementing it in a fork of Clojure and see what problems you run into. I think you’ll find it far harder than it looks (and I still think it would be horrible syntax).

borkdude23:03:10

e.g.:

#+
Yolo!
+
But now you would need to escape + in your text.

seancorfield23:03:49

He’s suggesting something like #" sym unconstrained arbitrary text sym I think.

seancorfield23:03:42

(presumably with required newlines after the first sym and before the second one to make it a bit more tractable?)

borkdude23:03:50

#+EOT
yolo! "string!"
EOT

borkdude23:03:12

I think that is doable

borkdude23:03:33

This is quite easy to hack into https://github.com/borkdude/edamame or tools.reader in the dispatch table

didibus23:03:23

Ya, the user picks the delimiter, it's a bit like how as-> has you pick the name of the symbol to bind. That way the user can choose a delimeter they know their string won't contain and so they won't need to escape.

dpsutton23:03:36

perhaps the hardest part of this would be updating all the tooling that needs to know how to move over forms

☝️ 3
dpsutton23:03:24

lots of code in tooling would need to be updated and it might be quite tricky

borkdude23:03:43

this is always the case with adding new dispatches to the reader table

didibus23:03:43

Most tooling relies on tools.reader though

dpsutton23:03:44

CIDER certainly does not and that's about 40% marketshare

didibus23:03:45

But ya, it is one downsides. It also secretly open the door to things much closer to reader macros. Because tagged literal can now accept arbitrary text and parse and interpret it.

borkdude23:03:46

I bet I could hack the above idea in edamame within an hour or so, but since it will never be in Clojure, I won't even bother

😝 3
didibus23:03:23

With what else I've seen you do, I'm sure you could haha.

dpsutton23:03:35

i would be surprised in Cursive used tools reader for its structural movements and such

dpsutton23:03:22

and obviously calva/conjure/Chlorine and others don't use tools reader as well

borkdude23:03:31

Cursive probably uses something more along the lines of rewrite-clj since editors / linters etc need something more precise than s-expressions

borkdude23:03:14

calva uses clojure-lsp which uses rewrite-clj / clj-kondo (which is also based on rewrite-clj)

borkdude23:03:29

and rewrite-clj uses tools.reader but not in the way you typically do

seancorfield23:03:38

I think that’s one of the few things on ask that I’ve downvoted 🙂

didibus23:03:19

It was.you!! :rolling_on_the_floor_laughing:

didibus23:03:46

I've had two times where I really wish Clojure had it. For scripting, it is quite nice if you need to generate some file, you can template things easily with this, without needing a seperate file, which when you have a script you don't really want resources along with it and all that. And for embedding JavaScript inside Hiccup for simple server side rendered websites.

borkdude23:03:47

Early on Clojure considered XML literals I think I read somewhere once

dpsutton23:03:53

does it use that kind of stuff for movements? not analysis but for moving to the next form; for determining what "the last form" is when sending the last form

borkdude23:03:35

define "it"?

seancorfield23:03:42

Part of what drew me to Scala was XML literals. After I used them in a project, I felt they were a terrible idea! 🙂

borkdude23:03:30

@dpsutton if you want to offer any kind of refactoring, you have to know locations and preserve whitespace, exactly what rewrite-clj is for, but I assume Cursive has its own variant of this, possibly written in Java or part of some proprietary IntelliJ API

dpsutton23:03:20

i mean, if you put your caret at a paren and say "send this form to the repl", the determination of what the last form is is certainly in a js implementation of paredit or parinfer right?

dpsutton23:03:46

and this multiline string allowing arbitrarily unmatched delimiters would wreak havoc on that stuff

dpsutton23:03:19

its not impossible, but i'm just thinking of all the paredits and parinfers that would have to be updated to handle this

borkdude23:03:40

paredits also handle ;; with arbitrary text?

dpsutton23:03:41

and yes i'm not talking about analysis which will likely use tools.reader

dpsutton23:03:51

yeah that's fair

didibus23:03:10

I like your twist to it borkdude.

#+SYM
Here's the big string.
SYM
Then you could build tagged literals like:
#my/xml #+END
<xml>
  <foo bar="wtv">
<\xml>
END

borkdude23:03:10

and docstrings without escaped strings as well.

didibus23:03:21

True:

(defn foo
  #+DOC
  This function does bla
  Example:
   (foo "value" 1)
   ;;> "value1"
  DOC
[a b]
...)

p-himik23:03:03

@U04V70XH6 Could you elaborate a bit on why you felt that way? What do you think about JSX that's rampant in the frontend world right now?

seancorfield23:03:16

I hate that too 🙂

didibus23:03:13

What about ERB like templates?

seancorfield23:03:02

Scala is already fairly punctuation heavy so allowing arbitrary blocks of text full of < and > just makes for very distracting-looking code.

seancorfield23:03:07

I’ll be honest, I find large blocks of SQL embedded as strings in Clojure to be distracting too. Although we have plenty of that at work. Where we’re not using HoneySQL, that is.

borkdude23:03:12

This is why Scala chose [] for generics ;)

p-himik23:03:14

Hmm, right, I can see that. A cognitive load creep. :)

seancorfield23:03:27

Templates of any stripe are fine outside the code.

seancorfield23:03:17

Scala was trying to learn from C++’s mistake with < > for templates because of the contextual lexing issue of >>.

didibus23:03:57

Well I guess if a code base started using this for all strings. But I expect it be for rare instances. Like a quick on-click JS function inside Hiccup, or in a script where you need to create some config file from and want to quickly template it without setting up resources, and all. And for doc-strings it actually looks much cleaner to me. Seeing all the escape characters in them is distracting.

borkdude23:03:55

how do literate programming tools solve this - they must have a solution for this. do they start with foo.template.clj or so?

didibus23:03:01

I don't know, any Rubyist or Perlers? Do heredoc end up polluting things?

seancorfield23:03:19

(it will likely be unsurprising to hear that I’m no fan of literate programming either — for similar reasons)

🙃 3
didibus23:03:43

Well it seems heredoc is quite controversial. My idea was one day when I'm bored I'd make an Emacs unescape plugin instead. Where it visually unescapes things inside Clojure strings, and automatically escapes them as I type/paste (but visually won't show the escapes. Maybe this already exists actually...

borkdude23:03:10

it seems marginalia just uses comments and strings, no special stuff

seancorfield23:03:35

@U04V15CAJ Because I wanted to give it a fair whip — and used it to build an entire project at work. This came up on ClojureVerse recently, BTW.

borkdude23:03:47

cool. I have made some diagrams with http://draw.io which works on all platforms. it's not as as good as omnigraffle but it works and it's free

borkdude23:03:18

they have a desktop app too. I'm off now, g'nite.

Darin Douglass00:03:56

@didibus re Perl/Ruby heredocs: our Perl code at work, iirc, only has a few heredocs and I can’t think of any in our ruby codebase either