Fork me on GitHub
#clojure
<
2021-07-27
>
lilactown00:07:50

in clojurescript I can use the analyzer that comes with it at macro time to statically detect things like local bindings that are used in a body passed to the macro. is there an easy way to get that sort of local context in JVM clojure?

lilactown00:07:58

ah I see that stuff just shows up in &env

lilactown00:07:52

oh it just has the local bindings in &env

noisesmith02:07:25

I am very fond of this macro

(ins)user=> (defmacro locals [] (into {} (map (juxt (comp keyword name) identity)) (keys &env)))
#'user/locals
(cmd)user=> (let [a 0 b 1] ((fn [x y] (locals)) "fruit" "albatross"))
{:a 0, :b 1, :x "fruit", :y "albatross"}

noisesmith02:07:22

move the creation of the fn and the let bindings are no longer visible

ins)user=> (defn show-locals [x y] (locals))
#'user/show-locals
(ins)user=> (let [a 0 b 1] (show-locals "fruit" "albatross"))
{:x "fruit", :y "albatross"}

dominicm15:07:59

@U4YGF4NGM if it's not in &env, then it should resolve otherwise 💥

Jovanni09:07:45

Hi I have been having a problem with configuring the clojure project. Anyone who help me would be appreciated. Thanks!

vemv11:07:16

Sounds like you would find best help in #beginners A preliminary description over there would help. Good luck with your project! :)

Jim Newton16:07:27

can someone tell me what is the correct way to write the defmulti for the following defmethod

(defmethod rte/match :pattern
  [pattern items & {:keys [promise-disjoint
                           hot-spot]}]
  (rte/match (rte/compile pattern) items :promise-disjoint true :hot-spot hot-spot))
Here is what I have, but I'm not sure what to do with the &key specification in the defmulti.
(defmulti rte/match
  "(rte/match rte sequence :promise-disjoint true|false)
   Given an rte pattern or finite automaton generated by rte-to-dfa (or rte/compile), 
   determine whether the given sequence, items, matches the regular type expression.

   If the caller wishes to check more than one sequence against the same
   pattern, it is probably better to call rte/compile, to get an automaton, and
   use that same automaton in several calls to rte/match to avoid
   multiple conversions/look-ups, as the correspondence of pattern
   to compiled Dfa is maintained via the memoize function."
  (fn [rte _items & {:keys [promise-disjoint
                            hot-spot]}]
    (dispatch rte 'rte/match)))
The problem is that promise-disjoint and hot-spot are unused in the (fn...)

Jim Newton16:07:21

is that really the good way? It doesn't indicate to the caller what the valid/indented/supported keyword arguments are.

seancorfield16:07:14

It depends why you're doing it. Since you said "The problem is that promise-disjoint and hot-spot are unused in the (fn...)" I thought you didn't want the names bound and unused.

Jim Newton16:07:12

it is just the clj-kondo complains that the variables are unused, and I cannot rename them to start with _ because that'll change the semantics. I didn't want to compile to the clj-kondo maintainers if there was a clojure-esque way to handle it.

seancorfield16:07:47

{_promise-disjoint :promise-disjoint _hot-spot :hot-spot} should work then.

Jim Newton16:07:06

ahhhh. good suggestion!!

seancorfield16:07:21

That form of destructuring allows you to name the bound vars whatever you want and kondo should ignore them because of the leading _

Jim Newton16:07:23

unfortunately it appears clj-kondo still complains, but that seems like a bug in cli-kondo. maybe there's already an issue about that. I'll check

seancorfield16:07:27

It looks like defmulti allows an attr-map so I you could use :arglists metadata there to declare readable help for users and then still use & {:as _} for the actual arglist?

seancorfield16:07:26

dev=> (defmulti example "docstring" {:arglists '([foo bar & {:keys [quux]}])} (fn [x _ & {:as _}] x))
#'dev/example
dev=> (doc example)
-------------------------
dev/example
([foo bar & {:keys [quux]}])
  docstring

Jim Newton16:07:53

{_promise-disjoint :promise-disjoint _hot-spot :hot-spot}  is that the correct order, or should it be {:promise-disjoint _disjoint, :hot-spot _hot-spot} ? just want to make sure before I complain any further.

seancorfield16:07:27

I'd use the :arglists approach 🙂

Jim Newton18:07:17

Hey Sean, do you have an idea what is spec trying to tell me here?

(defmulti rte/match
  "(rte/match rte sequence :promise-disjoint true|false)
   Given an rte pattern or finite automaton generated by rte-to-dfa (or rte/compile), 
   determine whether the given sequence, items, matches the regular type expression.

   If the caller wishes to check more than one sequence against the same
   pattern, it is probably better to call rte/compile, to get an automaton, and
   use that same automaton in several calls to rte/match to avoid
   multiple conversions/look-ups, as the correspondence of pattern
   to compiled Dfa is maintained via the memoize function."

  (fn [rte _items & {:keys {_promise-disjoint :promise-disjoint
                            _hot-spot :hot-spot}}]
    (dispatch rte 'rte/match)))
here is the spec message.
Show: Project-Only All 
  Hide: Clojure Java REPL Tooling Duplicates  (45 frames hidden)

2. Unhandled clojure.lang.Compiler$CompilerException
   Error compiling src/clojure_rte/rte_construct.clj at (2056:3)
   #:clojure.error{:phase :macro-syntax-check,
                   :line 2056,
                   :column 3,
                   :source
                   "/Users/jnewton/Repos/clojure-rte/src/clojure_rte/rte_construct.clj",
                   :symbol clojure.core/fn}
             Compiler.java: 6971  clojure.lang.Compiler/checkSpecs
             Compiler.java: 6987  clojure.lang.Compiler/macroexpand1

                  core.clj: 3214  clojure.core/eval
                  core.clj: 3210  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:  665  clojure.core/apply
                  core.clj: 1973  clojure.core/with-bindings*
 ...
               Thread.java:  834  java.lang.Thread/run

1. Caused by clojure.lang.ExceptionInfo
   Call to clojure.core/fn did not conform to spec.
   #:clojure.spec.alpha{:problems
                        ({:path
                          [:fn-tail
                           :arity-1
                           :params
                           :var-params
                           :var-form
                           :local-symbol],
                          :pred clojure.core/simple-symbol?,
                          :val
                          {:keys
                           {_promise-disjoint :promise-disjoint,
                            _hot-spot :hot-spot}},
                          :via
                          [:clojure.core.specs.alpha/params+body
                           :clojure.core.specs.alpha/param-list
                           :clojure.core.specs.alpha/param-list
                           :clojure.core.specs.alpha/binding-form
                           :clojure.core.specs.alpha/binding-form
                           :clojure.core.specs.alpha/local-name],
                          :in [0 3]}
                         {:path
                          [:fn-tail
                           :arity-1
                           :params
                           :var-params
                           :var-form
                           :seq-destructure],
                          :pred clojure.core/vector?,
                          :val
                          {:keys
                           {_promise-disjoint :promise-disjoint,
                            _hot-spot :hot-spot}},
                          :via
                          [:clojure.core.specs.alpha/params+body
                           :clojure.core.specs.alpha/param-list
                           :clojure.core.specs.alpha/param-list
                           :clojure.core.specs.alpha/binding-form
                           :clojure.core.specs.alpha/binding-form
                           :clojure.core.specs.alpha/seq-binding-form],
                          :in [0 3]}
                         {:path
                          [:fn-tail
                           :arity-1
                           :params
                           :var-params
                           :var-form
                           :map-destructure
                           :keys],
                          :pred clojure.core/vector?,
                          :val
                          {_promise-disjoint :promise-disjoint,
                           _hot-spot :hot-spot},
                          :via
                          [:clojure.core.specs.alpha/params+body
                           :clojure.core.specs.alpha/param-list
                           :clojure.core.specs.alpha/param-list
                           :clojure.core.specs.alpha/binding-form
                           :clojure.core.specs.alpha/binding-form
                           :clojure.core.specs.alpha/map-binding-form
                           :clojure.core.specs.alpha/map-special-binding
                           :clojure.core.specs.alpha/keys],
                          :in [0 3 :keys]}
                         {:path [:fn-tail :arity-n :params],
                          :pred clojure.core/vector?,
                          :val rte,
                          :via
                          [:clojure.core.specs.alpha/params+body
                           :clojure.core.specs.alpha/params+body
                           :clojure.core.specs.alpha/params+body
                           :clojure.core.specs.alpha/param-list
                           :clojure.core.specs.alpha/param-list],
                          :in [0 0]}),
                        :spec
                        #object[clojure.spec.alpha$regex_spec_impl$reify__2509 0x2bea9778 "clojure.spec.alpha$regex_spec_impl$reify__2509@2bea9778"],
                        :value
                        ([rte
                          _items
                          &
                          {:keys
                           {_promise-disjoint :promise-disjoint,
                            _hot-spot :hot-spot}}]
                         (dispatch rte 'rte/match)),
                        :args
                        ([rte
                          _items
                          &
                          {:keys
                           {_promise-disjoint :promise-disjoint,
                            _hot-spot :hot-spot}}]
                         (dispatch rte 'rte/match))}
                 alpha.clj:  705  clojure.spec.alpha/macroexpand-check
                 alpha.clj:  697  clojure.spec.alpha/macroexpand-check
                  AFn.java:  156  clojure.lang.AFn/applyToHelper
                  AFn.java:  144  clojure.lang.AFn/applyTo
                  Var.java:  705  clojure.lang.Var/applyTo
             Compiler.java: 6969  clojure.lang.Compiler/checkSpecs
             Compiler.java: 6987  clojure.lang.Compiler/macroexpand1
             Compiler.java: 7092  clojure.lang.Compiler/analyzeSeq
             Compiler.java: 6789  clojure.lang.Compiler/analyze
             Compiler.java: 6745  clojure.lang.Compiler/analyze
             Compiler.java: 2666  clojure.lang.Compiler$NewExpr$Parser/parse
             Compiler.java: 7106  clojure.lang.Compiler/analyzeSeq
             Compiler.java: 6789  clojure.lang.Compiler/analyze
             Compiler.java:   38  clojure.lang.Compiler/access$300
             Compiler.java:  596  clojure.lang.Compiler$DefExpr$Parser/parse
             Compiler.java: 7106  clojure.lang.Compiler/analyzeSeq
             Compiler.java: 6789  clojure.lang.Compiler/analyze
             Compiler.java: 6745  clojure.lang.Compiler/analyze
             Compiler.java: 6120  clojure.lang.Compiler$BodyExpr$Parser/parse
             Compiler.java: 7106  clojure.lang.Compiler/analyzeSeq
             Compiler.java: 6789  clojure.lang.Compiler/analyze
             Compiler.java: 6745  clojure.lang.Compiler/analyze
             Compiler.java: 2837  clojure.lang.Compiler$IfExpr$Parser/parse
             Compiler.java: 7106  clojure.lang.Compiler/analyzeSeq
             Compiler.java: 6789  clojure.lang.Compiler/analyze
             Compiler.java: 7094  clojure.lang.Compiler/analyzeSeq
             Compiler.java: 6789  clojure.lang.Compiler/analyze
             Compiler.java: 6745  clojure.lang.Compiler/analyze
             Compiler.java: 6120  clojure.lang.Compiler$BodyExpr$Parser/parse
             Compiler.java: 6436  clojure.lang.Compiler$LetExpr$Parser/parse
             Compiler.java: 7106  clojure.lang.Compiler/analyzeSeq
             Compiler.java: 6789  clojure.lang.Compiler/analyze
             Compiler.java: 6745  clojure.lang.Compiler/analyze
             Compiler.java: 6120  clojure.lang.Compiler$BodyExpr$Parser/parse
             Compiler.java: 5467  clojure.lang.Compiler$FnMethod/parse
             Compiler.java: 4029  clojure.lang.Compiler$FnExpr/parse
             Compiler.java: 7104  clojure.lang.Compiler/analyzeSeq
             Compiler.java: 6789  clojure.lang.Compiler/analyze
             Compiler.java: 7173  clojure.lang.Compiler/eval
             Compiler.java: 7131  clojure.lang.Compiler/eval
                  core.clj: 3214  clojure.core/eval
                  core.clj: 3210  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:  665  clojure.core/apply
                  core.clj: 1973  clojure.core/with-bindings*
                  core.clj: 1973  clojure.core/with-bindings*
               RestFn.java:  425  clojure.lang.RestFn/invoke
    interruptible_eval.clj:   87  nrepl.middleware.interruptible-eval/evaluate/fn
                  main.clj:  414  clojure.main/repl/read-eval-print/fn
                  main.clj:  414  clojure.main/repl/read-eval-print
                  main.clj:  435  clojure.main/repl/fn
                  main.clj:  435  clojure.main/repl
                  main.clj:  345  clojure.main/repl
               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:  834  java.lang.Thread/run

seancorfield18:07:31

:keys expects a vector, not a hash map. You want

{_promise-disjoint :promise-disjoint _hot-spot :hot-spot}
not
{:keys {_promise-disjoint :promise-disjoint
                            _hot-spot :hot-spot}}

Jim Newton18:07:54

so where does the :or {a 100 b 200} go and the :as all-args?

Jim Newton18:07:51

I see, it goes right there in the same {...} not what I'd have guessed

Jim Newton18:07:06

and If I want promise-disjoint to be unused, but hot-spot to be used. I cannot use the [...] form, apparently I have to use the {_promise-disjoint :promise-disjoint, hot-spot :hot-spot} form.

seancorfield19:07:33

Yeah, it's enough of a strange syntax that I pretty much never use that style of destructuring. Sometimes I'll use it in a let where I really do need renaming but that's about it.

seancorfield19:07:36

Pretty sure you can combine (re)named bindings with :keys and :or and :as all in one hash map. I know you can also combine :keys and :foo/keys when you want to bind to :foo/bar as well as :quux for example.

seancorfield16:07:57

I pretty much always have to look up how the renaming destructuring works!

borkdude17:07:05

symbols first

borkdude17:07:11

keys become the locals

Jim Newton17:07:37

yes probably, but it seems the same problem exists in clj-kondo even with fns, not really related to defmulti.

borkdude17:07:13

you're right, this is a bug

2
indy18:07:28

Do all values that return true for fn? also return true for ifn? . I guess that means do all objects that implement clojure.lang.Fn also implement clojure.lang.IFn? How do I infer this piece of information from Clojure's source?

indy18:07:46

I guess it might be worth adding it as a note https://clojuredocs.org/clojure.core/ifn_q whether all things that return true for fn? also return true for ifn?.

seancorfield18:07:09

I don't know if everything that implements Fn also implements IFn...

hiredman18:07:41

(misread that)

seancorfield18:07:27

AFn implements IFn and AFunction extends AFn and implements Fn -- and that seems to be the only thing that implements Fn so, yeah, everything that satisfies fn? will also happen to satisfy ifn?.

indy18:07:06

Perfect, that is exactly what I was looking for

fogus (Clojure Team)18:07:44

The marker interface Fn is useful for determining if you have an actual function in hand rather than something that acts like a function.

3
hiredman18:07:20

the surprising thing is multimethods aren't Fns

hlship19:07:42

Does anyone have any experience using clj-async-profiler (https://github.com/clojure-goes-fast/clj-async-profiler) w/ OpenJDK 8?

hlship19:07:54

I get an error:

Could not find libjvm among loaded libraries. Unsupported JVM?
so I’m concerned I need to switch over to Oracle JDK.

Russell Mull19:07:57

Certainly appears like openjdk 8 should be supported, by the underlying lib anyway. A brief perusal through the source suggests that this error could happen if their agent binary isn't attached to the jvm. But that's barely-educated speculation.

didibus20:07:05

I used it with OpenJDK many times

didibus20:07:34

I was using the OpenSuse build of Open JDK

hlship22:07:51

Not sure what I’m doing wrong, then.

jumar04:07:14

Here's some advice regarding JDK: https://github.com/jvm-profiling-tools/async-profiler/issues/407 So maybe try Zulu OpenJDK? In either case, I would advice you to file an issue here - you will likely get a response from Andrei soon.

Ben Sless18:07:25

Which OS are you using?

hlship22:07:20

I’m on OS X, using (now) Oracle JDK 16.0.2 (I was originally on OpenJDK 8 at the start of this process).

hlship22:07:15

At least part of the problem is that I did not have the environment variable JAVA_HOME set. New error message is can not attach to current VM which is better.

hlship22:07:32

Also looks like -Djdk.attach.allowAttachSelf is needed.

☝️ 3
kwladyka19:07:36

I will add more info in thread to not spam the channel. The issue is about wild string to paste into test which throw Unsupported escape character: \ or is not =

(is
      (= (.format json-payload/formatter
                  (doto (message->LogRecord "foo")
                    (.setThrown (Exception. "bar"))))
         "")
      "exception")

kwladyka19:07:48

(.format json-payload/formatter
                  (doto (message->LogRecord "foo")
                    (.setThrown (Exception. "bar"))))
=>
"{\"severity\":\"INFO\",\"logger-name\":\"ns\",\"message\":\"java.lang.Exception: bar\
 \\tat logs_helpers.google.json_payload_test$eval3010.invokeStatic(json_payload_test.clj:2)\
 \\tat logs_helpers.google.json_payload_test$eval3010.invoke(json_payload_test.clj:23)\
 \\tat clojure.lang.Compiler.eval(Compiler.java:7181)\
 \\tat clojure.lang.Compiler.eval(Compiler.java:7136)\
 \\tat clojure.core$eval.invokeStatic(core.clj:3202)\
 \\tat clojure.core$eval.invoke(core.clj:3198)\
 \\tat nrepl.middleware.interruptible_eval$evaluate$fn__939.invoke(interruptible_eval.clj:91)\
 \\tat clojure.main$repl$read_eval_print__9110$fn__9113.invoke(main.clj:437)\
 \\tat clojure.main$repl$read_eval_print__9110.invoke(main.clj:437)\
 \\tat clojure.main$repl$fn__9119.invoke(main.clj:458)\
 \\tat clojure.main$repl.invokeStatic(main.clj:458)\
 \\tat clojure.main$repl.doInvoke(main.clj:368)\
 \\tat clojure.lang.RestFn.invoke(RestFn.java:1523)\
 \\tat nrepl.middleware.interruptible_eval$evaluate.invokeStatic(interruptible_eval.clj:84)\
 \\tat nrepl.middleware.interruptible_eval$evaluate.invoke(interruptible_eval.clj:56)\
 \\tat nrepl.middleware.interruptible_eval$interruptible_eval$fn__965$fn__969.invoke(interruptible_eval.clj:155)\
 \\tat clojure.lang.AFn.run(AFn.java:22)\
 \\tat nrepl.middleware.session$session_exec$main_loop__1067$fn__1071.invoke(session.clj:190)\
 \\tat nrepl.middleware.session$session_exec$main_loop__1067.invoke(session.clj:189)\
 \\tat clojure.lang.AFn.run(AFn.java:22)\
 \\tat java.base/java.lang.Thread.run(Thread.java:834)\
 \",\"logger-message\":\"foo\"}
 "

kwladyka19:07:56

If I will try to copy & paste this string

kwladyka19:07:42

If I will try to do

(print (.format json-payload/formatter
                         (doto (message->LogRecord "foo")
                           (.setThrown (Exception. "bar")))))
and use this string for test, then it is not =

kwladyka19:07:02

how can I write test using this string?

hiredman19:07:55

Could your editor be line wrapping the string?

hiredman19:07:27

Looks like your are copy and pasting the \ emacs uses to indicate a too long line

hiredman19:07:37

Err, indicate line wrapping

💯 2
kwladyka19:07:03

unfortunately it is not about line wrapping in editor

kwladyka19:07:56

with turned off line wrapping I have the same issue

kwladyka19:07:40

This string is produced by

(if thrown
                   (let [w (StringWriter.)]
                     (.printStackTrace thrown (PrintWriter. w))
                     (.toString w))
                   (.getMessage record))
if it matters

kwladyka19:07:40

I am trying with all kinds of

(spit "foo.edn" (pr-str (.format json-payload/formatter
                                          (doto (message->LogRecord "foo")
                                            (.setThrown (Exception. "bar"))))))
with the same effect

p-himik20:07:24

What if you slurp what you have spit before, instead of hard-coding the string in your code?

kwladyka20:07:08

oh I think I found a true issue…. In exception there is eval3180 which can have different number…

👍 2
kwladyka20:07:13

nevermind, sorry guys

borkdude19:07:44

Turned out this wasn't a bug, the code was just incorrect https://clojurians.slack.com/archives/C03S1KBA2/p1627405393446200 :)

✔️ 3
didibus20:07:49

I remember seeing an old project which basically had an alternate clojure.core, it was meant that you'd exclude clojure.core and use their standard lib instead. Does anyone know what I'm talking about? I'm trying to find it again. The big difference was that it broke down clojure.core in many smaller Namespaces

😨 2
didibus21:07:57

Hum, yes that could have been it

didibus21:07:36

Ya that was it. Its a very interesting project, have you tried it?

p-himik05:07:28

Nope, I just decided to exercise my google-fu. :)

didibus06:07:05

Haha, well yours is superior to mine, as I had failed to find it with my own google-fu

🙂 3
dpsutton21:07:13

i'm trying to use emit some html with a style attribute background-color rgb(). hiccup is seemingly trying to prevent some dangerous html but i don't want sanitization in this case. Does anyone know a workaround?

(hiccup.core/html
        [:span {:style {:background-color "rgb(239, 140, 140)"}}
         "hi"])
"<span style=\"{:background-color &quot;rgb(239, 140, 140)&quot;}\">hi</span>"

hiredman21:07:08

you have too many maps

hiredman21:07:35

you get a single level of names to values for html attributes

dpsutton21:07:13

ah right. thanks

dpsutton21:07:31

ah, i'm writing reagent style hiccup which does handle this like that

isak21:07:52

It may work with hiccup2.core, I see this in the https://github.com/weavejester/hiccup/blob/master/CHANGELOG.md#200-alpha1-2017-01-15: "Added new syntax for class and style attributes"

dgb2321:07:16

I really like how macroexpand(-all) helps to understand and visualize a macro. I don’t think anything similar exists for functions, as in a stepwise substitution of the evaluations. That would be very useful. How crazy would it be to be to try to implement that?

dpsutton21:07:11

all backend so i don't have access to reagent here

dpsutton21:07:56

also, no hiccup2.core in 1.0.5. that seems to be in 2.0.0-alpha2

2
isak22:07:25

This looks like it is the PR that added it btw: https://github.com/weavejester/hiccup/pull/139