Fork me on GitHub

This has probably been discussed to death already, but I haven’t had the bandwith to follow it, so I’m asking here WRT to the and the, I’m wondering at the approach saying: • Portability to CLJS is a non-goal (so namespace is If portability is not a concern, then I’m wondering what the namespace is for, given that it is such a thin wrapper around Is it just the typehinting? Having a namespace that was outside of would have made portability possible, given that most of the functions are already available in, and the rest can be implemented. After all, IEEE754 math is not platform dependent. I can understand not making portability a priority, but blocking it out seems like the wrong approach. (Yes, I know that ClojureScript could implement, but that would be a poor idea).

☝️ 1
Alex Miller (Clojure team)01:11:03

If you're interested more discussion in #clojure-dev which is a better place for this


So that is what that channel is for!

Drew Verlee03:11:13

If i expost f and s in this could, would f be considered thread safe? e.g if 2 threads try to call `foo "at the same time" is it safe? Or do i have to express that another way?

(ns core)

(defn foo [] "hi")

(def s (atom {'foo 0}))

(defn f [x] 
  (when (= 0 (@s x))
      (swap! s update x inc)
      ((eval x)))

@s;; => {foo 0}

(f 'foo);; => "hi"

@s;; => {foo 1}

(f 'foo);; => nil

Alex Miller (Clojure team)03:11:27

it's not thread safe - between the deref and the swap the value of s can change - this is a classic data race

Drew Verlee03:11:53

So this is a job for compare-and-set! then?


swap-vals! will do. Or just look at the return value from swap! .

Drew Verlee03:11:42

(ns core)

(defn foo [] "hi")

(def s (atom {'foo 0}))

(defn f [x] 
  (when (= 1 ((swap! s update x inc) x))
    ((eval x))))

@s;; => {foo 0}

(f 'foo)

@s;; => {foo 1}

(f 'foo);; => nil


yep, looks good to me


Is there a way to figure out if/when a subprocess is requesting something from stdin when using ProcessBuilder? The usecase is I'm running some long shell commands, and I want to print a little ascii loading icon thing. That works fine, but if any of the subprocess request input from stdin - specifically a sudo prompt, that immediately screws things up because suddenly I have a sudo prompt that's immediately getting written over by a loading icon. What I'd like is if the ProcessBuilder can recognize when it's subprocess is requesting input, signal to my loading (which is on a different thread) to stop and wait for the input to be done, then once the input is entered, continue the loading icon. I can't just run the program using sudo cause that breaks all sorts of stuff since I'm relying on the user's environment - using their home directory and user installs and stuff

Cora (she/her)04:11:09

weird, does ProcessBuilder not let you read stdout of the subprocess as it executes?


I know that it lets you take control of it, but I don't actually want to take control of the sudo prompt if I don't have to.

Cora (she/her)05:11:19

@phdumaresq this is reminding me of a Tcl tool called Expect. there are ports to many languages, including java


I’ve been trying to write an Expect script, and maybe I’m spoiled by not having to do that much terminal scripting in my day job, but I found it a little hairy. But I really want what it can give me.

Cora (she/her)05:11:18

you're depending on output from the subprocess asking for input like a password, and you need to handle their password, but it handles the thing you're talking about.

Cora (she/her)05:11:23

@phdumaresq also I was reminded of this, which could be helpful -- apt keeps its progress bar at the bottom of the screen using terminal tricks that could be helpful


Thank you so much @corasaurus-hex! I'll check these out tomorrow!

👍 1

ELI5: are functions values? if yes, how and why? (I have a hunch they are, I just don't know why)


i mean - it really depends how you define value


in a loose sense - all things have observable properties. The full set of those observable properties is the “value” of a thing.


the way we talk about values here generally is in distinction to an “identity”, which is a label attached to a succession of values


you can define a function “object” by all the different results it would produce when called with different arguments


but stepping back in to the “real” - if a function in your program depends on context that will change outside of itself then that function itself is not a “value”. The full state of that function and the properties of its environment that it relies on are its “value”


(def state (volatile! 0))

(defn f [x]
  (+ x @state))


so the “value” of the function bound to the identity of f includes the current value associated with the identity of state


which becomes more complicated when you introduce concurrency, since the definition for what exactly the value for f is depends on what processes are doing what with regards to state and at which time/clock cycle the value of state is accessed


which is to say - “pure” functions are values in a way that can be usefully described


“impure” functions are also values that include the value of every property of their environment


its the same kind of thought train that “pure newtonian mechanics” drives you down - If you knew all the properties of the universe at some time P(t), then the laws of physics are just the function from P(t) -> P(t')


which probably doesn’t hold for the universe on account of quantumness


So if your very real function in your program called RDRAND and sampled the randomness of the surrounding universe it would be impossible to define the value of that function at any given point in time, even with infinite knowledge of P(t)


which is your 2am answer of the day


@U3JH98J4R Damn, I appreciate your 2am answer. haha. what I understood from this is that since pure functions in the mathematical sense map one value to another they can be considered values themselves. Whereas impure functions aka procedures are not values.


clojure.lang.Namespace has an implementation for Navigable. But why don't I see that type show up here?

(keys (:impls clojure.core.protocols/Navigable))


I see there is even a public function for this:

(extenders clojure.core.protocols/Navigable)
;;=> (java.lang.Object)


> Returns a collection of the types explicitly extending protocol


wild guess: clojure.lang.Namespace implements the Navigable interface, which is generated by the Navigable protocol, but not equal to it


also where did you find the Navigable implementation? it's not in


that's Datafiable, not Navigable, and it seems to work for me:

user=> (require 'clojure.datafy)
user=> (extenders clojure.core.protocols/Datafiable)
(nil java.lang.Object java.lang.Throwable clojure.lang.IRef clojure.lang.Namespace java.lang.Class)


$ clj
Clojure 1.11.0-alpha3
user=> (extenders clojure.core.protocols/Navigable)
user=> (extenders clojure.core.protocols/Datafiable)
(nil java.lang.Object)


how about after the (require 'clojure.datafy) ?


That worked.

user=> (extenders clojure.core.protocols/Navigable)
user=> (extenders clojure.core.protocols/Datafiable)
(nil java.lang.Object java.lang.Throwable clojure.lang.IRef clojure.lang.Namespace java.lang.Class)


Ah sorry yeah, got confused about Navigable and Datafiable


protocols, my favourite source of bugs


e.g. code that happens to work due to namespace loading order breaks when somebody makes a new namespace


explicit requires are the best, but linters want to remove them


eh, as the author of clj-kondo I don't agree


clj-kondo only wants you to remove it as if you don't use it for side effects


if you're using it for side effects, don't give it an alias


right, so clj-kondo is fine with (:require ... [] ...)? that's a good convention


also it "forces" you to require explicitly even if you know the namespace is already loaded. e.g. (clojure.string/join ...) isn't accepted if you don't require clojure.string


not a clojure question, but ... does git statusconsider .gitignorebefore showing you modified files?


There's also #off-topic IIRC Git only considers .gitignore for files that have not been tracked already. If you track a file, adding it to .gitignore will change nothing. But there are ways around that.


i initially forgot adding an /compiled folder to my .gitignore, so now everything in there shows up as modified with git status


just want to figure out if git add and git commit will ignore it, or if I need to reset those modified files first


Try searching online for "git untrack directory" or something like that. Plenty of answers on StackOverflow and similar websites or blogs.


some time ago I ran across a snippet that somehow called stest/instrument automatically whenever any var was (re)defined. But I can't find it now; does anybody know how they might've done it? Some kind of watch?


(I didn't post in #clojure-spec because I think it's only tangentially related— I believe the key here is watching vars.)

Alex Miller (Clojure team)18:11:35

we have full search in the slack at the moment, I bet you can find it...


it was on the web, and I've tried every search variation I can think of without success. The part I can't figure out is that it worked on all vars, and didn't require manually creating a watch for each one


is there a single var somewhere that holds Clojure's entire var registry?

Alex Miller (Clojure team)18:11:25

no - vars are held in each namespace


is there a way to watch a single namespace's vars, at least?

Alex Miller (Clojure team)18:11:37

no, don't know of any single thing that does that, although the pieces to build it exist


any pointers on what to look at if I want to build that?


interesting, I'll pursue that angle. Thank you!


A good way to accomplish this is:

( :after `stest/instrument)

Drew Verlee01:11:26

if i run that from inside emacs with cider i'm told it can't find class. I can't require it either. hm


Is there a library anywhere of transducer functions over and above those provided by clojure.core? I have a couple of custom partition functions I’ve used in situations where partition-by doesn’t quite do what I need, but now find myself needing transducer versions of them. Before I create transducer versions of them myself, it would be good to see if there’s a well-supported option that I can use? Or alternatively if there’s some way to get equivalent functionality with clojure.core that I’m missing? Specifically the functionality I need is:

(defn partition-with
  "Partitions a sequence whenever pred returns true"
  [pred? coll]

(defn partition-when
  "Pass sequential pairs of values to comp? and partition the collection whenever it returns true (splitting the pair)"
  [comp? coll]


cgrand has an xform library


Thanks - I'll check it out 👍


partition-by is what you want though


I'm missing something, clearly, as I'm I sure how I can get the same functionality from partition-by?


user=> (into []
      (comp (map biginteger)
            (partition-by #(.isProbablePrime % Integer/MAX_VALUE))
            (partition-all 2)
            (map (partial apply concat)))
      (range 20))
[(0 1 2 3) (4 5) (6 7) (8 9 10 11) (12 13) (14 15 16 17) (18 19)]


Ah! Of course. Thank you. I’ll have to see if I can come up with a similar replacement for partition-with. Thanks again!


The thing with partition-when is that it deals with delimiters and you then have a lot of choices: should delimiters be returned? (and if yes how? As single items? Sequence? Appended to the previous partition? Prepended to the next partition?) How delimiters runs are treated?


So either a single function with an options map or many functions. Or you find a way to compose it out of other fns.


our production jar is AOT compiled for startup speed. When i start the jar with a socket repl, I can successfully evaluate things but it seems that I cannot replace vars. I suspect this is because the classfiles are on the classpath. Is it possible to get an AOT jar back into a more dynamic environment, able to redefine vars and functions in the repl?


@dpsutton you should be able to "replace" vars, but perhaps you compiled with direct linking, which goes against that


yeah i was wondering that. Let me check. Our build system is a bit complicated


(System/getProperty "") in your socket REPL


(b/compile-clj {:basis      basis
                :src-dirs   paths
                :class-dir  class-dir
                :ns-compile ns-decls})
i don't see that set in this call. Would that property exist in the jar? Or would that only be relevant in the jvm that created the jar?


the property would be set in the compilation environment, not the socket REPL


ok, there doesn't seem to be direct linking at play here then


i cannot find any grep results of "direct-linking" so i do not think it is enabled


it may depend on what you are trying to define


clojure.core is aot compiled with direct linking on

👍 1

functions called by api handlers. So I would expect that these can be replaced at runtime with the jar but it does not seem to be happening


all the usual caveats for var redefinition apply


like once the var has been derefed and that value is being passed around, redefing the var won't do anything


i do not think that is the case here. which is why i was so confused


have the class files on the classpath doesn't do anything re-vars


the class files on the classpath could only possible effect looking for classes, but if you are evaling things in the repl, you can get brand new classes


does "replacing" the vars work in dev though? you've probably already checked this


yes when running a repl from source everything works just fine.


the possible explanations are really: 1, direct linking 2. taking the value of the var once and using that value without ever checking the var again 3. you aren't defing what you think you are defining


MB_JETTY_PORT=3006 java -Dclojure.server.repl="{:port 50506 :accept clojure.core.server/repl}" -jar ~/projects/work/jars/0.41.2.jar vs clj -M:dev:...:reveal etc


thanks @hiredman and @borkdude. That's what I was worried about. I'll keep looking then


#2 is very likely


i'm glad to know that my expectation is correct and the AOT nature isn't the culprit


things could get weird if what you are evaluating don't just set the value of vars, but generate named classes, like deftype, defrecord, or defprotocol


ah, i've realized what it is. I'm used to changing source and (require ns :reload) and forgot that this doesn't work like this here. I've been reloading the namespaces. The thing that mislead me so much was that i would log to the repl and interact but forgot to individually evaluate forms rather than work on the namespace


thanks everyone and i am embarrassed 🙂