This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-11-25
Channels
- # announcements (1)
- # asami (3)
- # aws (2)
- # babashka (8)
- # beginners (60)
- # biff (3)
- # calva (45)
- # clj-http (3)
- # clj-kondo (19)
- # clojure (50)
- # clojure-europe (23)
- # clojure-nl (8)
- # clojure-spec (4)
- # clojure-uk (3)
- # clojurescript (32)
- # conjure (3)
- # datomic (7)
- # events (2)
- # fulcro (24)
- # graalvm (3)
- # inf-clojure (3)
- # jackdaw (1)
- # lsp (3)
- # malli (8)
- # missionary (14)
- # off-topic (1)
- # polylith (3)
- # portal (11)
- # rewrite-clj (63)
- # shadow-cljs (21)
- # spacemacs (7)
- # tools-build (6)
- # xtdb (4)
Hello, I am currently on a team using intellij with cursive and I'm personally using emacs for development. May I ask if there are any suggestions to ensure consistent formatting? I know the standard is cljfmt but from my understanding there is no integration with cursive. I understand there's https://clojureverse.org/t/cursive-how-to-match-cljfmt-formatting/7246 but I'm not sure how well it works. I also looked into https://cursive-ide.com/userguide/formatting.html#matching-indentation-to-emacs but that doesn't seem to be entirely consistent with cljfmt
Both intellij and emacs have a way of configuring an external formatter to run on save. It's not perfect, but perhaps it would be good enough? Everyone could then install cljfmt, cljstyle, or clojure-lsp (which uses cljfmt internally) and use the same config from the repo.
Could you point me to how I can configure format on save on both intellij and emacs?
If you use git you could use git-hooks pre-commit to format code before committing?
Hi I'm wondering what are the ways to implement a 2d grid using clojure data structures. It sounds obvious: just use nested vectors or something, but I'm curious if this is idiomatic in clojure. Or, more importantly, is this the best solution for the problem at hand. In particular, I'm trying to create a https://en.wikipedia.org/wiki/Cellular_automaton, so the operation I'm going to need the most is getting the neighbors of each cell. What approach would you recommend? Also, how do I parallelize this task? I'm thinking pmap, but how exactly do I use it for this?
(ns conway.core
(:import [java.awt Color Dimension Graphics]
[javax.swing JPanel JFrame Timer]
[java.awt.event ActionListener KeyListener])
(:require [clojure.set])
(:gen-class))
(defn make-game-of-life
([initially-filled]
{:alive (into #{} initially-filled)})
([]
{:alive #{}}))
(defn make-cell [x y]
{:x x :y y})
(defn filled [game-of-life]
(:alive game-of-life))
(defn- neighboring-cells [cell]
(let [{:keys [x y]} cell
neighbor-fns [[dec dec]
[dec identity]
[dec inc]
[identity dec]
[identity inc]
[inc dec]
[inc identity]
[inc inc]]
neighbors (for [[x-fn y-fn] neighbor-fns]
(make-cell (x-fn x) (y-fn y)))]
neighbors))
(defn- alive-neighbors [game-of-life cell]
(let [{:keys [alive]} game-of-life
neighbors (neighboring-cells cell)
not-open-neighbors (filter (fn [cell]
(contains? alive cell))
neighbors)]
(set not-open-neighbors)))
(defn- who-dies [game-of-life]
(let [{:keys [alive]} game-of-life
to-die (filter
(fn [cell]
(not (contains? #{2 3}
(count (alive-neighbors game-of-life cell)))))
alive)]
(set to-die)))
(defn- who-is-born [game-of-life]
(let [{:keys [alive]} game-of-life
all-neighbors (mapcat identity
(for [cell alive]
(neighboring-cells cell)))
count-of-neighbors (frequencies all-neighbors)
has-3-neighbors (filter
(fn [cell] (= (get count-of-neighbors cell) 3))
(keys count-of-neighbors))
to-be-born (filter
(fn [cell] (nil? (get alive cell)))
has-3-neighbors)]
(set to-be-born)))
(defn advance [game-of-life]
(let [{:keys [alive]} game-of-life
to-die (who-dies game-of-life)
to-be-born (who-is-born game-of-life)]
(assoc game-of-life
:alive
(-> alive
(clojure.set/difference to-die)
(clojure.set/union to-be-born)))))
;; ----------------------------------------------------------------------------
(def starting-cells #{;; Gosper Glider gun
(make-cell 1 5)
(make-cell 2 5)
(make-cell 1 6)
(make-cell 2 6)
(make-cell 11 5)
(make-cell 11 6)
(make-cell 11 7)
(make-cell 12 4)
(make-cell 13 3)
(make-cell 14 3)
(make-cell 12 8)
(make-cell 13 9)
(make-cell 14 9)
(make-cell 15 6)
(make-cell 16 4)
(make-cell 17 5)
(make-cell 17 6)
(make-cell 17 7)
(make-cell 18 6)
(make-cell 16 8)
(make-cell 21 3)
(make-cell 21 4)
(make-cell 21 5)
(make-cell 22 3)
(make-cell 22 4)
(make-cell 22 5)
(make-cell 23 2)
(make-cell 23 6)
(make-cell 25 1)
(make-cell 25 2)
(make-cell 25 6)
(make-cell 25 7)
(make-cell 35 3)
(make-cell 35 4)
(make-cell 36 3)
(make-cell 36 4)})
(def field-width 50)
(def field-height 30)
(def point-size 15)
(def square-color Color/BLACK)
(defn game-panel [initial-game-of-life-state]
(let [game-of-life-atom (atom initial-game-of-life-state)]
(proxy [JPanel ActionListener KeyListener] []
(paintComponent [g]
(proxy-super paintComponent g)
(let [game-of-life @game-of-life-atom]
(doseq [{:keys [x y]} (filled game-of-life)]
(.setColor g square-color)
(.fillRect g
(* x point-size)
(* y point-size)
point-size
point-size))))
(getPreferredSize []
(Dimension. (* (inc field-width) point-size)
(* (inc field-height) point-size)))
;; ActionListener
(actionPerformed [_]
(.repaint this))
;; KeyListener
(keyPressed [_]
(swap! game-of-life-atom advance))
(keyReleased [_])
(keyTyped [_]))))
(defn game []
(let [game-of-life (make-game-of-life starting-cells)
frame (JFrame. "Conways Game of Life")
panel (game-panel game-of-life)
timer (Timer. (/ 1 60) panel)
_ (do (.setFocusable panel true)
(.addKeyListener panel panel)
(.add frame ^JPanel panel)
(.pack frame)
(.setDefaultCloseOperation frame JFrame/DISPOSE_ON_CLOSE)
(.setVisible frame true)
(.start timer))]
frame))
(defn -main
"Starts the default game. TODO: Custom input to specify the initial state."
[& args]
(game))
check out http://clj-me.cgrand.net/2011/08/19/conways-game-of-life/ different approach much simpler
@UE0T2PKJA Wow, I'm impressed. I like the idea of using a set of living cells to represent the board state. I would like to modify it to work with any ruleset, though. I'm not sure if it's possible for this solution, but I feel enlightened nonetheless.
Hey, hello, I'm writing my first code attempts in clojure using hackerank, and I'm solving a "string compression" task by reducing a string with a transducer that compact duplicates The issue is that - probably for longer inputs - some of the checks fails because they take too long to finish. Is there any known practice or solution to speed up such kind of operations. I'm thinking of map-reducing, in parallel chunks, yet there might be simpler solutions before going async Thanks for any advice
What counts as long here? Both a simple threaded version (`(time (->> input (partition-by identity) (map first) (apply str) (def output)))`) and a tranducer version (`(time (def output (apply str (transduce (comp (partition-by identity) (map first)) conj input))))`) seem to work up to strings of length 1e7 in reasonable time. Beyond that it's more painful, and you'd want something like:

Can anyone that uses Calva in VSCode tell me why my cursor doesn't tab forward when I press tab? Space works just fine but is kind of slow if I want to line up something with the line above.
indeed, but thats only the starting indentation. I need indentation between wrapped expressions
I doubt that you haven't googled it already, but still https://stackoverflow.com/questions/35519538/visual-studio-code-tab-key-does-not-insert-a-tab
Nothing. 😀 but it is just defaults. You can of course rebind the tab key, or bind something else to the insert tab action.
Was going through component https://github.com/stuartsierra/component i did not get
(defn new-database [host port]
(map->Database {:host host :port port}))
because , this has 2 parameters, does it act like arbitrary argument?
(defrecord Database [host port connection]
map->Database
is an automatically generated function that will take a map and turn it into a database record. ->Database
will take 3 args of host
port
and connection
and return a database record. This https://clojure.org/reference/datatypes#_deftype_and_defrecord says:
> when a defrecord Bar is defined a corresponding function map->Bar is defined that takes a map and initializes a new record instance with its contents
Hello! I was wondering if it's realistic in 2022 to find a job as a Clojure Dev? Beginner Clojure Dev but experienced developer (from Java and Kotlin) Thanks a lot!
I do think it is realistic, though of course this might depend a lot on eg. geography - different countries will have different amounts of Clojure jobs available.
Clojure being a rather niche language, I think a lot of places will not require you to have prior experience in Clojure per se, but rather ask for general programming experience and perhaps previous exposure to functional programming.
I do think your JVM (and especially Kotlin) background will be to your advantage, though - again - this will depend a whole lot on your particular situation.
(There's also #jobs-discuss in case you have more targeted questions regarding finding a Clojure job.)
The company I work at are recruiting Clojure developers as much as we can find. We are located @ Tel Aviv
Ok thanks for the info. I live in Berlin, I don't know here the situation about clojure. But I guess there are also opportunities full remote from other countries right?
I have the feeling that it's a niche language but probably it's quite stable on the market (or maybe it's growing)
And you can also search with various criteria on sites such as https://functional.works-hub.com/ or https://jobs.braveclojure.com/
Cool thanks! For now I have to think about learning the language and practicing 😁 I'm reading Clojure for brave and true, then I want to explore testing and also some stack for building APIs, use queues, etc
Adding to what I wrote about my company looking for Clojure programmers - since Clojure experience is not very common, we are looking for people with knowledge in functional programming as well. Check the career page link I posted
I have list of urls (url1, url2, url3 ..) and I am trying to make a ajax/get-json request by mapping but it is not working anything wrong with that code? (map (fn [x] (ajax/get-json x
(fn [response]
(if (empty? response)
(notify 102 "No results")
(do
(debug "intra-day-analysis returned...")
(swap! intra-analysis-data assoc (keyword x ) response)))))) url-list)
map
is lazy, so unless you’re doing something to realise the result, it will appear to not do anything. The easiest way to do that is to wrap the call to map
in a doall
- that forces de-lazying.
e.g. (doall (map (fn [x] (ajax/…
let me check it
For anything side-effecty (especially I/O) within map
, I usually just wrap it in a doall
to force de-lazying ASAP. Makes it easier for me to reason about the temporality of the side effects.
it works brother thank you so much
You’re welcome! Laziness is a common trap - I think everyone has been bitten by it at one time or another. 😉
If you're calling the function purely for side-effects and don't care about the result, use run!
(or doseq
). Otherwise, consider mapv
instead of doall
/`map` (my opinion). mapv
is eager -- based on reduce
-- and you get a vector of the results.
Also probably a time where your code could benefit from promises
clj꞉user꞉>
(defn mock-ajax-get [callback]
(future
(Thread/sleep 1000)
(callback {:data 123})))
#'user/mock-ajax-get
clj꞉user꞉>
(def result
(p/all (for [_ (range 5)]
(let [p (p/deferred)]
(mock-ajax-get (fn [response]
(p/resolve! p response)))
p))))
#'user/result
clj꞉user꞉>
@result
[{:data 123} {:data 123} {:data 123} {:data 123} {:data 123}]
clj꞉user꞉>
so in this case you could make your requests in parallel, then just have regular code build up that map / do your notify
Some observations re: OP's original code:
1. If a result isn't found, it's better to explicitly keep information of that fact. Chances are something else may need to make decisions about missing data later.
2. The atom seems unnecessary. Keywordising the URL seems unnecessary.
3. Even if one replaces map
with mapv
, the expression is doing too much. It is hard to test. It's harder to improve, e.g. notifier need not care how a response is fetched. It is also brittle because multiple things can go wrong (ajax fails, notify fails, ajax is slow and notify is slow etc.)
Here's a translation of the original code to something more testable, debug-friendly, and robust:
(defn proc-response
[response]
;; this definition of response can become a standard
;; invariant for the whole program
(if (empty? response)
::no-data
response))
(defn fetch-intra-data
([url]
(fetch-intra-data url ajax/get-json))
([url fetcher-fn] ; now it's easy to mock out ajax/get-json
(fetcher-fn url
proc-intra-response)))
(defn fetch-all-intra-data
[url-list]
(reduce (fn [intra-analysis-data urlx]
;; record data for all urls, response or not
(assoc intra-analysis-data
urlx ; no need to keywordise url
(fetch-intra-data urlx)))
{} ; now we don't need an atom
url-list))
;; decouple notification logic from fetching logic
(defn notify-missing-analysis
[intra-analysis-data]
(doseq [[url response] intra-analysis-data]
(when (= response ::no-data)
(notify 102 (str "No response for " url)))))