I’m not sure how exactly to ask this question but the gist is that I have a program that is a loop, that is a chat bot, so it sits and loops and listens to input and responds, pretty starightforward. Doing REPL driven development on it has been challenging because when I run the listening loop it hangs the REPL
is there a way to async that loop in the “background”
and then i can poke and and update a function it calls
to have a more interactive experience?
one option to consider is that the bot and the repl can listen to different file descriptors, either because you have multiple connections to one repl process, or you use a dedicated pipe/fifo - a question of making an alternate binding for *in*
connected to a different tty
(a process with multiple repl connections already makes multiple *in*
bindings for you)
generally a loop will call some function with some kind of message and then recur. from the repl you would want to not start the loop but just call the function that handles the message
kind of a "functional core, imperative shell" type thing. top level you have a loop which takes a message from a socket/web endpoint/queue/what have you and then does actions based on it, and then back to the top of the loop
i’d love to be able to poke at it while it’s running the loop and getting stuff from the server
in that case i’d be passing my own messages in yeah?
i think it’s waiting on a channel for input
(a/<!! event-ch)
in go i would call this as a go routine
and it wouldn’t block anything while it did its thing
core async has go routines? woah
Hi is there an iterate
that allows for side effects?
am I looking for doseq
?
I want to do something like
(take-while #(>= number-of-weeks %)
(iterate
(partial + (rand-nth days-store1)) (rand-nth days-store1)))
^ this runs but the result used for rand-nth is fixed
Is there a function or a better way to do what I want.? Am trying to create a simulation of when a factory will refill its stock. So (def days-store1 [2 3 3 4 4 5 5 6])
is saying after there is a 1/8 chance that after 2 days, there is a need to restock. And then it undergoes a renewal process. So it any of those number of days in days-store1
are equally likely again
Did you try repeatedly
?
whoops I did not. But I'm not sure how I might want to form the sequence with repeatedly
(take 10 (repeatedly #(rand-nth [1 2 3 4 5]))) => (2 5 3 1 2 5 3 5 3 2)
Yeap I got that part 🙂 but how might i sum it up with the earlier element
so if the random seq produced is [1 2 3 4 5]
I want [1 3 6 10 15
I want to take-while
the last number in the seq is under 1280
(take 10 (map + (repeatedly #(rand-nth [1 2 3 4 5])) (repeatedly #(rand-nth [1 2 3 4 5]))))
hmmm thanks for all your help but map doesn't take the earlier element :thinking_face:
I want something like [1 5 7 10 14 19 22 26 .....]
maybe reductions
cool I got it 😄
(take-while #(>= number-of-weeks %) (reductions +
(repeatedly #(rand-nth [1 2 3 4 5]))))
Thanks @hindol.adhya for your help 😄
Wait ....
no I still can't use take-while
Okay, now I finally understood what you mean by [1 3 6 10 15]
, 😅
Sorry if I wasn't too clear 😅
The technical term is cumulative sums
. reductions
is definitely the right way. I don't understand what you mean by side effect of rand-nth
?
Currently. The take-while will only evaluate the rand-nth
once. Meaning if the evaluation is 3
it will always increment by 3
Whoops yeap am familiar with cumulative sum but didn't think of using that to describe what I wanted whoops
(take-while #(>= 1280 %)
(reductions +
(repeatedly #(let [n (rand-nth [1 2 3 4 5])]
(println "Rand:" n)
n))))
I still don't get it. It seems rand-nth
is called every time.
Rand: 3
Rand: 3
Rand: 5
Rand: 5
Rand: 1
Rand: 1
Rand: 1
Rand: 5
Sorry, I shared the link to cumulative sum
thinking you might not know the term. But if you already know it, great.
(run!
(fn [x]
;TODO do side effect
(println x))
(take-while
#(>= 1280 %)
(reductions + (repeatedly #(rand-nth [1 2 3 4 5])))))
The rand-nth is the part that needs the side effect. Let me try...
Why does rand-nth need side effect? Perhaps you mean that you need the value that rand-nth produces to be used in a side-effect?
(reduce
(fn [accum item]
;item is the output of rand-nth
;TODO side effect here
(println item)
(if (<= 1280 accum)
;stop reducing
(reduced accum)
;else, reduce further
(+ accum item)))
;initial value of accum
0
;infinite lazy seq
(repeatedly #(rand-nth [1 2 3 4 5])))
If you want to do side effects, reduce
is a good choice
Hey all! I'm going to be recording a screen cast about how to setup a Clojure + ClojureScript setup from SCRATCH! I struggled quite a bit when starting out trying to create a full-stack project without using templates. So hopefully this would help someone! I'm planning on starting with a blank directory and then walking through each of the following (in order): • deps.edn and REPL Driven Development • Ring + Jetty backend server • JSON api handler + HTML page handler • Hiccup and rendering html • CSS files • Simple vanilla clojurescript example (no additional tools) • Auto building cljs->js (no additiona tools, except cljs itself) • Solving server startup with `dev/user.clj` • REPL jacking in with dev profile • Easier server lifecycle management (basic introduction to the reloaded flow) • Adding in shadow-cljs and jacking in with clj&cljs BOTH • Adding Reagent and fetching our API from frontend • Adding Integrant • Small quick notes on repl_sessions and easy deployment What do you think would be some other important points to cover? or any other suggestions?
cider seems to work better with figwheel than with shadow-cljs (although I am not an expert on the latter, perhaps I was doing it wrong)
like, all the nice cider features were missing
Oh! Could you perhaps mention a few features you're missing with cider & shadow-cljs? I haven't noticed anything in particular and found that after a bit of middle ware setup it works perfectly!
the one I specifically remember missing (with a cider cljs repl) was cider-inspector
cider-enlighten I think was another
also completions weren't working for me
Yup, inspect and enlighten don't work for me either, but I rarely use them! Completions do work fine me though :thinking_face:
good to know... I'll fool around with the emacs side next time and get completions working. Thanks!
making a jar file for deployment
Thanks yes I could talk quickly about it showing an example. I was trying to stay away from deployment as I wanted to create a separate video on it 🙂
it is more of a build phase anyway 🙂
backend and frontend routing may be
Thanks. Yes routing is something I want to cover but I'm confused to what depth? I do plan to add a simple (case (:uri request)..
router in my jetty handler to explain the flow of how routers work at their core.
I mostly tend to use reitit as it's quite nice on both backend and frontend, do you think I should cover those to setup separately? Or are you thinking more along the lines of a single shared router between both frontend and backend?
I m thinking of separate routing setup for backend and frontend. I don't know that shared routing setup is even possible. If it is possible, would love to see this setup. Im thinking in the lines that, e.g. in nodejs/react app, we mostly add experess and react router at the start. because even a smallish app tend to have few pages on front end and few crud operations on backend.
> I don't know that shared routing setup is even possible. > If it is possible, would love to see this setup. It's definitely possible with reitit, I don't have much experience with it but it would be a great way to learn and document. I would love to do this separately!! Thanks
> Im thinking in the lines that, e.g. in nodejs/react app, we mostly add experess and react router at the start. > because even a smallish app tend to have few pages on front end and few crud operations on backend. Yes that is indeed true, but with adding routers do you think I need to talk a bit about content negotiation/encoding, middlewares or maybe interceptors too? :thinking_face: Edit: Maybe that would be a bit too much haha. I'll think about the most minimal example I can whip up with reitit
Yeh indeed, negotiation/encoding and middleware come into play. And it may drag the direction to library usage, instead of minimal setup. May be you can have another screen cast, that is more involve with routing after the setup one
> May be you can have another screen cast, that is more involve with routing after the setup one Yes looks like that would be best! Thanks for your suggestions and feedback, super appreciate it 😄 ^_^
Here how i setup a minimal reitit example. May be it can be further simplify.
(def app
(ring/ring-handler
(ring/router
["/api"
["/scramble" {:post scramble-handler}]]
{:data {:muuntaja m/instance
:middleware [muuntaja/format-middleware]}})
(ring/routes
(ring/create-resource-handler {:path "/"})
(ring/create-default-handler))))
thanks @mitesh looking forward to the screen cast. :cljs:
Lovely! I was thinking something very similar, but I also understand that this can get really daunting for someone quite new 🙈
> looking forward to the screen cast. Thanks haha, I'll be sure to ping you once I have it up 🙂:nyantocat:
Yes pls do. I m fairly new in clojure land, And when I was try to setup my project, I was not able to find such screen cast. So I m sure, it will help a lot of new comers
I had the exact same experience! Trying my best to fill in this assumed gap, I already have a few beginner friendly clojure videos up here: https://www.youtube.com/channel/UCd588hDu4bszrSHlLXC8eZA If you're interested in checking it out 🙂
🙌 wow Im sure I will go through each of these videos one by one. thanks of making and sharing, 🎯
Thanks a lot this means a lot! :sharkdance: 🙏
In the below code the let only differs for the outer loop.
(for [[rulename jobs] (group-by :in-rule jobinfo)
job jobs
:let [{:keys [params shell script]} (rules rulename)]]
Still, is the let computed anew for each inner iteration?Had no idea I could move the let. Thanks!
What about re-frame? It is on the very top of the stack though.
I like using Selmer for html templates so you can pass in variables and invoke them in the html template {{like-so}} I also like using rum a lot for cljs development, and it can actually render html on the serverside faster than hiccup if i recall correctly. Nice list. I think the goal ought to be to get to a repl as fast as possible and after each big step.
@raspasov no, I meant that if I use rand-nth only evaluates once. But I want it to reevaluate each time it is called in the seq
I believe you’re mistaken. Look at the doc string for repeatedly
:
Takes a function of no args, presumably with side effects, and
returns an infinite (or length n if supplied) lazy sequence of calls
to it
I have registered cursive with intellij. I now want to run the tests of one of my clojure services. How do I run the tests using cursive?
If you run the code I pasted, you’ll see ‘item’ being printed many times. It’s different each time.
Also, the total sum at the end is different each time, which also shows that rand-nth is being called many times.
to find out, you could embed a (do (println "hey") (rules rulename))
but you can also move the :let
above the job jobs
line
user=> (for [a (range 1 5) :let [b (inc a)] c (range b)] c)
(0 1 0 1 2 0 1 2 3 0 1 2 3 4)
You've tried the instructions on Cursive's documentation and they don't work for you? https://cursive-ide.com/userguide/testing.html If so, it would help if you could be more specific
Hi Everyone, how would yall approach a problem of generating a list of numbers that looks like [0 0 2 0 2 0 0 0 2 .... ] where the interval between the 2 are randomly chosen. Perhaps using something like rand-nth [2 2 3 4 5]
i'd probably make a lazy seq that would compute the random interval, put that many 0's and a 2, and then cons onto the "recursive" call
mapcat
seems useful
(mapcat #(repeat % 0) random-intervals)
will generate lists of 0
s of the specified lengths, then concatenate them together. I’ll leave it as an exercise to append the 2 and to generate random-intervals. (edit: replicate -> repeat)
TIL replicate
Me too. But repeat
is favored over replecate
.
(take 100
(flatten
(interpose 2 (map #(repeat % 0) (repeatedly #(rand-nth [2 2 3 4 5]))))))
Something like this?replicate
is deprecated
> What about re-frame? It is on the very top of the stack though. I plan to cover reagent, reframe, and building entire dashboards / admin panels / and complex real world projects with clojurescript. But those are for a separate video and I've been a bit lazy haha. I do have an intro to reagent video up with a simple todo app if you're interested in checking it out: https://www.youtube.com/watch?v=tRYreGS53Z4 🙂
> I like using Selmer for html templates I'm a bit on the opposite end here 🙈. After using html templating systems like Selmer over the years, I've come to really appreciate the hiccup approach (and to some extent even jsx). Composing html using clojure functions makes html painfree and powerful! But maybe selmer does make more sense to someone new :thinking_face:
> Nice list. I think the goal ought to be to get to a repl as fast as possible and after each big step. Yes EXACTLY!! 💯 REPL driven development makes everything so much more lively, I definitely want to give a feel of how to use the clj+cljs REPLs together.
Every element in the sequence basically has a random chance of being either a 0 or a 2 (assuming 2's can be adjacent to each other). So something like this should also be enough:
(repeatedly 10 #({0 0 1 2} (rand-int 2)))
;; => (0 2 0 2 0 2 0 0 0 0)
or maybe even (repeatedly 10 #(rand-nth [0 2]))
?
this way you have some control over the distribution of the numbers, e.g. you can say (repeatedly 10 #(rand-nth [0 0 2]))
if you want to have "twice" as many 0s as 2s (twice doesn't really make sense here, i'm using it figuratively)
you might also look at test.check generators to make these kinds of things
helpfully, spec makes them for you if you can describe the sequence
% clj -Sdeps '{:deps {org.clojure/test.check {:mvn/version "0.9.0"}}}'
Clojure 1.10.1
user=> (require '[clojure.spec.alpha :as s] '[clojure.spec.gen.alpha :as gen])
nil
user=> (gen/sample (s/gen (s/+ (s/cat :a (s/* #{0}) :b #{2}))))
((2) (2 2) (2) (0 2 0 0 2 0 0 2 0 2) (0 2 0 2 0 0 0 0 2 0 0 0 0 2) (0 0 0 0 2 0 0 0 0 2 0 0 0 2 0 0 2) (0 0 0 0 0 2 0 2) (0 2 0 0 0 0 0 2 0 0 0 0 0 0 0 2 0 2) (0 0 0 0 0 2 0 0 0 0 2 0 0 0 0 0 2 0 0 0 0 0 2 0 0 0 0 0 2 0 0 0 0 0 0 0 2 0 0 0 0 0 0 2) (0 0 0 0 0 2 0 0 0 0 0 2 0 0 0 0 0 2 0 0 0 0 2))
what is s/*
oh, multiply?
head scratching
https://clojure.org/guides/spec#_sequences
> *
- 0 or more of a predicate/pattern
(check out the examples in the docs, they're really helpful)
Ah, like FSM notation. So + is "one or more" ? thank you i will check out the link
btw replicate
is deprecated, use repeat
s/*
=> “Zero or more instances of” (like in regex)
Is there an easy way to parse a date string like this Fri, 02 Apr 2021 18:00:17 GMT
into a date instance? I’ve tried with java.time.Instant/parse
but didn’t work
DateTimeFormatter, in java time, will do that if you give it a pattern
do you know how you ended up with that string?
Last-Modified
header has a value like that, for example curl -I -X GET <https://martinfowler.com/feed.atom>
oh bummer
((juxt #(get % "Date") #(get % "Last-Modified"))
(:headers (http/get "<https://martinfowler.com/feed.atom>")))
["Fri, 02 Apr 2021 19:49:39 GMT" "Fri, 02 Apr 2021 18:00:17 GMT"]
was hoping those wouldn't be strings like that programatically.yeah 🙂
in case someone else finds it useful, the way I achieved that:
(def t (.parse java.time.format.DateTimeFormatter/RFC_1123_DATE_TIME "Fri, 02 Apr 2021 18:00:17 GMT"))
(java.time.Instant/from t)
maybe more of a spacemacs question... I have both the clojure layer and lsp layer enabled and when I open a new file I get the namespace autogenerated twice e.g.:
(ns my-ns)
(ns my-ns)
anyone know how I can disable 1 of these two from filling in the namespace?yes
Check *Conflict with clj-refactor when creating new files*
https://emacs-lsp.github.io/lsp-mode/tutorials/clojure-guide/
awesome, thanks!
This is great! I'd love to see figwheel-main in there as well
would anyone know how to include XML CDATA in a hiccup map? I am writing a babashka script that takes an edn file with markdown and turns it into an RSS feed. e.g.
[:item
[:title "new post"]
[:link "<https://posts.com>"]
[:description (markdown->html "**some stuff**")]]
@webmaster601 according to the readme of clojure.data.xml:
[:-cdata "not parsed <stuff"]
oh, my gosh, thank you!
Also, thank you for babashka. It is incredible!