Fork me on GitHub
#clojure
<
2022-11-22
>
Ben Lieberman00:11:32

If I'm running this command

java -cp `clj -Spath` clojure.examples.hello Fred
(with my own compiled clj code of course) what do I have to do to make it work on Powershell? Besides not using Powershell, which I wish was an option here.

Ben Lieberman00:11:05

I tried different quoting around "clj -Spath" and I get various errors

hiredman01:11:29

in posix shells runs a subshell

hiredman01:11:58

So it means run the command clj -Spath and insert its output here

hiredman01:11:36

So if you can do something like that in powershell

Jacob Rosenzweig04:11:20

For those that use Malli. Is there any equivalent of :enum for maps? E.g. I want to do this:

(def conj-auth
  [:map
    {:closed true}
    email
    pass])

(def google-auth 
  [:map
   {:closed true}
   provider
   code])

(def auth
  [:enum
   conj-auth
   google-auth])

vemv04:11:09

wouldn't

[:or
   conj-auth
   google-auth]
work for you?

👍 2
Jacob Rosenzweig04:11:02

That works!

🍻 1
Ben Sless04:11:08

Anyone else feeling the need for a schemas algebra? An ability to push a merge of a map schema into and, or, multi, etc

Martynas Maciulevičius07:11:07

Commutative schemas? Schema multiplication? Schema matrices? sin(schema)? 😄 But yes, currently I merge my schema "by hand" with my hardcoded defaults :thinking_face:

Ben Sless11:11:12

and multi multi is certainly schema multiplication 🙂

erwinrooijakkers09:11:06

Is there a way to know if code is evaluated during compilation or during runtime?

borkdude10:11:37

Maybe like this. I interpret your runtime as "non top level".

(ns handler)

(prn :file *file*)

(defn foo []
  (prn :file *file*))

(defmacro bar []
  (prn :file *file* )
  `(prn :file *file*))

(bar) ;; compile time :file

(defn baz []
  ;; compile time file and runtime file
  (bar))

(defn -main [& _args]
  (foo)
  (baz))
$ clj -Scp $(clojure -Spath):/tmp -M -m handler
:file "handler.clj"
:file "handler.clj"
:file "handler.clj"
:file "handler.clj"
:file "NO_SOURCE_PATH"
:file "NO_SOURCE_PATH"
So when it's executed non-top-level, :file is NO_SOURCE_PATH

👌 1
Rupert (All Street)11:11:26

You can add a println or spit anywhere in your code to see if something is being evaluated e.g.

(ns my-namespace)

(println "hello")
(spit "abc.txt" "evaluated")

(defn test[] (println "hello2"))

Ben Sless11:11:54

Is there a way to take a protocol's methodImplCache implementation and carry it around? I don't want a full on protocol, just a cached implementation for types

vemv14:11:59

Plumatic Schema recently added a s/defprotocol that does stuff with methodImplCache - worth checking out?

Ben Sless14:11:16

I'll look, but having peeked a bit into the core implementation I have an educated guess what it's doing

icemanmelting12:11:40

Guys, I have reached the limit in my knowledge regarding dependencies, I switched to clojure 1.11.1, and I keep getting this error

icemanmelting12:11:59

[{:type clojure.lang.Compiler$CompilerException
   :message Unexpected error macroexpanding go at (datomic/client/impl/shared.clj:99:5).
   :data {:clojure.error/phase :macroexpansion, :clojure.error/line 99, :clojure.error/column 5, :clojure.error/source datomic/client/impl/shared.clj, :clojure.error/symbol go}
   :at [clojure.lang.Compiler macroexpand1 Compiler.java 7036]}
  {:type java.lang.NoSuchFieldError
   :message __thunk__0__
   :at [clojure.tools.analyzer.jvm.utils__init load nil 259]}]

icemanmelting12:11:06

any ideas on why this keeps happening?

Rupert (All Street)12:11:41

Some tips for debugging this kind of thing: • Try undoing your change to be sure that it really is clojure depdency change that caused the issue. • Make sure you have cleaned the target directory (e.g. with lein use lein clean) • Try compiling the code outside of REPL (e.g. with lein use lein check) • Compare the full dependency graph before + after your change (e.g. with lein run lein deps :tree ) • Try eliminating a bunch of your code + dependencies until the error goes away. Then add them back slowly to see was causing the issue. • It's possible that the bug is a dependency conflict

icemanmelting12:11:18

@UJVEQPAKS I have done just that

icemanmelting12:11:26

it seems that the problem is core.async related

icemanmelting12:11:39

if I rollback to the older version everything works perfectly

borkdude12:11:49

@U9BQ06G6T Search for __thunk__0__ here on slack, it has been reported before this week

icemanmelting12:11:51

Yes, @U04V4KLKC has pointed me to that topic, I have checked the aot compilation of the suggested namespace, but either I am doing something wrong (which shouldn’t be to far from the truth) or the solution doesn’t work for me

icemanmelting12:11:57

Thanks everyone for your input

Dustin Getz18:11:36

why are clojure bindings evaluated in parallel? (binding [a ... b ...])

ghadi18:11:26

They aren’t

Dustin Getz18:11:56

sorry, "made"

The new bindings
are made in parallel (unlike let); all init-exprs are evaluated
before the vars are bound to their new values.

Rupert (All Street)18:11:50

Not sure, but it's trivial to nest them if you don't want that behaviour (binding [a 1] (binding [b 2] ...)) I agree that it's odd that they follow a different convention to let. I'm not sure which convention is more proper. It might just have been arbitrarily easier to do it this way when they wrote the code for it.

vemv18:11:03

> why are clojure bindings evaluated in parallel? (binding [a ... b ...]) I'd say it's because it's implemented in terms of with-bindings which accepts a hashmap (i.e. unordered semantics) ...of course one API doesn't have to be coupled to the other. my wild guess is that they initially were, then it was a little too late to fix it?

Dustin Getz18:11:29

yeah i'm about to write a bindings2 macro to de-pyramid a set of bindings

Rupert (All Street)18:11:06

I think making it like let would be completely backwards compatible (but not the other way around).

👍 1
Dustin Getz18:11:51

yeah it seems just lazy / good enough impl

vemv18:11:47

however it's a reasonable concern to not invite people to write code in clojure 1.N that would not correctly work in clojure 1.(N - 1)

dpsutton18:11:19

wouldn’t making it like let break the existing behavior?

dpsutton18:11:58

user=> (binding [*a* 10
                 *b* (+ *a* 1)]
         (+ *a* *b*))
12
user=> (binding [*a* 10]
         (binding [*b* (+ *a* 1)]
           (+ *a* *b*)))
21

👀 4
dpsutton18:11:18

>

all init-exprs are evaluated
> before the vars are bound to their new values.
> is the important part right?

dpsutton18:11:31

you get * value before the binding, not after the binding

dpsutton18:11:21

in my second example, like let, it uses the newly bound value of *a* (1) rather than the before-all-bindings value of *a* (10)

Dustin Getz18:11:26

yes you're right

Rupert (All Street)18:11:48

Oops - was thinking about the case where the binding didn't exist already.

1
dpsutton18:11:10

that condition doesn’t exist here > Creates new bindings for the (already-existing) vars

Rupert (All Street)18:11:22

ie was thinking of

(binding [*a* 10
          *b* (+ *a* 1)] ;;<-- Null pointer exception a is nil (not yet bound)
         (+ *a* *b*))

Rupert (All Street)19:11:25

Would be odd for someone to be relying on this

user=> (binding [*a* 10
                 *b* (+ *a* 1)]
         (+ *a* *b*))
12

dpsutton19:11:00

that’s the docstring described behavior right? Wouldn’t it be odd to rely on behavior contrary to the indicated behavior?

Rupert (All Street)19:11:29

I agree that they can rely on it since the docstring says that. I just expect it's probably very rare case in the wild (given your + my illustrations above). So it would technically be a breaking change but breaking very little.

Rupert (All Street)19:11:43

For me, I don't think the change is required though since I don't think we want to make binding particularly more common.

dpsutton19:11:14

we’re just using numbers. but lots of printing stuff uses this. from nrepl:

(binding [*print-readably* true
          *print-length*   nil
          *print-level*    nil]
  (doto out
    (.write (str %))
    (.flush)))
the fact that these all would reference the current binding could be very important and changing the behavior could radically alter how Clojure prints

👍 1
Noah Bogart18:11:55

I have a magic the gathering-like card game, and I have the card definitions separated by type, but we're coming up on 4k+ lines in each of these card files (and 6k+ lines in the associated test files), which is a little unwieldy. I'm considering breaking these files into multiple files, one definition per file. in javascript, it's easy to loop over a directory and require each file which will perform some side effect (adding an entry to a map). are there any common idioms for that in Clojure?

vemv18:11:24

(def data1 (delay (edn/read-string (io/resource "foo/bar.edn"))))
I use this a lot in tests

Noah Bogart19:11:11

Sadly, these are a lot of data but they have a lot of code too (`defcard` is a macro, for example)

(defcard "Underway Grid"
  {:events [{:event :pre-expose
             :req (req (same-server? card target))
             :msg "prevent 1 card from being exposed"
             :effect (req (expose-prevent 1))}]
   :constant-effects [{:type :bypass-ice
                       :req (req (same-server? card target))
                       :value false}]})

👀 1
dpsutton19:11:28

don’t forget load and load-file

🙂 1
Noah Bogart19:11:53

oh yeah, i forgot about those. interesting, maybe I can use that

dpsutton19:11:22

i think the source of pprint in Clojure can serve as prior art

clapping 1
Noah Bogart19:11:56

Thank you, that's great

Noah Bogart15:11:03

To follow up on this, when is it better to use in-ns vs ns? Given that calling ns multiple times on the same namespace is additive, seems like there's no reason except semantic clarity to use in-ns

dpsutton15:11:32

my preference is to use ns to define namespaces and in-ns to switch to a namespace programatically. Seeing multiple ns forms for the same ns would be strange to me (and might confuse tooling)

👍 2
vemv21:11:12

We have a certain (Thread/sleep) in our codebase, and nothing from our own side that would intentionally interrupt it. However in our production logs I'm seeing an InterruptedException with the familiar "sleep interrupted" message. I have no idea of what could be interrupting this thread. Are there some usual suspects? Is it something that a web server could be doing? (I'll grep for that) Or is it something that is implied with JVM shutdown perhaps? Other ideas welcome.

hiredman21:11:56

user=> (.interrupt (Thread/currentThread))
nil
user=> (Thread/sleep 100)
Execution error (InterruptedException) at java.lang.Thread/sleep (Thread.java:-2).
sleep interrupted
user=>

vemv21:11:29

My problem is that I don't know who is interrupting me

hiredman22:11:33

if you are re-using threads (I think thread pools are good about clearing this) then it could be something else running on the thread was interrupted, then your code runs on the thread, then you go to sleep and the interrupt flag is still set on the thread

hiredman22:11:21

but yeah, I believe interrupted exceptions can get thrown at jvm shutdown

isak22:11:50

I would think the web server/library (request timeouts)

vemv23:11:18

thanks both! I'll deploy a dummy endpoint that sleeps forever and observe what happens after: • some 60s (e.g. a timeout possibly propagated by nginx and then jetty) • jvm shutdown (following a re-deployment)

1