This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-10-21
Channels
- # announcements (10)
- # aws (38)
- # beginners (220)
- # calva (2)
- # cider (26)
- # clj-kondo (194)
- # cljs-dev (4)
- # clojure (190)
- # clojure-dev (7)
- # clojure-europe (3)
- # clojure-italy (6)
- # clojure-nl (4)
- # clojure-uk (8)
- # clojured (1)
- # clojurescript (29)
- # code-reviews (31)
- # community-development (9)
- # core-async (24)
- # cursive (38)
- # data-science (51)
- # datomic (52)
- # dirac (2)
- # emacs (3)
- # events (1)
- # figwheel-main (4)
- # fulcro (49)
- # graphql (13)
- # heroku (1)
- # hoplon (19)
- # immutant (3)
- # leiningen (1)
- # nrepl (59)
- # off-topic (12)
- # onyx (2)
- # pathom (51)
- # reitit (15)
- # shadow-cljs (88)
- # spacemacs (6)
- # sql (3)
- # tools-deps (107)
- # xtdb (11)
Is this pattern possible? I have many several namespaces under foo.bar
and would like to avoid requiring them each.
require
has no way that I am aware of to require multiple namespaces in a hierarchy, without listing each of their names explicitly.
There may be editor or other script-type assistance that people have created to generate such require statements for you, but I have not used them.
I recall a kind of 'abbreviated' form of require that I've only seen used rarely that may be helpful, if I can remember an example of it to show
Namespaces are not hierarchical like that, there is no "under" relationship between them
isn't foo.bar.baz/add
available from foo.core
without requiring it directly? or am i mistaken
i don't think i'm defining a hierarchy, only trying to imitate a pattern in Elixir which lets you alias namespaces like that
Here is an example of what I was thinking of: https://github.com/clojure/tools.analyzer.jvm/blob/master/src/main/clojure/clojure/tools/analyzer/jvm.clj#L17-L21
You still need to mention each 'leaf' namespace at least once, but the common prefix only needs to be mentioned once.
But in general it is bad practice to refer to names defined in code you don't have a explicit dependency on
maybe my approach of code distribution is flawed... would you say more numerous but smaller namespaces are discouraged in favor of fewer but larger ones?
That form of require
is not very commonly used, so may confuse some people, I expect. Also not sure whether it works in ClojureScript at all (I have half a memory of some warning about this)
Namespace size to taste, I think more namespaces are better then fewer, but I don't think there is a good hard and fast rule
Are we talking on the order of 10, 100, or 1000? I don't think anyone bats an eye at a namespace that require's 10 others.
probably 10, so maybe just overthinking it 🙂
thanks guys
Yes, this is very different from Elixir, which uses Erlang, where modules are more akin to classes
They don't really serve any other purpose. You could write your whole app in a single namespace if you fancied that
My suggestion would be: if you're building a library, organize it so users could do "mainline" stuff with just one required namespace and anything that is extra/optional can be in separate namespaces that they can require if they want. For example, honeysql.core
is all you need for basic stuff, but there are also optional honeysql.helpers
if you want the functional DSL and honeysql.types
if you want reader literals or "special" forms (designating inline SQL, raw SQL, specific function calls, etc). In next.jdbc
, the primary API is in that top-level namespace, but there are optional "friendly" SQL functions in next.jdbc.sql
and ways to extend handling of result sets in next.jdbc.result-set
and ways to extend handling of parameters and do batch execution of prepared statements in next.jdbc.prepare
and so on. @samcferrell
The analogy from @didibus is a good one: folders for your music, with subfolders just indicating additional categories of music (code) within the main category.
thanks @seancorfield. I should specify I'm building an application which has, potentially, a wide variety of domain objects. I've got one big namespace right now but playing around with different namespace layouts to help organize those domains
generally I'm trying to keep things flat, maybe at most 2 directories from the root, ex. src/foo/bar/baz/file.cljc
but with the majority of code in just the first directory down
Organizing an app by "domain concept" is reasonable. At work, our root ns segment is usually ws
or worldsingles
and we go down two more levels in several places, e.g., ws/admin/handlers/<domain>.clj
We only have one namespace nested deeper than that. We have 300 namespaces. A third of them are at that root+2 level, half of them are root+1, and the missing 1/6th (approx) are in the root (and those do not have the ws or worldsingles prefix -- but probably should).
Actually, I'll take a little bit of that last assertion back... we have quite a few worldsingles/<domain>.clj
namespaces in that 1/6th. Only eight have no World Singles style prefix (but they should).
that's really helpful to hear, most of the clojure code i see are libraries and not applications so its difficult to get a read on what people are doing in that space
For me, we have more of a micro-service style set of systems. So we rarely have more than 5 or 10 namespace per service.
To put things in context, those 300 namespaces are from src
folders so they're our production code (well, with a few very small build-related things included) and they make up about 70,000 lines of code. We have about 20,000 lines of test code in just over 300 files (because we have at least one test namespace for every single source namespace).
And they tend to all be the same.. You have a global namespace that hosts some configuration, and a few namespaces for the components handling the logic, and a core namespace which hosts the APIs, and a spec namespace for the domain objects that are persisted/exchanged to DB/other services
I also need to ask, what do you mean by domain objects? It triggers my, I'm worried you're doing OOP with namespaces alert
Like is it something more like DataAccess.clj or is it more like Car.clj Car.Mercedes.clj Car.Bmw.clj , etc.
(note: that's why I said "domain concepts" 🙂 )
You want your namespaces to be more like: Auth.clj, Search.clj, Login.clj, SQL.clj, Persistence.clj, API.clj, etc.
something like users, orgs, forms (like a form you submit to a government agency), etc
Our "domain objects" are just hash maps.
(gotta go pick up the wife from the airport -- this is an interesting discussion and I'll check back in later!)
Hum... hard to say since I'm not fully aware of the domain. But I think a good trick is to start with just one giant namespace, and than as you start to see clusters of functionality, you can split them up into their own.
@seancorfield See you later!
Cause its much more about someone else coming to look at the code, to be able to get a quick grasp of, what are the different logical pieces. So you know when you give someone a break down of an app? You generally draw big components and some arrows between them, and you rarely have hundreds, normally you draw 5 to 20 of them per app.
So like, if it makes sense to put all the forms and the form logic together you can do that. But sometimes, it makes more sense to break things not say by form, but by program instead, so you could have the GovernmentXHandlingComponent, and GovernmentYHandlingComponent. Or it might make more sense to break things in terms of functionality, like the FormSubmitter component, the FormDataAggregator component, etc
And like Sean mentioned, your domain objects, or what you could call your data schemas, those don't really need to exist anywhere in Clojure 😛. Since you don't have to specify a schema for the data the app handles. Though, it can be good practice to do so using clojure.spec, in which case you can put all of the schemas into one big namespace which defines to full set of data and all their shapes and relations for the app in one place.
So if your users, orgs and forms, are really just describing data, they might not be necessary. But if they are more like UserHandling, OrgHandling, FormHandling components, that seems fine to me
Anyways, there's no real right or wrong answer. At the end of the day, it is whatever works best for your app. The important thing is to realize the namespaces only solve three problems: (1) They prevent name clash when importing code from somewhere else. (2) They allow you to share a set of code together easily for reuse. (3) They can help split up a code base, in case your file gets way too big to navigate.
What they don't do is encapsulate and manage state and the life-cycle of data. Using them as such is what I would consider wrong.
Hello, everyone. Since Clojure doesn't allow assignments as we know from other languages, what would be the most idiomatic workaround for this seemingly limitation? (For instance, "capturing" some value for later use in the same function)
let
works pretty much the same way as assignment does on other languages, except for two differences. (1) It is scoped to itself, so its not local to the function, but to the surrounding parenthesis of the let
itself. Leave the block of the let
and the variables defined by it are gone.
(2) You can not mutate the bound variables that let
has assigned. You can only shadow them, but not change what they point too.
(let [x 10]
;; Prints 10
(println x)
(let [x 100]
;; Prints 100, but not because it mutated x, but this is another x that shadows the previous one
(println x))
;; Prints 10 again, since the x of the outer let was never mutated, it is immutable to whatever it was assigned too originally.
(println x))
@yokoyama.km Hope that answers your question
Thank you, @didibus for replying. Actually I'm think in a scenario like the following (in pseudo code):
op1()
op2()
x = op3()
op4()
op5()
...
opN(x)
To add to that, this is generally the difference between what we call binding and what we call assignment. Assignment assigns to an existing variable defined in the nearest scope, thus implies mutability. Binding means creating a new variable in the current scope and assigning it a value at creation time. Generally, once bound, the value can not be assigned to later. Though in Clojure in some cases it can be re-bound... which gets a bit more confusing, and you can mostly ignore for now.
Right, it certainly does the job. But it leads me to another question, is it ok to have all this code (from (op4)
up to (opN-1)
) in the let
scope just because of x
?
Well, it is okay, if you absolutely need to have all this imperative side-effectful logic, which you do need too sometimes. But in a lot of cases, you don't need too, and can change things to be less imperative.
I see. Maybe it can be a symptom of a too imperative way of thinking, right?
Like, how come op3 and op5 can not be called before op3 ? It can only be because they are secretly modifyin state outside the function, which makes their order matter, and a source of possible bug as well.
(op4)
(op5)
(opN (op3))
If you can't rewrite as above, its because you are dealing with state outside the function.Yes, rewriting the function may be the right solution in some cases
So once you get more into the functional mindset, and start writing mostly pure, side-effect free functions. You won't have this problem as much, because you'll almost always be able to do what I just did.
Which is why code will start to look like pipelines, or just composed functions nested one in another
(a (b (c)))
;; or
(-> (c) (b) (a))
But, sometimes you need side effect. Mostly when dealing with I/O, like writing and reading to a file or the database, taking user input, etc.
(println "Hello!")
(println "What is your name?")
(let [x (read-line)]
(println "Don't you worry though...")
(println "I will keep your name a secret.")
(println x))
And would it be OK to have something like
(let [x (some-large-piece-of-code)]
...)
?Especially when starting, people use let
a lot. And even later, let
is used I'd say in almost 50% of all functions at least once.
Really cool
But, functions that take no arguments in Clojure should be avoided as much as possible. Again, they are an indicator of side effect. And unless its a scenario like I described, where side effect is unavoidable, better avoid it.
So it would be more like:
(let [x (some-large-piece-of-code y)]
(* 2 x))
And in scenarios like this, the let is really useful just to give a name to the result of (some-large-piece-of-code).I have another question that is killing me: what is the most idiomatic way to do error handling? My first experience with FP was with Elixir. There, is idiomatic to return tuples, where its first element is an Elixir's atom (Clojure's keyword) with value, e.g., :ok
or :error
This thread can help you: https://clojureverse.org/t/error-handling-in-clojure/1877
Nice! Really thanks, @didibus!
The exception handling in Clojure is not classic FP, it is done the way Java, C#, etc. do it. That's because Clojure is a hosted language, and adopts the host's exception mechanism. So it just uses Java style exceptions.
You don't create new Exception types in Clojure though. Instead you use (ex-info)
and (ex-data)
functions.
That way, there's one coherent way to do exceptions. If it had added its own, you would still have needed to deal with Java's exceptions, and then you just would need to learn and use two different ways to deal with errors all the time, which would have been annoying.
Some people go out of their way and use a library that allows for more FP like error handling, but this is not idiomatic, and causes the problem I just described. So code like that is not portable, and other code doesn't know how to handle its errors.
See you! And thanks again!
It is certainly reasonable for functions within your own code to return a map with a key like :error
with values like true
or false
, or some keyword or nil
, but there is no standard practice there that I am aware of across Clojure projects. If you do that, you would need a way to propagate those up multiple levels of calls if the handling of the error was several levels up the call stack.
As a beginner, I must admit I'm very surprised with the lack of standard for error handling in Clojure. I'll stick with the exception approach for a while.
As someone else mentioned, exceptions that contains data in the form of maps are fairly standard, both on Clojure and ClojureScript. I just wanted to mention that you can use non-exception means if you wish.
So for example:
(def levenstein
(memoize (fn [x y]
(cond (empty? x) (count y)
(empty? y) (count x)
:else (min
(+ (if (= (.substring x 0 1) (.substring y 0 1)) 0 1) (levenstein (.substring x 1) (.substring y 1)))
(inc (levenstein x (.substring y 1)))
(inc (levenstein (.substring x 1) y)))))))
((memoize (fn levenstein [x y]
(cond (empty? x) (count y)
(empty? y) (count x)
:else (min
(+ (if (= (.substring x 0 1) (.substring y 0 1)) 0 1) (levenstein (.substring x 1) (.substring y 1)))
(inc (levenstein x (.substring y 1)))
(inc (levenstein (.substring x 1) y))))))
"asdf" "Asde")
You can name the anonymous fn by including a name before the arglist
levenstein
is not memoized in you case.
ah yes
(defmacro mmemoize [f]
(let [n (second f)]
`(do
(def ~n (memoize ~(cons 'fn (rest (rest f)))))
~n)))
((mmemoize (fn levenstein [x y] ...)) "asdf" "Asde")
and another possible solution without macro -
((let [levenstein (fn [mem-fn x y]
(let [levenstein (fn [x y]
(mem-fn mem-fn x y))]
(prn "!!")
(cond (empty? x) (count y)
(empty? y) (count x)
:else (min
(+ (if (= (.substring x 0 1) (.substring y 0 1)) 0 1) (levenstein (.substring x 1) (.substring y 1)))
(inc (levenstein x (.substring y 1)))
(inc (levenstein (.substring x 1) y))))))
mem-fn (memoize levenstein)]
(partial mem-fn mem-fn))
"asd" "ASD")
The trick is to generate memoized function that should have itself as a first argumentI'm trying to write a max-key
that returns a collections of things that are equivalent and maximum. But my code looks ugly. Any suggestions?
user=> (defn maxima
#_=> ([coll] (maxima identity coll))
#_=> ([key-fn [f & rst :as coll]]
#_=> (cond (empty? coll) []
#_=> (empty? rst) [f]
#_=> :else (second
#_=> (reduce (fn [[curr-max max-vals :as state] x]
#_=> (let [k (key-fn x)]
#_=> (cond (> k curr-max) [k [x]]
#_=> (= k curr-max) [curr-max (conj max-vals x)]
#_=> :else state)))
#_=> [(key-fn f) [f]]
#_=> rst)))))
#'user/maxima
user=> (->> (maxima val (zipmap [:a :b :c :d :e] [1 2 1 2 2]))
#_=> (map key))
(:b :d :e)
user=> (maxima val {})
[]
user=>
Or is there something in core I'm missing?
I've been able to improve this slightly by removing the 0 size and 1 size handling by using a sentinel value:
(defn maxima-3
([coll] (maxima identity coll))
([key-fn coll]
(first
(reduce (fn [[ms m :as state] [x k]]
(cond (or (identical? ::none m) (= m k)) [(conj ms x) k]
(> k m) [[x] k]
:else state))
[[] ::none]
(map (juxt identity key-fn) coll)))))
But the first
after reduce
still smells a bit to me.
Also, adding the sentinel, introduces the (identical? ::none m)
check for each item, slowing it down a bit.
(defn maxima [k v]
(let [m (zipmap k v)
selector (apply max v)]
(keys (filter #(= (second %) selector) m))))
Maybe?
Trying to figure out a one-pass solution to this
Not quite one-pass but this works too I guess:
(defn maxima-4
([coll] (maxima identity coll))
([key-fn coll]
(if (empty? coll) []
(->> (group-by key-fn coll)
(apply max-key key)
val))))
can you group by into a sorted map or something like that
(defn maxima
[key-fn coll]
(last (reduce (fn [acc x]
(update acc (key-fn x) (fnil conj #{}) x))
(sorted-map)
coll)))
Yup. The last one is basically what it does. I'm satisfied with it in-terms of how the code looks but, it still requires more memory than is really needed to do the job at hand. I don't need to carry around all groups (which is what group-by does), just the one with max-value.
I find sometimes if you are looking for maximum performance, good old loop/recur turns out to be the most readable code:
(defn max-equal
[m]
(loop [acc [], m m, curr-max (Integer/MIN_VALUE)]
(let [e (first m)]
(cond (empty? m)
acc
(> (val e) curr-max)
(recur [(key e)] (rest m) (val e))
(= (val e) curr-max)
(recur (conj acc (key e)) (rest m) curr-max)
:else
(recur acc (rest m) curr-max)))))
(max-equal (zipmap [:a :b :c :d :e] [1 2 1 2 2]))
;; => [:b :d :e]
Time once again for monday morning macros with Cas. I've attached a code snippet showing the barest form of my problem. I'm confused as to why the lambda shorthand works, but the fn
does not.
It appears you have attempted to define macro-test-fail
inside of a namespace named converter
. I guess that because part of the error message mentioned converter/m
converter/k
etc. Symbols inside of a backquoted expression are expanded to symbols with explicit namespaces, so that when the macro is invoked later from some arbitrary namespace, the names referred to are the ones active where the macro was defined, not where the macro was called.
To create a variant of macro-test-fail
that works, you could write it so that this does not happen for the function parameter m
, k
, and v
.
I am experimenting at my own Clojure REPL to remember how to do this
Yeah, that is definitely one way to do it:
(defmacro macro-test-2
[m f]
`(let [m# ~m ]
(reduce-kv (fn [acc# k# v#]
(assoc acc# k# (~f v#)))
{} m#)))
If you have not used macroexpand-1
before, that can be useful when understanding what macros are doing. e.g.
(pprint (macroexpand-1 '(macro-test-fail {:one 1 :two 2} inc)))
Sometimes the error messages (like in your you pasted above) make more sense when you look at the macroexpanded expression.
and the backtick makes things into vars but you need a symbol. if you type
``(fn [x] 3)` compare the output to
``(fn [x#] 3)` in a repl. no need for macroexpadn
using double backticks to surround the whole thing works kinda like double-quotes I guess is what they’re going for but oh geez is that ever not I also give up
intuitive
`
@dpsutton I'm not sure how to read the [x]
in the ~'
version. I assume that's a symbol?
backquote is also called "syntax quote" in clojure, and one of the things it does is fully qualify symbols
(`~` is often just called unquote, which is confusing because it only unquotes in syntax quote)
saying "resolves symbols" can also be confusing in this context, because typically when one talks about resolving symbols in clojure it is mapping symbols to vars, but in the syntax quote case when it says "resolves symbols" it means turning the symbol in to a namespace qualified symbol
it really has no meaning by itself because ~
doesn't mean anything without an enclosing syntax quote
ok, I understand that I believe. However, I'm still partially lost as to where x "exists" in
`(foo [~'x] f)
but a "namespaced" symbol is just a longer symbol, it doesn't mean the namespace exists or that there is a var with that name
I'm still fuzzy on the difference between a symbol and a var, but I think that just made it clearer for me
a "local" isn't a first class value, it is just some storage used internally in some code
on the jvm when a method is called it has basically an array of storage for values, and you can think of a local as just being one of those slots
a symbol is a name; a var is a little mutable cell you can fiddle with the contents of, usually part of some namespace and named by some symbol
what is the term for when a symbol is associated with a var? (I assume "associated" is incorrect)?
symbols have both syntax and semantics. syntactically, a symbol is just a word-like name. it is given semantic meaning based on both its lexical context and the state of the Clojure runtime environment.
symbols may be unqualified names that refer to "locals" only in a lexical context (a chunk of code that uses defn/fn/let etc to define a meaning)
or they may be qualified or unqualified names that are resolved to a meaning - either a var in a namespace or a Java class instance
who else is determining meaning? :)
maybe you were making a different point than I read it as
or I was reading your description as overly restrictive, I just mean you can have unqualified names that don't refer to locals just fine as long as you don't ask the compiler to do something with them
yes, that's why I said "qualified or unqualified names"
the compiler can of course do stuff with unqualified non-locals
by resolving them in the context of the current namespace
is there any way to lein ring uberjar
verbosely? i'd like to see a log of the classes being added to the jar
I have not tried it for a lein ring uberjar
command, but it should be quick to try the command DEBUG=y lein ring uberjar
to see what, if any, extra output is produced.
You can always run jar tvf <path to uber>.jar
after the fact to see what is in it @csd
Ah, OK.
to answer that, you could try lein with-profile +uberjar deps :plugin-tree
- or whatever profile ring ubjerjar uses while building classpath...
Hello all, I have a VERY noobish issue. I am reading "Clojure for the Brave and True" and I have gotten stuck early. I cannot figure out what the last three lines in this code block actually do: (defn my-reduce ([f initial coll] (loop [result initial remaining coll] (if (empty? remaining) result (recur (f result (first remaining)) (rest remaining))))) ([f [head & tail]] (my-reduce f head tail))) Could someone explain what the recur is actually doing here?
the last two lines are distinct from the line with recur
in it. that's how you create different arity versions of the same function
basically, it jumps back to loop
but replaces the values of result
and initial
with the result of (f result (first remaining))
and (rest remaining)
> if give two args, f
and a list, split the list into head
and the rest into tail
and call the three arity version with (my-reduce f head tail)
dpsutton - that makes sense, i was not seeing it as a different arity
and thanks bfabry, you cleared up the recur a good bit for me
smaller example can help. from https://clojuredocs.org/clojure.core/loop:
(loop [x 10]
(when (> x 1)
(println x)
(recur (- x 2))))
;;=> 10 8 6 4 2
It seems like im going to need MULTIPLE resources at once to learn this lol. I truly appreciate the help 🙂
At the cider repl in emacs, with evil mode on, can I somehow cycle through and run previous commands?
Control with up and down arrows works