Fork me on GitHub

yep. since moving to deps.edn / clojure cli tools, all of my projects have a .dir-locals.el that tells CIDER to add a -A:dev to the command


@lilactown I have (setq cider-clojure-cli-global-options "-A:dev") in my .dir-locals.el is that what is needed?


this is what my .dir-locals.el looks like:

  (cider-clojure-cli-global-options . "-A:dev")))

👍 4

there is plenty of documentation online about it as well


Yeah, found it after some time 🙂


the emacs manual can sometimes be terse 😛


you’ll want to make sure you run M-x reload-dir-locals-for-current-buffer as well after changing them


yeah definitely 😅


glad you figured it out


thanks for your help 🙂

👍 4

does not work


Error compiling NO_SOURCE_PATH at (1:1)


how can i resolve the error ?


@mishraantash34 No namespace declaration?


Assuming that what you pasted is at the top of your file that is.

Denis G08:09:04

Are Clojure Agents also called Agents (not talking about AI thing) in academia, or CS world. Found this article and am trying to understand what is written there, and under their definition of agent → communicate to an agent by modifying something that it is observing; you do not need to know that the agent exists What does this even mean, do not need to know that the agent exists? Are we talking about the same thing?


"In computer science, a software agent is a computer program that acts for a user or other program in a relationship of agency, which derives from the Latin agere (to do): an agreement to act on one's behalf."

Denis G08:09:48

is this an AI definition?


"Agents provide independent, asynchronous change of individual locations." So, they provide access on the behalf of others."


no its a software architecture definition I believe

Denis G08:09:36

So Clojure Agents is just a way to illustrate this concept, not the absolute truth how agents should look like, right?


well it's an implementation, yeah


the only 'absolute truth' definition is what I posted above


It's like a isolated robot that you send to do a task and then it comes back. I guess that's the 'archetype' of it

Denis G09:09:35

i mean, if you think of actors, it's more or less always the same, right? You can not go wrong with it

Denis G09:09:13

when it comes to agents, that's the only thing I know (Clojure agents) Reading about Microsoft Agents Lib. To understand how they do it and how it's different


I think not having to know the agent exists is because you can implement watchers on values and they trigger


Rich Hickey begs his audience not to call them actors in this talk, so maybe not. 🙂;t=1h12m03

Denis G09:09:09

I didn't claim they are actors


I think they're used for the same purpose, is that what you mean?

Denis G09:09:28

On the clojure website they even say what's the different and the problems with actors


An agent is some data you can throw functions at and you don’t want to have the result synchronously. An atom is some data you can throw functions at and you want to have the result synchronously. Atoms are far more prevalent in Clojure code than agents.

Denis G09:09:23

Yeah. But I talk about concept here

Denis G09:09:27

not what it is in Clojure

Denis G09:09:04

An 'Agent', as from ConcurrentConstraintProgramming or ReactiveDemandProgramming, is different: * active continuously - making observations on an environment, constraint store, or perhaps other agents * presence of agent may also affect the system, i.e. applying a rule or demand; nature of effect distinguishes Agent systems * communicate to an agent by modifying something that it is observing; you do not need to know that the agent exists * upon observing certain conditions, in some systems agents might spawn new agents or update local state * the information that agents need to perform their jobs is continuously maintained by their runtime environment * agents tend to process all relevant information at once, and thus need consider only combinations * it takes some discipline to prevent 'feedback' systems, similar to placing a microphone near a speaker

Denis G09:09:49

So the question was whether or not this applies to Clojure agents, are they representing the same thing/concept or not

Denis G09:09:25

This is not an agent vs actor talk. It's about this agent definition vs Clojure agent definition if you wish.

Denis G09:09:42

E.g. here MS calls this agent library, but agent is used as an actor So what it an agent in the absolute meaning of it. Not applied to any language or framework


there are like 3 definitions depending on the context


simulation, a model of something, and asynchronous entities that you 'send out to do stuff'


I don't think anyone knows for sure

Denis G10:09:40

sound good 😄


IMO it's mostly a "shared memory environment" vs a "non-shared memory environment"


And even in a shared memory env, actors act as if they are in a non-shared memory env


Actors live in a house and they send and receive all info via the mailbox at their front door. Agents can go to PO boxes and check the memory stores of the shared world.


so basically agents have a mission (in their head), actors have a script (from the director) 🙂

😅 4

It's also a container type (like an atom) that runs it's updates off the main thread


It's basically a thread with a container attached


Pretty simple. But that model satisfies the "agent" model better than the "actor" model


The fact that updates to the container participate in the "unified update model" of the entire clojure world gives it a lot of leverage


But, technically, you could leave that container nilled out all the time and just send functions to the agent like it's a thread to run things off the main thread.


And agents are backed by a thread pool, so you can fan work out to them just like a java thread pool, without touching their "local" containers at all.


Threads with their own coordinated memory, where coordinated means updates consistently with the rest of the clojure state model


(is another description, you could say)

Denis G14:09:11

Is agents implementation the only one for this "concurrency model"? Meaning are there other programming languages, that are using agents?


I think it's a more amorphous term outside of clojure. I'm not aware of many other languages giving a first class implementation like clojure


and most other context I'm familiar with the term is from the AI world, MAS and what not


But, one could argue, most threading models that act a little like java, is a little agent-ish

Denis G14:09:10

This is why this article confused me a little:


The terms in that piece refer to theoretical abstractions from the early days of Comp Sci. Hewitt's Actors paper is from the 1970s. The term "Agent" has been variously defined by lots of folks since at least the 1960s. Unfortunately that history, while fascinating, is a red herring when it comes to puzzling out what modern code is doing, or how current authors have made decisions about division of responsibility and so forth in their frameworks.


One could argue that threads in java satisfy some of those agent-like properties


So I kinda backed myself into a corner here. The first format is used while the user fills out the form where as the second format is used to validate the data and submit. Unfortunately this is making it difficult to load the form back after submission and clearly I should only be using one format but I’m not sure which one to pick. What questions should I be asking?


seems like you can always easily change between the two?


That’s true, it wouldn’t be difficult to change between the two. Perhaps the trick is converting the validation format back to the storage format after validation succeeds so it’s always stored\fetched the same way?


I'm a little confused by different terms here. But i would figure out what you want your data to look like in your form and then translate it into what the storage needs at the last moment after its been validated


you said "backed into a corner". not sure how far into the corner you are or if it would be easy to refactor. but i bet it would pay off


What is confusing about the terms? I know I’m not always great at communicating. Second, the form and storage both operate with that first format. After discussing this situation it appears I’m less into a corner and more just stubbed my toe 😛


I think the issue is that it’s mostly the first format, the storage format -> validation format -> validate -> submit where it should be storage format -> validation format -> validate -> back to storage format -> submit


maybe this is a better question for #cider, but how do y’all deal with a go-loop (or similar) running of the rails when running a repl in cider?


haha, don't write code that goes off the rails?

😅 4

in all seriousness, you can't kill go machinery from the outside, you pretty much need to restart your vm


(which is a good reason to make sure you write go-loops so they accept a termination message of course)

👍 4

If you are just playing around, you could always add an alts inside the go-loop that tries to read from a “poison”/“kill”/“termination” channel. Or even an atom you’ve defined (if only playing in the REPL)

👍 4

yeah i wondered if there was maybe some mitigating thing i could do outside of kill since this almost always happens when i’m being sloppy playing around lol


yeah, sadly the go machinery is not really open enough for that


@UCDG904RW keep a reference around to the channel where your loop is reading from. when the channel is closed (you know by reading a nil), then terminate the go-loop. this way you can quit the go-loop from outside.

👍 4

@U0E2EQFME Do you have an example of that termination atom or channel?


Example from

(defn make-printer-component [input-ch]
  (println "[printer-component] starting")
  (let [poison-ch (chan)]
    (go-loop []
      (let [[v ch] (alts! [poison-ch input-ch])]
        (if (= ch poison-ch)
          (println "[printer-component] stopping")
            (println (<! input-ch))
    (fn stop! []
      (put! poison-ch :stop))))
Though that code embeds the poison channel and returns a function that can be called to put a value onto the channel. You could pass the poison channel as another argument to the function and then place a value onto the poison-ch yourself.


the core thing is to always check a channel read/write for a nil, and not recur if you get a nil. If you close a chan that a go-loop uses and it doesn't check for nil it will often go into a hot loop consuming nils (unless this makes it blow up in someother way of course)


;; for dev sakes
(def quit? (atom false))

(a/go-loop []
  (println "hello")
  (a/<! (a/timeout 10000))
  (if @quit?
    (println "quit!")

  (reset! quit? true)


Ah that makes sense, thanks for the examples


I’m trying to sort-by alphabetically, but with an exceptional case. so I’m using sort-by with my own comparator:

(defn special-comparator
  [e1 e2]
  (if (and (= "speciala" e1) (= "specialz" e2)) -1
      (compare e1 e2)))
 (sort-by identity special-comparator ["s" "speciala" "specialz" "z"])
current result: ("s" "speciala" "specialz" "z")
desired result: specialz should be before speciala: ("s" "specialz" "speciala" "z")


i’m not sure what i’m missing in my implementation of special-comparator


oh hm. having stepped through it, i see there’s no comparison of speciala with specialz. hm.


yeah, a sort assume's it's commutative - that comparator breaks that rule


hm hm hm. thanks. i wonder how to get what i want.


does it? I think you can assume the order... because you can sort-by > and <, which are not commutative


2 < 3 == 3 < 2. That is a valid sort property, but not commutative.


I think you just need to swap e1 and e2...


replace -1 with false and it works


use comparator to make a legit comparator

Alex Miller (Clojure team)18:09:59

hey look, a whole guide! :)

👍 4

sorry, @john, this for me doesn’t work:

(defn special-comparator
  [e1 e2]
  (if (and (= "speciala" e1) (= "specialz" e2)) false
      (compare e1 e2)))
at repl: (sort-by identity special-comparator ["s" "speciala" "specialz" "z"])
result: ("s" "speciala" "specialz" "z")


@mfm sorry! I just realized that. That hack apparently works in cljs but not clj.


interesting! hmm


Yeah, probably since java.util.Comparator isn't in JS


and yes-- instead of the term “commutative” the clojure guide mentioned “totally-ordered set”--i think that’s the set of properties we were talking about.


i think what’s going on is, the assumption that the input is totally-ordered, means that you can do fewer comparison operations. so speciala is never getting compared with specialz. i could be wrong…


yeah, I don't think commutative was the right term, totally-ordered is the one


and yeah, it's not doing an O(n^2) sort that compares every item to every other item, we can assume that


What is your desired total order? Do you want "speciala" to be the minimum possible value among all possible, and "specialz" to be maximum among all possible, and all other pairs to be compared normally via compare?


@andy.fingerhut: speciala and specialz sorted normally among all elements except specialz comes before speciala


i think you could solve it if you added the reflexive case. make sure your function returns compare Special-Z Special-A = -1 and compare Special-A Sepcial-Z = 1


right now you assert special-A < special-Z AND special-Z < special-A


@mfm but where should specialm be relative to those two, if all three appear in the input to be sorted?


totally fair point, but in my desired case, there is only ever speciala and specialz. : |.


In the default clojure.core/compare function given strings, there are an unlimited number of strings after "speciala" but before "specialz"


actually: there is only one “rule”: specialz comes before speciala


Do you mean that the only values you will be sorting are the strings "speciala" and "specialz". There are no other string values you want to sort relative to those?


and i can generalize: specialz comes before all special’s


I understand each of the words of that rule, but that rule is not enough to specify a total order.


why isn’t that a total order? a b c … r s specialz speciala specialb … t


should "specialz" come before or after "speiak" ?


Sorry I meant "speciak" there.


before, i think. what’s wrong with it being before?


oh wait i think i meant after


(compare "speciak" "special") is -1, so "speciak" before "special". Same for the pair "speciak" and "speciala"


speciaj speciak special specialz speciala


Then there is where "specialzoo" goes relative to the rest. Probably where it was originally by what compare returns?


If yes, then it sounds like you want a custom comparator that could be described as: "When comparing any string except "speciala" to "specialz", compare it to "speciala" instead. When comparing "special" to "specialz", treat "specialz" as earlier."


the current implementation problem is i can’t guarantee that special will be compared to specialz


You don't need to do that, if your custom compare function always gives the correct answer given an arbitrary pair of strings.


the above comparator you’re talking about is what i was trying to write simple_smile


The trick is defining what that correct answer is for an arbitrary pair of strings.


the rule for "specialz" needs to fire when comparing with "specialy" also, because the sort could easily compare "speciala" to "specialy", then "specialy" to "specialz" and with a total order, it doesn't need to compare z and a


and the algorithm takes that for granted for efficiency


Let me hack up a proposed comparator fn in a couple of mins...


It won't be as short as you wish 🙂

🌞 4

a proposal. strip the special-a and z out of the seq, sort it, and then adjoin them at the end as you like


unless you are taking the exercise to learn (also a good option :)


thank you andy, noisesmith, enforser, alexmiller, john, dpsutton for all your help so far! i rigged up what i wanted as an ugly filter with a bunch of predicates. so no obligation @andy.fingerhut to make a comparator fn.


There may be something shorter, but I don't know how to make it much clearer yet:


`(defn my-custom-comparator [a b] (cond (= a b) 0 (= a "specialz") (if (= b "speciala") -1 ;; "specialz" is in same place as "speciala" ;; relative to any other string. (compare "speciala" b)) (= b "specialz") (if (= a "speciala") 1 (compare a "speciala")) :else ;; else neither of them are "specialz". Compare normally. (compare a b))) `


multiline is surrounded by three backticks not just one


Is the first case needed? I think (= a b) would be handled by the else's compare?


If I leave that (= a b) case out, then I think the middle cases need checks to see if you are comparing "specialz" to itself.


A general rule: using a comparator function for sorting, it can be given an arbitrary pair of values from your input collection, not only the ones that are next to each other in the sorted output sequence. You need to think "If I was given an arbitrary pair of values, and had to answer which one should be earlier and which one later, how would I do that?" You can't use the sorted sequence in the answer to that. 🙂


Well, I guess there are special cases where you are only sorting a finite set of values, and then you can use the complete list of items in the order you want to specify the compare result. But it doesn't work when there are an unlimited number of possible values to compare.

Drew Verlee21:09:21

On the subject of names, is it better to lean towards what a thing is, or how your going to use it?

Drew Verlee21:09:42

children vs children-to-feed


I would say it's better to use a name saying what something is -- since how you use it may change over time.