This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-04-25
Channels
- # announcements (4)
- # babashka (3)
- # beginners (79)
- # biff (4)
- # calva (17)
- # cider (18)
- # clj-kondo (21)
- # cljdoc (45)
- # cljs-dev (14)
- # cljsrn (9)
- # clojure (90)
- # clojure-europe (86)
- # clojure-italy (3)
- # clojure-nl (3)
- # clojure-portugal (1)
- # clojure-uk (9)
- # clojurescript (20)
- # code-reviews (23)
- # conjure (14)
- # cursive (12)
- # datascript (12)
- # emacs (5)
- # events (2)
- # fulcro (13)
- # gratitude (1)
- # holy-lambda (9)
- # lambdaisland (2)
- # malli (6)
- # nbb (1)
- # nextjournal (2)
- # nrepl (30)
- # off-topic (63)
- # pathom (1)
- # portal (24)
- # reagent (5)
- # reitit (13)
- # releases (2)
- # remote-jobs (1)
- # sci (90)
- # shadow-cljs (59)
- # spacemacs (5)
- # sql (13)
- # testing (20)
- # tools-build (17)
- # xtdb (27)
I just sumpled over nrepl/drawbridge 0.2.1 (nREPL over http(s)) not working with Leiningen 2.9.5 doing lein repl :connect
. It hangs with the message Connecting to nREPL at
- the server gets masses of requests, though.
I tried this in the project.clj
:
(defproject gungfu/mini-app "0.1.0-SNAPSHOT"
:plugins [[nrepl/drawbridge "0.2.1"]]
:managed-dependencies [[nrepl "0.6.0"]])
Or has an alternative to drawbridge emerged?Clojure now supports a socket REPL https://clojure.org/reference/repl_and_main (scroll down to section on socket server) Not quite the same as drawbridge, but maybe of use
Hi guys! Using next.jdbc query in clojure, I get results of the format down below. Now my question is how do i access the data inside #:tenant? There must be a straightforward way to do this. What am i not understanding? Thank you!
The result of your next.jdbc query is a namespaced map
. To access the data, you can: (:tenants/name result)
or (get result :tenants/name)
More informations on https://clojure.org/reference/reader#_maps
Thank you. That works fine but is there a way to simply get all the content at once without the namespace?
Like i can write a function that manipulates the data but sounds like a pretty basic thing to do
Yes. next.jdbc has specific config for this https://cljdoc.org/d/com.github.seancorfield/next.jdbc/1.2.780/doc/getting-started#options--result-set-builders
You're the best! Thank you!
@UHZPYLPU1 there is a very strong argument for keeping the namespace, which manifests when doing joins. If you join a table to another table (and those tables have similar column names), then unless you take preventative measures yourself, then there is no guarantee that the value of the column will contain the value you want.
Using namespaced keys prevents that, in addition, it's quite easy to destructure the data, i.e.,
(let [{:tenants/keys [created_at name id deleted_at]} tenants] (println created_at name id deleted_at))
....
Namespaces are good, but Clojure’s printing of “namespaced maps” are not, in my opinion. If you turn it off it is much easier to understand how to work with the data, and in my eyes easier to read:
(set! *print-namespace-maps* false)
This just changes the visualization, so instead you’d see
{:tenants/created-at ,,,
:tenants/name ,,,
:tenants/id ,,,}
Will keep all that in mind! Thanks a lot guys!
Is the something like mapcat
but for for
? I think (apply concat (for
is clunky.
I have this beauty in several codebases :thinking_face:
(defmacro forcat
"`forcat` is to `for` like `mapcat` is to `map`."
[& body]
`(mapcat identity (for ~@body)))
reduce
is closer to mapcat
than to for
, but you'll be building a single collection, without anything intermediate. With either for
or mapcat
you will have either one intermediate lazy collection that will be thrown away or a whole bunch of them.
But maybe I'm overthinking things, that happens too. :)
Thanks all 🙂
> how about common lisp loop
macro if you really want to overkill
did someone actually port loop to clojure, or do you mean clojure.core/loop?
loop in common lisp is a DSL implementing a language that definitely isn't lisp
(loop with list-a = '(1 2 3)
with infinite-list = (setf (cdr (last list-a)) list-a)
for item in infinite-list
repeat 8
collect item)
;; (1 2 3 1 2 3 1 2)
does anyone ever feel like you should be able to send into go blocks?
or can you and I just don't know the syntax?
Like
(def go-block-that-accepts-values (go (+ 3 %sent-in)))
(go (println (<! (>! go-block-that-accepts-values 5)))) ;; prints 8
like go returns a channel but AFAIK not one that can be sent into, it feels a lot like a generator but without that one useful feature
you can close over for a one-time thing, or you can give the go block a channel and send values to the channel
Thanks, I've used both of those before and they work fine. I guess if one allowed values to be pushed into go blocks, there has to be some thought put into buffering and orders, like I send a shitload of values, does it just block/explode? I send a value before it's expecting one, does it just hold it until it needs it? I send a value when it's never expecting one, does it throw?
that's why we channels with a variety of buffer choices
go blocks are kind of implicitly buffer 1 right, they'll wait until each value is pulled out to continue
go blocks don't have buffers at all
are you referring to the output channel returned by a go block?
if so, that's a channel with buffer of fixed size 1
but you can also give a go block an explicit output channel that does whatever you need
Exactly, so to make input and output symmetric since they're implicitly buffersize 1 for output, being buffersize 1 for input would be logical
they are symmetric - you can supply both to do whatever you want :)
yeah it's definitely not a concrete limitation I was just wondering whether there was another design choice that would allowed for slightly more succinct code
You should think of go as starting a sequential process. It is more akin to (Thread.)
It's like that in a primitive way. And then you can if you want build higher level abstractions on top.
(defn adder-3
[value]
(go (+ 3 value)))
(go (println (<! (adder-3 10)))
machines can take inputs or provide outputs on 0...N belts
So to be clear, in your case, you can easily achieve what you want by just wrapping a go block in a function, like in my example code above.
And to Alex Miller's point, that's often how you do it, just using a function around the go machine.
(defn some-go-process
[input-chan-0 input-chan-1 ... input-chan-N
output-chan-0 output-chan-1 ... output-chan-N]
(go
;; Take from the input chans as needed
;; Put on the output chans as needed))
The implicitly returned channel from the GO block itself is best thought as a completion signal, it tells you when the process is done, so you can block/park or poll! it for completion. And the single result it contains could be details of what the process did or didn't do, errors, etc.
Though you can also conveniently use it for process that return a single result as well, instead of taking an explicit output channel.Ok, this surprised me: [EDIT: because I’m an idiot :P] [Code deleted, but basically I was surprised because I accidentally typed in my data as a set, thinking I was typing it as a map, and was surprised that my “keys” and “values” came out mixed up.]
Notice that for the second line, the key is [2nd item of a pair] and the value is [first item of the pair] instead of the other way around.
Oh, derp, that was it. I’m getting schema data from datomic, and pulling out bits of it to generate mock data for tests, and somehow the extra #
slipped in while I was editing.
Aha, I figured out where I got myself confused:
#:foo{:abraham 1
:martin 2
:john 3}
;; Need to add a new key from the :bar/ ns, so move the `:foo` inside the curly braces
#{:foo/abraham 1
:foo/martin 2
:foo/john 3
:bar/puff 4}
just want to point out you can leave the prefix style and use other namespaces or even no namespaces
#:foo{:abraham 1
:martin 2
:john 3
:bar/puff 4
:_/no-namespace 5}
so how do you refer to the namespace called _
?
do you just not?
i was thinking about that. its a legal keyword :_/foo
. Not sure if it is expressable in this instance
Yeah, seems to be the case
I moved the prefix inside the braces, but left the #
in front, so my map is now a set, and I didn’t even notice.
LFMF.
ya, it’s one of the only objectively bad things in the language, imo
It's actually the default
The clojure.main repl overrides it
Anyone know if there’s anything better/more mature than clojail these days for sandboxing clojure exprs?
ah nice, i haven’t checked it out. use case: I am reviving an old project where I scraped a ton of s-expressions from the #clojure IRC channel’s logs, and then ran everything that looks like a valid sexp in a sandbox. i then captured the values and outputs of each of them, and made the result searchable
as of 1.5.1 I got to about ~32,000 working expressions, looking to make another pass on this with latest clojure
one thing i don’t immediately see in SCI is a notion of a timeout. plenty of expressions in the input set run for an infinite amount of time
I know that someone has tried using clojurescript + https://www.stopify.org/ for this purpose. Not sure how well it worked.
I know sci is sometimes mentioned as a sandbox tool, but I haven't seen anything that demonstrates what usage might be safe or demonstrate that "safe" usage exists. Since sci relies on an uninterpreted clojure.core library, I don't think it's realistically possible to prevent non-terminating programs or programs that consume arbitrary amounts of memory. Another approach is to set restrictions at the OS process level.
Is there an alternative to using dynamic variables if I want to pass a state as part of a test fixture?
A couple of weeks ago I had the same question. After reading the source code of clojure.test
, the relevant documentation, examples, and other materials, it seems that dynamic variables are the way to go.
is there ever any use in calling bounded-count
on strings? my understanding is that strings are Counted, and thus O(1) for count
(I think alex was saying "correct" to your last clause @U06DQC6MA -- there's no need to call bounded-count on strings)
clojure.core/count
should be O(1) runtime on strings, but because clojure.lang.RT/count Java method has an O(1) implementation for it.
Yeah, but strings do not implement the Counted
interface, so looks like bounded-count
would be linear time on strings.