This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-12-17
Channels
- # adventofcode (25)
- # announcements (2)
- # babashka (16)
- # babashka-sci-dev (16)
- # beginners (213)
- # calva (15)
- # clj-kondo (126)
- # clj-on-windows (1)
- # cljdoc (5)
- # cljfx (1)
- # cljs-dev (6)
- # clojure (230)
- # clojure-europe (38)
- # clojure-nl (3)
- # clojure-uk (3)
- # conjure (10)
- # core-async (15)
- # cursive (33)
- # fulcro (58)
- # hyperfiddle (4)
- # jobs-discuss (1)
- # kaocha (5)
- # lsp (46)
- # meander (3)
- # off-topic (30)
- # polylith (10)
- # portal (9)
- # re-frame (5)
- # reitit (7)
- # releases (2)
- # ring (17)
- # sci (8)
- # shadow-cljs (6)
- # specter (1)
- # sql (1)
- # testing (9)
- # tools-deps (4)
- # vim (12)
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 https://docs.python.org/3/library/pathlib.html#pathlib.PurePath
you can also use this, it's quite nice https://github.com/babashka/fs
and then you can just call path with multiple arguments https://github.com/babashka/fs/blob/master/src/babashka/fs.cljc#L43
(
also works
(i totally didn’t see that you found this on your own, whoops 😛 )
Actually it looks like I can do that https://clojuredocs.org/clojure.java.io/file
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?
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 https://github.com/sicmutils/sicmutils/search?q=deftype&type=
I’ll check that out!
I will often scan the protocol implementations in Clojurescript as a nice way to navigate
I think I'm hoping for a table like https://docs.python.org/3/library/collections.abc.html#collections-abstract-base-classes for Python’s collections that somewhat neatly shows me which interfaces and methods needed to get which functionality
A cool gist that's floated around for years … https://gist.github.com/semperos/3835392

oh this is awesome
was originally a Christophe Grand hack, but you can find a variety of variants of it around with embellishments
^^ given a type / object, builds a scaffold to fill in
Oh excellent, I’ve been looking for a reason to pick that book up
the one in Clojure Applied includes the Java methods and their mappings to Clojure fns. I would share it but copyright etc
But I should finish the above diagram, filling in the missing pieces, etc. Despite its shortcomings, I still find it useful
is there something i'm missing, because in the book they presented a macro like this:
but i was able to reproduce the macro with just a regular function
although granted, the '
had to be added
Well your backwards function uses eval to evaluate the newly created form (with arguments reversed) at runtime
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.
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 🙂
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
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.
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.
alright thanks
when i use str
directly, this works, but
when i use expression that evaluates to str
˛it doesn't?
ofcourse
(ns app1.core
(:gen-class))
; (nth (reverse args) 0)
(defn
backwards
"doesn't do much"
[args]
(apply str (vec (drop 1 (vec (reverse args))))))
(defn -main
"I don't do a whole lot ... yet."
[& args]
(do
(println (backwards '(1 2 3 str)))))
this one works
(ns app1.core
(:gen-class))
; (nth (reverse args) 0)
(defn
backwards
"doesn't do much"
[args]
(apply (nth (reverse args) 0) (vec (drop 1 (vec (reverse args))))))
(defn -main
"I don't do a whole lot ... yet."
[& args]
(do
(println (backwards '(1 2 3 str)))))
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
i thought symbol is the function
so how would i pass in a function
if function is 1st class citizen, i have it in the list, this should mean i can access function inside the list
At my repl, this prints as:
(1 2 3 #object[clojure.core$str 0x3241713e "clojure.core$str@3241713e"])
Yeah, I would say using quote, aka ' , is rare in day-to-day Clojure https://clojuredocs.org/clojure.core/quote
@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]
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)
oh, this works thanks
clearly I'm missing knowledge on the escape characters
i really appriciate
clarified a lot, once again
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
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
i could just (vector )
same thing right?
i know, I just get carried away to simplify the syntax
because with simple () you get to do so much in clojure
it just carries me away 😅
Also, this is a stylistic advice, but I think it's relevant. Use let
for clarity and to showcase the "order" of operations:
(defn
backwards
"doesn't do much"
[args]
(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])))
i'm using calva and whenever i format, it kinda does it own thing
I've been doing Clojure since ~2013 and it took me a few minutes to unpack the initial code 🙂
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 🙂
(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.
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.
I see, unfortunate
would be fun to use just the () in entire program
thanks for the answer
Why would you consider it useful to use (vector ...)
inside of defn
?
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.
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 errori.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 agree it's more readable
Perhaps some of the conversation can go back to the main channel, so individual questions can be threaded out?
so, what I'm hearing is, I could make a macro such as (vectorify)
, which would evaluate that list to a vector?
which would allow me to use lists for function argument
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.
fair enough
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.
oh yea, that'd work
thanks
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.
understood
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
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 https://developers.google.com/closure ?
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)
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?
well certainly the Clojure collection interfaces, but I meant the JDK collection interfaces
okay, cool. thanks
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
certainly, you should implement the IAssociative / ILookup stuff - you know Clojure will depend on those
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] (…))
: https://clojure.org/reference/reader#_dispatch
which is to say, an anonymous function
and fyi, in Clojure 1.11, you'll be able to use parse-long
for this

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
it's just syntax sugar for more concise fns
@U01188CHUFL This is good reading about the #(..)
syntax: https://stuartsierra.com/2019/09/11/clojure-donts-short-fn-syntax
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
At a previous job they wouldn’t use defn-
but rather defn ^:private
so it would mimic the def ^:private
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!
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- %))
Thanks for the suggestion.
In my case, I must assign nil
if the value is equal to zero.
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
Thanks for the suggestion.
In my case, I must assign nil
if the value is equal to zero.
What could be the reason that
(defn render-text-fragments-overview-page
[data target-file fragments-dir]
(spit target-file
"Hello"
)
)
throws the exception
(render-all data)
Execution error (FileNotFoundException) at java.io.FileOutputStream/open0 (FileOutputStream.java:-2).
clojure.core$str@6d91790b/Users/dp118m/dev/misc/dpisarenko.com/content/conscience-of-nation/fragments/overview.org (No such file or directory)
even though the directory exists?
(Similar spit
statements work fine with other files being written in the same call.)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.
@U01GXCWSRMW If I add (println (str "target-file: " target-file))
, I get the following output:
target-file: clojure.core$str@6d91790b/Users/dp118m/dev/misc/dpisarenko.com/content/conscience-of-nation/fragments/overview.org
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?
target-file
is FRAGMENTS_OVERVIEW_PAGE
below.
(def MAIN_DIR "/Users/dp118m/dev/misc/dpisarenko.com/content/conscience-of-nation/")
(def FRAGMENTS_DIR (str str MAIN_DIR "fragments/"))
(def FRAGMENTS_OVERVIEW_PAGE (str FRAGMENTS_DIR ""))
There was a duplicate str
in definition of FRAGMENTS_DIR
.
Now it works.
Thanks, @U01GXCWSRMW and @U051N6TTC.if you don't write clojure like
(defn foo [bar]
(frob bar nil
)
)
I won't write javascript like
function foo
(bar)
{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);};
undefined
> foo("help");
1help
undefined
@jabeen2699 what are you trying to do?
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
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)
MB_DIR=~/projects/work/metabase/
MB_SCRATCH_DIR=~/projects/work/scratch/
which sets some environmental vars. You could do the sameosx, 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
also there's a direnv library, if that's how you're loading things
intellij supports dotenv
how do i include a local dependency with leiningen?
See https://github.com/technomancy/leiningen/blob/master/doc/TUTORIAL.md#checkout-dependencies
I've tried checkout but it doesn't work, perhaps because i'm on windows
all i did was a shortcut, may not be same as a link on linux
@U02QJVDHHE2 When you have time look into using clojure deps so you can take advantage of the logic emccue is pointing out above.
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)