Ah I think I have it, should have been
(defne nevero [] ([] (nevero)))
Most likely you have evaled one in a namespace already and so now there was already an alias in that namespace.
Usually, keyword namespaces are not meant to be programmatically manipulated and interpreted in "parts". This is a subject that comes up once in a while e.g. in clojure.spec discussions, but my understanding is that this is not something the Clojure Core team feels is a good practice, so you won't find a lot of clojure.core functions to manipulate the namespace as a hierarchy of segments.
To not go against the grain, you can ask yourself if your request should be asking for the name of item :sword
or simply should be asking for the :item.sword/name
? The latter would make it unambiguous and no need for the monkeying around with strings; the former and writing some helper function to hide (keyword (str/join "." ["item" (name item)]) "name")
is probably as good as it gets.
Does :use
only to import java classes?
https://clojuredocs.org/clojure.core/use No, it is only for clojure namespaces.
@delaguardo 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"])
what about require ?
usually, best practices of clojure suggesting to not use use
but use require
with :as alias
modifier
i have 42 lines in my :require and i would really like to use circular dependencies
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?
cond->
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
would be nice if they could be named optionally like fns
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
i don't see anything in a stacktrace that helps though
reify is by definition unnamed
well... uncontrolled classnames
(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 itthe stacktrace however should exactly pinpoint any fault
https://clojurians.slack.com/archives/C053AK3F9/p1621440408074300
@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)
gotta focus on the problem statement
"I can't tell which of the reifies is implicated in this stack trace"
that should be determinable from the line numbers appearing in the trace
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
yes you are of course right
it is not impossible
but it would be way more simple to parse and understand if they were nameable even for such cosmetic purposes
i don't want to refer to the generated class by its name or anything
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!
a macro can make this approach easier to read
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 macrowild stab, but i guess you look at each form to determine if it begins with a ?
?
yes i do
always look at your full stack trace *e
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
(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))))
ah i see
so, I am already going to qualify this ^ In the specific case of ClassCastExceptions and NullPointerExceptions, sometimes the JVM elides traces 🙂
(that is controllable)
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
[]}
right, elided -- normal traces are not empty vectors []
somewhere in your macro you're asking for the name
of a symbol, but calling it on a number (which are Longs in clojure)
okay thank you
That helps I guess I can track it now down (there is one part where I call name
)
you can pass -XX:-OmitStackTraceInFastThrow
to your REPL
which would fill out the empty :trace []
it's a speed thing. Prod code never throws ClassCastExceptions, so the JVM optimizes for not filling out full stack traces.
🙏 ty soo much, very good input
could you help and tell my how I pass -XX:-OmitStackTraceInFastThrow` to my repl? 🙈
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)
We’re still here and generally respond to important bug reports 🙂 Also I answer questions in #instaparse sometimes
just typing in does not work
In clojurespace libraries do not get updates when they are done
your fine using this library
okay, thank you
Anyways you guys rock, and thanks a lot for helping strangers on the internet you are great :hugging_face:
@djonih 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).
@seancorfield thank you! should be good for my toy program then 😄
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
🙏 Thanks a lot
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
).
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
Is it preferable to use all
and conde
or *and
and *or
in core.logic
?
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\"))"
no
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=>