Fork me on GitHub

in case you haven’t read it, this thread between alan kay and rich hickey a while back is pretty awesome:


"Other than in this conversation apparently, if you say you have some data, I know what you mean"


it'd be nice to see that discussion in person maybe, I felt like over the internet they were talking in opposite directions. also possible that I'm just too dumb to understand either of them




I’m not sure where to ask this because it’s library specific… happy to be pointed to the right place.


I’m using hugsql on top of postgresql. I can’t figure out how to deal with optional columns, and searching the docs hasn’t helped me


For example, a user table with optional address1, address2, city etc. columns… in the update SQL, if any of those are missing from my passed-in map, an exception is thrown


But I obviously don’t want to write an update statement for every combination of possible optional column values


All examples and documentation have simple cases where all fields are present in the map arg, and the docs don’t mention nil values as far as I can find.


@credulous You could write a wrapper function for your hugsql call. This function would generate a defaults map containing all the required keys, with nil values. Then call your hugsql function like (hugsql-fn (merge defaults args)) Then all your required keys will be present, and any that weren’t given in the map you passed in will have nil as the default


@credulous Take a look at Clojure Expressions support in HugSQL, which allows you to conditionally include portions of your SQL and parameters based on their existence during runtime:


@manutter51 that would however mean that existing values are overwritten during an update For this reason I use a very dynamic update function for update and insert statements. And for more fixed queries I use yesql or honeysql. That's MySQL in my case, but idea should be similar:


the thing above is actually a 'normal'!


@jasonjckn @sorenmacbeth FYI, Onyx doesn’t support dynamic topologies. Jobs can be constructed at runtime since they’re data structures, but once submitted they are immutable.


Our stuff is extensively Jepsen and property-based tested. We had to go from scratch to solve a number of systemic issues that are present in other runtimes. Not really trying to sell you on it, just giving you the rationale why we had to do it.


So, I realize this question is so 2 years ago, but I've been having a discussion with a colleague about transducers and wondering if anyone can help shed some light... I understand the benefits of transducers in terms of a useful abstraction and reuse via separating the data from the transformation, but I'm still a bit hazy on how they can improve performance. As a contrived example, why would:

(def xform
    (map dec)
    (filter even?)
    (filter #(> % 2))))
(transduce xform + [1 2 3 4 5 6 7])
Perform better than:
  [1 2 3 4 5 6 7]
  (map dec)
  (filter even?)
  (filter #(> % 2))
  (reduce +))


@manderson because the first one creates no interim data structures, it passes each value through a function that transforms/drops it and then puts it in the final data structure


the second one creates a lazyseq at each step, which includes the overhead of creating, as well as overhead of caching specific to lazy seqs


ie, the first one is as if you did everything in a hand-tuned function passed to a single reduce call


interesting, thanks @bfabry. So the laziness of the second example only helps in that we don't have to iterate the whole sequence each time, but we are still instantiating the seqs at each step. Is that right?


the first example is equivalent to:

(fn [acc v]
  (let [v' (dec v)]
    (if-not (and (even? v') (> v' 2))
      (+ acc v'))))
[1 2 3 4 5 6 7])


which if you think about what is going on, is a seriously efficient operation


and it's kinda incredible that you can describe it in that high level and get similar performance to that hand-written pain


Very cool. Yea, that makes sense. I think the "magic" is starting to be revealed to me 🙂


there's a bug in my hand-written code. probably not giving an initial value for reduce


no... eh whatever. you get the point


the difference is like: seq -> map -> seq -> filter -> seq -> filter -> + ->seq; versus seq-> (all combined) -> seq


@tsulej in this specific case there's not a final seq, he's transducing to a number, but yes


oh and yes, I forgot the initial zero in my hand-written reduce


some very rough benchmarks on the three ways you could define that problem:


transducer ~2x slower than hand written code, interim sequences about an order of magnitude slower


Nice. That's good info.


After 2 years of clojure, I just learnt there is a (while ...) in clojure.


Okay, so if I run a ring server using

(jetty/run-jetty (var slack-app) {:port 3000})


it doesn't open up a connection to a dev repl


like, in my project.clj i have the

:ring {:handler slack-server.handler/slack-app
         :nrepl {:start? true
                 :port 9998}}
bit that lets you open up an nrepl to your server


when you run it with lein ring server-headless


(I think you can tell I'm stitching together documentation from several different incarnations of ring/compojure)


so how do I make it still open up a dev repl on 9998?


@idiomancy the lein-ring plugin uses tools.nrepl to do that when you run lein ring server


if you’re starting the jetty server manually, I think you’ll need to start the repl server yourself as well


tools.nrepl has instructions for that in the readme


okay, awesome. thanks, @loganmhb


Does anyone know who admins We're running a ClojureBridge and can't get students to signup !!!


...and it's down