Fork me on GitHub

Thanks. Also wondering if clojure (or I suppose if Java) has anything similar to python's pathlib: specifically contructing paths from pieces similar to the pathsegment argument of

Cora (she/her)00:12:34

you can also use this, it's quite nice

Cora (she/her)00:12:05

it's a single file, too, which is nice

👍 1
Darin Douglass14:12:28

( some-dir inner-dir file-name) also works

Darin Douglass14:12:03

(i totally didn’t see that you found this on your own, whoops 😛 )


Actually it looks like I can do that

👍 1

If I want to implement my own type (not just a specialization of a map), I know I should use deftype. Is there an equivalent to Python’s dunder methods or Abstract Base Classes to help guide creating my desired type?

Sam Ritchie00:12:37

I have a bunch of not too wild types that try to mimic clj data structures to some extent here if you want to skim a list of potential interfaces or protocols;type=


I’ll check that out!

Sam Ritchie00:12:33

I will often scan the protocol implementations in Clojurescript as a nice way to navigate

👍 2

I think I'm hoping for a table like for Python’s collections that somewhat neatly shows me which interfaces and methods needed to get which functionality

Alex Miller (Clojure team)01:12:59

I have a diagram for that in Clojure Applied

👍 1
Alex Miller (Clojure team)01:12:26

A cool gist that's floated around for years …

chef_kiss 1

oh this is awesome

Alex Miller (Clojure team)02:12:19

was originally a Christophe Grand hack, but you can find a variety of variants of it around with embellishments

👍 1
Alex Miller (Clojure team)01:12:01

^^ given a type / object, builds a scaffold to fill in


Oh excellent, I’ve been looking for a reason to pick that book up


I did a partial diagram at one point

Alex Miller (Clojure team)02:12:30

the one in Clojure Applied includes the Java methods and their mappings to Clojure fns. I would share it but copyright etc


I need to read that book one day! 🙂


But I should finish the above diagram, filling in the missing pieces, etc. Despite its shortcomings, I still find it useful

Filip Strajnar10:12:57

is there something i'm missing, because in the book they presented a macro like this:

Filip Strajnar10:12:15

but i was able to reproduce the macro with just a regular function

Filip Strajnar10:12:28

although granted, the ' had to be added

Lennart Buit10:12:29

Well your backwards function uses eval to evaluate the newly created form (with arguments reversed) at runtime

Lennart Buit10:12:01

The macro implementation will run at compile time, expand to the reversal of the args, and splice in the result on the macro call site


If you are wondering: Why do I need macros for this? The answer is: For this use case, you don't, unless you want the reversal to happen at compile time instead of run time. A general rule of thumb in Clojure is that implementing something as a function is usually preferable to implementing something as a macro, because you usually don't NEED a macro. You can pass functions to map apply filter, etc. You can't pass macros to those.


But when you NEED a macro, they are nice to have.

Filip Strajnar11:12:28

what'd be an example where a macro is necessary? maybe that will paint a better picture for me


you should never need eval really, its a dangerous operation (may allow remote users to run arbitrary code if not used with a lot of care).


I've doing Clojure for 7 years now, 5 professionally, I had never used eval in any of my applications 🙂


(defmacro time-compiled [] 
  (str (Instant/now)))


basic and perhaps not super-dee-duper useful, but this is a thing you can only accomplish with macros - eval runs at runtime


most macros are either def-like, wrapping up some boilerplate for a declaration of something


(defrecord ABC [a b c])


or with-like, wrapping up some lexical context


(with-open [will-close-when-done (thing)]


the more DSL-ey macros that have more complex semantics tend not to survive


but one of my favorite examples of macros is this


(let [name "bob"]
  (>> "Hello ~{name}, how are you?"))


this >> macro expands to (str "Hello " name ", how are you?")


you need to do that as a macro other wise you wouldn’t have name in scope


and its a clear example of something that other languages need to add language features for explicitly, but can be accomplished by a library in clojure


Implement a variant of when, where the body is only evaluated if the condition is true.


Implement a variant of for, where the body is evaluated a variable number of times, e.g. the number of times equal to the number of elements in an input sequence.

Lennart Buit12:12:11

Right, not sure how you stand in this, Andy, but my personal preference would be to use eval as rarely, or even more rarely than a macro


Macros have (at least) 2 unique powers that are either impossible or at least harder to do than without using macros: (1) Control whether the arguments are evaluated, or not, or how many times they are evaluated, and (2) introduce new names bound to values, e.g. as let does.


You don't need to use eval to write something that behaves like when as a Clojure / Common Lisp macro.


Nor to write for as a macro


And I completely agree that eval is rarely, if ever, needed for most applications.

Filip Strajnar12:12:07

when i use str directly, this works, but

Filip Strajnar12:12:31

when i use expression that evaluates to str˛it doesn't?


Can you please paste the code as text?

Filip Strajnar12:12:26

(ns app1.core
; (nth (reverse args) 0)

  "doesn't do much"
  (apply str (vec (drop 1 (vec (reverse args))))))

(defn -main
  "I don't do a whole lot ... yet."
  [& args]
    (println (backwards '(1 2 3 str)))))

Filip Strajnar12:12:50

(ns app1.core
; (nth (reverse args) 0)

  "doesn't do much"
  (apply (nth (reverse args) 0) (vec (drop 1 (vec (reverse args))))))

(defn -main
  "I don't do a whole lot ... yet."
  [& args]
    (println (backwards '(1 2 3 str)))))

Filip Strajnar12:12:52

this one doesn't


Because of the quote, you are passing the symbol str, and not the function that str is bound to in the clojure.core namespace

Filip Strajnar12:12:53

i thought symbol is the function

Filip Strajnar12:12:33

so how would i pass in a function

Filip Strajnar12:12:10

if function is 1st class citizen, i have it in the list, this should mean i can access function inside the list


(list 1 2 3 str)


Well, you can build the list with the function in it. For instance: (list 1 2 3 str)


So when you do that, str is evaluated as the function that str is bound to


At my repl, this prints as:

(1 2 3 #object[clojure.core$str 0x3241713e "[email protected]"])


Yeah, I would say using quote, aka ' , is rare in day-to-day Clojure


If you use ', it quotes everything in the list, including the str


Which prevents it from evaluating str to the function


If you were to evaluate it a second time, it would evaluate to the function


@U02QJVDHHE2 In Clojure, we typically use vectors to store and pass data around rather than lists; that would work right away: [1 2 3 str]


'str evals to the symbol str which then evals to the function


If you ever have a symbol, you can get the function that it’s bound to in a namespace (like clojure.core), but that’s getting more advanced, and unlikely to be what you want to do here. (you can call eval, or you can look up in the namespace)

Filip Strajnar12:12:42

oh, this works thanks

Filip Strajnar12:12:52

clearly I'm missing knowledge on the escape characters

Filip Strajnar12:12:00

thank you all very very much

❤️ 2

It’s a little tricky, but honestly, it’s rare for most code to need it

Filip Strajnar12:12:45

i really appriciate

Filip Strajnar12:12:53

clarified a lot, once again

Filip Strajnar12:12:05

really helpful people on this server 🙂


It's more useful for when you get to macros, which clj doesn't push as much as other lisps

Filip Strajnar12:12:35

i can see why, the functions are insanely powerful


I recommend @U050KSS8M’s advice: use […] for passing around sequences of data. Vectors convert to seqs automatically in most cases

Filip Strajnar12:12:17

i could just (vector )

Filip Strajnar12:12:33

same thing right?


You could, but it's longer


Well, that’s what square brackets do for you, and they’re shorter 🙂

Filip Strajnar12:12:04

i know, I just get carried away to simplify the syntax


The compiler turns it into a call to vector, yes

Filip Strajnar12:12:12

because with simple () you get to do so much in clojure

Filip Strajnar12:12:26

it just carries me away 😅


Unless I’m working at parsing or emitting code, then I don’t need lists very much

💯 1

Also, this is a stylistic advice, but I think it's relevant. Use let for clarity and to showcase the "order" of operations:

 "doesn't do much"
 (let [args         (reverse args)
       f            (nth args 0)
       numbers-data (drop 1 args)]
  (apply f numbers-data)))

(defn -main-2
 "I don't do a whole lot ... yet."
 [& args]
 (println (backwards [1 2 3 str])))


Brevity in excess can obscure clarity

☝️ 1
Filip Strajnar12:12:55

i'm using calva and whenever i format, it kinda does it own thing


That’s OK. But the let advice is sound


I've been doing Clojure since ~2013 and it took me a few minutes to unpack the initial code 🙂


You could also destructure with (let [[f & args] (reverse args)] ...)


But that's getting to more terse and less readable


Also, I advise people who are new to Clojure to learn about macros, but not to use them. I also advise people who have used Clojure for several years to not use macros 🙂

☝️ 2
😂 1

You should know what they are for those few times when you need to use them


And it's very rarely you need them


(Stuart Sierra did a talk about this many years ago: The first rule of macro club: Do not use macros. The second rule of macro club: DO NOT USE MACROS. … the talk went on to give sound advice about how to use macros if you REALLY have to use them)


Yeah... Macros are hard to get right. I would even say that you don't need to worry about them until you have a decent understanding of the entire language. But curiosity is always good.


@U051N6TTC Do you have a link to that talk by any chance? I might have watched it but not quite sure.


There is no video, but the slides are available


Ah, got it. Thanks anyway.

Filip Strajnar13:12:36

this is better style?

💥 1
Filip Strajnar13:12:06

out of curiosity, can i use (vector ) instead of [] for function arguments?


@U02QJVDHHE2 this looks much nicer, yes


When you define a function using defn, you must use [] around its arguments.


When you call a function, you can put whatever expressions you want in the call to send as parameter values.

Filip Strajnar13:12:55

I see, unfortunate

Filip Strajnar13:12:07

would be fun to use just the () in entire program

Filip Strajnar13:12:12

thanks for the answer


Why would you consider it useful to use (vector ...) inside of defn ?

Filip Strajnar13:12:51

it's not useful, it'd just be ultimately simple, as I'd use symbols and parentheses


Some other Lisp family languages use () consistently everywhere. Rich Hickey knew about that, and explicitly chose to use [] in places like defn and let for readability.

🙌 1

When defining, the defn is a macro so if you tried:

(defn add (vector a b) (+ a b))
Then the defn macro would see a list in the argument position, with the first element being the symbol vector. But it needs to see an actual vector object there, so you would get an error


i.e. NOT always using () for everything, so there are explicit visual cues that some things are parameter lists in a function definition, or a vector, or a map, and they look different

🙌 1
Filip Strajnar13:12:02

i agree it's more readable


Perhaps some of the conversation can go back to the main channel, so individual questions can be threaded out?

👌 1
Filip Strajnar13:12:05

so, what I'm hearing is, I could make a macro such as (vectorify) , which would evaluate that list to a vector?

Filip Strajnar13:12:26

which would allow me to use lists for function argument

Filip Strajnar13:12:38

even though, again, this is by no means useful


I am not sure about that. I think that perhaps a macro is restricted to replace lists with lists.


You could define your own macro mydefn that had a list of parameters inside of it, and replaced it with a standard defn with a vector for the parameters.

Filip Strajnar13:12:41

oh yea, that'd work


When I say "restricted to replace lists with lists", I meant more precisely that the top level thing returned by a macro must be a list. It can replace "inner lists" with other things.

Filip Strajnar12:12:48

how come this doesn't work


From the thread: @andy.fingerhut > i.e. NOT always using `()` for everything, so there are explicit visual cues that some things are parameter lists in a function definition, or a vector, or a map, and they look different I hate reading Scheme for this reason

Filip Strajnar15:12:10

is google still invested in clojure/clojurescript anyhow? (i'm aware this might be wrong channel to ask this type of thing but i don't know where it'd fit)


Would think not? I wonder if you're mistaking Clojure for ?


to follow up on my questions about deftype and creating a new type, I have been poking at the clj-commons/ordered library and the implementation of OrderedMap. In the implementation of the IPersistentMap interface, the method entrySet is defined, but that only exists on java.util.Map . When defining my own types, should I be looking at the java interfaces for methods to implement or just the clojure ones? (I don’t plan on using my type in any java interopt)

Alex Miller (Clojure team)15:12:56

I think the real answer is "it depends" but generally I'd say that you should plan to implement the read parts of the collection interfaces


the clojure collection interfaces?

Alex Miller (Clojure team)15:12:25

well certainly the Clojure collection interfaces, but I meant the JDK collection interfaces


okay, cool. thanks

Alex Miller (Clojure team)15:12:37

so, I would expect get to work on a map, but much less likely Clojure's impl would ever put (as we don't do that on persistent colls)


you’re talking about .get as an explicit method, right? vs IAssociative’s .entryAt or ILookup’s .valAt


thanks for all the help, i appreciate it

Alex Miller (Clojure team)15:12:55

yes was referring to Map.get()

👍 1
Alex Miller (Clojure team)15:12:27

certainly, you should implement the IAssociative / ILookup stuff - you know Clojure will depend on those

Alex Miller (Clojure team)15:12:15

it's possible some code may rely on the Java interfaces somewhere, but I can't say I've ever audited for that, for sure things like .iterator() are called


that makes sense


What is the #(Integer/parseInt %) syntax called when using a java method in a higher order function like map?


the #(…) form is a concise form of (fn [args] (…)) :


which is to say, an anonymous function


ah thank you

Alex Miller (Clojure team)15:12:11

and fyi, in Clojure 1.11, you'll be able to use parse-long for this

nice 1

Is the only reason to use #(..) over (fn ...) because it is more concise? I imagine it maybe is more helpful in other contexts - like maybe macro writing - when you need to grab parameters

Alex Miller (Clojure team)15:12:52

it's just syntax sugar for more concise fns


Thank you both


Is there a shorthand for def similar to defn- that will allow me to make a var defined as (def my-var 42) private and only accessible in my current namespace? I am aware that I could add ^:private as metadata to the my-var def .


I can cycle the privacy easily enough in emacs just wondering about a more concise way to do it


there’s no shorthand for def.


At a previous job they wouldn’t use defn- but rather defn ^:private so it would mimic the def ^:private

☝️ 1

actually that raises a good point; that would make private methods and defs easily searchable


@U01188CHUFL Also worth noting that you can "get around" private in Clojure by using #'some.ns/private.var to reference it -- which bypasses the access check. So ^:private is more "advisory" than, say, Java's private access.


ah I see - I didn't know that. I think that is okay, common lisp is similar in that regard you can use :: to access non-exported symbols in a namespace as opposed to : to access the exported symbols. As long as people know they are being naughty!

Michaël Salihi16:12:24

Hello, is there a more idiomatic way to write:

#(reset! form-value- (when-not (zero? %) %))


I wouldn’t do the reset unless the value required it, so:

#(if (zero? %) % (reset! form-value- %))


Or reverse the arguments:

#(if-not (zero? %) (reset! form-value- %) %)

Michaël Salihi17:12:00

Thanks for the suggestion. In my case, I must assign nil if the value is equal to zero.


Ah, I misunderstood. Then it was all good as it was

Michaël Salihi17:12:39

Perfect, thanks!


or I think this follow's @U051N6TTC's intent - not doing a reset unless the value changes:

#(if (zero? %) (reset! form-value nil) %)


atom operations are expensive

Michaël Salihi17:12:00

Thanks for the suggestion. In my case, I must assign nil if the value is equal to zero.

Dmitrii Pisarenko17:12:36

What could be the reason that

(defn render-text-fragments-overview-page
  [data target-file fragments-dir]
  (spit target-file
throws the exception
(render-all data)
Execution error (FileNotFoundException) at (
[email protected]/Users/dp118m/dev/misc/ (No such file or directory)
even though the directory exists? (Similar spitstatements work fine with other files being written in the same call.)

R.A. Porter17:12:23

I suggest you tap>, log, or prn the value of target-file there. It's not what you think it is, based on that exception.

Dmitrii Pisarenko17:12:43

@U01GXCWSRMW If I add (println (str "target-file: " target-file)), I get the following output:

target-file: [email protected]/Users/dp118m/dev/misc/


It looks like the str function was prepended to the front of the path. Maybe an extra str that you didn’t need got in where you were building the path?

☝️ 1
Dmitrii Pisarenko17:12:14

target-fileis FRAGMENTS_OVERVIEW_PAGEbelow.

(def MAIN_DIR "/Users/dp118m/dev/misc/")

(def FRAGMENTS_DIR (str str MAIN_DIR "fragments/"))
There was a duplicate strin definition of FRAGMENTS_DIR. Now it works. Thanks, @U01GXCWSRMW and @U051N6TTC.

👍 1

if you don't write clojure like

(defn foo [bar]
   (frob bar nil
I won't write javascript like
function foo
  {frob(bar null);};


(to be less snarky, it helps readability / mutual understanding if we use coding conventions native to the language we are writing, and we don't do hanging ) in clojure)


I actually had to double check that even worked 😆

> function foo
... (bar)
... {console.log(1 + bar);};
> foo("help");


How to add path in the system variable on Mac?


@jabeen2699 what are you trying to do?


The part in this image which says, in the system variables.. go to path etc


to persist things in a terminal session you can just type export VAR_NAME=value. I’m not sure what directions you are following though


or if you need those values to be set in all future terminal sessions or just this particular terminal session while you do a tutorial


It should be a permanent variable


I tried doing that already and it dint work


not sure what you shell is but most likely zsh on macosx. you might already have a file called ~/.zshrc. I have the following in there:

path=(~/bin $path)

which sets some environmental vars. You could do the same

👍 1

osx, years ago, when I used it, would set PATH differently for apps launched via the gui, and you had to edit an xml file to adjust that


similarly, if you are setting environment variables in your shell, but then doing stuff via emacs launched from the gui, I don't believe emacs will get your env variables

Cora (she/her)21:12:25

also there's a direnv library, if that's how you're loading things

Cora (she/her)21:12:35

intellij supports dotenv

Filip Strajnar22:12:43

how do i include a local dependency with leiningen?


this was a driving force behind our switch to deps.edn its a bit easier there


{components/abc {:local/root "../../components/abc"}}

Filip Strajnar00:12:51

I've tried checkout but it doesn't work, perhaps because i'm on windows

Filip Strajnar00:12:44

all i did was a shortcut, may not be same as a link on linux

Drew Verlee05:12:46

@U02QJVDHHE2 When you have time look into using clojure deps so you can take advantage of the logic emccue is pointing out above.

Filip Strajnar22:12:57

I made a simple library, I wish to use it in a completely different project


if I'm not working on both projects in parallel, the thing I've found easiest is running lein install in the lib project, then adding it to the other project as a normal dep


the gotcha with lein install is you need to remember that projects that use libs installed that way won't work on other computers (and the version installed and your latest edits can go out of sync)