This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-05-19
Channels
- # aleph (11)
- # announcements (1)
- # babashka (9)
- # beginners (90)
- # calva (6)
- # clj-kondo (24)
- # cljs-dev (26)
- # clojure (92)
- # clojure-europe (48)
- # clojure-nl (1)
- # clojure-spec (4)
- # clojure-sweden (2)
- # clojure-uk (41)
- # clojurescript (60)
- # code-reviews (1)
- # conjure (6)
- # core-logic (3)
- # datascript (1)
- # datomic (3)
- # deps-new (1)
- # depstar (4)
- # dirac (3)
- # emacs (8)
- # fulcro (1)
- # helix (27)
- # introduce-yourself (2)
- # jobs (1)
- # off-topic (4)
- # pathom (2)
- # polylith (8)
- # re-frame (3)
- # remote-jobs (1)
- # shadow-cljs (5)
- # spacemacs (2)
- # tools-deps (22)
- # vim (3)
- # xtdb (27)
https://clojuredocs.org/clojure.core/use No, it is only for clojure namespaces.
@U04V4KLKC I referred few documents , and I did not get when to use :require
and :use
the only difference is that use
also refer to each function from namespace.
(use 'clojure.string)
(join "," ["a" "b" "c"]) ;; => "a,b,c"
but with require you have to use fullyqualified function name
(require 'clojure.string)
(clojure.string/join "," ["a" "b" "c"])
usually, best practices of clojure suggesting to not use use
but use require
with :as alias
modifier
What’s the most idiomatic way to thread a function if it exists - something like
(-> foo
...
#(if sorter (sort sorter %) (identity %))
...)
I made some-as->
(like some-> and as-> combined). It will short-circuit on nil
https://github.com/raspasov/alexandria-clj/blob/main/src/ss/core.cljc#L111
the "else" above is (identity %)
. My imagination fails me: how will that be different than %
? Otherwise, your approach seems fine.
Is there something like when
for this kind of usecase?
In a world like Common Lisp where sort
is destructive we could use when sorter sort X
knowing X will either get sorted or sail on untroubled as is, but not so with clojure.
well, kind of depends on the whole thing
this is the only conditional item, but there’s only like 4 things in the macro
could switch to as-> too
or lift it out into let
(let [f (if sorter (sort sorter %) (identity %))]
(-> foo
...
f
...))
not sure if i asked this before, but is there a way to name a reify-produced class?
just asking because when i have multiple things reified in the same namespace, it is impossible to tell from the stacktrace which one of them caused trouble
you can customize toString and you can put it inside a named parent
user=> ((fn foo [] (reify Object (toString [_] "a foo"))))
#object[user$eval142$foo$reify__144 0x7fab4be7 "a foo"]
notice that foo shows up in the class name, and "a foo" shows up as the second half of the #object data
(defprotocol Foo (foo [_]))
(foo (reify Object (toString [_] "custom") Foo (foo [_] (throw (ex-info "boom" {})))))
doesn't have that tostring message in the stacktrace, nor would i expect it@dpsutton the wrapping named function addresses the stack trace identifiability
that's why I used both the fn and toString
(ins)user=> (def frobber ((fn frobber [] (reify Object (toString [_] "a frobber") clojure.lang.IFn (invoke [_] (:frobbing-error))))))
#'user/frobber
(ins)user=> frobber
#object[user$frobber$reify__153 0x432034a "a frobber"]
(ins)user=> (frobber)
Execution error (IllegalArgumentException) at user/frobber$reify (REPL:1).
Wrong number of args passed to keyword: :frobbing-error
(ins)user=> *e
#error {
:cause "Wrong number of args passed to keyword: :frobbing-error"
:via
[{:type java.lang.IllegalArgumentException
:message "Wrong number of args passed to keyword: :frobbing-error"
:at [clojure.lang.Keyword throwArity "Keyword.java" 98]}]
:trace
[[clojure.lang.Keyword throwArity "Keyword.java" 98]
[clojure.lang.Keyword invoke "Keyword.java" 110]
[user$frobber$reify__153 invoke "NO_SOURCE_FILE" 1]
...
@dpsutton @vale more complete example, showing how both the toString and the wrapping thunk help with readabilityand accidentally even showing how it is especially useful in the repl where there's no source file or line number
it's taking advantage of the fact that reify inside an fn is an inner class of that fn (which we already established can be named)
right, so if the desired thing is a readable name (like with fn), using a wrapping fn addresses that
I agree that line numbers help too, but as a workflow issue, I find it easier to go by human readable names I can search rather than line numbers
but it would be way more simple to parse and understand if they were nameable even for such cosmetic purposes
a macro can make this approach easier to read
I wonder if it's possible to solve a circular dependency between 2 functions somehow? I'm trying to do this: https://gist.github.com/Sose/b07f44536f3e97fd1307b1edfa8b5840
use declare
thanks!
Huhu, I wrote a macro, and I get an error when try to put a number in a form
Unexpected error (ClassCastException) macroexpanding q at (src/lhrb/engine.clj:327:3).
class java.lang.Long cannot be cast to class clojure.lang.Named (java.lang.Long is in module java.base of loader 'bootstrap'; clojure.lang.Named is in unnamed module of loader 'app')
for some reason it works when I substitute the number with a symbol
;; does not work
(macroexpand
'(q {:find [?num ?loc]
:where [(gr-th ?num 1000)
[?b :battle/attacker_size ?num]]}
db))
;; does work
(def n 100)
(macroexpand
'(q {:find [?num ?loc]
:where [(gr-th ?num n)
[?b :battle/attacker_size ?num]]}
db))
I figured that this is probably a silly beginner mistake, so could maybe a wise person please enlighten me? 😋 Any help is greatly appreciated
background: I wrote a micro-kanren implementation and try to give it a datomic flavored query api with the macro(defn compile-where-clauses
"transforms vector clauses into q-db queries
e.g. [?a :age 10] => (q-db db ?a :age 10)"
[clauses db]
(->> clauses
(map (fn [clause]
(if (vector? clause)
`(q-db ~db ~@clause)
clause)))))
(defn find-lvars
"finds and returns all unique logic-variables.
A logic var begins with an '?'"
[find where] ;; maybe decouple from concrete impl?
(->> (into find where)
(flatten)
(filter
(fn [s]
(str/starts-with? (name s) "?")))
(distinct)))
(defmacro q [{:keys [find where]} db]
(prn &form)
(prn &env)
(let [;; test if vars in find clause are also in where clause
lvars (find-lvars find where)
where-compiled (compile-where-clauses where db)]
`(let [~@(interleave
lvars
(map
(fn [sym]
`(gensym ~(name sym)))
lvars))]
(run
(reify-var ~@find)
~@where-compiled))))
Show: Project-Only All
Hide: Clojure Java REPL Tooling Duplicates (0 frames hidden)
2. Unhandled clojure.lang.Compiler$CompilerException
Error compiling src/lhrb/engine.clj at (331:3)
#:clojure.error{:phase :macroexpansion,
:line 331,
:column 3,
:source "/home/lukas/projects/datahog/src/lhrb/engine.clj",
:symbol q}
Compiler.java: 7023 clojure.lang.Compiler/macroexpand1
core.clj: 4012 clojure.core/macroexpand-1
core.clj: 4014 clojure.core/macroexpand
core.clj: 4014 clojure.core/macroexpand
REPL: 331 lhrb.engine/eval10264
REPL: 331 lhrb.engine/eval10264
Compiler.java: 7181 clojure.lang.Compiler/eval
Compiler.java: 7136 clojure.lang.Compiler/eval
core.clj: 3202 clojure.core/eval
core.clj: 3198 clojure.core/eval
interruptible_eval.clj: 87 nrepl.middleware.interruptible-eval/evaluate/fn/fn
AFn.java: 152 clojure.lang.AFn/applyToHelper
AFn.java: 144 clojure.lang.AFn/applyTo
core.clj: 667 clojure.core/apply
core.clj: 1977 clojure.core/with-bindings*
core.clj: 1977 clojure.core/with-bindings*
RestFn.java: 425 clojure.lang.RestFn/invoke
interruptible_eval.clj: 87 nrepl.middleware.interruptible-eval/evaluate/fn
main.clj: 437 clojure.main/repl/read-eval-print/fn
main.clj: 437 clojure.main/repl/read-eval-print
main.clj: 458 clojure.main/repl/fn
main.clj: 458 clojure.main/repl
main.clj: 368 clojure.main/repl
RestFn.java: 137 clojure.lang.RestFn/applyTo
core.clj: 667 clojure.core/apply
core.clj: 662 clojure.core/apply
regrow.clj: 20 refactor-nrepl.ns.slam.hound.regrow/wrap-clojure-repl/fn
RestFn.java: 1523 clojure.lang.RestFn/invoke
interruptible_eval.clj: 84 nrepl.middleware.interruptible-eval/evaluate
interruptible_eval.clj: 56 nrepl.middleware.interruptible-eval/evaluate
interruptible_eval.clj: 152 nrepl.middleware.interruptible-eval/interruptible-eval/fn/fn
AFn.java: 22 clojure.lang.AFn/run
session.clj: 202 nrepl.middleware.session/session-exec/main-loop/fn
session.clj: 201 nrepl.middleware.session/session-exec/main-loop
AFn.java: 22 clojure.lang.AFn/run
Thread.java: 832 java.lang.Thread/run
1. Caused by java.lang.ClassCastException
(No message)
by default, the REPL presents a one or two line summary, but fuller information is available in the trace, including which line of your source file threw an exception
so, I am already going to qualify this ^ In the specific case of ClassCastExceptions and NullPointerExceptions, sometimes the JVM elides traces 🙂
this is the output from *e
#error {
:cause nil
:via
[{:type clojure.lang.Compiler$CompilerException
:message "Unexpected error macroexpanding q at (/home/lukas/projects/datahog/src/lhrb/engine.clj:331:3)."
:data #:clojure.error{:phase :macroexpansion, :line 331, :column 3, :source "/home/lukas/projects/datahog/src/lhrb/engine.clj", :symbol q}
:at [clojure.lang.Compiler macroexpand1 "Compiler.java" 7023]}
{:type java.lang.ClassCastException
:message nil}]
:trace
[]}
somewhere in your macro you're asking for the name
of a symbol, but calling it on a number (which are Longs in clojure)
it's a speed thing. Prod code never throws ClassCastExceptions, so the JVM optimizes for not filling out full stack traces.
good parsing library? I searched online and found https://github.com/Engelberg/instaparse but it hasn't been updated in a while. is it abandoned or is it just so finished that it hasn't needed any updates recently? I wanna parse a simple imperative language (for moving a turtle)
okay, thank you
@UQDFC6V4Z You’ll find a lot of Clojure libraries that haven’t been updated in ages — Clojure folks value stability and also tend to like libraries that solve one problem “completely” and therefore can be “done” and not need constant updates. It always looks strange to folks coming from language backgrounds where there is always a lot of “churn” on libraries.
We use Instaparse heavily at work for our custom search rules (driving 40+ online dating sites).
@U04V70XH6 thank you! should be good for my toy program then 😄
I am really happy now to see a library with an old Last commit. I only have a doubt with dependencies. I guess an ideal library have very few dependencies but in most cases there are. For instance version of clojure clojurescript and reader. So what is your practise concerning these dependencies ? Do you update them manually ?
I usually don’t bother much about whatever version of tools.reader
is pulled in these days. I have a top-level dependency for Clojure (or ClojureScript) so that takes precedence over whatever any libraries bring in (I’m using the CLI / deps.edn
).
We’re still here and generally respond to important bug reports 🙂 Also I answer questions in #instaparse sometimes
Anyways you guys rock, and thanks a lot for helping strangers on the internet you are great :hugging_face:
in the repl, (clojure.repl/pst *e)
is often more readable than *e
(and does some other useful things like eliding top frames related to error throwing)
And -XX:-OmitStackTraceInFastThrow
is a jvm option. You start a jvm with this option
Any great libraries or repos for beginners to play around with to learn, particularly through projects?
I’d be very curious about any libraries that analyze quantitative data. Statistics is super interesting to me, but I’m interested in just about anything that’s fun to play with
Hey all, I was wondering if there is a way in Clojure to convert a function back into it's source string, as in
user=> (defn foo [] (println "foo"))
user=> (clj->str foo)
"(defn foo [] (println \"foo\"))"
sometimes you can look up the source (if it is still around via a file somewhere) via metadata on foo
I tend to prefer conde and usually use fresh with no lvars, but likely should be using all
user=> (doc source)
-------------------------
clojure.repl/source
([n])
Macro
Prints the source code for the given symbol, if it can find it.
This requires that the symbol resolve to a Var defined in a
namespace for which the .clj is in the classpath.
Example: (source filter)
nil
user=>