This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-03-30
Channels
- # announcements (8)
- # babashka (102)
- # beginners (312)
- # calva (9)
- # clj-kondo (9)
- # cljfx (7)
- # clojure (128)
- # clojure-europe (52)
- # clojure-nl (2)
- # clojure-norway (2)
- # clojure-spec (5)
- # clojure-uk (4)
- # clojurescript (13)
- # conjure (5)
- # cursive (5)
- # datalog (18)
- # datomic (8)
- # emacs (1)
- # events (3)
- # fulcro (16)
- # graphql (2)
- # gratitude (1)
- # helix (16)
- # inf-clojure (17)
- # introduce-yourself (9)
- # java (11)
- # lambdaisland (3)
- # leiningen (3)
- # lsp (8)
- # malli (3)
- # membrane (7)
- # missionary (26)
- # nextjournal (1)
- # off-topic (19)
- # pathom (3)
- # polylith (13)
- # portal (16)
- # reagent (39)
- # reitit (2)
- # releases (23)
- # remote-jobs (1)
- # shadow-cljs (40)
- # specter (3)
- # sql (12)
- # tools-deps (8)
- # tree-sitter (1)
- # vim (3)
- # web-security (6)
- # xtdb (16)
I have a database connection pool I am messing around with in the REPL. Is there any sort of sophisticated way to view active resources such as a database connection pool or open files, etc etc, beyond inspecting things namespace by namespace? I'm finding keeping track of what is in the REPL quite difficult.
You could use something like Integrant to orchestrate each and their dependencies. Then you can initialize and destroy them as you like. I'm sure there's a “check state” function
From the looks of it, it might store the state of the of each component on metadata of the config map
I’d rather choose a proper component management library, e.g. integrant, mount, component or clip, instead of just storing the component state in metadata :thinking_face:
the concept of https://github.com/weavejester/integrant is interesting and worth take a look, instead of just an service component management tool, it can be used as a general dependency injection micro-framework
If you want loops, try https://clojuredocs.org/clojure.core/loop/https://clojuredocs.org/clojure.core/recur
Depending on your purpose.
If you're generating a sequence, for
If you're accumulating a value, reduce
If you're just iterating for a side effect, doseq
If you don't know when you're going to finish, loop
/`recur`
Of course, every case is different, so there are no hard and fast rules. But I generally prefer to focus on clojure.core functions before loop
/`recur`
There are many looping constructs. A few more
dotimes
if you want to repeat the same thing n number of times
while
a typical while loop that lets you repeat code with side effects
iterate
if you want f(f(f(f(x)))))
any number of times
It's useful for cutting an outer loop rather than an inner loop.
(for [x (range 5) y (range 5)] [x y])
generates coordinates from 0,0 to 4,4.
(for [x (range 5) :when (odd? x) y (range 5)] [x y])
Only generates for x of 1 and 3. It doesn't even try to run y from 0-4 for the unwanted even values of x.
If the :when
were at the end, then the output here would be the same, but the inner loop would run right through 0-4 for the unwanted values of x (i.e. twice the work)
Sorry, I typed all of the above on a phone. I just got on a computer, and see that the conversation has moved on, but I still don't think the :when
was considered fully. But here's my example:
(for [x (range 5) y (range 5)] [x y])
Gives you:
([0 0] [0 1] [0 2] [0 3] [0 4] [1 0] [1 1] [1 2] [1 3] [1 4] [2 0] [2 1] [2 2] [2 3] [2 4] [3 0] [3 1] [3 2] [3 3] [3 4] [4 0] [4 1] [4 2] [4 3] [4 4])
If we filter by (odd? x)
then we see:
(for [x (range 5) :when (odd? x) y (range 5)] [x y])
([1 0] [1 1] [1 2] [1 3] [1 4] [3 0] [3 1] [3 2] [3 3] [3 4])
(for [x (range 5) y (range 5) :when (odd? x)] [x y])
([1 0] [1 1] [1 2] [1 3] [1 4] [3 0] [3 1] [3 2] [3 3] [3 4])
Same, right?
So now, let's put a side-effect into the range for y
and see how it gets called...
(for [x (range 5) y ((fn [] (println "\nx=" x) (range 5))) :when (odd? x)] [x y])
(
x= 0
x= 1
[1 0] [1 1] [1 2] [1 3]
x= 2
x= 3
[1 4] [3 0] [3 1] [3 2] [3 3]
x= 4
[3 4])
(Sorry the output is messy)
Notice how x
appears for all 4 values? Now let's filter before the y
:
(for [x (range 5) :when (odd? x) y ((fn [] (println "\nx=" x) (range 5)))] [x y])
(
x= 1
[1 0] [1 1] [1 2] [1 3]
x= 3
[1 4] [3 0] [3 1] [3 2] [3 3] [3 4])
that’s why https://clojuredocs.org/clojure.core/for stated that, it is list comprehension
for(int x = 0; x < 3; ++x) if(x > 2) for(int y = 0; y < 3; ++y) if(y < 1) { do something}
(for [a (range 10) b (range 11)] (+ a b))
= (mapcat (fn [a] (map (fn [b] (+ a b)) (range 11))) (range 10))
I would avoid drawing any equivalency between a for loop and a for list comprehension
its purpose is different than a C/C++ for
. Its just for transforming a sequence of data and getting a new sequence out.
A list comprehension is a basically a dsl for composing list processing operations (map, mapcat, filter, etc) to build a new list from some given lists
The key thing to understand with for, is the order of clauses in the dsl determines how they would be nested when but from map, filter, and mapcat
I just have to re-implement this functionality in C so I’m trying to understand it completely
If you have implementations of map, filter, and mapcat the easiest thing is to have the for macro expand into those calls
I first read the for description and I was like… yeah I’m gonna do this later. And here we are
No, that is invalid syntax. But you can say:
(for [x (range 3) :when (> x 1) :when (> x 2) y (range 3)] ...)
Of course, this is an empty sequence, but if the first range moves up to 4, then it works:
(for [x (range 4) :when (> x 1) :when (> x 2) y (range 3)] [x y])
([3 0] [3 1] [3 2])
I thinking writing your own lisp is a great project, and looking at clojure for inspiration while doing it is great, but saying it is clojure when you don't know clojure might not be a the best plan
I’m an experienced coder of many languages, this is my first interaction with clojure of course
I found that I made a lot more progress after I stopped trying to find analogous constructs from other languages
If you are going to claim to be faster then clojure on the jvm, then I think you need to be clear about what your benchmarks are. And I would be shocked if you are new to clojure if you are benchmark it well. But even what "well" means can be debated(start up performance, before jit after jit, jit agnostic, etc)
though the implementation is incomplete, so who knows if that will still be a 2x perf gain vs JVM when I’m done
Like, as a beginner, maybe you are just typing stuff in the repl, benchmarking the special cases interpreter clojure uses for simple forms in the repl, when most complex clojure programs are compiled to jvm bytecode and then fed to the jvm and then host loops are chewed through by the jit
Like I said, depending on what you are testing, you may just be testing in a way that is slow
And being a beginner you don't know that, and don't give any details of your benchmarking in the readme
meaning, embeddable inside another program written in some other language with minimal overhead and fuss and compiling nonsense
If it's in a JVM language, then there are APIs for this. If it's on a Javascript (or Javascript compatible) system, then that's supported too. If it's in a binary system, and you don't want to start a VM, then there are better languages, such as https://ferret-lang.org/ (which was built to be a native Clojure)
I mean, I've been hanging out in various clojure channels since the early days, I've watched lots
@zelexi - quick question. You’ve about 3000 lines of code, but I don’t see any tests. How do you detect/handle any regression? It looks like you’ve implemented persistent vectors and bi directional persistent vectors too. How do you verify expected behaviour?
Thats on the TODO, and if there is a good set of test programs to run which do that, please point it out
I mean, as of now, you’ve benchmarked, but how are you so sure that what you are benchmarking works to begin with?
There are no tests at all for any of the vectors stuff
Why not test the C++ code itself? I mean, testing your interpreter for correctness is one thing, but there’s so much code out there, that it might make sense to write at least a few unit tests maybe? At least that’s how I feel like I have a grip on things
why not stick a target in your Makefile and make it repeatable instead of commenting out some where?
Oh, I missed the link to jo_lisp. Nice. I mentioned in a thread that this sort of thing https://ferret-lang.org/#outline-container-sec-2, but I'm almost thinking I shouldn't say so, since I think that it's always worthwhile trying these things again. After all, it's always a valuable learning exercise, and anyone can potentially come up with ideas that other people haven't had before!
That’s good to hear. I would just hold off on benchmarking or saying anything public yet. The clojure community is generally quite welcoming, but you’d definitely ruffle a few feathers if you make bold claims and your Makefile is 3 days old
https://janet-lang.org/ is by the author, and more clojure-like (and probably the most embeddable clojure-like atm - great C interop) - edit: correction - fennel === janet author - ferret is not - should have double checked before commenting (ferret seems to keep parity with clojure while janet/fennel diverge)
If you need to be in C/C++, having these options are amazing - problem with any of the C-buddy langs as an option for general computing is that it's very hard to compete with the ecosystems/momentum of the higher level languages (even if they may be less performant) - I like using janet or bb for various things since they both have fast startup, but languages are never really competing in a 1 on 1 void of lang vs lang - its always lang+ecosystem vs lang+ecosystem, and its difficult for any ecosystem to beat out npm or maven (and stack clojars/gitlibs on top)
And anybody else who wants it, but even if it's only me that finds it useful, that's good enough for me
I think that's awesome - I just caught the tail end of the conversation and the mention of ferret-lang - are you transpiling into generated c/c++, or making a VM/bytecode layer?
This is exactly the use case of babashka. (Hence the "bash" in the middle of the name).
It's a binary (yes, built with the graalvm compiler, but you don't have to do that. You can just download the binary), it starts instantly, and it does Clojure
For a long-running process, then Clojure/JVM is better, but the JVM can compete with C++ in that environment too.
its basically just one chonky file. i don't think its impossible to translate to C if that is your chosen life path. stuff like uuids and bigints would be a thing to keep in mind
Also > its the simplest embeddable method If its a C/C++ codebase yes. If its anything else then the implicit "we don't have anything resembling a package manager" state of the world is no longer true
I work with Sean Barret (author of stb libraries) we do single file libs all the time
I don't want to ruffle any religion feathers too much, sufficed to say, I don't like the JVM or java at all. It's kind of repulsive to me. I like clojure though
Don't worry, non of us work for Oracle. I get not liking java but the JVM is just a stack machine with GC and great JIT. What's wrong with that? :thinking_face:
Yeah saying any more will just spark a debate and I don't want to debate right now lol
Hey folks, try to remember to use threads for conversations please -- especially long, rambling ones that are unlikely to be of interest to most of the nearly 15K members of this channel. Thank you. /admin
![parens](https://emoji.slack-edge.com/T03RZGPFR/parens/76eec9b1397fa441.png)
In next.jdbc. I want to get camlCase key in result map
(require '[next.jdbc.optional :as jdbc-opt])
(defn as-caml-maps
[rs opts]
(jdbc-opt/as-maps rs (assoc opts :label-fn csk/->camelCase)))
(query ds ["select * from wf_run_task limit 1"] {:builder-fn as-caml-maps})
result : [{ :user_name "Jerry"}] is not :userName(next.jdbc/execute! db ["select * from starship"] {:builder-fn (fn [rs opts] (next.jdbc.result-set/as-modified-maps rs (assoc opts :qualifier-fn camel-snake-kebab.core/->camelCase :label-fn camel-snake-kebab.core/->camelCase)))})
;; [#:starship{:class "Constitution",
;; :uuid #uuid "ba91976e-a01f-4165-957a-f5d5d50ea7a3",
;; :image "ncc1701-a.jpg",
;; :created #inst "2021-05-02T19:19:25.915454000-00:00",
;; :captain "James T. Kirk",
;; :affiliation "United Federation of Planets",
;; :registry "NCC-1701-A",
;; :starshipId 3,
;; :launched 2286}
I am practising clojure ring and I am hitting a post req and getting the value in the body as rg.eclipse.jetty.server.HttpInputOverHTTP
how to retrieve the value from body? I refereed https://stackoverflow.com/questions/42829594/how-to-get-the-content-of-httpinputoverhttp-in-clojure-compojure-ring-project and added (wrap-multipart-params)
handler, my body parameter from input is :body {:Studyid 45}
struggling to google this how do i do "\" if i eval that in a repl it fails which I get so I though i would do "\\" but that prints 2 slashes I get the meaning of the slash just not how to make it a single slash, hitting an issue where I have \= in a string causing me issues.
yeah I am not using print though this is a string I have when I eval it shows 2 and it fails when i pass it to another function I assume because its also seeing 2 slashes
Oh, yeah! How peculiar. When I evaluate just \
or "\"
the REPL hangs indefinitely. Interesting. I don’t know why that happens.
yeah, I did my string was indeed wrong and the slash is actually fine when passed in, but its still a bit weird you would expect it to show the real version when you eval
I found this: https://stackoverflow.com/a/48662861/195964
user=> "ex\\*mple"
"ex\\*mple"
user=> (println "ex\\*mple")
ex\*mple
nil
I think what’s happening is that, when you evaluate \
, you evaluate the escape character by itself (Clojure uses Java strings, which use \
as its escape character). To print \
, it must be escaped, so \\
is the correct way to represent a single \
.
user=> (str "\\")
"\\"
user=> (count "\\")
1
user=> (count (str "\\"))
1
user=> (println (str "\\"))
\
nil
user=> (println "\\")
\
nil
user=> (println (str \u005C "="))
\=
nil
It prints as one \
, and the count is 1.My current understanding is that when we evaluate expressions like "\\"
and (str "\\")
, we see the escaped string meant for machine consumption in the REPL. But when we pass the same string to certain functions like println
, we see the unescaped string meant for human consumption in the REPL. The actual string is the same in both cases, but its representation is different. Perhaps a more experienced Clojurian could confirm or disconfirm and provide further clarification.
yeah certainly seems that way, one of those quirks that can catch you out when your not expecting it 🙂
Yeah! Thanks for asking this question. Although it derailed my task at work, I learned something new by digging into it ☺️
I was thinking about posting a question. Then find the answer by myself 😺. How and in which channel should I discuss such thing where I sort of have an answer?
If you think it might be interesting or useful to other beginners, then I suppose this channels is a good place for it!
Hey guys, how is it going?. Currently I'm reading an edn file as an exercise of my clojure training. Im using the following function which seems to find the file but not able to read and serialize the edn content
(defn read-edn-file
"read edn file content"
[file-path]
(clojure.edn/read (java.io.PushbackReader. ( file-path))))
The error I got is No reader function for tag [var]
.
As my research looks like there is a reader definition missing but actually I don't know what reader should i go with and how to define it. Any suggestion will be appreciatedYour EDN file has a tagged element (https://github.com/edn-format/edn#tagged-elements) that the Clojure EDN reader doesn't know how to read by default. It's difficult to say what that element is from that error message alone.
You can use the :readers
option to pass a map from symbol to function that knows how to read the tagged element.
For example:
(slurp "/tmp/bar.edn")
;;=> "{:foo #var [:a]}\n"
(clojure.edn/read
{:readers {'var (fn [x] x)}}
(java.io.PushbackReader. ( "/tmp/bar.edn")))
;;=> {:foo [:a]}
Alternatively, as a first step in debugging the issue, you can use :default
:
(clojure.edn/read
{:default tagged-literal}
(java.io.PushbackReader. ( "/tmp/bar.edn")))
;;=> {:foo #var [:a]}
Using {:default tagged-literal}
works for me
I have a question over this function {:readers {'var (fn [x] x)}}
. How do I figure out what function will be the (fn [x] x)
for each tag-literal?
So for example, in your EDN file, you could have something like this:
{:date #my/date "2022-03-31"}
Then, you could have:
{:readers {'my/date (fn [date-string] (java.time.LocalDate/parse date-string))}}
Then, when you read the EDN, every value tagged with #my/date is going to be read into a LocalDate
instance.
Uff, that looks good!!!. thanks bro. i will refactor the script to use specific readers
the map is written in the "namespaced" syntax
#:dumrat.bookkeeper{:ledger 2}
which is equivalent to
{:dumrat.bookkeeper/ledger 2}
Is there a more up to date version of https://cognitect.com/blog/2013/06/04/clojure-workflow-reloaded available? I've been sort of doing this with my own component system to just mess around with the system in the repl (without the reloading of various namespaces). Has anything majorly changed since this was written?
not to my knowledge, although I'd suggest ideas from https://clojure.org/guides/dev_startup_time can help a lot with startup time
I am passing a hash-map from a one end-point to another using compojure as {:study-id 1 name "john"}
but when I recieve it another end point it is converting hash-map to the string type, How can we overcome this problem?
Can you share some code please?
I guess you mean you call one handler function from another? Maybe updating the request
parameter? How exactly?
How can I understand #' ? I saw it from https://clojure.org/guides/weird_characters#_var_quote and I known #' is var. but in realword project's code I can't understand it. like this:
(->> params
(#'profile/create-profile conn)
Why use #' or not use like as:
(->> params
(profile/create-profile conn)
(defn foo[x y]
(+ x y))
(foo 1 2) =>3
(#'foo 1 2) =>3
Why use the #'#'profile/create-profile
is referring to the reference itself, here that's the symbol profile/create-profile
Although you can invoke a function with the #'
, that's only really used to add to read metadata to it from it.
profile/create-profile
= I'm referencing the value this symbol points to.
#'profile/create-profile
= I'm referencing the symbol itself.
https://replit.com/@mruzekw/ClojureVarExample#main.clj Look at this http://repl.it, first run will be slow because it's pulling down all the deps
Both the var and the fn value implement function behavior. But the var quote can help you with rebinding with the REPL: https://clojure.org/guides/repl/enhancing_your_repl_workflow#writing-repl-friendly-programs
also here for reference: https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Var.java#L20
Thanks, for reply. I know #'profile/create-profile
= I'm referencing the symbol itself.
I don't understand Both are function calls, Why is use '# or not direct call function use name.
(defn create-profile*
([i] (create-profile* *pool* i {}))
([i params] (create-profile* *pool* i params))
([conn i params]
(let [params (merge {:id (mk-uuid "profile" i)
:fullname (str "Profile " i)
:email (str "profile" i "[email protected]")
:password "123123"
:is-demo false}
params)]
(->> params
(#'profile/create-profile conn)
(#'profile/create-profile-relations conn)))))
why not direct call function like this:
(->> params
(profile/create-profile conn)
(profile/create-profile-relations conn))
I don't see the difference, so I'm confusedNot sure about your specific example, but there are two tricks to use #'fn-var
instead of fn-var
directly:
• Accessing private vars. If your namespace defines a function using (defn-
, it will be private, and not callable from other namespaces. Accessing the var with #'
will still be possible though. This is often used in tests, to test private functions from a separate test namespace. Maybe profile/create-profile
is private in your case?
• Keeping indirection. When resolving a symbol to a function, to pass this function to another function, updating the original var will not cause this already resolved “old version” to be updated. For example, Ring server adapters take a handler function: (start-server handler)
. When you now change and evaluate your handler
in the REPL without restarting the server, the server will keep calling the old handler. Using (start-server #'handler)
passes the var as a handler, and every time this var is called it will resolve to the latest version. So changing the defn
of handler
will immediately be reflected without restarting the server.
rephrasing something more succinctly: when using a var, the current value is looked up before every call, when calling the function, the lookup happens only once if the function was an argument passed in
(cmd)user=> (defn foo [f] #(vector (f) (f)))
#'user/foo
(cmd)user=> (defn bar [] 12)
#'user/bar
(cmd)user=> (def captured-f (foo bar))
#'user/captured-f
(cmd)user=> (def indirected-f (foo #'bar))
#'user/indirected-f
(ins)user=> (captured-f)
[12 12]
(ins)user=> (indirected-f)
[12 12]
(ins)user=> (defn bar [] 42)
#'user/bar
(cmd)user=> (captured-f)
[12 12]
(cmd)user=> (indirected-f)
[42 42]
• thank you @U031CHTGX1T The words you explain are simple and easy to understand • and @U051SS2EU thank you as same. Your code should have a deeper understanding of the above text
I have a question regarding protocols and extend-protocol
. Is there any reason to favour extend-protocol
over modifying your code that uses defrecord
? I can see that when you want to update a running Clojure instance that extend-protocol
is useful. But when updating an application I would immediately favour updating the initial call to defrecord
to implemented the protocol.
putting it in on defrecord is the fastest possible implementation
you are using exactly what Java leverages on the JVM to make virtual calls fast
but you could also say you have tightly coupled the type to the behavior
From what I read yes, you can! I just saw an example where you can extend a protocol on a boolean:
"(extend-protocol Marketable
String
(make-slogan [s] (str \" s \" " is a string! WOW!"))
Boolean
(make-slogan [b] (str b " is one of the two surviving Booleans!")))"
yes, although there is some guidance about that
https://clojure.org/reference/protocols#_guidelines_for_extension
See here for an example in the JS world where monkey patching led to problems (under 2.3): https://2ality.com/2022/03/naming-conflicts.html
Are there any resources or guidance about how to decide if a protocol should set :extend-via-metadata
to true? Should authors default to allowing extension via metadata?
if it's available for open extension, I think doing so opens some possibilities
but worth considering that satisfies?
does not catch metadata extensions
Does it affect performance?
per https://clojure.org/reference/protocols#_extend_via_metadata - these are checked in the order of direct implementation (so no change there), then metadata, then external extension. But the checks happen regardless.
we made external extension slower to add the check when we added metadata extension but that was considered and assessed at that point
For protocols that do, uh, I guess business logic sort of things, I think it is a no brainner to allow for metadata extension
awesome. that's just what I was hoping to learn. I think I have a few protocols that I think would benefit from being open to extension via metadata. Thanks! 🙏
hey need some help in why compilation is throwing error CompilerException java.lang.RuntimeException: No such var:
I just declared a constant name
If you are evaluating in the REPL you might need to reload the ns
so that the declared var is available.
hey thanks, I was able to figure out problem in my code.