This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-06-16
Channels
- # announcements (8)
- # aws (28)
- # babashka (26)
- # beginners (125)
- # calva (18)
- # chlorine-clover (2)
- # cider (12)
- # cljs-dev (6)
- # cljsrn (4)
- # clojure (134)
- # clojure-europe (31)
- # clojure-italy (2)
- # clojure-nl (14)
- # clojure-uk (83)
- # clojurescript (81)
- # conjure (4)
- # cursive (2)
- # datomic (145)
- # emacs (13)
- # events (3)
- # figwheel-main (14)
- # fulcro (30)
- # graalvm (23)
- # graphql (15)
- # helix (21)
- # jackdaw (20)
- # juxt (1)
- # lambdaisland (4)
- # leiningen (2)
- # malli (12)
- # meander (22)
- # observability (22)
- # off-topic (27)
- # pedestal (3)
- # re-frame (12)
- # reitit (1)
- # releases (2)
- # rewrite-clj (3)
- # shadow-cljs (67)
- # spacemacs (7)
- # sql (1)
- # tools-deps (19)
- # unrepl (2)
- # xtdb (25)
I’m using depstar to build a .jar, but I’m having some problems with including resources. I’m using :extra-paths ["resources"]
in my deps.edn
, which works when I run the application from clj
.
is it idiomatic to include resources in the jar, or should they be distributed through some other means and placed in the file system?
It's not so much an idomatic
thing, just normal. You find that too in Java, Kotlin etc...anything that is "distributable"
Of course, it also depends upon the usecase, for example, some applications load things from the filesystem, some from a database...all down to the needs of the application.
that makes sense, in this case, I just want to deploy a ring-application, so I need an .edn
with some data and the regular web-sidekicks
but i still get Exception in thread "main"
even though the path in the jar should be edn/*.edn. Is it because I’m reading it with slurp?
If you need to slurp a file from a JAR file, don't call io/file on the result of calling io/resource, or you will get an exception that says the resource is "not a file". Instead, call slurp directly on the result of io/resource.
that makes sense! I guess my naked slurp
tried to read form the file system, as it should
Hey, do you have any recommendations for someone who would like to create his own datalog implementation? I already done some research and found a good amount of papers/books about the topic and also look at the source code of clojure.contrib.datalog. But what I'm missing are resources that leaning more towards the practical side of implementing such an engine and/or understanding the requirements needed. I will probably figure out what I have to do with the resources I already found but I don't find it particular joyful to read/understand research papers. I know that I eventually have to read them anyways 😂 but just want to check if maybe someone knows a bit more motivational material which gets me started? 😇
You may want to ask on the #datascript or #datahike channels for such questions, too.
datahike exists btw
Hi! I’m considering Clojure/Clojurescript for a project. (Don’t have a lot of experience with it yet!) I need to create a library that has to run on both our backend (java/kotlin) and in the browser. Is it possible to compile the source to both JavaScript and a JAR? And are there other things to consider or are there any pitfalls?
what is the harm of nil
in maps in clojure?
I seem to recall Rich Hickey warning against this in "Maybe Not"
it’s more like don’t use nil if you don’t need to
you can prune them off
unless you explicitly need to convey that it is broken
may cause ambiguous interpretation: (get m :key) ;; => nil
now.. the :key
is missing in your m
or it is there, but its value is nil
?
it’s like conveying that humans having two hands, but this guy has one missing hand
but snakes has no hands, not no missing hands
and clojure uses the same data representation for snakes and humans
and if you need to explicit tell that some hands are not there hahaha .. maybe is better to be explicit: {:hands :both}, {:hands :one}, {:hands :missing}
representing objects as just data has the nice thing of handling them the same way
(defn chop-hands [animal]
(if (contains? animal :hands)
(assoc animal :hands :missing)))
yep sounds good tyty
i'm trying out leiningen on WSL and for the same repo i get this warning WARNING: cat already refers to: #'clojure.core/cat in namespace: net.cgrand.regex, being replaced by: #'net.cgrand.regex/cat
that warning is standard, and doesn't indicate an error - cgrand.regex was implemented before cat existed, so won't be broken by shadowing the new clojure.core/cat
you could compare the output of (System/getProperty "java.class.path")
in case you are getting different versions - another possibility is different logging config
ah i think that's it WSL : Leiningen 2.8.1 on Java 1.8.0_252 OpenJDK 64-Bit Server VM Command Prompt : Leiningen 2.9.1 on Java 11.0.2 Java HotSpot(TM) 64-Bit Server VM
switching to see if i can get a colorful repl. pretty drab working in the command prompt
you might be interested in rebel in that case https://github.com/bhauman/rebel-readline
how to (map fancshan coll) when the coll is more than one element and simply (fankshan coll) when there's only one element?
cs and ks interchangeable in my world today
@sova I would change the code to not have that ambiguity -- see Heisenparameter on Stuart Sierra's Don'ts list.
first off, avoid ever doing that but if you are forced to because it's data from an api, transform the single thing into a coll at the earliest point you can
I used to do it quite a bit when I was learning Clojure and I still curse my earlier self when I run across an old function in our code base that still does this 😞
okay so i want to make sure it's a collection (even of one item) before passing it in.
right - the general solution is hard to do in clojure since we use collections of collections everywhere but at an API boundary you probably have a better idea of when to convert
I do the conversion in the same place where I get the data
I see... Very good very good. tie the shoes before entering clojureland
exactly
Cool, i feel like each day i'm moving a little bit faster and more fluidly... it's a delight to figure stuff out
Now this is super cool https://kimh.github.io/clojure-by-example/#about
"clojure by example"
Quick question about Reagent. Following a couple of tutorials now, I add reagent as a dependency, then (:require [reagent.core :as r]) When I do r/render it doesn't work the way any of the tutorials suggest it should, I get errors suggesting r/render is undefined, but if I (:require [reagent.dom :as rd]) and do rd/render it works fine. Has something changed recently?
are you doing this in clojure or clojurescript?
I mean, I seem to be able to do everything expected using the reagent.dom version, but I'm puzzled because I've hit this on several different people's tutorials now.
It's an issue with reagent 1.0.0-alpha2. If I use 0.9.1 it works the way the tutorials expect and compiles without error.
Reagent was updated. Now there’s a reagent.dom namespace which has the render function
does that mean reagent is close to supporting other renderers besides react?
https://github.com/reagent-project/reagent/commit/ea42671d832be77acabe012df6386cd5d34d5ac1
I’m trying to swap!
an atom
inside a ring handler but I can’t seem to get it to work. I would appreciate a pointer. 🙂
games
is not getting updated here:
(defonce games (atom {}))
(defn view [game]
(layout
[:div (:name game)
[:pre {} @games]]
))
(defn create-game [name]
(swap! games assoc name {:name name}))
(defn handler [request]
(let [name (->> (:uri request)
url-decode
(remove #{\/})
(apply str))
game (get @games name (create-game name))]
{:status 200
:headers {"Content-Type" "text/html"}
:body (html (spyfall.game/view game))}))
Also I’m running this with ring.adapter.jetty/run-jetty
but the REPL doesn’t seem to be in sync with the state of the server running separately.
are the repl and server in the same vm?
I suspect @games
is evaluated before (create-game name)
since arguments are evaluated left-to-right in function calls.
here the value of "game" will either be a specific game (if it exists) or all the games defined so far (if it wasn't found, so created)
because swap! returns the entire state of the atom
Hmm, good point. That's another bug.
oh! never mind, this is even worse - game is a global state - the name of the game will change on every request
no, I was right the first time
I was momentarily confused by the weird structure of the hash
user=> (def foo (atom {}))
#'user/foo
user=> (defn bar [n] (swap! foo assoc n {:name n}))
#'user/bar
user=> (get @foo "hello" (bar "hello"))
{"hello" {:name "hello"}}
user=> (get @foo "hello" (bar "hello"))
{:name "hello"}
user=> (get @foo "world" (bar "world"))
{"hello" {:name "hello"}, "world" {:name "world"}}
user=> (get @foo "world" (bar "world"))
{:name "world"}
user=>
In the first get
, @foo
is {}
and does not contain "hello"
so the not-found value is used, which is the full hash map after creating the new item.
In the second get
, @foo
is now the hash map containing "hello"
so its value is returned.
as for the atom not changing at all, I go back to my first question: you mention a repl and a http server, are they in the same jvm?
> are the repl and server in the same vm?
it’s one lein repl
and one lein run
separately
so the answer is no, so the one in the repl won't change
atoms are local to one process
And so is the code -- so changing things in the REPL won't affect your running server.
right,launching a future
and binding it is handy for that (def server (future (run-jetty ...)))
that way you can still get at the process (to check if it exited with realized?
or see the return value / error by using deref
if it has...)
Created a namespace like this with stuff to evaluate when developing:
(ns spyfall.dev
(:require [ring.adapter.jetty :refer [run-jetty]]
[ring.middleware.reload :refer [wrap-reload]]
[spyfall.game]))
(comment
(def server
(future
(run-jetty (wrap-reload #'spyfall.game/handler)
{:port 3000 :join? false})))
)
if you use join? false already, you don't need a future, sorry
but yeah, that's the idea
oh no, the facepalm was at myself, I should have remembered that run-jetty already lets you start in a background thread and return a server handle
So this made things work better
(defonce games (atom {}))
(defn view [game]
(layout
[:div (view-name (:name game))
[:pre {} @games]]
))
(defn create-game [name]
{:name name
:players []})
(defn handler [request]
(let [name (->> (:uri request)
url-decode
(remove #{\/})
(apply str))
game (get @games name (create-game name))]
(swap! games assoc name game)
{:status 200
:headers {"Content-Type" "text/html"}
:body (html (spyfall.game/view game))}))
@US3HM05U5 If you have multiple concurrent requests to the same "game" URI you will have a race condition there because you're fetching the game's current value and then swapping it back into the atom as two separate operations.
Depending on exactly how/where you are also updating that atom, you may lose changes (because both concurrent get
's could get the old version of the game, make changes, and then whichever assoc
happens last will "win").
Ah, ok! I’m not sure how that can be mitigated. I guess the only way to make sure is to queue up the mutations so that they happen one at a time?
I just want this ad hoc “database” atom for my program. Implementing something my co-worker did in Elixir to see how the implementations differ. 🙂
swap!
is fine, if you operate on the current value rather than trying to fetch a value first and then bashing it back in.
Consider swap!
with update
instead of assoc
and take a look at fnil
as a way to provide a "default" for a nil
value.
Hey! I have been writing an API in clojure but I have some doubts in what wrap-json-body
/`wrap-json-params` actually do. Why is it required to include this in the response?
ring uses middleware to add features to the http stack, using those middleware allows using json automatically, but seeing the data as clojure data in your code (in your params or response)
wrap-json-body takes a request handler function, and returns a new one which will transform output data into json