Fork me on GitHub

Does anyone know of any places in the DC area that use clojure? I'm enjoying learning the language but am not sure if there are really career prospects for someone who has never had a dev job before.


#jobs or #remote-jobs may have leads but my previous and current employers were and are based in DC and use clojure. I am dimly aware of a couple of consultancies in the area that do a good bit of clojure as well. It’s probably not as easy to find an entry-level clojure job as other langs, but it is possible.


Yeah, we're a full clojure shop in Baltimore and I know some other shops that dabble in it. They're around.


Just nice to know it exists. Thanks! I'm going to keep plodding away and set the goal to get there someday.


😞 just wasted half an hour to figure out that pre-conditions have to come before the docstring


or maybe it's more accurate to say immediately after the argument list


Also your docstrings are in the wrong place


They go before the argument list


oh dear, thanks @hiredman, I hadn't realised this!


A linter like eastwood can be helpful catching that kind of thing (it is a super common thing to do)


There have even been a function or two inside of Clojure's implementation itself that had the doc string in the wrong place (now fixed, I believe)


hey folks, i trying to understand the code below which is a part of clojure fn implementation. But till now no success. can anyone help please.

body (if post
          `((let [~'% ~(if (< 1 (count body)) ===> ~'% resolve to %. so % is a local var name? ~(if (< 1 (count body)) = (if (< 1 (~count ~body)) ?
                      `(do ~@body) ===> (do (list body) ?
                       (first body))]
               ~@(map (fn* [c] `(assert ~c)) post)  ===> (list map (fn* [c] (assert ~c)) post) ? what is being done here?
               ~'%))  ===> % ?


Fns have a more complicated syntax then is usually used, and that is a complicated hand rolled parser for it


post conditions have access to the result of the function bound to '%' which is what is being setup there, ~'% doesn't resolve to %, but it splices the symbol % into the syntax quote surrounding it (if you don't splice a symbol in like that syntax quote will namespace qualify it, and namespace qualified symbols cannot be used for locals)


My bad, i meant exactly what you describe but used the wrong verb


@ is unquote splice, `(1 @[2 3] 4) => '(1 2 3 4)


you seem to have a hard time keeping quotations straight, so I would suggest investing time in that

✔️ 5

that if is not quoted, so unquoting count and body would be really weird


(and not work)



~@(map (fn* [c] `(assert ~c)) post)
can you tell me what this line is for? cause actually what is being return is ~'%


it builds the post conditions


the map results in a seq like ((assert ...) (assert ...)) where ... is filled in by one item from post


~@ splices the seq in to the syntax quote


back tick is syntax quote


Thanks for this link, i got to understand the difference between

` and ' 


in macros, you are constructing a form in some meta language to be interpreted in a language, in this case both the meta language and the language are clojure


a quotation is a literal bit of the language embedded in the meta language


a syntax quote is a templated version of a quote, meaning a mostly literal bit of the language, but you can fill bits in from the meta language


Is it poor etiquette to bump this? I’m still fighting with this a bit and starting to feel like I’m going around in circles


I went with for my SQS work. It works very well.

Wes Hall13:02:27

Beyond even this, I would suggest that actually working with the basic Java AWS library is relatively straightforward with interop. I mostly just do that these days. The Java library is well maintained, complete and consistent. Wrapping Java interop calls in simple clojure functions works really nicely and also doesn't isolate you from the details too much.


Thanks both - this is really useful. When I looked at the Java library, it didn’t have anything for mocking (or something similar) out of the box. Did I miss something? I’m currently looking at for manual testing

Sy Borg14:02:10

I'm learning by solving Project Euler problems. For the Problem 2 I've come up with smth like:

(defn sum-even-fibs-upto [n]
  (let [fib-seq (lazy-cat [0 1] (map + (rest fib-seq) fib-seq))]
        (apply + (filter even? (take-while #(< % n) fib-seq)))))
It probably is not the most efficient, but my question is - can somebody show me an example how it can be re-written with a transducer?


@sy_borg I would probably do it like this.

(defn fib 
  ([]  (fib 1 1))
  ([a b] (lazy-seq (cons a (fib b (+ a b))))))

(defn fib-even-sum-up-to [n]
  (transduce (comp (take-while #(< % n)) (filter even?)) + (fib)))


Transduce is essentially transform and reduce, your transformation is (->> fib-seq (take-while #(< % n)) (filter even?)) and your reduce is +

Sy Borg15:02:39


👍 5

I'm trying to wrap my head around this example

(reduce (fn [new-map [key val]]
          (assoc new-map key (inc val)))
        {:max 30 :min 10})
; => {:max 31, :min 11}
I think it's the destructuring part in the anonymous function that gets me. So it seems we are feeding it one map but the variables are calling for new-map and then destructuring that same map into key and value?


when the map gets passed into the reduce function, entries are passed as MapEntry which looks like this [:key val]


When you reduce over a map, each entry is a MapEntry (small vector)


haha no problem xP


so it's seeing it as ([:max 30] [:min 10])


yup, and the reason you don’t destructure new-map is because the init value is {}


and every subsequent new-map is an entire map, where the [key val] is just a chunk of the {:max 30 :min 10} you are passing in


it probably helps to print out in the anonymous function


how do i do that? I think I still need help seeing what's happening.


i really wish I could just see what the evaluation steps are in functions step by step


you can just add a println inside the fn


(before the assoc, so you don't change the return value)


(reduce (fn [new-map map-entry]
          (let [[key val] map-entry]
            (println new-map)
            (println map-entry)
            (println key val)
            (assoc new-map key (inc val))))
        {:max 30 :min 10})


you could also destructure in a let binding to see the map entry before it gets changed


ahhh, cool. This will help. Let me wrap my brain around this. ty


i have a bunch of misunderstandings about exceptions and logging: i set the default uncaught exception handler as per

user> (Thread/setDefaultUncaughtExceptionHandler
       (reify Thread$UncaughtExceptionHandler
         (uncaughtException [_ thread ex]
           (println "dummy text"))))
user> (/ 1 0)
java.lang.ArithmeticException: Divide by zero ;; plus i get the whole stacktrace
;; i incorrectly expected it to print "dummy text"
- i would think "uncaught exceptions" are any exceptions not (try ... (catch)'d . but it looks like the above is actually Thread/setDefaultUncaughtExceptionHandlerThatsOffTheMainThread. - i'm trying to understand this because i actually want extra information whenever i get an exception in production. i'd like to log the bindings in the lexical environment. i found taoensso.timbre/get-env, which does what i want, but i can't get main-thread exceptions to show up there without an explicit (log/error stuff). - i want what i consider uncaught exceptions to go to timbre, but i don't know what i don't know


often the most succinct thing is to pprint a hash-map (clojure.pprint/pprint {:new-map new-map :map-entry map-entry :key key :val val})


@mfm by the time the exception is thrown, the lexical environment is ready to be garbage collected - in fact much of it can be collected before it even exits (and clojure does so, it's called locals clearing)- you can throw ex-info in a catch clause in order to provide a hash-map with extra data, and test for that in your handler, but it's a fundamental problem


very interesting. thank you. dumb question: how do you know this? that is, where can i look up more info?


I've frequently ended up in slightly awkward nesting of code (or using a delay defined in one let block, then forced inside a try, so that the value if any can be used in a catch) - these things are awkward, they conflict with the semantic model of bindings that clojure is trying to create


I've picked it up by following discussions around bugs and debugging tools, I don't know a good reference outside the clojure code itself


clojure's jira and changelog would also likely be enlightening


ok thanks. googling locals clearing has yielded some good stuff


yeah - often when running a proper debugger you need to increase resource usage by turning off locals clearing


and it can fundamentally break some code (eg. using a very long lazy-seq and now you are holding the head...)


is it reasonable for a webapp to disable locals clearing in production?


ah by your second comment, perhaps not


depends, how much ram can you afford


damn. our production box is 32gb. are we talking gigabytes or terabytes?


this is highly variable, it really depends on how much of your code is implicitly relying on locals clearing - you could try locally and see what happens to resource usage?


sounds good and interesting to me


but it might be more straightforward to rearrange things so that local events and values that matter enough are logged or made available in an ex-info object


small question: what is the main thread exception handler? and how to i modify it? for use in timbre


there's a defaultExceptionHandler on java.lang.Thread - that's used if the current thread doesn't have a default set - I might be misremembering that name, it's long and awkward


there's also a property on each thread that holds a handler


ok cool i'll look at that. the answer might be: "by default timbre does capture the main-thread-exceptions" and i have misconfigured something


you can access the current thread in order to set it's handler with (Thread/currentThread)


oO thanks


I don''t think this has anything to do with Timbre, I'd be mad if Timbre was going and changing my uncaught exception handlers without me explicitly making it do so


for example in my app we want to hit a rest api to make a pagerduty alert -that's not Timbre's job, we also log in the same handler, but that's separate


in an app that's critical enough, you might even ask the whole vm to shut down if certain unexpected conditions are hit (that's safer than running in unknown bad state)


I’ve wonder if that’s something that a component/system framework could help with (similar in vein to integrant/etc.)


like if you have this thing starting and defining your internal deps/resources, I wonder if that’s the correct point in the system to take control of things like exceptions and recovery as well


@lilactown the difference for my usage is that the default uncaught exception handler and recovery logic aren't stateful - they are an idempotent setting that I can safely do each time -main is invoked


I guess they do rely on config (loading up proper logging settings and knowing which endpoint to hit with info about emergency states), but that's similarly not a stateful thing per se, they are loaded up on startup and idempotent


(by idempotent I of course mean that loading my configs twice gives me the same result as loading once, so it's safe to just do every time -main is launched)


as opposed to what integrant and friends are for, where you don't want N db connection pools sitting around, and you can't own the same port with two server instances


sure. I think that’s agreeable with what I’m saying


in my first app using component, the configs were a component


I think that’s simply a function of some inflexibility of integrant and friends


in retrospect that just increased complexity


I think it's becuase integrant and friends are for a specific task, and that task isn't "startup", it's "managing stateful resources"


maybe the comparison is bad, yeah


I mean, I think they’re related


e.g. I could imagine a framework that would allow you to “load” a system, and subsequent “loads” would only restart resources that needed to change


e.g. I updated my route handler so I need to restart my webserver, but no need to restart my db pool.


maybe I just need to create an example framework 😄 I think the comparison with component/integrant is bad, you’re right


I'm not saying it's a bad comparison, but my experiences structuring an app with component led me to differentiating things that are idempotent (safe to simply run on every restart) vs. things that use or define fragile state (that requires careful startup order, and specific shutdown steps)


FWIW I don’t appreciate component or integrant as much as others due to the way it warps your app like you’re saying 😛

Mario C.17:02:42

Good morning gentlemen! I have a query (str "SELECT " fields " FROM interviews WHERE _id IN (" interview-ids ")"). I have a list of interviews ids and I want to select certain fields from those interviews. Is this the best way I can do it?

Mario C.17:02:10

(sql/query url [query])


I wouldn't use str to create a query

Mario C.17:02:50

Whats the issue with using str? :thinking_face:


I think most libraries have some way of interpolating queries


if you use the ? syntax in the string, and provide the substitutions via extra args in the query vector, you get a much safer parameterized query, which prevents injection

🔐 10

if you just use str, anything in the fields or interview-ids strings could be an unintended sql command, or even an exploit if you use any user provided data


"select a_field from foo where val > ?"


then you provide an actual number, rather than putting a number into the string


@mario.cordova.862 what library are you using to do your sql query?


that looks like just

Mario C.17:02:37

that is correct

Mario C.17:02:41

Perfect! But aside from the parameterized query is the query itself fine? Is there a better way to structure this query?


if you do need to use string concatenation for some things (where the query can't be parameterized in the way you need), at least separate the parameters from the query construction, and if possible have query construction be static and verifiable


that looks like reasonable sql, but I don't know your db and schema of course :D

Mario C.17:02:43

okay okay fair enough


and these questions about query construction vs. parameterization is why people end up using higher level libs that abstract over (eg. hugsql, honeysql which is provided by the devs, etc.)

👍 10
Mario C.18:02:59

After refactoring I have ["SELECT ? FROM interviews WHERE _id IN (?)" fields interview-ids] but this is not return anything. Using the same values for fields and interview-ids when I run (str "SELECT " fields " FROM interviews WHERE _id IN (" interview-ids ")") using (sql/query url [query]) it works.

Mario C.18:02:24

Any idea what I am doing wrong?

Mario C.18:02:13

interview-ids looks like this '123', '456'


JDBC requires a separate ? placeholder for each value -- it doesn't automatically expand collections.


So you'd need SELECT ?,?,?,... FROM interviews WHERE _id IN (?,?) for however many fields and interview-ids you have.


(and I'm not sure that JDBC accepts ? for column names anyway?)

Mario C.18:02:20

What if I dont know how many interview ids I will have?


(str/join "," (repeat (count interview-ids) "?")))


So you end up with something like (into [(str "SELECT " fields " FROM interviews WHERE _id IN (" (str/join "," (repeat (count interview-ids))) ")"] interview-ids)


(assuming interview-ids is a collection of IDs, not a comma-delimited string!)

Mario C.18:02:21

Doesn't this go back to using str to create a query?


You're still creating a parameterized query.


The above would produce (for interview-ids being [123 456]) ["SELECT ... IN (?,?)" 123 456]


This is why a lot of people use things like HoneySQL since it handles this for you.

Mario C.18:02:38

Okay got it. And yea we probably should have used that. Maybe we can refactor and integrate into our project.


Anyone know a good clojure image->text library?