Fork me on GitHub

Thanks very much for your answers!


Yep, I came across Honey SQL some time ago. I plan to use it. But it seems it doesn't support DDL


I had already read 50 pages from this book. I tried to use Luminus. it confused me little bit because it uses django like templates instead of hiccup. I have googled, it's possible to use hiccup by just providing +hiccup command line parameter. I should look at Luminus one more time.


@sigmaray If you happen to be using Postgres you can do basic DDL with an HoneySQL extension:


(defn vector
  "Creates a new vector containing the args."
  {:added "1.0"
   :static true}
  ([] [])
  ([a] [a])
  ([a b] [a b])      ;;Why just didn't call clojure.lang.LazilyPersistentVector here????
  ([a b c] [a b c])
  ([a b c d] [a b c d])
	([a b c d e] [a b c d e])
	([a b c d e f] [a b c d e f]) 
  ([a b c d e f & args]  ;;Why call only now the clojure.lang.LazilyPersistentVector
     (. clojure.lang.LazilyPersistentVector (create (cons a (cons b (cons c (cons d (cons e (cons f args))))))))))


Probably for performance reasons @quieterkali -- I'm a more surprised at the implementation of the 7+ argument version TBH.

cider 5

@seancorfield i thought about performance too, but wanted to make sure 🙂


I'm a more surprised at the implementation of the 7+ argument version TBH. can you tell me why please?


and what mean TBH?


To be honest. Sorry, I shouldn't use abbreviations like that on a global forum.

😄 5

My surprise about the 7+ argument form is that it uses something with "lazy" in the name and cons because vectors are inherently not lazy.


I'd have to dig into the source of the runtime to see what it all did.


Please, let me know what you'll find out in case you end up digging into it. I'll do the same too 🙂


Thanks! That's what I was looking for


I read one of the main benefits of transducers is that it eliminates intermediate collection values between steps. If each of your steps returns a lazy seq though, are intermediate values really a big deal?


So (->> [1 2 3] (map foo) (map bar)) returns a lazy sequence and creates an intermediate sequence in the thread-macro ((foo 1) (foo 2) (foo 3)) but (transduce (comp (map foo) (map bar)) + [1 2 3]) will pass values in one by one through the comp defined then pass them into the reducing function +


map returns lazy seqs when a collection is passed into it (map foo [1 2 3]), but without it is a transducer (map foo)


With transduce you’re only really interested in composing transducers, so functions that only ever return lazy seqs won’t work.


Just to clarify (->> [1 2 3] (map foo) (map bar)) is really the same as (map bar (map foo [1 2 3]))


I suppose that would be helpful if you have a transformation step that isn’t lazy and didn’t want to realize a really large intermediate, or just wanted to keep things as fast as possible in a hot loop?


Yeah I think a big benefit to using a transducer is if you have a really large collection, and are only really interested in reducing the dimension of the data to a number or string or something [1 2 3] => 6, though you can also keep dimension by doing (into [] ...). Avoiding intermediate sequences will help performance in either case.


Transducers are also really good if you need to create a composable data transformation that is independent of the input and output specifics


You can pass collections, streams, channels, observables as inputs/outputs, while the actual transducer functions only ever worry about what happens to one item at a time


thanks, that makes a lot of sense


@risinglight If it helps, there really aren't that many situations in real world code where you really need lazy sequences so transducers can be used more often than you might think, and they'll have better performance than a lot of threaded code.


We have a few places where we genuinely need lazy sequences but pretty much everywhere else, it doesn't really matter whether a sequence is lazy or eager. We could use transducers a lot more than we do -- but our code base started in 2011 so we have a lot of "legacy" code 🙂


Are there certain conditions that make you decide to reach for transducers, or is it basically anywhere/everywhere that you would reduce, you go ahead and write one?


Pretty much anywhere you need to produce a collection as a transformation of another collection.


It's going to take a while before they become "the norm" just because we've had years of writing transformations the "old way" 🙂


I’ve done nothing but write things the “old way”, but keep feeling like I’m missing something after hearing about transducers over and over. I think it would take a big update to docs/learning material before people accept them as the right thing to do all the time


seems like it also would be used a lot of places the threading macros would otherwise be used


What’s a good first resource to read up on transducers? 🙂


(edited to point to the specific section that describes the pros and cons)

👍 10

I’ll be honest it took me a long while to wrap my head around transducers, especially writing one. It’s not exactly easy to switch over from using thread macros.


Are there any examples of the Clean/Hexagonal architecture in Clojure? All the examples I have seen are in C# and all use a IOC/DI framework to resolve all the statful dependencies within the (controllers/handlers) and (service/application usecase).


I'm not familiar with "Clean/Hexagonal architecture", but many Clojure developers also use IOC/DI-like approaches to manage the creation of stateful dependencies during application startup.


Here's one approach that seems to have a lot of mindshare:


There was a talk at Clojure/Conj that reminds me of that, they call it Declarative Domain Modeling. And there’s a good slide at 27:20 in the video that seems to follow that hexagonal model.


This is my best implementation of 'Clean/Hexagonal' by just converting a C# project into Clojure project with Integrant. I haven't seen anyone else do this though.


So..... what's so great about tagged literals? And how do you start developing with them / defining them sensibly? I have a couple of projects in mind where I'll be hand-authoring a lot of content in order to define a lexicon and grammar(s) for text generation. Some of it will be context sensitive. I'm trying to imagine what the authored input would look like.... I dunno, something like {:actor.dialogue/innkeeper ["Welcome to my inn, #world/state {:characters :wealthy} honored guests! #world/state {:characters :poor} filthy itinerants!"]}....

Alex Miller (Clojure team)18:01:23

I don’t see any reason to use tagged literals here. Why not just use maps?


Maybe my example is bad. I'm trying to understand, what would be the complexity level of the data that would be a use case for tagged literals? I know that I read some people getting excited about defining a data_readers file but I never understood why it was a cool thing to do

Alex Miller (Clojure team)17:01:34

If you want to be able to get a function in the “data construction” process, like interop calls to construct a Java object or create a more complex object

Alex Miller (Clojure team)17:01:43

If it’s just data, use data


Ohhhhh HMM. So a better example might be, I'm reading some data and it has dates but they're represented as "YYYY-MM-DD", so I transform that into a real Date object by defining a reader function.

Alex Miller (Clojure team)17:01:59

yes (which is what the built-in #inst does)


this makes more sense. Thank you Alex


This tree: should I continue barking up it? confusedparrot


Hi. I'm experimenting with Spec. I think I'm approaching it (incorrectly) from an OO background. Suppose I have a spec ::vehicle #{:car :truck :semi-truck :bicycle :motorbike}. It is part of a map (s/keys :req [::vehicle ::color]). At some time later in processing, I have a function that requires 2-wheeled vehicles, so I might have ::two-wheeled-vehicle (s/and ::car has-two-wheels?). My problem is I've already used the ::vehicle key for the more "generic" specification of a vehicle. I would need to create a new map with new keys (`(s/keys :req [::two-wheeled-vehicle ::color])`), and copy all the values over, in order to validate the stricter specification. Am I doing it wrong?


@mattmorten your best bet is to ask this question in #clojure-spec. it’s a problem others have had before. I think Rich talked about this in his latest talk.

Daw-Ran Liou20:01:30

Hi everyone, I'm wondering if this is the only way to generate java class method that returns its own class:


From context, I assume you mean returning an instance of its own class. One hacky way to do it would be to take declare return type of Object or some other superclass / parent interface

Daw-Ran Liou20:01:26

Thanks @noisesmith, yes that's what I want to do. I think that's a good idea to try. Instead of returning the type of the instance, returning an interface sounds a better idea


especially since in Clojure you are pushed toward only defining methods based on some interface in the first place...

Sy Borg21:01:31

(doc munge)
=> nil
not very helpful

Alex Miller (Clojure team)21:01:10

It’s not intended to be part of the public api