This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-09-08
Channels
- # admin-announcements (3)
- # bangalore-clj (3)
- # beginners (21)
- # boot (32)
- # cider (14)
- # clara (2)
- # cljs-dev (19)
- # cljsjs (8)
- # cljsrn (1)
- # clojars (1)
- # clojure (147)
- # clojure-australia (6)
- # clojure-brasil (8)
- # clojure-canada (2)
- # clojure-gamedev (3)
- # clojure-greece (2)
- # clojure-hk (5)
- # clojure-italy (10)
- # clojure-japan (8)
- # clojure-korea (4)
- # clojure-russia (25)
- # clojure-sg (2)
- # clojure-spec (36)
- # clojure-uk (34)
- # clojurescript (88)
- # cursive (157)
- # datomic (6)
- # devcards (1)
- # dirac (1)
- # editors-rus (3)
- # events (2)
- # funcool (1)
- # hoplon (57)
- # jobs (9)
- # lein-figwheel (2)
- # luminus (1)
- # om (156)
- # onyx (93)
- # perun (11)
- # rdf (65)
- # re-frame (36)
- # reagent (17)
- # ring-swagger (3)
- # specter (19)
- # untangled (33)
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)
#_etc)
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?
I would recommend from the very beginning trying to be more specific and break things out in to distinct namespaces
once you have a few thousand lines in a utils namespace, it can become hard to muster the effort to break it up
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”..
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.There was a change in defrecord hash caching in alpha12
Would love to see something that can repro
Unless data script is using hasheq or hash already
Well, that's bad
They shouldn't do that
Records use prefix for special fields
deftype won't matter but they shouldn't do that either
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 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))]
)
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)
@lvh re the hash stuff, I would like to get more information on whether this practice is more widespread before making any decisions
re ordered, I think it is used enough that it is a good candidate for a contrib
I have only needed it rarely, but when you need it, you need it
(I needed it last week :)
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
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?
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 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
as I said, core.memoize uses delays (actually a custom implementation, not clojure.core/delay) to synchronize cache misses
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
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.
But, I'm not sure, testing this out in my eclipse repl, maybe a bug with the out display of eclipse
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
this is working as intended
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
@didibus http://yellerapp.com/posts/2014-12-11-14-race-condition-in-clojure-println.html
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
Has anyone tried using the Scala GraphQL library Sangria in Clojure?
@james any of those is probably fine although I'd prefer in reverse order you listed
@alexmiller Thanks Alex, that’s good to know.
(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 data.world-matches|empty? %}
<tr>
<td colspan="4" align="center">
<font face="Arial, Helvetica, sans-serif" style="font-size:16px;">
<b>{% resource world.new_members %}</b>
</font>
</td>
</tr>
… {% 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 #"\.")))
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))
args)
(i18n/get-resource key (:locale context-map)))
filter? transform))))
The context-map
includes the locale to use.
We can say {% resource deref foo.bar %}
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.
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? https://bitbucket.org/kotarak/j18n 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
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
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)
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
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
Has anyone tried using the Scala GraphQL library Sangria in Clojure?