This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-09-23
Channels
- # announcements (5)
- # babashka (22)
- # beginners (240)
- # calva (51)
- # clj-commons (1)
- # cljsrn (9)
- # clojars (12)
- # clojure (81)
- # clojure-australia (2)
- # clojure-europe (40)
- # clojure-france (10)
- # clojure-italy (1)
- # clojure-nl (2)
- # clojure-uk (37)
- # clojurescript (59)
- # clojureverse-ops (2)
- # copenhagen-clojurians (1)
- # cursive (9)
- # datomic (18)
- # emacs (12)
- # fulcro (24)
- # graalvm (48)
- # hyperfiddle (5)
- # introduce-yourself (1)
- # jackdaw (1)
- # jobs (2)
- # juxt (8)
- # lsp (25)
- # malli (8)
- # missionary (1)
- # music (3)
- # off-topic (32)
- # polylith (16)
- # quil (4)
- # re-frame (52)
- # reitit (5)
- # reveal (3)
- # rewrite-clj (26)
- # rum (1)
- # sci (1)
- # shadow-cljs (14)
- # sql (2)
- # tools-build (40)
- # tools-deps (14)
- # vrac (2)
- # xtdb (63)
How do I say with spec "The thing should have keys x
, y
and I don't care what the values are" ?
(s/def ::x any?)
(s/def ::y any?)
(s/keys :req-un [::x ::y])
If the hash-map definitely should have those keys present, then it would be req
rather than req-un
for optional keys
Optional keys defined as :opt-un and :opt.
Ah, I got un/qualified key names (`:req-un` and :`req` ) mixed up with optional keys, :`opt`, thanks for the correction.
(require '[clojure.spec.alpha :as s])
(s/def ::x any?)
(s/def ::y any?)
(s/def ::unqualified-keys (s/keys :req-un [::x] :opt-un [::y]))
(s/def ::qualified-keys (s/keys :req [::x] :opt [::y]))
(s/valid? ::unqualified-keys {::x 1 ::y 2}) ; => false because :x is required
(s/valid? ::unqualified-keys {:x 1 :y 2}) ; => true because required :x and optional :y present
(s/valid? ::unqualified-keys {:y 2}) ; => false because :x is required
(s/valid? ::qualified-keys {:x 1 :y 2}) ; => false because ::x is required
(s/valid? ::qualified-keys {::x 1}) ; => true
I did write a whole bunch of pages about spec, but still haven't got into the rhythm of regularly using them at work yet 😞 https://practical.li/clojure/clojure-spec/data/entity-maps.html#defining-entity-maps
was looking into https://github.com/stuartsierra/component/blob/master/dev/examples.clj#L130 example of component, How this same as https://github.com/stuartsierra/component/blob/master/dev/examples.clj#L118 (defrecord ExampleSystem [config-options db scheduler app]
I mean whenever I click on map->ExampleSystem
it is pointing to (defrecord ExampleSystem
https://clojure.org/reference/datatypes#_deftype_and_defrecord
defrecord
generates that function together with ->ExampleSystem
variant
map->Bar
is defined that takes a map and initializes , what if we use vec->Bar , does that take vector argument?
there are two functions: map->Bar
and ->Bar
there is no vec->Bar
but you can call ->Bar
with arglist
(type Bar) ;; => java.lang.Class
Behind the scenes, Bar
is a Java class, and java classes are instantiated with new
or the .
I can imagine an alternate timeline where putting a class in a calling position would invoke the constructor - there's no alternate behavior / ambiguity since Class can't be extended to implement IFn
or can it?
I've also speculated Number in call position could have been implemented as *
just like in math
but that would lead to really weird error messages / bugs when you put number in call position accidentally
or regex in call position doing re-matches
actually if numbers multiplied when called, the common newb bug of ((+ x y))
would work as expected, for an unexpected reason: *
with one arg is identity lol
This all is possible in ClojureScript, since IFn is a ClojureScript protocols and hence extendable to every type. In Clojure the user can't extend Java interface to a type, if I understand correctly
right - protocols can be extended, interfaces cannot, and IFn is an interface
to be more concrete: you can only extend an interface at the time of class declaration, while protocols can be extended later
so you could also fork the jvm itself to make Number implement IFn - absurd but technically possible
@U024X3V2YN4 though I do have some suspicion that js engines might have special case code for numbers that could prevent our extension of numerics from working
I think numbers work fine
(extend-type js/Number IFn (-invoke ([this op x] (op this x))))
#object[Function]
cljs.user=> (71 + 171)
242
that's silly, at least making them implement multiply makes mathematical sense
or more precisely: that's a syntactic change, I was suggesting a semantic change
(syntax remains as is, numbers now mean multiply)
This was en example posted by @U0CKDHF4L while ago, btw
ahh OK - I'm allergic to infix sorry for the knee jerk
No worries, I just added that because I forgot to give them credit! It's just a fun example, occuring in the discussion of why (nil)
is syntax error, while (1)
isn't, in Clojure.
ClojureScript 1.10.758
(cmd)cljs.user=> (extend-type js/Number IFn (-invoke ([this & args] (apply * this args))))
WARNING: Protocol IFn implements method -invoke with variadic signature (&) at line 1 <cljs repl>
WARNING: Extending an existing JavaScript type - use a different symbol name instead of js/Number e.g number at line 1 <cljs repl>
#object[G__629]
(cmd)cljs.user=> (1)
#object[Number 1]
(cmd)cljs.user=> (3 7 2)
42
*fixed@U051SS2EU (71 + 171)
is prefix when numbers are functions
only if + is somehow a valid argument
it's prefix emulating infix
no, it's prefix. The number is a function which returns its value combined via the given operation with another number
it is silly, as you say, but it's perfectly valid
Is there a core function to test wheter a map is a subset of another ? Something like
(submap? {:a 1 :b 2} {:a 1 :b 2 :c 3}) ; => true
No, but it's something I've written a lot of times for testing
diff ?
There are a lot of choices about what exactly is a sub map
As @delaguardo mentioned, you can also compare part-in-both
returned by diff
against your potential submap. If they're equal, it's a submap.
(some #{:foo :bar} (keys {:foo 10}))
(or (:foo thing) (:bar thing))
is there preferred way to check if either of some keys are present in a map?Also that requires that your keys are in vocable as a lookup. The contains? check contains neither of these two subtle buggy behavior for your purposes. Handles keys that aren’t in vocable and handles nil and false values in the map.
Hi everyone, when I try to deploy my web app to heroku, I get the error
Error: Could not find or load main class
Any idea what I need to fix?When I first do
git push heroku main
I also get this error:
Error encountered performing task 'run' with profile(s): 'base,system,user,provided,dev,dev'
I have a bin/build file that says this:
#!/usr/bin/env bash
npm install
npx shadow-cljs release main
lein uberjar
making an uberjar and "performing task 'run'" are mutually exclusive - if you do one the other isn't needed
Thanks @U051SS2EU. I'm a total beginner. What commands do you suggest I have listed?
pedantically, lein run
(which is what produces that message you show elsewhere) is meant for local development, and not for running a program on a server
but I know that heroku has its own tooling and might expect to use lein to run your app
normally what I would do is produce a jar with lein uberjar
, no need to AOT compile / gen-class my clj code, then run java -cp my-standalone.jar clojrue.main -m my.ns
which uses the clojure.main class to load an run my code on startup
but if you need to use lein run, there's no need to run the uberjar task
Ok that makes sense. How do I fix the -main error I'm getting? In my project.clj file I have
:main ^:skip-aot kewl-app.core
right, :skip-aot
specifally requests that you don't produce a class
so you need to tell the java process the right class to run - usually that would be clojure.main
Ok, so I would change it to be
:main clojure.main
or is there something else?And do I change my bin/build file to say
lein uberjar
java -cp my-standalone.jar clojrue.main -m my.ns
For my project would I use kewl-app.core
instead of my.ns
? Thanks for helping @U051SS2EU
right - and it would be target/something-standalone.jar
based on the name of your project
try running lein uberjar
and see what files get created
and yes, it would be the actual ns name instead of my.ns
you can run all these things locally from a terminal to see what works
I also have a Procfile that says this:
web: java $JVM_OPTS -cp target/kewl-app.jar \
clojure.main -m kewl-app.core
Should I change any of that?Ok I ran lein uberjar
in the terminal and got
Created /Users/user/kewl-app-deploy-2/target/uberjar/kewl-app-0.1.0-SNAPSHOT.jar
Created /Users/user/kewl-app-deploy-2/target/uberjar/kewl-app.jar
weird - usually one has "standalone" in the name - try the kewl-app.jar
one and see if it works
Ok so I'm gonna try java -cp kewl-app.jar clojure.main -m kewl-app.core
in the terminal
Ok that's the cause of my error. I get
Error: Could not find or load main class clojure.main
well it would be target/uberjar/kewl-app.jar
unless you are in that directory
Ohhhh I see thanks. That might be my issue. I'm going to try that now.
you can open the jar in an editor (both emacs and vim support this for example) and see which resources are included - there should be class files for clojure in there
as well as your source code and project resources
or use the unzip
or jar
command on the cli to investigate the contents or unpack it if that's more comfortable
Ok now I changed to target/uberjar/kewl-app.jar and now I get this error: ERROR kewl-app.core - Database configuration not found, :database-url environment variable must be set before running
I did have a dev-config file with database-url. I deleted it because I thought Heroku had it's own database (I added on postgres with heroku). I just added the file back though and ran the lein uberjar command again and it still says there's no database url
cool, so you found the right command line, you just didn't set the env var it expected - the stuff in project.clj that sets that is only applicable inside lein
heroku should have its own setup for that
the env var is provided by the shell, not the jar
Ok awesome should I try heroku again?
I think so yes
a common thing is to separate the jar-building step from the running step, so that the app can be restarted (or started on another parallel instance) without having to rebuild the jar if your code hasn't changed
but I don't know if/how this would work with heroku
This might help cuz I know you have a big ole luminus template you are working off of: https://luminusweb.com/docs/deployment.html#heroku_deployment
Ok so I changed my procfile to have target/uberjar/kewl-app.jar instead of target/kewl-app.jar which was incorrect
And just to confirm, in my project.clj I had :main ^:skip-aot kewl-app.core
and I want to change this to :main clojure.main
or should it be :main kewl-app.core
?
you can keep the project.clj :main option the same as it was
using clojure.main means that :skip-aot
is fine
Ok sounds good
And then in my bin/build file I just want to have lein uberjar?
I'm just double checking because I just tried running again and still got the no main class
error
don't forget to git add and commit before pushing to heroku so it picks up these changes
is no main class
a warning from lein or an error when running the jar?
if it's a warning from lein you can ignore it
@U9J50BY4C thanks I remember now since learning yesterday! Thanks for checking
I am trying git push heroku main
and then when it says it is built successfully, then I click on the app which says Application Error, and then I try heroku logs --tail
and that is the only error I see. But I'll post the whole thing in case. There are some errors at the bottom I don't understand for example adn taht might be it
it looks like it is treating \
which in a shell script is "continue this line" as a token, here the main class
try taking out the \
and joining the lines
Oh I see. I'll remove that and try again
remember to join the next line too
Ok now it's all on one line
I'll try pushing to heroku again (after doing git init, git add ., git commit -m "fixing things") 🙂
you don't need to use git init
any more. That is just the first time you start a project.
Ok thanks!
Ok progress!! Thanks for all the help. Now I can click on the app in Heroku and I just get a blank page, but the favicon and site title show up in the browser. I think this might be due to the port issue you mentioned yesterday @U9J50BY4C
How do I link up the port correctly? And I also added on postgres, do you know if I have to do anything special for the database?
DB I haven't figured out yet. But yeah, for port you need to just do something where instead of you saying {:port 8000}
you say {:port (or (System/getenv "PORT") 8000)}
Ok I made that change, and recompiling now
If that doesn't work there is a chance that (System/getenv "PORT")
returns a string so you need to convert to an integer first.
Thanks, it didn't work so I'll try that
I also get these warnings, so I think I might have up update the react dependencies to be 17 instead of 16? Do you think that might be affecting it?
Do I use (Integer/parseInt (System/getenv "PORT")) to convert to an integer? Thanks again for all your help
yep but change your default port (for when you are doing local development) to a string too or you get an error.
Those warnings are unrelated and have to do with Google closure compiler issues when trying to optimize your production build. Unfortunately when I tried to get help on #shadow-cljs I was told they weren't familiar with lein and/or the luminus template setup and were unable to help me. Part of the reason I started from scratch.
Well at least that dead code elimination warning is about that. Not sure about the rest.
Alright I added parseInt, and updated the dependencies it was warning about, and now I'm trying it again
Ok that's interesting. How long did it take you to start from scratch? I want to build a basic social media type web app where people can post their own blog posts basically. I was following this book https://pragprog.com/titles/dswdcloj3/web-development-with-clojure-third-edition/ because it goes through how to add lots of features, but it's all based in luminus, so I'm not sure how I'd go about re-doing it all from scratch. But it might be worth it to try
Yeah I have started with that book too and am using it alongside trying to build up from scratch. A lot of others recommend it as well. You will probably be fine with it. I just found whenever I built out my full stack app with it using the whole lein new luminus my-app +reitit +shadow-cljs +re-frame +...
I just never really understood what I was looking at. Way too many moving parts for me to wrap my head around it.
And it made it difficult to seek support because the luminus channel was dead and it was tough asking the right questions about things like the big project.clj
file it setups up for you. I just never felt like I had a good grasp on my app.
The good and bad of this amazing clojure slack community is I find I get totally stuck and would not be able to solve things without these folks. The offshoot is I try and gear some of my tech/library choices to those I've seen commonly discussed on here by helpful people so that I know I can get support if needed.
That makes a lot of sense. Are there any books or resources you recommend for building from scratch? I think I'll look into it. Even if I still use the luminus template, I'd love to learn more
Yes the slack community here is amazing. I'm so grateful for it.
Ok recompiled and still nothing shows up 😕 any ideas what it might be? I can try asking again in the main channel too
This channel has been great for down to earth explanations for some of the things we are looking to do: https://www.youtube.com/watch?v=yVb8PS6a4Mk&list=PLqunUpREWrwKdi3DEkTnIia54JjnWk8JB&index=7
Here he happens to be creating an app where users can post articles, which could be perfect for you.
https://www.youtube.com/watch?v=6jvG3XbSeos&list=PLqunUpREWrwKdi3DEkTnIia54JjnWk8JB&index=27 this is them setting up the backend and frontend
I'm still using that web dev book but I'm starting from scratch like they do after the 2nd chapter or whatever instead of using the huge template starter with all the tech I eventually want
So anyways, if the heroku logs are telling you that there was a "timeout" situation or something when trying to connect then you are still having the port issues.
You could push your current repo to github again git push origin main
and I could take a look maybe.
Here is my logs from heroku. Can you help me decipher it?
I LOVE that youtube channel. I haven't seen those videos because I felt intimidated by http-fx and all the new stuff but I should probably work through them
I tried for a while to correct my react dependencies but that didn't fix anything
I'll push to git again and post here I would really, really appreciate if you have time to take a look at it
If I go to https://agile-harbor-95125.herokuapp.com I get a 404 page
I have a routes.app.cljc file : (almost exactly like the guestbook examples from the book)
(ns
(:require
[spec-tools.data-spec :as ds]
#?@(:clj [[kewl-app.layout :as layout]
[kewl-app.middleware :as middleware]]
:cljs [[kewl-app.views.home :as home]
[kewl-app.views.about :as about]
[kewl-app.views.profile :as profile]
[kewl-app.views.author :as author]
[kewl-app.views.upload :as upload]
[ :as post]
])))
;;...
;
#?(:clj
(defn home-page [request]
(layout/render
request
"home.html")))
;
(defn app-routes []
[""
#?(:clj {:middleware [middleware/wrap-csrf]
:get home-page})
;
;; require [spec-tools.data-spec :as ds]
["/"
(merge
{:name ::home}
#?(:cljs
{:parameters {:query {(ds/opt :post) pos-int?}}
:controllers home/home-controllers
:view #'home/home}))]
Unfortunately, I think you have surpassed my abilities to help at this point. And we are probably way too deep to have others following this thread so you may need to start a new one. haha. sorry
No worries! Thanks so much for all your help. I couldn't have gotten this far without you.
Yes it does! Although with all the changes I should probably double check that it still runs on localhost
I just realized I had a typo in my Database_url setting so I'm going to fix it and try running again
You can see a 404 error in the console when looking at the main page of your app too. It is not finding your app.js file created by shadow-cljs I don't think.
Ok I must have messed something up when I starting making edits to try and deploy on heroku...
Thanks for letting me know
I saved a version of the project right before trying to deploy. I might go back to that version of my project, make sure it works locally, follow all the steps I learned here, and see where that gets me.
Sounds good. I had a single typo that prevented anything showing up on my own site myself but your repo is too big for me to see where everything is routing and whatnot
When i have my dev-config.edn file the way it was previously, I can get the app working. When I replace :port 3000
with :port (Integer/parseInt (or (System/getenv "PORT") "3000"))
I get
Syntax error (ClassCastException) compiling at (/private/var/folders/9q/1d7v8kjx3y3d9ntysj9js76c0000gn/T/form-init2785940755153321540.clj:1:125).
class clojure.lang.PersistentList cannot be cast to class java.lang.Number (clojure.lang.PersistentList is in unnamed module of loader 'app'; java.lang.Number is in module java.base of loader 'bootstrap')
*I can get the app working locally, not heroku lol
I have to go to a few zoom meetings now but I will tinker a little more and then ask the slack channel about how my dev-config.edn should be set up for heroku deployment. I think the way I have my database is also wrong so I'll have to ask about that regardless. Thanks again SO MUCH for all your help. I hope you have a great rest of your day @U9J50BY4C
I wonder if on your own local system you already have something set to PORT. What does (System/getenv "PORT")
give you at the repl?
that error from config.edn is because the list
(Integer/parseInt (or (System/getenv "PORT") "3000"))
isn't evaluated, just read
@U9J50BY4C I get zsh: no such file or directory: System/getenv
@U051SS2EU thanks! How do I make it evaluate? I just tried doall
but I got errors again
the edn file will not be evaluated
Oh I see. Do I need to add any new file to specify post & database_url or does heroku take care of that automatically?
oh ok. hmmm. Somewhere in your actual clojure code you are probably reaching in to that config file for the port. That is where you would put in the whole (Integer...) thing.
I think heroku might default to port 8080
so you could just try that but I wouldn't rely on that at all. But just something desperate I would try to see my app deployed. haha
Another thing I would try is add $PORT
at the end of your Procfile command but I suspect your own code might override that
Wow so I tried again from a previous version I had, and followed all the same steps only changed what worked to change, ie adding the bin/build file, editing the procfile to remove the / and have it all on one line, and I just commented out the whole dev-config.edn that had the ports. Now the app shows up!
I don't think I have the database connected or working, but I will look at the link you sent https://folcon.github.io/post/2020-04-12-Fulcro-on-Heroku/ because there is a section on postgres there
that message about a main class means you didn't AOT compile / gen-class the ns with -main in it, or didn't declare one
one workaround is to specify clojure.main as your main class (comes compiled for you with clojure.jar) and then provide your ns as a startup arg to clojure.main
I am a fan of https://github.com/cognitect-labs/aws-api style apis these days
basically a single "invoke" function that you pass descriptions of the operation you want to peform
I recently wrote a little client for the google androidpublisher api at work, and call it looks something like
(adp/invoke!!
androidpublisher
{:op :purchases.subscriptions/defer
:packageName app-id
:subscriptionId in-app-product-id
:token token
:request {:deferralInfo
{:expectedExpiryTimeMillis (str (:expiryTimeMillis subscription))
:desiredExpiryTimeMillis (add-days (Long/parseLong (:expiryTimeMillis subscription)) 360)}}})))
the code that invoke!! eventually calls uses the json document google publishes describing the api to figure out urls, methods, etc
Any good examples to look at?
This is such a beginner question but if you had a vector of strings how would you go about removing the last character from the last array? So this:
["this" "is" "the" "string"]
becomes this:
["this" "is" "the" "strin"]
There are a lot of ways to do that. Here's one (it's pretty ugly):
(let [l ["this" "is" "the" "string"]]
(assoc l (dec (count l)) (apply str (butlast (last l)))))
Or...
(let [l ["this" "is" "the" "string"]]
(conj (vec (butlast l)) (apply str (butlast (last l)))))
(let [x ["this" "is" "the" "string"]]
(update x (dec (count x)) #(subs % 0 (dec (count %)))))
(let [[l & ?rest] (reverse ["this" "is" "the" "string"])]
(conj (vec (reverse ?rest)) (apply str (butlast l))))
Our point, of course, being that there are a LOT of ways. Some more or less efficient, clear to read, idiomatic, etc.
(let [x ["this" "is" "the" "string"]
y (last x)
z (clojure.string/join (butlast y))
res (conj (vec (butlast x)) z)]
res)
(def a ["this" "is" "the" "string"])
(conj (pop a)(subs (last a) 0 (+(count a) 1)))
Only thing I know is https://codegolf.stackexchange.com/ its not clojure specific
Yeah, not really a right way. There's probably some solution that incorporates the threading macro to make things a bit more legible, but it's a simple enough problem that any one of the possible solutions is good enough in most cases.
Did someone say code golf?
(defn fx [c] (conj (pop c) (apply str (butlast (last c)))))
(fx ["this" "is" "the" "string"]) => ["this" "is" "the" "strin"]
Yes, Clojure is harder for some tasks than other languages like Python where you just side-effect the last element of the array. The reason is that without side effects, we have to pick out the last part of the vector, create a new value (without the last character), then create a new vector that has that as the last element. See @UPWHQK562’s code. Why do this extra work? (Exercise for the reader ?)
If you start with a vector, peek
and pop
are the "fast" ways to interact with it. last
is linear, peek
is "much more efficient than last" (per the docstring).
dev=> (let [l ["this" "is" "a" "string"]
#_=> w (peek l)]
#_=> (conj (pop l) (subs w 0 (dec (count w)))))
["this" "is" "a" "strin"]
with Specter:
user=> (setval [LAST LAST] NONE ["this" "is" "the" "string"])
["this" "is" "a" "strin"]
https://github.com/redplanetlabs/specter/That's debatable. I find Specter's "DSL" style to be impenetrable for the most part. And I think it's a poor choice for beginners until they've got a good, solid understanding of the core data structures and their O(1) vs O(n) operations.
So I’ve been thinking about this some more and wondering if anyone has any abstractions for these kind of problems. I was thinking of making a function called something like apply-only
and it only performs the transformation if it passes some test or maybe if it’s in a range passed in. Has anyone done anything like this already?
Sounds like cond->
@U028TA3H3PA take a look at Specter that I posted above, it is precisely “abstractions for these kind of problems”
If I see a dependency that has "^16.0.0" what does that ^ symbol mean?
It means any version in the range 16.X.X. See https://docs.npmjs.com/about-semantic-versioning
Cool thank you
That is for npm and JavaScript packages, maven style dependencies (common in clojure) don't do that
Ok thanks, good to know!
Not sure how much overlap there is between slack/clojure and reddit/clojure I ended posting my code for review on reddit, I got some feedback. This is basically my first program time doing this , posting my code for feedback. Before this I basically just opened a repl did some really short stuff. https://github.com/rng-ftw/basic-paint its a really basic paint style program nothing fancy save file to test.txt where ever file is run from loads from same location does nothing if the file does not exists any feedback would be appreciated.
you can also try posting in #code-reviews
some thoughts:
• in update state, it looks like the arg, state
, is a map, but it's used as a function. There are times when using maps as functions is useful, but if you're just using it as a map, I would prefer (:button-state state)
over (state :button-state)
• (doall (map ..))
can be replace with (run! ...)
• I'm a little confused by the cond->
usage. I would probably either use cond
if only one branch is to be chosen or just have a bunch of when
statements.
• some of the lines are really long 😛
• for the functions that handle lots of cases using cond, I might consider breaking them up and using something like multi methods or reduce to compose them.
Thanks for looking at the code, appreciate it.
Guess I really dont understand the difference between (:button-state state)
and `(state :button-state)`
They functionally do the same thing ??
dorun doall and run! all basically seem to do the same thing havent found anything that really differentiates them
Yeah the cond-> initially I though was going to have to modify several different states at once but if I pull out quil I might be able to do it without cond->
> Guess I really dont understand the difference between `(:button-state state)` and `(state :button-state)`
Since state
is a map, the result is the same. However, programming is about communicating with future readers of the code as much as it is about getting the right result. The two different versions communicate different intents:
• (:button-state state)
: look up the key :button-state
in the associative data structure, state
• (state :button-state)
: call the function state with :button-state
as the first argument.
The difference between doall
+`map` vs run!
is similar.
• (doall (map ..))
: create a lazy sequence using map
and force execution now. Additionally, doall
will cause the full sequence to reside in memory as opposed to dorun
• (run! ...)
: execute a function for each item in a collection for side effects.
Generally, it's easier to give advice about stylistic stuff so that's what you'll tend to get in code reviews.
The main design idea I would consider is that update-state
combines many different operations into one place. I would try to split up all the operations into their own separate pieces that can be used/tested/debugged in isolation.
Thanks for the reply. yeah update-state seems to of become a catch all. The basic idea was the capture state change in one location...
Hi everyone! I am trying to replace a string using https://clojuredocs.org/clojure.string/replace but my match is not a literal string it is a value, how can I do that? for example. Instead of:
(clojure.string/replace "The color is red" #"red" "blue")
It is:
(def color <value-recupered-from-http-param>) ;; -> "red"
(clojure.string/replace "The color is red" color "blue")
🧵(def color <value-recupered-from-http-param>) ;; -> "red"
(clojure.string/replace "The color is red" (re-pattern color) "blue")
you don't need an re:
user=> (clojure.string/replace "the red color" "red" "blue")
"the blue color"
> match/replacement can be: > > string / string > char / char > pattern / (string or function of match).
True. But since the OP had a #".."
regex, I assumed they wanted to treat the http param as a regex 🙂