This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-07-30
Channels
- # announcements (4)
- # babashka (8)
- # beginners (124)
- # calva (13)
- # cider (10)
- # circleci (6)
- # clj-kondo (193)
- # cljdoc (1)
- # cljs-dev (4)
- # clojure (50)
- # clojure-europe (28)
- # clojure-serbia (1)
- # clojure-spec (22)
- # clojure-uk (30)
- # clojurescript (11)
- # clojureverse-ops (3)
- # community-development (1)
- # conjure (5)
- # cursive (1)
- # datomic (11)
- # depstar (1)
- # events (2)
- # fulcro (7)
- # graalvm (2)
- # graphql (10)
- # helix (43)
- # hyperfiddle (14)
- # introduce-yourself (6)
- # jobs (2)
- # jobs-discuss (14)
- # kaocha (4)
- # luminus (2)
- # malli (24)
- # meander (6)
- # off-topic (4)
- # pathom (1)
- # polylith (13)
- # re-frame (6)
- # releases (1)
- # remote-jobs (1)
- # sci (14)
- # shadow-cljs (209)
- # tools-deps (30)
- # xtdb (26)
Is there the opposite function of filter
? By that I mean filter
filters items for which the predicate is true, I'm looking for a fn that would filter items for which the predicate is false.
Example: (filter even? [1 2 3])
=> (2)
, whereas (hypothetical-reject-fn even? [1 2 3])
=> (1 3)
.
Thanks guys!
Haven't seen the cheatsheet before, nice!
some might call it a cheat sheet... others, a guidebook to life
Can someone help me diagnose this porblam?
2021-07-29 20:16:40.289:WARN:oejs.HttpChannel:qtp1307785347-2565: /authenticate
java.lang.NullPointerException
at java.base/java.util.regex.Matcher.getTextLength(Matcher.java:1770)
at java.base/java.util.regex.Matcher.reset(Matcher.java:416)
at java.base/java.util.regex.Matcher.<init>(Matcher.java:253)
at java.base/java.util.regex.Pattern.matcher(Pattern.java:1135)
at clojure.core$re_matcher.invokeStatic(core.clj:4856)
at clojure.core$re_find.invokeStatic(core.clj:4898)
at clojure.core$re_find.invoke(core.clj:4898)
at jpdrills.server$convert_to_int.invokeStatic(server.clj:106)
at jpdrills.server$convert_to_int.invoke(server.clj:105)
at jpdrills.server$fn__53358.invokeStatic(server.clj:2877)
at jpdrills.server$fn__53358.invoke(server.clj:2875)
at compojure.core$wrap_response$fn__22505.invoke(core.clj:158)
at compojure.core$wrap_route_middleware$fn__22489.invoke(core.clj:128)
at compojure.core$wrap_route_info$fn__22494.invoke(core.clj:137)
at compojure.core$wrap_route_matches$fn__22498.invoke(core.clj:146)
at compojure.core$routing$fn__22513.invoke(core.clj:185)
at clojure.core$some.invokeStatic(core.clj:2701)
at clojure.core$some.invoke(core.clj:2692)
at compojure.core$routing.invokeStatic(core.clj:185)
at compojure.core$routing.doInvoke(core.clj:182)
at clojure.lang.RestFn.applyTo(RestFn.java:139)
at clojure.core$apply.invokeStatic(core.clj:667)
at clojure.core$apply.invoke(core.clj:660)
at compojure.core$routes$fn__22517.invoke(core.clj:192)
at clojure.lang.Var.invoke(Var.java:384)
at ring.middleware.anti_forgery$wrap_anti_forgery$fn__24296.invoke(anti_forgery.clj:94)
at compojure.response$eval20620$fn__20621.invoke(response.clj:47)
at compojure.response$eval20542$fn__20543$G__20533__20550.invoke(response.clj:7)
at compojure.core$wrap_response$fn__22505.invoke(core.clj:158)
at compojure.core$wrap_route_middleware$fn__22489.invoke(core.clj:128)
at compojure.core$wrap_route_info$fn__22494.invoke(core.clj:137)
at compojure.core$wrap_route_matches$fn__22498.invoke(core.clj:146)
at compojure.core$routing$fn__22513.invoke(core.clj:185)
at clojure.core$some.invokeStatic(core.clj:2701)
at clojure.core$some.invoke(core.clj:2692)
at compojure.core$routing.invokeStatic(core.clj:185)
at compojure.core$routing.doInvoke(core.clj:182)
at clojure.lang.RestFn.applyTo(RestFn.java:139)
at clojure.core$apply.invokeStatic(core.clj:667)
at clojure.core$apply.invoke(core.clj:660)
at compojure.core$routes$fn__22517.invoke(core.clj:192)
at ring.middleware.flash$wrap_flash$fn__22966.invoke(flash.clj:39)
at ring.middleware.session$wrap_session$fn__24034.invoke(session.clj:108)
at ring.middleware.keyword_params$wrap_keyword_params$fn__24076.invoke(keyword_params.clj:36)
at ring.middleware.nested_params$wrap_nested_params$fn__24134.invoke(nested_params.clj:89)
at ring.middleware.multipart_params$wrap_multipart_params$fn__24382.invoke(multipart_params.clj:173)
at ring.middleware.params$wrap_params$fn__22900.invoke(params.clj:67)
at ring.middleware.cookies$wrap_cookies$fn__23913.invoke(cookies.clj:175)
at ring.middleware.absolute_redirects$wrap_absolute_redirects$fn__24488.invoke(absolute_redirects.clj:47)
at ring.middleware.resource$wrap_resource$fn__24398.invoke(resource.clj:37)
at ring.middleware.content_type$wrap_content_type$fn__24436.invoke(content_type.clj:34)
at ring.middleware.default_charset$wrap_default_charset$fn__24460.invoke(default_charset.clj:31)
at ring.middleware.not_modified$wrap_not_modified$fn__17924.invoke(not_modified.clj:53)
at ring.middleware.x_headers$wrap_x_header$fn__22929.invoke(x_headers.clj:22)
at ring.middleware.x_headers$wrap_x_header$fn__22929.invoke(x_headers.clj:22)
at ring.middleware.x_headers$wrap_x_header$fn__22929.invoke(x_headers.clj:22)
at ring.middleware.session$wrap_session$fn__24034.invoke(session.clj:108)
at ring_range_middleware.core$wrap_range_header$fn__25623.invoke(core.clj:548)
at ring.middleware.reload$wrap_reload$fn__25114.invoke(reload.clj:39)
at ring.adapter.jetty$proxy_handler$fn__22800.invoke(jetty.clj:27)
at ring.adapter.jetty.proxy$org.eclipse.jetty.server.handler.AbstractHandler$ff19274a.handle(Unknown Source)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)
at org.eclipse.jetty.server.Server.handle(Server.java:501)
at org.eclipse.jetty.server.HttpChannel.lambda$handle$1(HttpChannel.java:383)
at org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:556)
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:375)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:273)
at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:105)
at org.eclipse.jetty.io.ChannelEndPoint$1.run(ChannelEndPoint.java:104)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:806)
at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:938)
at java.base/java.lang.Thread.run(Thread.java:832)
does that likely indicate a regex problem? or maybe a cant-cast-to-integer problem?
just off-hand, it looks like it's trying to cast a nil to an integer that it expects to be a string
Thank you. You are wise in the jedi way.
just make lots of mistakes and eventually you can start to appreciate all the different kinds of nullpointers in nature
Yeah, I have this thing:
(defn convert-to-int [s]
(Integer/parseInt (re-find #"\d+" s )))
but apparently, it's sometimes getting passed a nil
? I mean, you haven't seen the whole codebase but I can't imagine it's happening elsewhere...
so yeah, maybe if it's nil have it return 0 ?
I don't think convert-to-int
should necessarily coerce nils
where is it getting the value from?
why isn't it there?
it's a web <form>
element
with <input>
s
if you do explicitly want 0 as the default when the value isn't found, then I would make providing the default an explicit step
it's ok for someone to provide a default for "not found", but I don't think that's convert-to-int
's job
also, I find this convert-to-int
function suspicious. Why is it silently truncating the end of the string after the numbers?
> (Integer/parseInt (re-find #"\d+" "123asdf" ))
123
great question
Thanks for your help. Apparently the person who wrote this code months ago (me) was thinking something very different xD
I often look at code and think "what idiot wrote this?" (me, five years ago) 🙂
Hey I recently found a function that I wrote that I actually still like, well at least the interface, but still! 😁
haha, I have git blame inline in my editor[s]. Three years ago, when I started this job, it was always someone else. Now… its sometimes me…
That’s a good sign! It implies that we improve our understanding of what we’re doing and how we do it.
I was reading Joy of Clojure (ch5) and came across this function:
(defn neighbors [size yx]
(let [delta [[0 1] [1 0] [0 -1] [-1 0]]]
(filter
(fn [new-yx] (every? #(< -1 % size) new-yx))
(map #(vec (map + yx %)) delta))))
The function works equally well (similar time) if, on the last line, `#(vec (map + yx %))` is replaced by `#(map + yx %)`.
As both of them implements the seq API, I wonder if leaving out `vec` is just fine in such cases?how are you deciding that they work in similar time? I ask because it returns a lazy seq, and if you're not timing the consumption of that seq and the consumption is done by the repl printing the result, you'll get the same timing results no matter what you make that fn do 😉 ... but vec
converts the incoming sequence to a vector, which involves consuming the whole sequence and will be slower for larger collections. Reading the code though, it does seem like and extra call that isn't needed 😉
@U0P0TMEFJ Thank you very much for your help. Insightful point about the timing indeed! I am still wrapping my head around the minutiae of the sequence abstraction. The minutiae of which seems to be all over the place for beginners, but I do hope the bits and pieces will "compose" for me through practice so that the understanding becomes second nature. Would really appreciate it if anyone knows of any good learning resources (book, blogpost, summary, etc) on this topic. Thanks a lot for sharing.
Now that I am reading ch7 and trying out the A* implementation which utilizes the above neighbors function from ch5, I understand why it is necessary for the neighbors function to use #(vec (map + yx %))
which returns a vector instead of #(map + yx %)
which returns a lazy sequence.
This is because in the A* implementation, the output of the neighbors function would ultimately be fed into
a sorted-set and the sorted-set requires every item of the input collection (including the nested items) to have implemented the Comparable interface.
How do I check whether a file on path (that may or may not actually exist) is executable?
I'm trying to implement functionality of the which
Linux command.
(first (filter HERE-WHAT? (str/split (System/getenv "PATH") #":"))))
you can just call executable?
from babashka.fs
though instead of dealing with the interop horror from java.nio
, I think @jakub.stastny.pt_serv might already be in bb anyway (if I remember correctly from #babashka)
i’ve run into the java.lang.RuntimeException: Method code too large!
error. is there a good way to debug which part of the code has generated the too-large method?
i've got a likely culprit in mind but lets wait for the stacktrace because that will point directly at it unless things get weird with this kind of error
Yeah that's correct, I'm in Babashka.
the stacktrace shows each of the namespaces loaded: clojure.main.main (main.java:37)
and then a bunch of internal calls into at web.core$loading__6434__auto____262.invoke(core.clj:1)
which is the entrypoint for my app, then more internal calls into at web.system$loading__6434__auto____603.invoke(system.clj:1)
and then more internal calls into Exception in thread "main" java.lang.RuntimeException: Method code too large!, compiling:(agendas.clj:1:1)
, which has
(ns game.cards.agendas
(:require [game.core :refer :all]
[game.utils :refer :all]
[jinteki.utils :refer :all]
[clojure.string :as string]
[clojure.set :as clj-set]))
game.core exports a lot of functions. will that do it?
so the compiler is compiling the dependencies of that namespace and is running into an error because something is expanding to a single function that is too long
i can’t get a repl running because of this. i’ll see if :verbose
works in the namespace definition
i don't believe your problem is in how many functions are in a particular namespace but that one individual one is too large
okay, it shows the output. the output is quite large because of all of the required namespaces
sure. hopefully right before the error it will say which namespace it is trying to load?
the final bit is (clojure.core/refer 'potemkin :refer '[import-vars])
i should say that this has been working fine up until i created two new namespaces and used import-vars
to import/export them as well
if i comment out those two import-vars
calls, the project loads again
and the require
verbose call shows this:
(clojure.core/refer 'potemkin :refer '[import-vars])
(clojure.core/refer 'game.core :refer ':all)
so that (clojure.core/refer 'game.core :refer ':all)
call is where it’s failing
that prevents the code from being required which prevents the code from being compiled.
What do you mean?
there's a clojure form that when expanded and compiled produces too much bytecode for a single jvm method. It is not compiled until you require its namespace somewhere. By not requiring the namespace you avoid this problem
but now i'm starting to doubt if refer
does the requiring. so perhaps i am wrong here
clojure.core/refer
definition is here: https://github.com/clojure/clojure/blob/clojure-1.10.1/src/clj/clojure/core.clj#L4217 and i can’t tell exactly how it works
the final line seems to call a different refer
i’m using the potemkin function import-vars
to export all of the methods from the numerous sub-namespaces in the engine. using a quick-and-dirty search, looks like i’m exporting 576 functions lol
Total beginner here. Trying to practice some problems at work during lunch break on Code Wars and working out my code in a Clojurescript online REPL. I have a problem where I need a function that takes two strings, finds only the unique characters in both, sorts them alphabetically and returns that new string. So far I have this which evaluates what I want in the REPL:
(str/join "" (sort (distinct (apply concat (str/split s1 #"") (str/split s2 #"")))))
But then when I add the rest of the function, I get back nil in the REPL and in the Code Wars evaluation I get the error: "java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Character"
(defn longest [s1 s2]
(str/join ""
(sort
(distinct
(apply concat (str/split s1 #"") (str/split s2 #""))))))
Can anyone help me with what I am not properly comprehending? (apologies as I am sure my formatting surely is incorrect)
@U01BQJWGV16 evaluate the forms from the inside out: start with (str/split...)
then (apply concat (str/split...))
and so on
ahh, you said you are in a Clojurescript REPL! that explains why you’re not getting the error. here’s what happens: when you call
; eval (current-form): (apply concat (str/split "asdf" #"") (str/split "dfgh" #""))
("a" "s" "d" "f" \d \f \g \h)
you can see that the first half looks differentwhen you do (apply concat ...)
the second (str/split...)
will pass each character of the String to concat
, and in Java char
s are not the same as Strings (first half of the array are Strings, second half are char
s)
so after apply
the call will look like this: (concat (str/split "asdf" #"") "d" "f" "g" "h")
, so each 1 character String is interpreted as a collection of 1 char!
changing the code to use just concat
instead:
; eval (current-form): (concat (str/split "asdf" #"") (str/split "dfgh" #""))
("a" "s" "d" "f" "d" "f" "g" "h")
and you see that they now look the samethis doesn’t happen on Cljs because Javascript doesn’t have a separate types for Strings and Characters, it’s all String.
my take 😄
(defn longest [s1 s2]
(->> (into (str/split s1 #"") (str/split s2 #""))
distinct
sort
str/join))
Loving all the valuable insight here, sure beats being confused by yourself 🙂 Thank you both!
oh yeah, I guess that isn't needed. Not exactly sure, just sort of fumbling around through the cheatsheet
Actually I'm pretty sure that's the only issue (I'm not near a repl to test things out right now)
How to handle name collision like this: db_ because of db is already used. Is there some macro to bypass it ?
(fx/defn remove-account
{:events [:account/remove]}
[{:keys [db]} uuid]
(let [db_ (update-in db [:accounts] dissoc uuid)]
(persist-accounts {:accounts (:accounts db_)})
{:db db_}))
I saw the db’ flavour to. But I cannot remember where it is advocated. I know in Python, mostly people will use the underscore such as db_.
I think it's a haskell thing. It was introduced by my other engineer and I just kinda picked it up
@UGC0NEP4Y Hard to find open source examples, but using the same name tells me that I'm transforming the value. The db
value travels starting as the arg, then is transformed in the let
and finally returned.
If one had another transformation of db_
in the let, one wouldn't bother finding another name for it, I guess the same logic applies when it starts as the arg itself
if this were an effect (and maybe i'm using the wrong terminology, its been a bit since i've been doing re-frame) i would expect to see {:db db' :persist-accounts (:accounts db_)}
and dispatch to that effect from what i think is an event here?
There’s also an ergonomic reason for db'
over db_
- the underscore needs an extra keystroke. But yes, as @UMPJRJU9E suggests, using the same symbol is fine if we are transforming to a next version of the same thing, and we don’t need to refer to both values at once.
What am I doing wrong? (letfn [(^{:doc "Doc string"} doc-fn [] "body")] (meta #'doc-fn))
=> nil
. I expected the hash with :name
, :doc
and the likes.
For context, why I'm not using the defn
macro: This is just some code in the rich comment block, I don't want anything to bubble up into the global namespace. (Plus I want to be able to C-x C-e
to eval last sexp.)
Running this is a clean repl, I get:
Syntax error compiling var at (REPL:1:50).
Unable to resolve var: doc-fn in this context
Which makes sense, because #'doc-fn
is specifically looking for a var, but you don't get a var with letfn
I'm not sure I understand your use case 100%, but using regular 'let' and 'fn' works fine:
(let [doc-fn ^{:doc "Doc string"} (fn [] "body")] (meta doc-fn))
{:doc "Doc string"}
letfn
is not just a shortcut combining let
and fn
; it's a special construct that allows for a local recursive function definition.
Thanks @U7ZL911B3, I'll go with let
then.
@jakub.stastny.pt_serv: Please if you find some time, can you explain the syntax you are using.... ? I am new and I don't follow your code at all... I'll greatly appreciate it!!
@U022LK3L4JJ sure man. So my original code was built on the assumption that letfn
is simply a macro for let
+ fn
(just like defn
is a macro for def
+ fn
), but as @U7ZL911B3 pointed out, it's not.
My objective was to get an alternative of (defn doc-fn "Doc string" [] "body")
, but as a local variable using let, rather than a global one using def.
Now (defn doc-fn "Doc string" ...)
is a shorthand for (defn doc-fn ^{:doc "Doc string" ...)
. This is CJ syntax for metadata. The :doc
is a common one, :private
would mark a private function (there's a shortcut for it as defn-
) and :name
would contain the fn name, so doc-fn
in here.
And (meta '#<fn-name>)
is how you get the metadata. For instance you can try (meta #'str)
in the REPL and see what comes out.
A thing to know about the metadata is that they are bound to the reference itself, not to its value. So if you do (let [my-fn str] (meta my-fn))
, it will return nil, as the metadata are in the reference of str
and not its value and don't get copied when we assign str
to another variable my-fn
.
Does it make sense? Feel free to ask more. Anyway this is my understanding, I'm new to CJ, so take with a grain of salt.
ok so ^ is for metadata... Why would you need to use something like this? ... if you don't mind me asking...
@U022LK3L4JJ the code is here https://github.com/jakub-stastny/dev/blob/literate.dev/build.org#give-for-review, look for defn fun
if you want some context.
Essentially I have these helpers to either run a shell command (`run`) or a CLJ fn (`fun`). Both are meant to print out what they are running.
I wanted fun
to print out name of the function it is running and it's doc string.
So (defn download-github-gpg-key "Gets the GH GPG key that's required for installation of GH CLI tools" ... )
has both :name
and :doc
in its metadata.
I was wondering whether I could simply pass the fn name and get metadata from it like so: (fun download-github-gpg-key)
, but it's not possible, because the metadata is attach to the reference itself and once you bind it in the definition to another reference (say fn-name
), its metadata won't be bind to it. So that's why I have to pass the metadata separately from the fn-name
thus: (fun (meta #'download-github-gpg-key) download-github-gpg-key)
Of course here I use it in a (comment)
block (rich comments), for testing only, so I do not want to define a global fn, but only a local one, that's why all the weird things with let
.
thanks for the explanation Jakub. I'll look it up!!
is there a library/plugin that does what slamhound did? I want to expand my :refer :all
namespace requires into fully specified :refer
vectors
but just a bit of personal style that i think is far better and might even be widespread, this is a bad pattern and just use an alias.
Hey all, trying to store some data compactly (some pen and paper RPG character sheet stuff for some fun learning projects) and am wondering about the most idiomatic way to store a collection of data. The map version would be something like { :ns.skill/name "Name of the Skill" :ns.skill/base-stat :ns.stat/agility :ns.skill/value 13} ... was thinking it'd be nice to write it as a vector like ["Name of the Skill" :agility 13] then process it, but not sure if that's suitably idiomatic. Any thoughts?