Fork me on GitHub

Sorry, just got back from dinner. I’ll be considering other approaches as things evolve, but for now the eval/fn is ideal. Thank you @gfredericks. I just needed to unquote the x, since it may be something like:

(let (x (gensym)
      the-list (build-list-using-symbols x)
      f (eval `(fn [~x] ~the-list))]
  (f 1)
  (f 2)


Yeah that works too


hey guys, i have a function to generate a timestamp for a file (like 2016083112…).. i think that is a good function to be on a utils ns or something.. what do you guys do usually?


do you have a utils.clj somewhere?


Yes! In every project! 😆


it is very common


I would recommend from the very beginning trying to be more specific and break things out in to distinct namespaces


something.utils.files or something


i already have a something.files that’s responsible for writing files to local or S3


once you have a few thousand lines in a utils namespace, it can become hard to muster the effort to break it up


i could put there and not have a utils file for now?


sure, put it where ever you like


in general I am in favor of more shorter namespaces


shorter in file length, not in namespace name length


and what about function names? it’s called “timestamp”, but it’s not pure as it gets data from the sysclock.. i read somewhere (maybe stuart sierra) that this kind of fn should have a verb… like “get-timestamp” or “create-timestamp”..


is that common sense around?


Huh; I’m getting:

Exception in thread "main" java.lang.AssertionError: The names in #{__hash __meta __hasheq __extmap} cannot be used as field names for types or records., compiling:(datascript/db.cljc:369:1)
… but only in the latest -alpha12.

Alex Miller (Clojure team)01:09:27

There was a change in defrecord hash caching in alpha12

Alex Miller (Clojure team)01:09:51

Would love to see something that can repro

Alex Miller (Clojure team)01:09:26

Unless data script is using hasheq or hash already


it’s the “obvious” thing: it defines a record with hash


it uses hash in two places: one is a defrecord, the other is a deftype


I think the only problem is with the defrecord

Alex Miller (Clojure team)01:09:23

Records use prefix for special fields

Alex Miller (Clojure team)01:09:08

deftype won't matter but they shouldn't do that either

Alex Miller (Clojure team)01:09:04

Feel free to file something or I will do so tomorrow


that record implements IHashEq; I’m not sure if they should just … rename that? I mean, they do really want to make it hashable


I’m filing something against datomic; do you mean on the Clojure JIRA?


so it seems like they’d want to do something different depending on the Clojure version


Yup, this exception is also blocking us on upgrading to alpha12


I’m trying my first pipeline-blocking thing with core.async … but its doing things one-by-one if I collect the result … e.g.

(let [foo (a/<!! (a/into [] results))]


without the into I get the desired parallelism


Is there any chance of flatland/ordered getting into core? it seems to have a weird thing going on with maintenance (PRs get review comments, but then not merged indefinitely)


It probably doesn’t need an awful lot to be of a quality and stability suitable for core


I could see if you’re not really interested in more data structures though

Alex Miller (Clojure team)02:09:52

@lvh re the hash stuff, I would like to get more information on whether this practice is more widespread before making any decisions


makes sense 🙂


That’s what made me think of flatmap btw

Alex Miller (Clojure team)02:09:12

re ordered, I think it is used enough that it is a good candidate for a contrib


err, flatland/ordered


(it does not use whatever)

Alex Miller (Clojure team)02:09:54

I have only needed it rarely, but when you need it, you need it

Alex Miller (Clojure team)02:09:07

(I needed it last week :)

Alex Miller (Clojure team)02:09:42

the process for this is for the owner/maintainer to offer this code on clojure-dev. typically all contributors need have a CA and agree etc. I’m not looking to seek any of that effort out right now, but that is the process


@hueyp: the behavior of the pipeline functions can be rather complex, I forget what constraints pipeline-blocking, but my first guess would be your consumer is too slow so the pipeline is blocking on writing to out


Is memoize thread safe?


What happens if its a really slow operation, like 10 seconds, if a second call is made before the first call finished, does it execute the function a second time? And what happens to the cache?


depends what you mean by thread safe


the cache is a map in an atom, no effort is made to avoid duplicating work on other threads


memoize isn't something you want to use seriously, checkout the core.memoize library or the caches in guava


I'm actually using the core.memoize library


core.memoize is entirely different from from the clojure .core/memoize function


I guess I'm asking if threads would block, and the only the first thread would run the function, and when its done, all threads would get the cached value


In specific to core.memoize


if I recall, core.memoize uses delays to achieve that


well, to be more specific, core.memoize/ttl


Ok, I tested it, and it seems other threads do block


Clojure memoize does 2


hum, or I might be testing this wrong


ya, testing it wrong for sure


as I said, core.memoize uses delays (actually a custom implementation, not clojure.core/delay) to synchronize cache misses


Ok, now I tested it properly.


And you are 100% correct


memoize won't guarantee the function to run exactly once, but core.memoize will


Interesting tidbit though, if you add ^:once meta to the normal memoize, then it does only run once


Another odity is that it looks like println isn't thread safe either. Run it in a future in a big loop, and you won't have everything on one line. The str and the newline could be interspersed

Alex Miller (Clojure team)04:09:40

println is thread safe (there is no corruption or danger from this), it’s just writing pieces of the message to a shared stream. str first if you want to avoid this.


Well, its not corruption, but it seems like it does not guarantee that the message you pass it and the newline it adds itself will follow each other. If another println runs concurrently, its possible the msg of the first is written to out, followed by the msg of the second and then the newline of the first and then the newline of the second.


And there's not really anyway for me to str the newline to it.


But, I'm not sure, testing this out in my eclipse repl, maybe a bug with the out display of eclipse


Someone else could try it: (dotimes [x 100] (future (println "test")))

Alex Miller (Clojure team)05:09:23

yes, this is all the expected behavior of the output stream in both Java and Clojure


Hum, interesting. You're right then, if someone doesn't want that behavior, they can do (print (str "msg" "\n")) instead. I guess I would have expected the implementation of println itself to follow that pattern.


@alexmiller Actually, that's not the behaviour of System.out.println. So I'm tempted to call this one out as a Clojure bug

Alex Miller (Clojure team)05:09:50

this is working as intended

Alex Miller (Clojure team)05:09:48

Java’s println is not the same thing - it takes a single string whereas Clojure takes many stringable things


I guess. Can't really think why that behaviour would be desired. I'd use print for that. Feels to me like a println should guarantee that my line actually shows up on one line


It's good to know though, I had not realized at all it behaved this way before.


is a pretty good description of what’s going on


Looking at it for me this is a typical language surprise. From a distant far I would expect it to not mess up the new lines. And even looking at why this is, from an implementation point of view, I cannot think of a reason for the implementation being that way.


@sveri (apply prn (iterate inc 0)) works with the current impl - it would not print anything and blow all your memory if the string was realised before printing


Does anyone know the standard for naming boolean values in Clojure? It’s clear that predicate functions should end in a question mark, but what about booleans? For example, if you wanted to name a boolean that records if a transaction completed okay, would you call it is-tx-okay,`tx-okay`, tx-okay?, or something else?


@mccraigmccraig Ok, that makes sense


realization of lazy seqs


Has anyone tried using the Scala GraphQL library Sangria in Clojure?

Alex Miller (Clojure team)12:09:37

@james any of those is probably fine although I'd prefer in reverse order you listed


@alexmiller Thanks Alex, that’s good to know.

Alex Miller (Clojure team)15:09:10

(require ‘clojure.inspector)


Hi, anyone tried Selmer template localization? I can use Tower to lookup strings passed into the template but seems weird to pass every text that needs to be translated. I can't find an example doing that. Do you know of any?


@katox the TL;DR is "it depends" — we use Selmer for localized emails at World Singles and we send over half a million a day (we have used it up to nearly 3M / day). We generally have the whole template localized and only inject data, but there a few places where we still need to inject localized strings (usually status or financial information).


So we have resources/emails/<locale>/<template>.html as the general pattern with the translated text, and then we have a custom (Selmer) tag for injecting a localized key (usually as part of a conditional tag pair), and the rest we localize in the setup code and provide in the data map.


(we have our own localization system, with a full admin console, with security, to support a team of translators — we have about 14 languages live on 90+ websites, including RTL such as Arabic)


@seancorfield custom tag seems like a way how to do it (for me). I only have a few places where to put short tags, the rest is html boilerplate. I don't see a way how to get request in custom tag though. Do you bind a dynamic var in middleware for it?


Here’s a small example from one of our templates:

{% if not|empty? %}
                      <td colspan="4" align="center">
                        <font face="Arial, Helvetica, sans-serif" style="font-size:16px;">
                          <b>{% resource world.new_members %}</b>
… {% endif %}


and then the resource tag is added as a function:

(selmer/add-tag! :resource
                     (fn [[key & args] context-map]
                       (let [filter? (#{"capitalize" "sentence-case"} (first args))
                             deref? (= "deref" (first args))
                             key (if deref?
                                   (get-in context-map (map keyword (str/split key #"\.")))
                             transform (when filter?
                                         (resolve (symbol (str "worldsingles.mail.template/" filter?))))
                             args    (if (or filter? deref?) (rest args) args)]
                         (cond-> (if (seq args)
                                   (i18n/format-string (i18n/get-resource key (:locale context-map))
                                   (i18n/get-resource key (:locale context-map)))
                                 filter? transform))))


The context-map includes the locale to use.


where do you put it into the context? in a custom render page fn?


We can say {% resource deref %} to pull data out of the context-map — that is the data struct passed into the Selmer render function — it is also passed to each tag.


So we say something like

(selmer/render html {:site site :user user :locale locale
                       :locale-language (i18n/get-language locale)
                       :locale-country (i18n/get-country locale)
                       :now (date/today)
                       :data annotated-data})


and that hash map is the "context" that the tag receives too.


No dynamic binding needed.


I see, so you get it directly from a request.


and you pass it into the render fn


Is partial the best way to pass around "object methods"? Suppose I need to register an event handler function, and I have a defrecord implementing defprotocol.


@seancorfield what do you use for resource lookup? is you code based on this? or just plain java i18n stuff?


@seancorfield I have a working custom tag now, thanks! I'll have to think about Tower/j18n choice a bit more.


@seancorfield One thing I don't like on clj i18n stuff is that it looks like a code in Cursive (as opposed to non-localized plain strings - no hiding/in-place-substitution). Did you manage to solve this in your custom solution?


@katox we’ve had to develop our own database-backed solution because we have pretty complex requirements about cascading lookups and management / access permissions for our translation team etc.


We also have multiple "types" of i18n content: some is short strings, which is a more traditional i18n "solution", but we also have full, dynamic "page" content that has different editing (and cascading lookup) constraints, as well as metadata (which is tied to "events" in the application as well as being tied to both locales and site-specific data, so the cascading lookup is complex).


(FWIW, we started with standard Java i18n resource files but very quickly outgrew that)


@mccraigmccraig That use case could be handles with a different implementation of prn for when the type of the argument is a LazySeq


@mccraigmccraig All in all too, that's the worst thing to ever want to print. And I suspect its the least used use-case of prn ever. So for all other uses, not knowing about the non atomicity of prn could lead to actual real errors in prod code.


it's a dumb example it's true @didibus but (->> (readmanylines) (map things) (apply prn)) is quite reasonable


@mccraigmccraig Its reasonable, but you would also never really do (->> (readsomanylinesIcan'tevenholdtheminmemory) (map things) (apply prn))


@mccraigmccraig Also, concatenation is not the only way to handle the race condition. You just need a synchronization strategy. Maybe prn should take a lock on the stream until it is done.


@mccraigmccraig Actually, that example isn't reasonable. (apply prn x y z) does not put a newline between x, y and z, only at the end of it. So I'm not sure why you would read a gigantic amount of line and print them all on the same line.


ha, true... bad example then


What is the more genteel way to do (if key (get map key) map)?


fwiw, that seems like a bit of weird thing to say


(cond-> map key (get key)) is one way


you can give get a default value, if I remember correctly


if you don’t have a second branch for that if


yeah, but the default is for when the map doesn't contain the key, not for if the key is falsy


i think the original is probably the clearest way to state that intent


if there’s not a second branch in the if, a when is slightly better


the OP wants to return map if the key is falsy


(in a sense there's always a second branch, it's just nil sometimes. I agree when is better for those cases)


when would a key be falsy?


when its nil


or false 😛


if you know that a) falsy values are never keys in your map and b) you never provide a non-falsy key that is not in your map, then (get map key map) would work fine


I like (cond-> map key (get key)), didn't guessed that cond-> would return map...


While you can use (get map key map), if it’s a Clojure map then you could make it (map key map) because, why not confuse everyone who wants to read it?


haha, that too. naming a map map is pretty confusing


I think it’s awesome that the map is called map 😄


but honestly, I think (if key (get m key) m) is super clear and adequately concise


My lein test runs are getting quite slow. I'd like to profile it but the instructions I see on using, say jvisualvm discuss attaching to a running process. lein test starts up a jvm, runs the tests, then shuts down, right? Suggestions on how to approach this?


@grzm: probably simplest to just run the tests from a repl instead, then you'll have a stable process


@bfabry makes sense 🙂


Has anyone tried using the Scala GraphQL library Sangria in Clojure?


is there any way to use the leiningen test selectors at the repl?