This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-10-06
Channels
- # aleph (15)
- # announcements (2)
- # babashka (121)
- # beginners (62)
- # biff (6)
- # cherry (2)
- # cider (51)
- # clerk (30)
- # cljs-dev (5)
- # clojure (77)
- # clojure-austin (2)
- # clojure-europe (10)
- # clojure-germany (6)
- # clojure-nl (1)
- # clojure-norway (19)
- # clojure-romania (1)
- # clojure-uk (3)
- # clojurescript (16)
- # core-typed (7)
- # cursive (17)
- # datomic (12)
- # deps-new (11)
- # emacs (7)
- # events (2)
- # fulcro (5)
- # honeysql (2)
- # hyperfiddle (32)
- # introduce-yourself (1)
- # jobs-discuss (2)
- # membrane (18)
- # missionary (2)
- # music (5)
- # polylith (7)
- # reagent (26)
- # releases (5)
- # testing (32)
- # tools-build (14)
- # tools-deps (7)
- # xtdb (8)
I wish to
(defn Long [x] ...)
But I get
Expecting var, but Long is mapped to class java.lang.Long
even with
(ns foo
(:refer-clojure :exclude [Long]))
Is there a way to do this?why do you want to?
you could unmap Long
(ns-unmap *ns* 'Long)
(defn Long [x])
but that's unlikely to be a good ideait's likely to be a bad idea even :)
I just haven't run into any symbol limitations like this yet.
I'm defining a yamlscript.ast
namespace with names like
Map Vec Str Key Sym Char Bool Long
and Long
was the first one to bite me. I can use LNum
or somesuch.
was just a but surprised, but I can see how it might lead to chaos.
Wondering what other (kinds of) symbols are off limits in my own namespace...Clojure by default imports many classes in the java.lang
package, including Long
Integer
Byte
probably a few dozen others.
I know. That's why I added "(kinds of)"
Reminds me of when we had just started with Common Lisp and one of us unbound t
. New languages are fun!
I am trying to find where in the Clojure implementation it does that, which should lead to a straightforward method of knowing the complete list of such names.
iow, are there other kinds of symbols besides classes that will cause the same kind of issue
(->> *ns*
ns-map
seq
(filter #(= (type (second %)) Class))
(map first)
sort
count
)
=> 96
(AbstractMethodError Appendable ArithmeticException ArrayIndexOutOfBoundsException ArrayStoreException AssertionError BigDecimal BigInteger Boolean Byte Callable CharSequence Character Class ClassCastException ClassCircularityError ClassFormatError ClassLoader ClassNotFoundException CloneNotSupportedException Cloneable Comparable Compiler Deprecated Double Enum EnumConstantNotPresentException Error Exception ExceptionInInitializerError Float IllegalAccessError IllegalAccessException IllegalArgumentException IllegalMonitorStateException IllegalStateException IllegalThreadStateException IncompatibleClassChangeError IndexOutOfBoundsException InheritableThreadLocal InstantiationError InstantiationException Integer InternalError InterruptedException Iterable LinkageError Long Math NegativeArraySizeException NoClassDefFoundError NoSuchFieldError NoSuchFieldException NoSuchMethodError NoSuchMethodException NullPointerException Number NumberFormatException Object OutOfMemoryError Override Package Process ProcessBuilder Readable Runnable Runtime RuntimeException RuntimePermission SecurityException SecurityManager Short StackOverflowError StackTraceElement StrictMath String StringBuffer StringBuilder StringIndexOutOfBoundsException SuppressWarnings System Thread Thread$State Thread$UncaughtExceptionHandler ThreadDeath ThreadGroup ThreadLocal Throwable TypeNotPresentException UnknownError UnsatisfiedLinkError UnsupportedClassVersionError UnsupportedOperationException VerifyError VirtualMachineError Void)
There are also symbols that you can't even really defn, but no error when you try, e.g.:
user=> (defn try [x] (inc x))
#'user/try
user=> (try 5)
5
the special forms?
special-symbol?
return true for that kind of symbol, e.g:
user=> (special-symbol? 'try)
true
(Enum Class Error Runtime Cloneable Object Process Double Callable String Void Override Iterable Runnable System Throwable Deprecated Thread Package Readable Boolean Math Comparable Integer Short Number Character Exception Float Long Compiler Appendable Byte)
Are the single word ones.so the custom of lowercase-hyphenated names in Clojure side-steps the possibility of such abstruse collisions
Nod. I have my reasons for using these symbols in this specific case.
@U0CMVHBL2 right, special form symbols are not looked up from a namespace.
note: most of limitations discussed here are more like "implementation details"
I believe that (defn Long [x] ...)
works in #C03S1L9DN and probably #C03A6GE8D32
btw @U05H8N9V0HZ
> I'm defining a yamlscript.ast namespace with names like
Seems that you are working in some kind of DSL
Did you tried #C015LCR9MHD (the engine behind #CLX41ASCS)? I think that this tool will allow you to do that kind of thing.
@U2J4FRT2T ys
and libyamlscript
are compiler/evaluators that use SCI for evaluation.
But I wasn't aware that you could (defn Long ...)
with SCI. Thanks!
$ bb -e "
(defn Long [x] (+ x 1))
(Long 41)
"
42
.
$ ys -Ee "
defn Long[x]: (x + 1)
Long: 41
"
42
But the YAMLScript compiler itself uses JVM Clojure so it can use GraalVM to compile to the native ys
and libyamlscript
.
Hello clojurians, I'm relatively new to the world of programming and web development. My goal is to be a proficient fullstack web developer Is there a roadmap / milestone layout / checklist that I can follow on the path to proficiency with Clojure in the domain of web development?
This gets asked from time-to-time but there's really no consensus on answers...
Some people might suggest the Web Development with Clojure book but I think the underlying collection of libraries is "too much" for a beginner. I think Getting Clojure or Living Clojure are good books to start with.
Full-stack in the Clojure world means ClojureScript on the frontend and that's a whole different beast in terms of tooling but you could try reading the shadow-cljs docs and see how you feel about it.
On the backend, Ring is the underpinning for everything else but you'll have a choice of routing libraries and lifecycle management libraries etc. I often point beginners to https://github.com/seancorfield/usermanager-example which uses Ring + Compojure + Component (+ next.jdbc
for the database and Selmer for the HTML templating). There's a link in the README to a variant of that app that uses Integrant and Reitit (instead of Component and Compojure).
• https://www.oreilly.com/library/view/getting-clojure/9781680506082/ (2018) • https://www.oreilly.com/library/view/living-clojure/9781491909270/ (2015)
Could you give an example path of what projects I could work on to apply what I learn maybe?
I'm not sure what you mean... specific existing projects you could contribute to, or ideas of new projects you could build? (I don't really have suggestions of either -- most of the former out there are libraries, not apps)
https://developer.mozilla.org/en-US/docs/Learn could be a good general reference for web development, and for Clojurescript I would second Sean's rec to read the https://shadow-cljs.github.io/docs/UsersGuide.html. On the corresponding GitHub repo there's also a bunch of sample projects.
Would you say there are milestones I can keep in mind at least? I've heard projects are an effective way to assert understanding and set milestones
Personal opinion as an advanced beginner but I think that's highly dependent on your learning style. I wouldn't get too bogged down in a project-oriented mode of learning, unless they are projects you are personally interested in. I've done a lot of tutorials and the like, and I have learned stuff, but the final product always feels a bit unsatisfying to me. YMMV, though. Clojure's a highly dynamic language by design and I think you can learn a lot by finding a good REPL workflow that works for you. Plenty of content out there on that subject.
I would recommend starting on the backend of the full stack journey, as it is arguably simpler (and a smaller set of choices) than the front end. There are many technology choices in the frontend (html, htmlx, JavaScript, react, react native, vue, etc) and more options in how humans and devices will interact. Creating an API based backend makes it relatively simple to build whatever kind of front end is desirable. Common backend aspects include • Understand the fundamentals of ring • Choose a HTTP server (http-kit, jetty) and adapt and learn how to manage it via the REPL (reload the server app without having to restart the REPL (dynamic var, atom, component library (donut, integrant, mount, etc.) • Routing requests (reitit & reitit-ring for a data centric config, or composure for macro abstraction) • Writing request handlers (functions) • Writing middleware (functions) • Testing handlers (test functions) • Open API (swagger) Practicalli Project templates has a service template that generates a new project with a working API example with the above aspects (with a choice of atom, donut system or integrant to manage components of the system) https://practical.li/clojure/clojure-cli/projects/templates/practicalli/ Additional backend aspects to consider • Persistence - most common is next.jdbc with a relational database, e.g postgresql or maria DB. Also consider web-based persistence services like firebase (useful for richer web UI & mobile apps ) • Authentication and authorization - buddy, friend and similar libraries. Also Java Web Service tokens and OAuth are quite prevalent • Data streaming - ingesting and producing streams of data especially useful for large data processing Once there is the basics of an API then decide what kind of front end is useful and what is the target platform (web browser, mobile, everything) • Server-side content - simplest approach, but static (although htmlx or JavaScript enables a richer interaction) • ClojureScript frontend • ClojureScript with react.js - start with reagent and then consider larger libraries such as re-frame, rum, etc if more stateful and involved UI workflows are required • JavaScript (or any other frontend technology that can consume APIs Other useful examples • https://kit-clj.github.io/ to create projects from templates with a range of different options, providing example code showing how libraries can be wired together • Various examples of the User Manage project are published on GitHub, with different component libraries and other features Hopefully this has given some further insight into an approach, although anyone Shou consider what goals are valuable to achieve and form the community opinions into their own learning path.

This might also help, especially to understand how an HTTP request works, which is fundamental for a web API or App. All the best !! 🙂 https://ericnormand.me/guide/clojure-web-tutorial
I am trying to “re-pull” down a library, referenced in deps from Github. Initially, the library pulled down fine. Now I want to repeat that process from scratch. It had pulled down into ~/.m2/repository
initially. I deleted its specific directory in there. I also wiped out ~/.clojure/.cpcache
. However - somehow it’s still cached somewhere. My test still works, without pulling it down again. So where else should I be looking here?
ha ha - ok thank you I thought I was going crazy 🙂
https://github.com/clojure/tools.gitlibs is the library that is used to manage git deps
Oh nice, bonus! Thank you.
Style question:
I have a function main-fn
that uses a filter-fn
in a map. That filter is based on arguments passed into main-fn
.
At first, I just defined filter-fn
in my let binding and then proceeded to use it successfully in my map.
Then, instead of defining it in my let binding, I just defined it with defn
at the top of the body of my main-fn
. This also works fine.
I get a clj-kondo warning about this though, so I’m wondering if this is “bad form” or if there is a downside to this?
Just an inline def
warning
oh yes, that. just use a let binding, vars should be defined top level, not within function bodies
def and things derived from it like defn always create global bindings of names to values
Ok, here’s the actual code (maybe I shouldn’t have tried to de-mystify it):
(defn replace-in-file [file string-regex replacement-string]
(defn replace-in-string [string]
(let [replaced-string (str/replace string string-regex replacement-string)]
(when (not= replaced-string string)
(println-now (<< "Replaced string in {{file|qq}}")))
replaced-string))
(let [contents (str/split (slurp file) #"\n")
updated-contents (map replace-in-string contents)]
(spit file (str/join "\n" updated-contents))))
So are we saying that the defn replace-in-string
function will be globally available after evaluating?
the name will be created and globally visible, but the value won't be assigned to it until after repace-in-file has run
Ok, so all things considered - it’s better to just keep it to a let in this case it sounds like.
(defn f [] (defn g []))
is basically (do (declare g) (defn f [] (alter-var-root #'g (constantly (fn [])))))
Interesting - that’s good to know. I don’t think I need more than the basic let binding in this case, but I was unaware of this option, so thank you!
(defn foo []
(defn bar [x] x))
(bar 3)
;; Attempting to call unbound fn: #'bar
(foo)
(bar 3)
;; 3
it's generally frowned upon (fwiw): <https://guide.clojure.style/#dont-def-vars-inside-fns>
as always, there might be cases where it makes sense, but if the desire is to scope replace-in-string
to the containing fn, let or letfn is the best bet - if the goal is to make replace-in-string
a namespace-level binding, defn it at the top-levelyou can get much weirder more interesting errors depending on what you are doing with the value of the unbound var
% clj
Clojure 1.11.1
user=> (defn f [] (defn g []))
#'user/f
user=> (identity g)
#object[clojure.lang.Var$Unbound 0x4e558728 "Unbound: #'user/g"]
user=>
Thanks all. The “plain” let binding will work fine for me. I didn’t really need anything more. I’ve just been experimenting with readability and different ways to do things. I liked that kondo gave that warning, it put me on this path to learn some new things. I’ve been also been putting partial
through it paces for more general purpose functions where I want to sort of “pre-load” them with arguments and then run the fn against a map. I’m just getting more functional in my thinking and doing lots of tests.