This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-07-31
Channels
- # beginners (153)
- # cider (30)
- # cljs-dev (8)
- # cljsrn (8)
- # clojure (105)
- # clojure-dev (6)
- # clojure-dusseldorf (5)
- # clojure-italy (6)
- # clojure-nl (3)
- # clojure-russia (34)
- # clojure-spec (23)
- # clojure-uk (54)
- # clojurescript (104)
- # core-matrix (3)
- # crypto (1)
- # cursive (17)
- # datomic (90)
- # duct (13)
- # editors (5)
- # emacs (1)
- # events (1)
- # figwheel-main (9)
- # fulcro (54)
- # hoplon (18)
- # hyperfiddle (2)
- # jobs-rus (1)
- # lein-figwheel (5)
- # leiningen (3)
- # luminus (52)
- # mount (6)
- # off-topic (22)
- # other-languages (3)
- # parinfer (7)
- # powderkeg (3)
- # re-frame (52)
- # reagent (58)
- # rum (4)
- # shadow-cljs (49)
- # spacemacs (12)
- # sql (13)
- # tools-deps (2)
- # yada (1)
@hoopes I would direct you to one of two strategies: (1) bundle all your javascript code with webpack and then include it use :foreign-libs
(https://clojurescript.org/guides/webpack), or (2) use the shadow-cljs
build tool. https://shadow-cljs.github.io/docs/UsersGuide.html
shadow is probably best if you don’t already have a big lein infrastructure in place
yeah, i’ve heard of shadow, i guess i should probably learn it…it’s meant to work best with npm?
the npm-deps feature is pretty “alpha”. it’ll break on quite a few things and is hard to debug. it’s getting better but it’s not quite there yet.
shadow works great with npm packages. it is super smooth: you just install via npm and it reads directly from node_modules
likely not if you use externs inference. jump into #shadow-cljs if you decide to go that way
Thanks @michael.gaare and @noisesmith. In my case I do in fact need to manage a stateful connection object, but you're right, a connect
function to create the handler and passing the handler in gives the most flexibility to the user. Appreciate the input!
as a value add you can premake eg. the version that stores the connection as a global singleton, or the version that implements a stuartsierra/component object, but bare minimum should be the ability to make your domain object with a function, and pass it to another function, and usually that's enough
What’s going on when my webapp works fine when I run it in REPL but when I package it as uberjar
I’m getting this when trying to run java -jar blabalba.jar
> Exception in thread “main” java.lang.NoSuchFieldError: thunk__0__
This probably has something to with aot
and having right settings in project.clj
. I’ve specified :main
pointing to a namespace where I have -main
function and :gen-class
. I’ve tried specifying :aot :all
in my lein uberjar profile and leaving it unspecified but I’m getting this same error.
Hmmm, after removing dependency [com.fzakaria/slf4j-timbre "0.3.7"]
uberjar works! Interesting. I’m not even sure why I had that dependency. 🙂 Anyways, is it a common thing that some libs or combos of libs just don’t work with uberjar
?
@valtteri - I am not an expert but https://github.com/fzakaria/slf4j-timbre has the version at 0.3.12 and also mentions 3 other dependencies you should have.
Thanks Keith, I had some rough times figuring out all the Java logging frameworks/wrappers/utils a few weeks ago and I guess slf4j-timbre
was leftovers from my experiments. I ended up using just timbre
and excluding any other logging libs. But it’s interesting that it breaks my uberjar. I’d like to know why that happens.
@valtteri I don't know offhand why that's causing problems, but the first thing I'd look for would be dependency version classes, which you can do (in projects using Leiningen) with lein deps :tree
. The beginning of the output from that should show any potential conflicts.
If you find a conflict that seems relevant, you can exclude it in project.clj
by adding exclusions like
[com.fzakaria/slf4j-timbre "0.3.7"
:exclusions [some.lib]]
It may not be a dependency conflict at all, but it's a good thing to check.However, I was able to proceed by removing the dependency. I just don’t like to leave ‘holes’ to my understanding, because I’m sure it will haunt me in the future. 🙂
timbre is what I use (ok, inherited from an example)
@valtteri I don't know offhand why that's causing problems, but the first thing I'd look for would be dependency version classes, which you can do (in projects using Leiningen) with lein deps :tree
. The beginning of the output from that should show any potential conflicts.
If you find a conflict that seems relevant, you can exclude it in project.clj
by adding exclusions like
[com.fzakaria/slf4j-timbre "0.3.7"
:exclusions [some.lib]]
It may not be a dependency conflict at all, but it's a good thing to check.Cool, thanks @eggsyntax! I didn’t realize there was useful human-readable debug info at the beginning of lein deps :tree
output.
What is "deps.edn" exactly? It seems like an official replacement for leiningen project.clj. Is that correct?
@somedude314 Not quite - it deals mostly with dependencies, whereas lein is a build tool.
There has been a push recently to try and replicate a lot of lein plugins into standalone libraries that can be then consumed without lein (e.g. uberjar) but it’s not quite widespread.
@orestis Hmm, that's odd. It deps.edn doesn't seem to be doing anything that can't be done in project.clj
It has a different philosophy. Plus you can get dependencies from git, github, gists and so on — also it’s simpler (in the clojure sense) than lein.
👋 Using Clojure spec how do I specify an "XOR" on keys. Namely that a map should have either :foo
or :bar
, but not both :foo
and :bar
?
So far I've got this, but it's a bit clunky:
(s/def ::foo int?)
(s/def ::bar int?)
(s/def ::foobar
(s/and
(s/or
:f (s/keys :req-un [::foo])
:b (s/keys :req-un [::bar]))
#(not (and (contains? % :foo)
(contains? % :bar)))))
James, this post helped me on this particular topic. https://stackoverflow.com/questions/41899511/clojure-spec-map-containing-either-a-with-or-a-height-xor/41901616
my hunch is usually that would be prevented by nil-checking the return value of io/resource
I changed a project's dependency to a different snapshot and I get this error
Exception in thread "main" java.lang.NoClassDefFoundError: clojure/lang/Tuple
If I go back to an older snapshot the error goes away the project starts up as normal
I have a feeling its because we are using an older version of Clojure in this project
@mario.cordova.862 Yes, Tuple was briefly added and then removed IIRC.
you're on the right track. You might have a dependency that is accidentally AOT-compiled, or some stale files in ./target
What's in your project.clj
file?
(and, maybe, lein clean
will help you get back to a sane state)
What version(s) were you trying to use?
hey, how can i have my resources path included in the jar file from lein uberjar
? I tried adding it to :resources-paths [...]
but it seems to just create the directory and not actually use it
OK, so that was an official released version -- sounds like one of the other dependencies in the project was expecting a different version of Clojure then maybe?
@jgh it's :resource-paths
Is your resources folder not just called resources
then?
The other dependency in question is using org.clojure/clojure "1.8.0" :scope "provided"
@mario.cordova.862 Ah, so it may well rely on things that weren't in Clojure 1.5.1 ...
1.5.1 is pretty old and a lot was added in 1.6, 1.7, and 1.8.
@jgh Yeah, whenever I've had resources
and project.clj
in the same directory, I don't think I've ever needed to specify :resource-paths
... that's the default, after all.
yeah for whatever reason it doesnt seem to be copying things into the jar....do i need to actually reference them in the program?
ah yeah thats whats going on, it looks like the resources are just copied into the base of the jar and not in a resources/ subdir
@jgh right, all your paths (source paths, resource paths...) are merged into the top level of the classpath
if you used io/resource to access the files you'd likely notice already that looking them up with the resources/
prefix doesn't work
(even before making a jar)
is there a way i can tell what came from a resource path after the fact? Basically i'm compiling things down to a native image with graal and want to copy the resources but not the unnecessary java stuff
Do you mean you want the "unnecessary java stuff" excluded from the uberjar?
Hey... I'm thinking about buying the book "Clojure Applied". Do you guys think it's a good book to read after you learn the basics?
@vrcca What books/tutorials have you worked through so far?
@seancorfield Clojure for the brave and true
so im taking the jar and doing native-image ...
to build a standalone executable, but this obviously doesnt include resources or anything else really.
I want to learn how to put all those things together. Clojure for the Brave taught me the syntax, but not how to use it in a structured real project
so there will be no jar, just an executable and the resources needed by the program (as in stuff they added)
isn't using a resources jar still an option?
you still need to ensure the resources are visible at runtime, right?
i'm not positive that it doesn't, there seems to be some documentation suggesting that it may (via -H:IncludeResourceBundles=
...) but it seems like that might be for something specific
I ran across http://www.landoflisp.com the other day, I saw that it was published in 2010. Is this book still a good read and helpful getting aboard Lisp land?
I’ve got that book — It’s a fun read, although after Clojure the code looks a bit unwieldy (Clojure’s [] {} #{} etc make much nicer visual distinctions). The LISP way is a bit different from the Clojure way, but LoL is a good look at the LISP way, for comparison.
@vrcca Clojure Applied should be a good second or third book. Maybe Programming Clojure first, after Brave and True?
See https://pragprog.com/book/shcloj3/programming-clojure-third-edition and https://pragprog.com/book/vmclojeco/clojure-applied (skill levels shown on the left).
@jgh For a JAR file? Sure, use jar tvf filename.jar
is there a way to have a s/keys
spec use a key different than the name that a spec was registered with?
e.g. I have a map with :status
that I want to use a spec called ::coverage-status
to validate
@seancorfield i mean for the native-image using something like -H:IncludeResources=".*"
which doesnt seem to be changing the size of the outputted binary 😞
Sorry, no clue about Graal...
@lilactown how would :coverage/status
do for you? (s/keys :req-un [:coverage/status])
will spec {:status "foo"}
with a spec definition of (s/def :coverage/status ...)
(@jgh and maybe Graal-related stuff isn't #beginners material? #graalvm might be a better venue...)
yeah i can take the graal stuff in there, my original question so far still stands and is maybe not so graal related haha
@seancorfield I'm afraid that that might be clobbered by other ns's; I wanted to keep it in the current ns
@jgh I think at this point I've lost track of your original question, sorry, or I thought it was answered 😞 Happy to try again...
ah i just wanted to copy the non-java stuff in the jar...whatever was originally in the resources paths and not generated by the compiler, i guess
@lilactown If you want to keep it in the current ns then ::status
would work. But part of the idea of namespace-qualified specs is to make them "as unique as necessary" so you're not going to run across a single-segment ns called coverage
so you could decide that :coverage/status
is "unique enough" for your app.
thanks. I ended up just using :coverage/status. makes me a little nervous, but seems like the best case for now
I'm just worried someone else, in another ns, might have a different notion of :coverage/status
(unfortunately)
@jgh I thought you said resources
was copied into the top-level of the JAR file? That wasn't the answer?
sorry yeah i was originally confused by where they should be so i thought they werent being copied at all, but since they're in the top-level of the jar file i can't just copy the directory wholesale and get all of the resources...well, i can, but it comes with other stuff too
Yeah, it's a bit of a sledgehammer/nut situation (I just ran across it in a situation where I point resources at a folder full of SQL files because I wanted them in the JAR -- and of course ended up with 800 of them in the top-level of my JAR file... urk!).
If you're using Boot, you can "sift" files based on regex so you have a lot more control than Leiningen exposes.
why not resources/foo/
- everything in foo is now in /foo/ on the classpath
hello. i'm in chapter 4 of the Brave book and it's already getting a little tough for me. like a seemingly easy example like this seems to be hard for me to wrap my brain around. I think i'm missing some of the fundamentals and was wondering if you could help with a strategy to break these functions down for understanding.
i had the same problem when playing around with Elm. when i see the same values (like new-map and key and val) all repeated over and over again in the same function my brain slows down.
the repetition here is the binding vs. usage - wouldn't you bind the value to some value before using it in any language?
the general idea is that to use a value, there's usually two steps - the name gets assigned to some value, then something is done with that name
(fn [x] (f x)) means that the function's arg is x
no, new-map and [key val] are a binding and a destructured binding
it's equivalent to (fn [new-map entry] (let [x (first entry) y (second entry)] ...))
destructuring is a special syntax that helps us write more concise code https://clojure.org/guides/destructuring
I bet if you spend ~15 or 30 minutes playing with variations of the examples in the above doc in a repl and seeing what does and doesn't work, you'd understand destructuring
will do. thanks! i'm hoping its not a bad sign that I am struggling this early on. with some introspection i realized i've been bouncing around various languages as soon as the going got tough with excuses that it wasn't the right fit for me. i'm trying to bear down and power through that now.
it's always rough going in the beginning! definitely not a bad sign, just very normal. keep at it and things will slowly click.
best of luck
I'm not sure how to setup Vim (fireplace) to talk through a single nREPL server with CLJ and CLJS
I'm beginner too and I got successful with vim and fireplace for clojurescript. Here are my note: https://notes.pinboard.in/u:emak/notes/172850031b7a5053f9f7
but I do not talk to backend in the same repl. For me it is a completely separated repo.
@chase-lambert there’s also #programming-beginners that is aimed for people who use Clojure as their first language. You are welcome to keep asking here, of course! Don’t give up :)
oh nice. not sure how active that one is but i'll use that one for the super newb general programming questions and keep this one to clojure beginner topics
that syntax indicates a method, not a function
in clojure the difference is important, because methods are not first class and functions are
you can pass str
to map as an arg, you can't pass .toString
Also could someone explain
Returns a memoized version of a referentially transparent function. The
memoized version of the function keeps a cache of the mapping from arguments
to results and, when calls with the same arguments are repeated often, has
higher performance at the expense of higher memory use.
So if I understand correctly memoize
will store the mappings in memory so if I call a function with the same arguments it doesn't have to calculate the transformation?
that means for the same inputs there should be the same outputs without observable side effects
which is kind of hilarious, because memoize is almost always used to cache the results of an impure function
@mario.cordova.862 even talking about Java and leaving Clojure aside, Java methods are not functions, and they have Function (and a bunch of related objects) that are first class and similar to clojure functions
@noisesmith duly noted! Idk where I got the idea that they are one and the same
for Java before the Function interface, most people used the terms interchangeably (and inevitably many still do...) - and on a more abstract level they are similar things. But it's really helpful to remember the difference so I get pedantic about it in a Clojure context.
This is why I prefer the term elidable. PyPy uses the term to mean something that could have side-effects but not in a way that we care