#clojure log - Jul 02 2014

The Joy of Clojure
Main Clojure site
Google Group
List of all logged dates

0:18 nex: Im trying to infer the type of a form using clojure.tools.analyzer.jvm, with (ana.jvm/analyze '(str 1 2)) i can get the :tag which tells its a string. with '(+ 1) or '(map identity []) I just get java.lang.Object, I think because those fns can return different types, depending on the args. Is there a way to accomplish what I want? so far i thought to keep sets of fns which return certain "types" such as :number or :vector and compare the first element of the f

0:18 orm to those sets

0:20 ambrosebs: nex: tools.analyzer only collects enough information to inform the emitter of reflection stuff.

0:21 nex: your idea of annotating a set of known return types is a good one.

0:23 nex: ambrosebs: i wouldnt mind the effort, but it would be a lot better to be able to do this on arbitrary fns.

0:24 ambrosebs: nex: you'd need to write a type inferencer then, probably based on success typing like dialyzer

0:25 so, not trivial

0:25 you could kinda use core.typed, but gradual typing is much more annoying to do arbitrary analysis with.

0:25 success typing is forgiving.

0:28 also it depends what you're actually using this for?

0:28 nex: ambrosebs: i heard from a friend that in haskell you could use this kind of procedure to help with debugging, cause you can infer the outputs class and compare with the possible input types of fathers forms

0:29 ambrosebs: sure, but we don't know how to do type checking on arbitrary clojure code yet.

0:29 core.typed is the best bet so far.

0:29 that's best described as a subset of clojure

0:30 fitzoh: Anyone thoughts on how to write this function? Trying to do some atom manipulation (f :key2 :val {:root [{:a 1}{:a 2}] } -> {:root [{:a 1 :key2 :val}{:a 2 :key2 :val}]}

0:31 nex: ambrosebs: im working on fractal.ai, think of it as googles text input but you write a clojure expression, additionaly im trying to do something like fractal.ai/some-fn where the webui could generate form fields according to the types of the input, for example if the fn recieved a date object, the ui would generate a date form field

0:33 ambrosebs: could you point me out in a direction, with typed clojure? cause ive looked into it but not deeply at all. i will also work a little on the naive approach of tagging fns manually, but id like to start brewing something more profound

0:34 icma: anyone know why I can't require clojure.contrib.trace? https://gist.github.com/anonymous/38f34eddc3fc0430aa59

0:35 puredanger: clojure.contrib.trace is part of the old "monolithic contrib" used prior to Clojure 1.3

0:36 http://dev.clojure.org/display/community/Where+Did+Clojure.Contrib+Go

0:36 the trace stuff is now in https://github.com/clojure/tools.trace/ which is a library you will need to include in your project

0:37 icma: puredanger: excellent. thanks.

0:38 ambrosebs: nex: you can pass forms to check-form-info to type check them http://clojure.github.io/core.typed/#clojure.core.typed/check-form-info

0:39 rufoa: fitzoh: (defn f [k v m] (update-in m [:root] (fn [ms] (map #(assoc % k v) ms))))

0:39 ambrosebs: icma: where did you hear about contrib.trace btw?

0:40 fitzoh: rufoa: awesome, ty

0:40 rufoa: np

0:41 icma: ambrosebs: not sure anymore. lost the page. I was just searching for "clojure deftrace" and "deftrace".

0:42 ambrosebs: icma: ok

0:44 mange: zanes: I'm looking at that backoff stuff again, because I wanted to write a version using ribol, and I'm not sure yours works how I would expect it to. It seems to be truncating the sequence on an exception, rather than delaying and retrying?

1:14 amalloy: very impressive, bbloom

1:26 yedi: what are some things you must know if you;re going to interview for clojure position

1:34 TEttinger: yedi: what does this type hint mean: ^"[[Z"

1:34 yedi: O_O

1:34 TEttinger: hehe

1:35 it's a 2d boolean array

1:35 puredanger: array of array of boolean

1:35 TEttinger: you won't need to know that unless you work at prismatic...

1:35 puredanger: [ = array, Z = boolean

1:37 TEttinger: yedi, how would you "partly flatten" a nested vector; where flatten removes all nesting, here you want to remove the outermost layer of nesting and only flatten that.

1:39 (___ __ _ [[1 2][3 4][[5][6]]])

1:39 fill in some blanks

1:40 it should return [1 2 3 4 [5] [6]]

1:42 razum2um: when i start a new clj new should i prefer dashed-name or underscore_name ?

1:42 i mean lib name

1:43 ah, I see only dashes here http://crossclj.info/

1:45 yedi: TEttinger: I feel like I can do it iteratively but filling in those blanks is a different story

1:45 oh wait

1:45 reduce into []

1:45 TEttinger: yep!

1:45 nice

1:45 that's a good trick

1:46 amalloy: well, apply concat is more typical than reduce into [] there

1:46 TEttinger: well true

1:46 amalloy: depends what data type you want back

1:46 TEttinger: I mostly used it for maps

1:46 so I never really got used to apply concat

1:47 ivan: https://www.refheap.com/9d8f8ea4d4d4f8bdbed6c817c/raw nrepl woes

1:48 TEttinger: ivan, it is failing to eval /1, then it evals 2 on the next line

1:48 ivan: (I'm fixing a few things in REPL-y's standalone REPL and looking a lot at what nREPL and clojure.main do)

1:48 TEttinger: so it isn't returning 24, it's 2 then 4 and the real value is 4

1:49 ivan: yeah, I know that much :)

1:49 TEttinger: maybe just stick a newline after that stuff

2:18 akurilin: Random question: in ring apps, do you guys generally tend to wrap your korma calls and perhaps store them all in a model namespace, say if you want to call them from a handler/controller? Or do you just directly invoke korma from the controller?

2:52 ttasterisco: akurilin: I structure my projects roughly following Amit's DDD http://www.infoq.com/presentations/DDD-Clojure

3:00 akurilin: ttasterisco: I'll check that video out, seems relevant :)

3:03 clgv: ttasterisco: is that only a "conceptual" talk. the slides seemed very spartanic when browsing through

3:03 ?

3:06 ttasterisco: clgv: it's mostly conceptual but he goes into the practicalities close to the end

3:07 I felt that his presentation at the SF Clojure meetup last year was more direct

3:12 magopian: ,(Character/isWhitespace "a")

3:12 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: No matching method found: isWhitespace>

3:12 amalloy: magopian: \a

3:12 magopian: ?

3:13 ttasterisco: character

3:13 not string

3:13 magopian: ohhh

3:13 it's my python background ;) (no difference between a char and a one-char string ;)

3:13 thanks

3:16 ,(every? :nothing nil)

3:16 clojurebot: true

3:16 magopian: ,(every? :nothing "")

3:16 clojurebot: true

3:17 magopian: (getting through the "programming clojure" book, and I first thought the very first example comparing java to clojure was unfair because the java version was also working for null/empty string)

3:17 (but seems that "every?" returns true for those cases, so it works the same... weird though, that every? returns true for nil/empty)

3:17 ,(some? :nothing "")

3:17 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (2) passed to: core/some?>

3:18 magopian: ,(some? :nothing nil)

3:18 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (2) passed to: core/some?>

3:18 magopian: ,(not-any? :nothing nil)

3:18 clojurebot: true

3:19 amalloy: magopian: every object in the empty collection is equal to five, and equal to six, and...

3:19 feel free to find a counterexample

3:21 clgv: mange: yeah thats the mathematical definition of the all quantifier

3:22 magopian: ^^

3:22 magopian: yup ;)

3:22 clgv: the exist quantifier alas `some` returns nil meaning false ;)

3:23 for empty collections

3:27 magopian: clgv: that's what i'm looking at atm ;)

3:36 are the books on it-ebooks really free... or pirated?

3:37 because i can see a lot of cloure books on there, downloadable for free

3:37 clojure*

3:41 ambrosebs: magopian: what's on there?

3:43 magopian: ambrosebs: http://it-ebooks.info/tag/clojure/

3:43 ambrosebs: I don't particularly want to click

3:45 magopian: ambrosebs: i'm sorry, i don't understand your question

3:45 there's a list of most (all?) of the clojure books I heard of

3:45 freely downloadable

3:45 but... dunno, the site doesn't look legit, so i'm wondering if those are "stolen"

3:46 i've seen at least some of those ebooks sold in various places, so having them freely downloadable here feels strange

3:48 ambrosebs: right, must be pirated.

3:50 magopian: ambrosebs: ah, thanks

3:51 i'll buy/download the ebooks from the publisher's sites

3:52 ambrosebs: which book would you recommend ?

3:53 ambrosebs: magopian: I like Clojure Programming or Joy of Clojure

3:54 magopian: thanks again

3:57 clgv: magopian: yeah those are not legally available without payment

3:58 magopian: the decision between "Clojure Programming" and "Programming Clojure (2nd edition)" depends on what style of book you like

4:01 magopian: clgv: ah... can you tell me a bit more?

4:04 clgv: magopian: hard to describe but I try like that: In my opinion "Clojure Programming" is more narrative whereas "Programming Clojure" is more technical. a student (computer science) of mine preferred "Programming Clojure" since it got him started faster with less ceremony

4:05 magopian: i see

4:05 clgv: so in fact reading both probably has a complementary effect. I'd read the available sample chapters to decide which style I like most

4:39 magopian: clgv: that's what i'm doing right now ;)

4:58 clgv: i went with programming clojure, bought on pragprog, thanks for the advices!

4:59 clgv: magopian: glad to help :)

5:53 sveri: Hi, did anyone here do authentication with websockets or sente and http-kit? Are there any best practices or examples available?

5:55 ergh: does clojure have a neat way to say "give me a vector of this value n times"?

5:58 oh, "(take 10 (repeat 1)" works. i knew there was something :p

5:58 Bronsa: .(repeat 10 1)

5:59 ,(repeat 10 1)

5:59 clojurebot: (1 1 1 1 1 ...)

6:01 ergh: Bronsa: oh that's better, thanks

7:25 rurumate: is there an easy way to call a private method of a java object?

7:25 stain_: I believe you may have to introspect and make the method public

7:26 rurumate: there used to be method-call in contrib.reflect or something but I can't find it in clojure.refect

7:29 clgv: hmm the seesaw :popup property seems broken. at least the examples from the code base wont work ... :(

7:39 damn, the copied example works. but not the analogue one in the codebase...

7:49 perplexa: hai

7:53 what's considered the best practice to handle configurations in clojure?

7:55 cmdrdats1: perplexa: 'best practise' is pretty subjective - but I would recommend http://12factor.net/config - regardless of language

7:56 perplexa: yeah but that's really meta :P

7:56 cmdrdats1: not really - just use environment variables

7:56 perplexa: i won't.

7:56 nobody wants a complete config in environment vars

7:57 cmdrdats1: ok - hence subjective :)

7:57 perplexa: that works when you want to override single parameters

7:57 but having like 50 params completely in the environment violates the whole point of having a config

7:58 i'm just not sure whether i should go for yaml or propertiy files

7:58 cmdrdats1: environments can be entirely localised to process though?

7:58 perplexa: and how to properly access the params from within clojure

7:58 Janiczek: perplexa: EDN instead of yaml maybe?

8:00 perplexa: that looks good :)

8:01 razum2um1: perplexa: look at https://github.com/weavejester/environ it uses EDN-like .lein-env file as config

8:01 but also accepts ENV

8:05 sveri: Hi, did anyone here do authentication with websockets or sente and http-kit? Are there any best practices or examples available?

8:06 perplexa: razum2um1: thx

8:51 hm. i have my config stored in my main namespace with (def config nil), and in my main method i run (intern *ns* 'config (props/load-props property-file)), this seems to work fine on the repl but when i run the jar, it's always nil when the config var is accessed from within other functions.

8:52 any ideas why that is, or how i would properly do what i'm trying to do?

8:58 justin_smith: perplexa: how are you accessing the property-file? as a resource or as a file?

8:58 in a jar, you should probably use clojure.java.io/resource

8:59 jcromartie: perplexa: why don't you use alter-var-root ?

8:59 justin_smith: or, at least, (def config) rather than (def config nil)

9:00 perplexa: java.io.reader ;p

9:00 justin_smith: perplexa: a reader of what though?

9:00 perplexa: jcromartie: cos i have no idea what you are telling me :D

9:00 justin_smith: a resource or a file or a URI?

9:00 perplexa: need to check

9:00 jcromartie: perplexa: BTW *ns* is bound to the namespace of the caller

9:00 ,(do (ns foo) (defn bar [] (println *ns*)))

9:00 clojurebot: #'foo/bar

9:01 perplexa: justin_smith: a file. that stuff works. it's just about accessing the result form everywhere without requiring the filename in all of these places

9:01 jcromartie: ,(ns user)

9:01 clojurebot: nil

9:01 jcromartie: ,(foo/bar)

9:01 clojurebot: #<Namespace sandbox>\n

9:01 perplexa: jcromartie: yeah i expected that. so when i run the jar, it might just intern the var in the wrong place

9:01 justin_smith: perplexa: oh, so you are running the uberjar in a place where that file is guaranteed to exist?

9:01 perplexa: justin_smith: yep

9:01 reading works, just overwriting my config def doesn't

9:02 justin_smith: OK, yeah, then it is likely some AOT binding of the var value

9:02 jcromartie: perplexa: instead, do this: (alter-var-root #'my.main.ns/config (constantly (load-config …)))

9:02 justin_smith: yeah, this is what alter-var-root is for

9:02 perplexa: jcromartie: thanks!

9:02 (inc jcromartie)

9:02 lazybot: ⇒ 7

9:02 jcromartie: I'm currently grappling with config woes

9:03 we used to load it all from a file

9:03 but then devops said we couldn't upload config files willy-nilly

9:03 so now we read it all in from env vars

9:03 perplexa: eeww :x

9:03 jcromartie: well it makes sense

9:04 perplexa: one more thing

9:04 justin_smith: jcromartie: I find having some abstraction for binding config that both files or other config loading methods use in common is helpful

9:04 perplexa: why (constantly)?

9:04 justin_smith: this also makes testing easier

9:04 jcromartie: yeah

9:04 justin_smith: perplexa: because alter-var-root acts on the previous value

9:04 jcromartie: we're using environ

9:04 perplexa: justin_smith: wat

9:04 jcromartie: and I have a config namespace and a defconfig macro that enables a config check

9:04 so in the config namespace we use (defconfig api-url :parser parse-url) etc.

9:05 justin_smith: ,(do (def x "hello") (alter-var-root x #(str % " world!")) x)

9:05 clojurebot: #<ClassCastException java.lang.ClassCastException: java.lang.String cannot be cast to clojure.lang.Var>

9:05 jcromartie: and then we can run (check-config) to assert that there are no missing config values

9:05 justin_smith: err

9:05 ,(do (def x "hello") (alter-var-root #'x #(str % " world!")) x)

9:05 clojurebot: "hello world!"

9:05 justin_smith: perplexa: that^

9:06 jcromartie: and (defconfig foo) looks for config named "foo" in several places, either a :foo key in a config map or a FOO environment variable, as per environ

9:07 perplexa: justin_smith: i still don't get it :)

9:07 ,(do (def x "hello") (alter-var-root #'x "replaced ;p") x)

9:07 clojurebot: #<ClassCastException java.lang.ClassCastException: java.lang.String cannot be cast to clojure.lang.IFn>

9:07 jcromartie: perplexa: alter-var-root takes a var (which are containers for values created by def/defn etc.) and a function which takes the var's current value and returns the new value that it should take

9:08 perplexa: ah

9:08 jcromartie: ,(def x)

9:08 clojurebot: #'sandbox/x

9:08 perplexa: the function part was the missing puzzle piece :)

9:08 jcromartie: ,x

9:08 clojurebot: "hello"

9:08 perplexa: thx

9:08 jcromartie: k

9:08 ,#'x

9:08 clojurebot: #'sandbox/x

9:08 jcromartie: ,(var x)

9:09 clojurebot: #'sandbox/x

9:09 jcromartie: ,(deref (var x))

9:09 clojurebot: "hello"

9:09 jcromartie: ,(deref (var sandbox/x))

9:09 clojurebot: "hello"

9:09 clgv: ,(-> "x" symbol resolve deref)

9:09 clojurebot: "hello"

9:12 perplexa: jcromartie: we're just migrating our aggregations from old perl+sql shizzle to cascalog ;x

9:12 jcromartie: awesome

9:13 perplexa: and i'm trying to build a rather flexible bootstrapping framework around that, so have it integrate easily with our other etl processes ;x

9:14 jcromartie: If I may suggest having: config values actually defined as vars in a namespace is really useful

9:14 err, that

9:14 that colon was supposed to go after "suggest"

9:15 perplexa: i seem to miss the point

9:15 jcromartie: but anyway, it's better to get a load-time "unable to resolve symbol" error than to have a mysterious nil at runtime

9:21 Glenjawork: i tend to have an (env!) function, which throws when the key doesn't exist

9:22 and tells me what environment variable it wanted

9:36 perplexa: i hate it when code runs in the repl but not as jar :|

10:05 clgv: perplexa: that's a clear sign that you did something wrong ;)

10:05 perplexa: Exception in thread "main" java.lang.RuntimeException: Invalid token: /user/camus/output

10:05 :|

10:05 yeah clgv :P

10:06 clgv: well probably not a string?

10:06 perplexa: well

10:06 (defn mk-src [in-path schema-path fields]

10:06 (println "fufufu" (str (:aggregations.input.base (cached-props)))))

10:06 should be a str ;p

10:06 and works fine in repl

10:07 clgv: no the error messages sounds as if you inserted the path literally and not as a string

10:07 perplexa: the path is (:aggregations.input.base (cached-props))

10:07 and it's a symbol

10:07 but (str ...) works locally at least ;/

10:11 augustl: perplexa: (cached-props) - that's not an argument to that function? :)

10:12 perplexa: do you get the error on the call to str, or the call to println, or something else?

10:13 seems like that error would probably come from whatever (cached-props) is doing, can't imagine a (:my-key thing) causes an error with /user/camus/output in it :)

10:13 g2g

10:14 clgv: as I said I get the error when I just enter that path into the REPL => RuntimeException Invalid token: /user/camus/output

10:14 perplexa: augustl: yeah it's the argument

10:14 clgv: so that path is actually read somewhere by clojures read where it probably should be specified as string

10:14 perplexa: ^^

10:15 ,/user/camus/output

10:15 clojurebot: #<RuntimeException java.lang.RuntimeException: Invalid token: /user/camus/output>

10:15 clgv: ,"/user/camus/output"

10:15 clojurebot: "/user/camus/output"

10:15 clgv: ^^

10:15 perplexa: i know.

10:16 clgv: well then fix it by making it a string or deleting the occurence ;)

10:17 perplexa: it's not that easy

10:17 i'm always converting it to a string

10:17 when passing it to other calls

10:17 i just don't get why it works in repl but not when i run the jar

10:18 clgv: ,(type (read-string "/user/camus/output"))

10:18 clojurebot: #<RuntimeException java.lang.RuntimeException: Invalid token: /user/camus/output>

10:19 clgv: ,(type (read-string "/user"))

10:19 clojurebot: #<RuntimeException java.lang.RuntimeException: Invalid token: /user>

10:19 clgv: ,(type (read-string "user"))

10:19 clojurebot: clojure.lang.Symbol

10:20 clgv: ah right it is not even a legal symbol, so in this phase the reader fails

10:20 perplexa: wtf

10:20 yeah locally i use a different config.. which does start with hdfs://

10:21 clgv: you should put up a minimal gist to show what you are doing. although I think you just need to specify any paths as strings and thats it

10:21 perplexa: ,(type (read-string "hdfs:///user/camus/output"))

10:21 clojurebot: clojure.lang.Symbol

10:21 perplexa: :|

10:21 clgv: there is no meaningful reason why that should be specified as symbol

10:23 perplexa: clgv: hm yeah. i'm a complete newb and i just use the function from the reply there: http://stackoverflow.com/questions/7777882/loading-configuration-file-in-clojure-as-data-structure

10:25 puredanger: cglv: looks like a symbol to the reader :)

10:25 ndp: perplexa: Could it be that you're missing quotes in the string itself? ex: (read-string "\"foo\"")

10:25 ,(type (read-string "\"foo\""))

10:25 clojurebot: java.lang.String

10:25 clgv: puredanger: what do you mean? (I was just investigating whether the read fails on trying to read it as symbol)

10:26 perplexa: ndp: see the link that i just pasted :)

10:26 i should probably just switch to edn and have proper values

10:26 clgv: perplexa: if that really happens on Properties/load you should see it in the stacktrace

10:27 perplexa: clgv: yes it does

10:27 at properties$load_props.invoke(properties.clj:8)

10:27 clgv: perplexa: ah no I spotted the read-string in the code

10:27 just surround the path in the conifg with ""

10:27 as I told you all the time :P

10:28 perplexa: yeah but it shouldn't be like that :|

10:28 ndp: I notice that in the config file from that link you read a property which is a list of strings but no properties which are just strings

10:28 So, let's try this:

10:28 perplexa: like, that's not really how a property file should work :)

10:28 clgv: perplexa: well then don't use read-string there

10:28 ndp: ,(type (read-string "[\"foo\", \"bar\"]"))

10:28 clojurebot: clojure.lang.PersistentVector

10:29 clgv: perplexa: perplexa: do you really want to specify clojure data structures in the property file?

10:29 perplexa: clgv: nope, but scalars, like doubles, strings, ints. that would be good.

10:29 clgv: perplexa: that would not be really how a property file should work as well ;)

10:29 perplexa: i'm just gonna drop the entire approach and use edn as suggested earlier, now that i know there's a definitive problem with the current solution

10:30 clgv: perplexa: then just skip the read-string for non-numeric read texts

10:30 gfredericks: is there a library somewhere for combining several defn'd functions into a single -main that dispatches on the first arg?

10:30 clgv: perplexa: you will need to wrap the path in "" in edn as well :P

10:30 gfredericks: I've got an ad hoc one in my latest project and might make it a lib if it makes sense

10:31 ndp: You're going to have to quote the path whether you use EDN or not

10:31 clgv: gfredericks: a comp-main macro?

10:31 perplexa: clgv: yeah but it's a different format in general :) a property file shouldn't break when you put paths without quotes in them.

10:31 i'm fine with quotes in edn ;p

10:32 ndp: The property file didn't break, your postprocessing did =)

10:32 clgv: perplexa: well you are not reading it as property file because of your read-string usage, that the reason

10:32 ndp: The other option is to wrap your read-string in a try-catch and ignore the exception

10:32 perplexa: clgv: yep

10:33 or just drop read-string completely and replace it with something that returns proper types based on regexes :)

10:33 gfredericks: clgv: doesn't have to be a macro it could be var-based

10:33 clgv: my current version just looks in the current namespace for vars with :command metadata

10:33 clgv: gfredericks: oh are you building a complete -main with tools.cli that way?

10:34 gfredericks: umms

10:34 hadn't decided the scope yet

10:34 handling the subsequent args is complicated :(

10:34 clgv: that would indeed be an awesome shortcut for default use cases ;)

10:35 gfredericks: if not position you mean?

10:35 *positional

10:35 gfredericks: yeah

10:35 it could have a hook for providing a function from [String] -> [Object]

10:35 which would let you do arbitrary things

10:35 like hook in tools.cli

10:35 clgv: just make them named as tools.cli offers you

10:36 gfredericks: but the main point is to let you have different tasks spread around different defns

10:37 the current approach is you put ^:command on the defn and the main bit finds it that way

10:37 clgv: lein run -- awesome-calc 42 23 => calling (awesome-calc 42 239 ?

10:37 gfredericks: (awesome-calc "42" "239")

10:37 clgv: ah right ;) could be with conversion if you parse the arg meta

10:38 gfredericks: yeah don't know how far to take it

10:41 yeoj___: if i return a jdbc result set with (query "select ..") ... how can i call the java method .ResultSetMetadata() on it? I'm confused on java interop (and if i even need to use it...)

10:44 clgv: gfredericks: well I'd add conversion and stop then. that way you dont need to bother with a command line interface at all to get a runnable (uber-)jar

10:44 gfredericks: that would be the main selling point, right?

10:45 gfredericks: what does a generic conversion interface look like?

10:45 the metedata has a symbol to lookup that resolves to a function to do the conversion?

10:46 clgv: I normally end up creating a dispatch map for my main, so that's what's getting replaced mostly

10:47 clgv: gfredericks: keyword for default builtin-case cases (:string, :long, :double ...) function for custom conversion

10:48 ifn? vs fn?

10:48 or keyword? vs fn? ;)

10:50 gfredericks: there should be a term for when there's an edge case overlap between two sets of a sort that isn't likely to be a problem but still drives people like me crazy

10:50 like when the keyword is also an IFn in this case

10:51 Glenjamin: is this the whole "should strings be iterable" thing?

10:51 clgv: yeah the distinction whether you want to support IFn or Fn is sometimes not trivial

10:53 yeoj___: afair clojure.jdbc/query returns a clojure sequence, hence you cant call a resultset method on it

10:53 yeoj___: at least not on the returned result. maybe you can use one of the hooks to extract the desired data

10:54 gfredericks: I wonder if it'd be weird if java.jdbc put the result set in the metadata of the return value

10:54 yeoj___: clgv: ok... i'm looking through the jdbc.clj code now to see if i can figure anything out... it's not clear exactly how query coerces a resultset into ...

10:54 clgv: gfredericks: I think there are hooks to access it

10:54 Glenjamin: you can drop down a level in the api and get the resultset

10:54 one sec

10:55 http://clojure.github.io/java.jdbc/#clojure.java.jdbc/db-query-with-resultset

10:55 query just uses db-query-with-resultset and runs the resultset through result-set-seq

10:56 yeoj___: Glenjamin: ah, cool thanks.

11:01 agarman: is there a way to examine the :pre & :post conditions on a fn?

11:02 something like get-validator for Var

11:03 ambrosebs: agarman: no

11:06 agarman: I couldn't find a way, but wanted to ask just in case there's something I missed

11:07 ambrosebs: agarman: there's nothing magic about :pre, it's just code. See clojure.core/fn

11:14 dave-7: Hi again, I'm having some trouble setting up secretary's routing using the goog.History object (http://squirrel.pl/blog/2014/03/14/clojurescript-routing-and-templating-with-secretary-and-enfocus/). It's probably some part of the closure library that I'm not understanding, but it seems like the dom is being overwritten whenever I eval the (doto ...) section (from the routing example in the link).

11:19 agarman: (inc ambrosebs)

11:19 lazybot: ⇒ 9

11:21 agarman: ambrosebs: didn't think of it as magic, but had looked in clojure.lang for where it was executed, skipping past (source fn)

11:22 ambrosebs: I just think validators are slightly more magic than pre :)

11:43 razum2um1: is there any way to use "-quote in a docstring?

11:48 clgv: ,(println "\"\"")

11:48 clojurebot: ""\n

11:48 clgv: ,"\"\""

11:48 clojurebot: "\"\""

11:48 rurumate: ,(fn ^{:doc "\"-quote" } foo [])

11:48 clojurebot: #<sandbox$eval71$foo__72 sandbox$eval71$foo__72@1a0fea4>

11:49 clgv: ,(defn f "\"bla\"" [x] (* x x))

11:49 clojurebot: #'sandbox/f

11:49 clgv: ,(doc f)

11:49 clojurebot: "([x]); \"bla\""

11:50 clgv: works on my repl

11:59 skinkitten: (1)

12:00 razum2um1: yep, escaping works, but wouldn't it be cool to have triple-quotes like python?

12:02 philandstuff: or reader macros :trollface:

12:05 clgv: of #ifdefs ?

12:05 * clgv roflmao

12:05 gfredericks: I was able to use reflection to add heredocs to the clojure reader in like 20 minutes

12:05 can't seem to find the code for it though

12:05 it's probably lost in refheap

12:06 clgv: gfredericks: refheap needs a random "did you know this gist?" functionality

12:06 then you could find it again by chance :P

12:07 or I guess registering an account there would work as well ;)

12:14 dbasch: gfredericks: do you remember more or less when that was?

12:15 site:refheap.com helps me find my stuff sometimes

12:17 gfredericks: yes.

12:18 Between 2014-02-25 and 2014-03-10

12:18 but I'm not 100% positive it's on refheap

12:24 ticking: sorenmacbeth: Nice work with flambo! :)

12:38 expez: https://www.refheap.com/87779 is there some clever construct I can use to get rid of all the nested ifs when dealing with the multiple arity constructors of bar?

12:38 rurumate: A go block will always wrap the return value in a channel. Will that channel remain open?

12:44 dbasch: expez: what does bar do and why can't it take nil arguments for x, y and z?

12:45 Glenjamin: expez: http://clojuredocs.org/clojure_core/clojure.core/defn#example_137

12:48 expez: dbasch: I didn't write bar, but it's a wrapper around a java constructor which comes in three flavors and doesn't accept null anywhere

12:52 dbasch: expez: why are you making foo a three-arity function instead of an argument list of variable lengths, or different arities?

12:52 expez: because it's being called with results from the db where x y and z can all by nil :(

12:52 I hate null values so much

12:54 dbasch: expez: so just OR your argument list with the default values and call bar with that

12:55 expez: Not sure why I didn't think of that, so obvious now. Thanks!

12:55 dbasch: e.g.

12:55 ,(map #(or %1 %2) [nil nil 5] [1 2 3])

12:55 clojurebot: (1 2 5)

12:55 dbasch: np

12:59 TimMc: Assuming none can be false

13:01 puredanger: fnil?

13:04 TimMc: ,((fnil (fn [a b c] [a b c]) 1 2 3) nil nil 5)

13:04 clojurebot: [1 2 5]

13:10 tuft: good morning clojuresphere

13:13 tspot: After 3 months of learning Clojure I'm ready to throw in the towel. Ch 9 of "Joy of Clojure" on namespaces and multimethods just seems incomprehensible :(.

13:13 cbp: tspot: you can try asking for help

13:13 tspot: I'm also finding too many things have multiple meanings eg. keywords as functions

13:15 TimMc: tspot: To be fair, I tend to avoid multimethods.

13:15 tspot: I was inspired by Rich Hickey's decomplecting but Cloure seems more complex than any language I've learned before.

13:15 TimMc: Try Scala. :-P

13:16 gfredericks: namespaces and multimethods is a weird pairing for a book chapter o_O

13:17 justin_smith: yeah, that is really odd

13:18 ambrosebs: keywords being functions isn't complex, in that sense. Possibly confusing and unintuitive.

13:18 justin_smith: tspot: keywords as functions is a syntax shortcut, you can just use get

13:18 aperiodic: tspot: "seems"? have you used it to implement anything outside of Joy of Clojure exercises? or are you trying to get through the whole book before starting anything?

13:18 mikerod: tspot: Be careful to interpret simple as easy and complex as difficult

13:19 tspot: There's so much qualifying and obscurity in Clojure such as :: prefixes and ' quoting that code doens't "speak" the way it does in other languages

13:19 justin_smith: tspot: well that's not complex, it's just different. mutability, on the other hand, is massively complex.

13:19 mikerod: tspot: And are you already familiar with functional-orientation in programming?

13:20 tbaldridge: tspot: you're really mentioning a lot of stuff that beginners don't need to use. I suggest learning from another text, and then picking up JoC after you understand the language a bit more

13:20 ndp: tspot: It really depends on which languages you're coming from. What's your background?

13:20 tspot: ndp: Ruby

13:20 ndp: Perl before that

13:20 tbaldridge: tspot: so talk to me about blocks vs lambdas vs procedures :-P

13:21 ndp: tspot: Ok, both of those are Algol-family languages; it'll take a little while before you fully internalize the characteristics of Lisps.

13:21 mikerod: Clojure takes huge steps to promote simplicity. This may involve moving away from what is easy / familiar.

13:21 tspot: tbaldridge: .each is as straightforward as it gets

13:21 tbaldridge: tspot: but in reality, Ruby is a OOP language, so it makes sense for everything to be an object. Clojure is a functional programming language, so it makes sense that most things would be functions

13:22 ,({:a 42} 42)

13:22 clojurebot: nil

13:22 tbaldridge: bleh

13:22 ,({:a 42} :a)

13:22 clojurebot: 42

13:22 ndp: tspot: I had a somewhat extended settling in time whne I first picked up Lisp after only having done C-like languages.

13:22 tbaldridge: ,(:a {:a 42})

13:22 clojurebot: 42

13:22 tspot: mikerod: I actually like the Lisp roots. It's just the contextual switching that throws me.

13:23 tbaldridge: tspot: and that just takes time (I came from C#/Python). You just have to start small and after awhile it'll come.

13:23 tspot: tbaldridge: I like the functional/immutable alternative to OO but Clojure has a LOT of syntax. Too much.

13:24 tbaldridge: tspot: but starting small is a good place to start, read a few chapters from a getting started in Clojure book (not JoC) and then go and write some stuff.

13:24 tspot: define syntax?

13:24 mikerod: tspot: I'm not seeing this "too much" syntax argument I guess

13:24 dbasch: tspot: it may seem that way because you're not used to it and it's all new, but it's really not that much compared to other languages

13:24 Glenjamin: JoC is possibly not a great intro do clojure book - i think it says that in chapter 2 actually

13:24 dbasch: tspot: have you tried the 4clojure exercises?

13:24 Glenjamin: or maybe it says not a great intro to programming, i forget

13:25 mikerod: I'd argue that Clojure, along with pretty much all popular Lisps, have the least "amount of syntax" when compared to other mainstream langs

13:25 dbasch: tspot: JoC can be overwhelming if you don't have some lisp and/or java background

13:25 mikerod: Clojure did add a bit more than traditional in other Lisps. This was done for the sake of simplicity in removing the overloading of the () construct.

13:25 tspot: Glenjamin: Yes, I'm also reading "Clojure in Action" for first steps. Much clearer but I'm only at the early chapters.

13:26 tbaldridge: (inc mikerod)

13:26 lazybot: ⇒ 1

13:26 Glenjamin: aphyr's blog series i think is excellent

13:26 mikerod: Rich Hickey has a good discussion of why he added a few more data literals.

13:26 tbaldridge: (let ((a 42) (b 433)) (+ a b)) is just gross

13:26 Glenjamin: but once you're beyond the basics, i think building something useful teaches you loads

13:26 mikerod: I can't recall the exact talk.

13:27 Glenjamin: the first thing i built was something i could have built in not-clojure, and if i built it now it'd be completely differently structured - but i really got the hang of the language while doing it

13:28 mdrogalis: mikerod: http://www.infoq.com/presentations/Simple-Made-Easy 25:13

13:28 atyz: Hey all... I've run into a weird problem with our production boxes. After a few hours of running the processor load will reach 100% and will trigger auto scaling. I have reason to believe that this is not because of load. Does anyone have any clues as to how I can figure out what this is?

13:28 tbaldridge: atyz: perhaps log the GC some and see if there is a connection?

13:29 tspot: It's not the data structure syntax that bothers me. More the @~ and :: stuff. Clojure seems cluttered with what I would call qualifiers and quoting seems to spill out well beyonds its use in macros. I have a hard time understanding its use in (ns ..... (:require and all its permutations

13:29 Glenjamin: ns is a mess

13:29 atyz: tbaldridge: thats a good idea, although I thoguht that would affect the memory more

13:30 Glenjamin: especially if you get the literals slightly wrong, the error messages are next-to useless

13:30 TimMc: atyz: Can you induce a thread dump?

13:30 Maybe you'll find something that is spawning threads.

13:31 atyz: TimMc: this is along the lines I was thinking. I am using futures to do some asynchronous processing. I'm under the impression that they will kill themselves on the completion of the job. Is this a correct assumption?

13:32 TimMc: They should, yeah. But I think those are on a pool of limited size.

13:32 mikerod: mdrogalis: Thanks :)

13:32 atyz: They are, 2 per core I believe

13:33 Do you think it could be that there are too many being spawned for the processor to keep up?

13:33 aperiodic: tspot: @~ is only needed in macros, which you almost never need to write. :: is not that common either: it's mainly used when you want to be sure to avoid conflicts in a map. quoting is only necessary in actual code when you want to use symbols without evaluating them which is extremely rare. at the repl, you do have to quote to use bare (require ...), but not when making a namespace with (ns ... (:require ...)).

13:34 tspot: i think you are trying to understand every possible language feature before actually writing something, which will make any language seem crazily complex and daunting to learn

13:34 TimMc: atyz: Dunno. But try running jstack PID if it's available.

13:34 atyz: What happens to the CPU if you take a machine out of the scaling group? (Can you do that?)

13:34 mikerod: Quoting is more of a Lisp thing than a Clojure-specific. I don't see why it would "leak out far beyond macros"

13:35 The syntax-quote ` ~@ stuff is just shorthand for quoting things.

13:35 And all this just relates back to having homoiconicity.

13:35 I think aperiodic is right that this shouldn't be the focus when getting started learning and using the language.

13:36 The ns macro is a bit whacky though, I'd agree. Just don't typo there. :)

13:37 ambrosebs: clojure is not a good language to make mistakes in.

13:37 TimMc: ,`[0 ~@(range 1 5) 0] ;; aperiodic, it's useful outside of macros as well

13:37 clojurebot: [0 1 2 3 4 ...]

13:38 aperiodic: oh, cool

13:39 atyz: TimMc sorry for the delay. I think If I take it out of the scaling group (and lb) it will continue to spin at 100%

13:39 mikerod: TimMc: do you find yourself often doing things like that?

13:39 atyz: But thats just a guess

13:39 I'll try to do so now

13:40 mikerod: I don't think I have many cases where that'd be something I wrote. Perhaps you have good use-cases though.

13:41 It is certainly convenient if you needed to unroll a bunch of stuff into a literal form :P

13:42 TimMc: atyz: Err yes, the LB. :-)

13:42 mikerod: It's rare, but when I do use it, it's super convenient. :-)

13:47 mr-foobar: in clojure does a symbol follow a protocol or an api ?

13:47 atyz: TimMc: I just pulled it out of the load balancer, so I guess we will see what happens in a few minutes

13:48 dbasch: mr-foobar: not sure what you're asking, can you rephrase your question?

13:49 mr-foobar: a symbol is just an instance of clojure.lang.Symbol

13:50 mr-foobar: dbasch: clojure.lang.Symbol is what I was looking for.

13:52 dbasch: symbols can be used like enums right ? ( i am in the js land. need something like symbols / js )

13:53 nkoza: mr-foobar: the common idiom is to use keywords for that

13:53 mr-foobar: as in :red :blue :green

13:54 mr-foobar: nkoza: oh, I am aware of that. I am using js :( I want to port that idiom to js basically.

13:58 atyz: TimMc: Interesting... Its still at 100 % after being out of the LB for 10 minutes

13:58 TimMc: So, it's definitely stuck on something. Do you have jstack on that machine? Should come with the JDK.

13:59 atyz: TimMc: I do indeed. sudo jstack 1277

13:59 1277: Unable to open socket file: target process not responding or HotSpot VM not loaded

13:59 The -F option can be used when the target process is not responding

14:00 Yep, it seems there is a deadlcok

14:00 TimMc: Apparently the -l option will print locks.

14:01 atyz: https://www.refheap.com/87785

14:01 There is no locks I don't think

14:01 But a bunch of the processes are locked

14:02 TimMc: "No deadlocks found"

14:03 atyz: Yep - this is really curious - I can't help but think this is because of my use of futures

14:03 TimMc: I'm not sure if those blocked threads are normal, though -- maybe they're a threadpool waiting for requests.

14:03 Check the thread dump for a server that is behaving nicely.

14:04 atyz: Well TimMc the issue is that *all* of the servers get into this state

14:04 Eventually

14:04 I'm having to kill the oldest one

14:05 Periodically

14:05 TimMc: Can you take one out of LB that is not yet at 100%, check the threads, and compare it?

14:06 atyz: I could do that

14:08 TimMc: I'm not entirely sure how to interpret these entrails, but there might be something obvious.

14:08 hiredman: http://wiki.eclipse.org/Jetty/Howto/High_Load#Thread_Pool

14:21 atyz: TimMc: https://www.refheap.com/87787 <-- the new one... Its the same

14:31 hotcore: ,({:a 42} :a)

14:31 clojurebot: 42

14:32 cbp: TIL multimethods don't realize sequences when you're dispatching on (map type x)

14:35 atyz: hiredman: that could be something! Thank you. Now to find where to configure this

14:35 Although that wouldn't explain why the cpu usage i still at 100% now

14:38 hiredman: atyz: who knows what the queue depth is, could take forever to chew through

14:40 atyz: hiredman: would this just be api requests that havent been processed? or threads pushing out data that haven't been sent yet?

14:42 hiredman: either

14:43 the picture may be more complicated if you are using the async reply features of pedastal

14:44 and imposing limits on jetty's request queue won't "fix" whatever the problem is, it will just cause hard failures fast instead of soft slow failures

14:45 atyz: hiredman: that is something, atleast

14:45 hiredman: yep

14:49 amalloy: cbp: that doesn't sound right. the first thing isa? does is check whether (= parent child)

14:49 hiredman: I wonder if it could be a gc pause causing a back up in jetty's queue, if the hard failures start happening, you can run the jvms with -verbose:gc and try to correlate that output with the hard failures

14:49 amalloy: so it should realize the sequence of (map type x)

14:50 atyz: hiredman: you seem quite confident that this has something to do with jetty?

14:50 amalloy: if you mean that the elements of x are themselves sequences, and it doesn't realize *those* sequences, then well, of course not

14:51 hiredman: atyz: I think the symptoms you are describing match what is in the wiki there pretty well, but I don't know what the underlying cause is

14:52 atyz: something must be "sticking" it jetty's queue for some reason, which is causing the back up of requests in the queue

14:52 yeoj___: i'm trying to reference java's .getMetaData but it's not seeming to be working... i wanted to pass that in as the function (third arg) to db-query-with-results .... is it possible it needs a type metadata somewhere to get interopp to work?

14:52 cbp: amalloy: https://www.refheap.com/87790

14:53 er

14:53 i messed up there

14:54 hiredman: atyz: it could be some other place you are doing unbounded queueing, futures run on an unbounded threadpool

14:55 jetty must expose its queue depth somewhere (as a mxbean or something) if you can find that and read it on one of these highload servers it would give you an idea

14:56 cbp: amalloy: https://www.refheap.com/87791

14:56 :-P

14:57 (mapv type x) does make that work though

14:57 atyz: hiredman: howw ould you create a future on an unbounded threadpool, I thought inheritly they were restricted?

14:57 cbp: also note that (foo [1 2]) doesnt work

14:58 hiredman: atyz: futures are not

14:58 arrdem: cbp: mapv :P

14:58 hiredman: clojure has two built in thread pools, futures use the unbounded one

14:59 arrdem: cbp: note that this explodes for more than the two-ary case, hence this https://github.com/clojure/algo.generic/blob/master/src/main/clojure/clojure/algo/generic.clj

14:59 amalloy: cbp: that's nothing to do with realizing sequences

15:00 the lazy seq is in fact realized there

15:00 you could see that by using, for example, (map #(doto (type %) prn) x)

15:01 rather, isa?'s behavior to "look inside vectors to see if their elements are isa?" only applies when both objects are specifically vectors

15:01 atyz: hiredman: thats very interesting, I'm even more confident that that is my problem now

15:02 amalloy: (and of course (map type x) is not a vector)

15:03 hiredman: atyz: are you familiar with the executors framework? switching from clojure's built in future to something more custom using your own threadpool is not too bad

15:05 atyz: hiredman: I am not at all. futures were just a really simple way to do some fire-and forget asynchronous work done

15:06 I could probably also use core.async too

15:06 hiredman: atyz: I would be very careful with core.async

15:07 atyz: You think I would end up with the same problem if I don't configure the channel properly?

15:07 hiredman: forkjoin threadpools are not supposed to have io schedule on them

15:07 (any blocking operation really)

15:08 atyz: my guess is you are doing something blocking at some point, in which case you'll want your own threadpool even if you use core.async

15:08 atyz: hiredman: they are. they are usually api calls

15:09 to other services

15:09 But in a lot of the cases it should have its own threadpool. https://github.com/dakrone/clj-http

15:10 hiredman: core.async can make those async calls look synchronous, but it doesn't obviate the need for a an io threadpool

15:10 atyz: but clj-http is still blocking

15:10 atyz: It is, I realise that

15:10 I think that that is the issue

15:11 hiredman: so you are spinning out these futures to do this blocking operation without any back pressure

15:11 infact executors might not work very well, they don't have a good way to do back pressure

15:12 atyz: Well those clj-http calls aren't done through futures

15:12 clj-http allows you to create your own threadpool

15:12 to work from

15:12 tbaldridge: as an aside, http-kit has a really nice async http client

15:12 dakrone: hiredman: they do, you can spin up an executor with a fixed-size queue

15:12 and then adding to the queue will block until work completes

15:12 atyz: https://www.refheap.com/87792

15:13 hiredman: dakrone: sure, but the Executors factory class won't make one of those for you

15:13 dakrone: hiredman: yes, quite true

15:13 hiredman: atyz: yeah, that doesn't really matter though, it may be running on connection manager threadpool, but on the calling thread it is still a blocking operation

15:14 atyz: OH that makes sense

15:24 cbp: amalloy: Oh so it will work as long as it's = and doesn't have to check for isa?

15:24 as in (defmethod foo [Long Long] ..) would work there

15:28 atyz: hiredman: I don't suppose you have configured jetty embedded jetty before? Does this mean I won't be able to use the version that comes with pedestal anymore?

15:28 ohpauleez: My ears are ringing :)

15:30 atyz: Are you using Pedestal 0.3.0?

15:30 atyz: ohpauleez: not yet

15:31 [io.pedestal/pedestal.service "0.2.2"]

15:31 ohpauleez: Ahh, that uses the latest Connection bits in the latest Jetty release

15:31 but requires you are on JDK 1.7 or higher

15:31 atyz: ohpauleez: I"m afraid to upgrade - I've had to make some changes to how pedestal boots

15:31 ohpauleez: If you're making clj-http calls within your service, it's advised you wrap them in Hystrix

15:32 The startup and integration is greatly simplied in 0.3.0. There are a bunch of performance improvements, extra security features you can toggle on if you want, and the ability to use ServletFilters right in your Pedestal App (at the container level)

15:32 or reach deep into the container to toggle whatever you need

15:33 atyz: Well lets see what happens if I upgrade it qucikly

15:33 Maybe it will work

15:35 ohpauleez: well surprisingly it worked!

15:36 ohpauleez: You may have to adjust some of your startup code, and adjust your namespaces

15:36 ie: there's no more *.service.*

15:36 atyz: Oh... Then some stuff is probably broken

15:38 Anyway, to the issue at hand.. woudl you maybe point me in the direction of where I could possibly configure jetty?

15:40 ohpauleez: How do you want to configure it? During startup, you can pass a function that is given the container (and returns it), and you can do whatever you want

15:41 in 0.3.0, you can reach even deeper, into the Container's context setup

15:41 which is difficult to do unless the hooks are exposed or you jump through a lot of hoops

15:42 If what you want is to specify your own interceptor chain, you do that on the :interceptors key on the service map

15:42 instead of accepting the default stack, you just assembly your own

15:42 atyz: ohpauleez: yes, but that didn't allow me to specify the order in which they were loaded

15:43 ohpauleez: yes

15:43 if you specify them in the original service map, the default ones aren't added

15:43 and the processing is always sequential to how they're specified

15:44 If you add :interceptors in your own function, that function *has-to* run before any startup or processing function on the Pedestal side

15:44 if Pedestal sees :interceptors on the service-map, it takes them and runs with them

15:45 You can also take the default stack (if you want it) and attach root interceptors at the root URL in your routes (if they're all HTTP/route specific)

15:47 sveri: Hi, I am trying to reload my enlive templates namespace based on a watcher on the resources path. However, I cannot get it working, as soon as I use: (use 'namespace :reload) my watcher function is not called anymore. Any ideas how to make it work? http://pastebin.com/X15vx6f5

15:47 cbp: methinks isa? should be better documented

15:52 tbaldridge: ,(doc isa?)

15:52 clojurebot: "([child parent] [h child parent]); Returns true if (= child parent), or child is directly or indirectly derived from parent, either via a Java type inheritance relationship or a relationship established via derive. h must be a hierarchy obtained from make-hierarchy, if not supplied defaults to the global hierarchy"

15:54 cbp: there's nothing there about (isa? [Long Long] [Number Number]) working or (isa? (list Long Long) [Number Number]) not working

15:56 TimMc: cbp: What? That's absurd. D-:

16:04 dbasch: ,(isa? '(Long Long) '(Number Number))

16:04 clojurebot: false

16:04 dbasch: ,(isa? [Long Long] [Number Number])

16:04 clojurebot: true

16:04 tbaldridge: ,(source isa?)

16:05 clojurebot: Source not found\n

16:05 Glenjamin: does anyone know why PersistentQueue doesn't have a function to create one in core?

16:06 ,(-> (clojure.lang.PersistentQueue/EMPTY) (conj 1 2 3) pop)

16:06 clojurebot: #<PersistentQueue clojure.lang.PersistentQueue@402>

16:06 Glenjamin: or a printer implementation apparently

16:06 ,(-> (clojure.lang.PersistentQueue/EMPTY) (conj 1 2 3) pop vec)

16:06 clojurebot: [2 3]

16:07 amalloy: Glenjamin: there's no good reason

16:07 dbasch: ,(isa? {Long Long} {Long Number})

16:07 clojurebot: false

16:07 dbasch: actually that one makes sense

16:07 bhauman: Glenjamin: I have often missed that function, medley has it though

16:07 Glenjamin: i only noticed because mori exposes it as a primary datatype http://swannodette.github.io/mori/#queue

16:07 tbaldridge: dbasch: ick, yeah, isa? has a special case for vectors

16:08 why? I haven't a clue

16:08 Glenjamin: although i want a structure which does random access, efficient append and effcient dropping of "old" entries in a windowing-fashion

16:08 which i don't think exists

16:08 eevar: a circle buffer?

16:09 amalloy: $google amalloy ring-buffer

16:09 lazybot: [amalloy/ring-buffer · GitHub] https://github.com/amalloy/ring-buffer

16:09 amalloy: Glenjamin: doesn't actually expose random-access, but there's no reason it couldn't

16:11 Glenjamin: Oh, in pure js

16:12 Oh I see, it's vector-backed

16:12 puredanger: Glenjamin: re Queue stuff, vote: http://dev.clojure.org/jira/browse/CLJ-1078

16:13 Glenjamin: Ta

16:14 amalloy: I might see if I can port this to JS backed on a mori vector if that's ok with you?

16:15 amalloy: sure. i don't own the idea of ring buffers; there's probably not even anything novel in my implementation

16:16 Glenjamin: I'll have to read up on some thing it seems :)

16:18 TimMc: dbasch: ##(isa? '[Long Long] '[Number Number])

16:18 lazybot: ⇒ false

16:18 TimMc: so your list example wouldn't have worked anyhow

16:18 ,(isa? (list Number Number) [Number Number])

16:18 clojurebot: true

16:19 dbasch: ,(isa? (list Long Long) (list Number Number))

16:19 clojurebot: false

16:47 borkdude: I have defined a macro in a namespace recipes.macros named with-data-loaded. I call it from clojurescript, but the clojurescript compiler says: WARNING: No such namespace: recipes.macros at line 115 src/recipes/app.cljs

16:49 bob2: https://github.com/clojure/clojurescript/wiki/Differences-from-Clojure#lisp i guess

16:50 borkdude: bob2 I've done that: https://www.refheap.com/87798

16:50 bob2: i feel like you missed the "The :as prefix selector is required in :require-macros." bit

16:51 borkdude: hmz

16:51 then why isn't it required in [cljs.core.async.macros :refer [go go-loop]]

16:52 but I will try

16:52 bob2: no idea

16:52 borkdude: nope, still the same

16:53 it's like it doesn't pick up the clj file

16:57 Clojurescript up and running says: "This assumes that a Clojure source file is available on the classpath at my_project/

16:57 foo.clj containing defmacro foo.". How can I assure that this is the case with lein cljsbuild auto?

16:58 PigDude: what does this mean? clojure.lang.ArityException: Wrong number of args (4) passed to: PersistentArrayMap>

16:58 i get this error with no line number or anything

16:59 amalloy: PigDude: you passed four arguments to a map. probably you didn't mean to call the map at all, but had too many parens or were missing a do

16:59 hiredman: PigDude: the stack trace will have line numbers in it

17:01 PigDude: hiredman: when?

17:01 hiredman: there is no stack trace

17:01 hiredman: PigDude: there is always a stracktrace, your tooling may not be displaying it

17:02 the exception will be in *e

17:02 you can use clojure.stacktrace/print-stack-trace to print it, or call the method I never case correctly on it

17:03 tbaldrid_: hiredman: except when it says "No trace found" still no clue what that means

17:03 PigDude: hiredman: my tooling consists of a terminal, bash, and leiningen

17:03 where is *e?

17:03 hiredman: ^

17:03 hiredman: tbaldrid_: the jit can some sometimes elide traces, there is some jvm option to turn it off

17:04 PigDude: type *e in the repl

17:04 Shayanjm: So I'm trying to use lein ring to handle a hot-reloaded ring server for me while I build on it. Here's the code: https://gist.github.com/shayanjm/65942169797fd2f84a54

17:04 PigDude: hiredman: what repl

17:04 hiredman: i'm running `lein test`

17:04 Shayanjm: everything starts fine, and I can access the server

17:04 hiredman: :(

17:04 Shayanjm: but I can't access the nrepl

17:04 if I try to connect, it just hangs

17:04 hiredman: PigDude: I find it very hard to believe that lein test isn't printing a stacktrace

17:05 PigDude: hiredman: do you want a screenshot?

17:05 Shayanjm: I tried passing join? false through the :adapter settings in the project.clj but it doesn't seem to be working

17:05 hiredman: PigDude: sure

17:05 dbasch: hiredman: that particular exception in cider doesn't print a trace either

17:05 , ({} 1 2 3 4)

17:05 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (4) passed to: PersistentArrayMap>

17:05 dbasch: ,(print *e)

17:05 clojurebot: #<Unbound Unbound: #'clojure.core/*e>

17:05 hiredman: dbasch: that is because cider has a stupid option that defaults to not displaying the stacktrace

17:06 amalloy: tbaldridge: "trace missing" kinda stuff comes when the jit has converted the relevant method into machine code that's optimized enough that it's no longer capable of keeping track of the bytecode that generated it, or something like that

17:06 hiredman: dbasch: don't assume clojurebot's evaluation environment is like the repls

17:06 dbasch: hiredman: but even *e has no stacktrace

17:06 PigDude: so do you want to see the screenshot still hiredman

17:06 dbasch seems to be right

17:06 hiredman: PigDude: show me lein test not printing a stacktrace

17:06 dbasch: there are a bunch of cases like that in core.clj, I remember one like that recently

17:07 where it essentially eats the stacktrace

17:07 hiredman: PigDude: he is not

17:08 PigDude: hiredman: here's a paste, i hope you trust me not to have doctored it https://www.refheap.com/b7f57290f403ef0dda758f63e

17:08 hiredman: PigDude: right, so you are catching the exception somewhere and printing it out

17:08 (try … (catch Exception e (prn e)))

17:08 actually

17:08 that is core.async

17:09 amalloy: yeah, notice that didn't even count as a failure in the tests. someone caught it and printed it

17:09 hiredman: there is a stupid line that got committed in core.async that prints out unhandled exceptions like that

17:09 PigDude: hiredman: the only exception handling in my program is in clojurescript code

17:09 hiredman: seriously?

17:09 hiredman: PigDude: right, but you have a go routine somewhere that is throwing that exception

17:09 benkay: so i've got a weird thing going on - for some hard-to-pin-down subset of pages on which i'm using enlive, it's setting a <style type="text/css> tag to the header, and setting other attrs on my images like "width=0,height=0". has anyone else run into this?

17:09 hiredman: PigDude: yep

17:09 cbp: hiredman: :|

17:10 hiredman: it may have been fixed in a later release, dunno

17:10 PigDude: so when programming with core.async, you don't get stacktraces??

17:10 lazybot: PigDude: Uh, no. Why would you even ask?

17:10 hiredman: PigDude: if you catch the exception yourself you will

17:10 cbp: core dont need no silly stacktraces

17:11 amalloy: hiredman: https://github.com/clojure/core.async/blob/76b25bf91c670b0c3542ed9cb687ff29fb2183a7/src/main/clojure/clojure/core/async/impl/exec/threadpool.clj#L24-L33 ?

17:11 dbasch: hiredman: you're wrong, there are cases in core where you don't get stacktraces

17:11 stuartsierra: PigDude: You get a stacktrace, but it can be difficult to predict where and when the stacktrace will appear.

17:11 hiredman: https://github.com/clojure/core.async/blob/master/src/main/clojure/clojure/core/async/impl/exec/threadpool.clj#L33

17:11 PigDude: discussion changed, is clojure a ghetto? :)

17:11 hiredman: stuartsierra: you don't, the executor prints out the exception, no trace

17:12 amalloy: yeah

17:12 dbasch: no, you just don't know where to look

17:12 amalloy: dbasch: i don't think that's true

17:12 stuartsierra: Wait, when did that happen?

17:12 dbasch: amalloy hiredman I remember an example that we found here a few weeks ago

17:12 trying to find it in the logs

17:12 PigDude: thanks for helping me figure this out dbasch and hiredman

17:12 amalloy: stuartsierra: https://github.com/clojure/core.async/commit/9fcae99576c0735a804bbd4cbec81307e2d34d90

17:13 specifically https://github.com/clojure/core.async/commit/9fcae99576c0735a804bbd4cbec81307e2d34d90#diff-2193dd8597437d6454bb74edd2f15e00L26

17:13 hiredman: core.async, land of random stuff

17:13 dbasch: it was an exception that did not even show a line number

17:13 PigDude: stuartsierra: so in my case i did not get a stacktrace because it was a special case in core, nothing to do with async

17:13 hiredman: dbasch: not having a line number and not have a stacktrace are different

17:14 dbasch: hiredman: it had neither

17:14 hiredman: dbasch: nope

17:14 amalloy: i think you can get exceptions with no stack trace at all if the jit has done something particularly aggressive

17:14 "trace missing"

17:14 hiredman: amalloy: and -XX:-OmitStackTraceInFastThrow will fix that

17:15 (in theory)

17:15 dbasch: amalloy: technically it had a stacktrace, but it was shallow because it was a freshly thrown exception that caught another one

17:15 hiredman: well, there you go, it had a stacktrace

17:15 dbasch: it was a really silly line, but I can't find it

17:16 amalloy: i just remembered an issue in the cljs compiler where it was catching an OOME and trying to alloc up a new exception to wrap around it

17:16 i wonder if that's fixed

17:18 yedi: is there a function that unqualifies a keyword

17:19 amalloy: i regard keywords as unqualified if they haven't got at least a bachelor's degree

17:20 Frozenlock: Is there a way to give a name to the :sender/:from in postal?

17:20 cbp: yedi: name

17:20 o you scared him away

17:20 Frozenlock: I'd like the recipient to see "Frozenlock" instead of "frozenlock@gmail.com" :-/

17:21 wheeee: :injections in project.clj

17:21 Err whoops.

17:22 cbp: $mail yedi (name :a/b)

17:22 lazybot: Message saved.

17:24 Frozenlock: Ah got it... :from "Frozenlock <frozenlock@gmail.com>"

17:26 dbasch: Frozenlock: :from can be "Mr. Frozenlock <frozenlock@gmail.com>"

17:26 you beat me to it

17:26 Frozenlock: By a single minute ;-p

17:27 dbasch: Frozenlock: I had to go look into an app of mine that does that :P

17:28 Frozenlock: Is this a javax/mail thing, or it's a universal email thing that I should have known?

17:32 Klaufir: I am trying to follow the STM tutorial at http://sw1nn.com/blog/2012/04/16/clojure-stm-ref-consistency/ , however I get a nullptr exception for reasons unknown to me, details: http://lpaste.net/106817

17:32 I need some help determining the reason for that nullptr exception

17:33 amalloy: Frozenlock: it's an email thing

17:34 hiredman: Klaufir: that tutorial is bogus, their code was never run and would never have worked

17:34 Frozenlock: amalloy: Awww, shame on me then.

17:34 hiredman: Klaufir: they are using #() incurrectly

17:34 Klaufir: it would always generate an npe

17:34 stuartsierra: amalloy, hiredman, PigDude, dbasch: I'm going to fix this.

17:35 hiredman: incorrectly

17:35 Klaufir: because of the way #() turns in to a function, that code is trying to call the result of (println "READ start") on the resut of (dosync ...)

17:36 and of course the result of a call to println is nil

17:36 switch to (fn [] ...) or #(do ...)

17:36 Klaufir: hiredman: ah, thank you.

17:36 hiredman: can you recommend a better text for learning stm?

17:37 hiredman: Klaufir: don't bother, you'll never use it

17:37 dbasch: Frozenlock: http://tools.ietf.org/html/rfc2822#appendix-A.1

17:39 wheeee: Can someone tell me what :injections does within a lein project.cljs?

17:39 project.clj

17:39 nhll: .

17:40 amalloy: a rule of thumb: if the tutorial you're reading has paragraphs of text crossed out and concludes with "we found a potential problem with the clojure runtime", the author is probably clueless

17:40 cbp: Klaufir: clojure programming has nice diagrams on the retry mechanisms of the different clojure refs

17:40 Klaufir: cbp: thanks

17:42 hiredman: hah they must have been running their code in some environment that sent the npe stacktraces somewhere else, so they never saw them

17:43 clojurebot: bloggers |are| the worst

17:43 clojurebot: In Ordnung

17:44 amalloy: hiredman: my guess was that it was originally written with (future #((...))), which squelches the exceptions

17:45 and then they switched to Thread/start to avoid having to explain futures or something

17:45 hiredman: amalloy: well, no future wouldn't call the function

17:45 amalloy: oh, right

17:47 PigDude: is it cleaner to use separate async channels than to share one and tag messages?

17:47 matching tagged messages isn't easy like in erlang

17:47 hiredman: PigDude: maybe use the pub/sub stuff

17:48 https://github.com/clojure/core.async/blob/master/src/main/clojure/clojure/core/async.clj#L823

17:50 PigDude: i wish async walkthrough.clj covered that usage, do you know of one?

17:50 hiredman: noppe

17:50 PigDude: (example of using async pub/sub)

17:50 ok :)

17:50 it looks like what i want though, thanks

17:53 stuartsierra: http://dev.clojure.org/jira/browse/ASYNC-76

17:58 Shayanjm: Does anyone know why `lein ring server` would start & execute correctly, but the nrepl hangs?

17:58 https://gist.github.com/shayanjm/65942169797fd2f84a54

18:01 benkay: did the optional query clauses ever make it into datomic? https://groups.google.com/d/msg/datomic/p3FLisquFH8/J1kXJ_9pQngJ

18:03 BobSchack: benkay: yep see http://docs.datomic.com/query.html#expression-clauses

18:03 benkay: thanks BobSchack

18:03 BobSchack: NP

18:03 alloyed: @Shayanjm lein-ring outputs a log when the nrepl comes up, does your app otherwise work without ever saying "nrepl has started on XXXX" or whatever?

18:04 Shayanjm: alloyed: Everything works fine, and it says nrepl has started on XXXX as well as the ring server has started on XXXXX

18:04 everything "works" I just can't connect to the repl :\

18:04 it doesn't even error upon connection either - it just keeps trying to connect indefinitely

18:04 (or it hangs, I can't really tell which is happening)

18:06 alloyed: hmm, what nrepl client are you using? just `lein repl :connect"?

18:06 serjeem: Is there an equivalent to (declare …) for classes/records?

18:07 technomancy: serjeem: no, you can't seamlessly replace a class or record afaik

18:08 which is basically the whole point of vars

18:08 serjeem: technomancy: heartbreaking :(. Is there some kind of hack I could use to forward-reference a class before I define it?

18:08 Shayanjm: sorry alloyed I just dc'd on my BNC :\ What was the last thing I said in the chan?

18:08 alloyed: 22:03 < Shayanjm> (or it hangs, I can't really tell which is happening)

18:09 hiredman: serjeem: why not create a factory function and declare that?

18:09 Shayanjm: Did you answer that, by chance?

18:09 hiredman: serjeem: if you are using a defrecord you automatically get 2 factory functions, which you can declare and use

18:09 Shayanjm: The latest logs I have are from technomancy saying "which is basically the whole point of vars"

18:09 technomancy: serjeem: this is why I hate using things that aren't vars

18:09 alloyed: I was just asking how you were connecting to the repl.

18:10 serjeem: hiredman: I’m writing a bunch of macros that more-or-less do some typechecking among their outputs. They output new defrecords, and I’d like to be able to use these new records in potentially recursive ways.

18:10 Shayanjm: alloyed: I'm trying to use a sublime plugin that supports nrepl

18:10 i tried on lighttable as well

18:11 sublime plugin: http://sublimerepl.readthedocs.org/en/latest/

18:11 hiredman: serjeem: type checking how?

18:11 alloyed: lets start super-basic then, what does `lein repl :connect` do?

18:11 hiredman: serjeem: do you mean inserting instance? checks?

18:11 Shayanjm: alloyed: while lein ring server is running?

18:12 serjeem: hiredman: yeah, that’s the idea.

18:12 I run the macro on thing A, it gives me a record A and a constructor, make-a, that “type-checks” the fields in cute ways

18:12 More like contract checking, but I digress

18:13 alloyed: yeah. usually what happens is the lein-ring starts nrepl, then puts the port number in .nrepl-port, and then you lein autoconnects from that

18:14 hiredman: serjeem: consider separating jvm notions of types from your contracts

18:14 Shayanjm: alloyed: lein repl :connect <port> works perfectly. It looks like the sublime plugin is a bit messed up :\

18:15 thanks for the help though

18:16 serjeem: hiredman: I was hoping it wouldn’t have to come to that, but I think I can work around that.

18:16 alloyed: np

18:17 hiredman: serjeem: so if you have type X that fulfills contract Y, and type Z that fullfills contract W, in W instead of saying "field whatever is of type X" you say "field whatever fullfills contract Y"

18:18 serjeem: are you dead set on writing this yourself? there are a number of schemaish clojure libraries

18:18 https://github.com/Prismatic/schema is maybe the most well known

18:20 serjeem: hiredman: We did a survey of a lot of them and not filled the exact hole we were hoping to fill, unfortunately.

18:21 hiredman: We might have to move closer to your suggestion, or just give up and force a linear ordering on types.

18:22 While contracts serve a similar purpose, we were really hoping that we’d be able to be super strict about the kinds of values we’d find in the schemas.

18:22 What I’d do for one more level of indirection between records and the jvm.

18:23 hiredman: have you considered using a language with a static type system?

18:23 being really strict about types is just not something you really do in clojure

18:24 serjeem: I argued a little for haskell at the offset, but clojure was a better fit for the project and the team

18:24 We’re all former racketeers, so there’ve been a few rough patches adjusting to the way clojure does stuff.

18:25 hiredman: if at all possible, any place you might use a defrecord instance, you should be able to use a map

18:25 technomancy: yeah records make more sense in racket than they do in clojure

18:25 serjeem: Yeah, it’s been the #1 element of cognitive dissonance since we started

18:25 hiredman: the reason defrecord implements so much of the same stuff as maps is try and bridge the worlds, which of course you do completely

18:26 so caring strictly about the type of a thing/map/record is weird

18:27 serjeem: It makes sense, at least to me, when you look at it from the perspective of building interfaces

18:28 hiredman: what do you mean by building interfaces?

18:28 serjeem: even in dynamic languages, I’m used to coming from a world where you just kind of say, “this function expects a foo? and returns a bar?” and having meaningful connotations to foo? and bar?

18:28 in racket, for structured data, you define foo? and bar? as structs. Python and ruby, you’ve got classes

18:29 yedi: TEttinger2: got that job =D

18:29 technomancy: serjeem: it's un-idiomatic to rely on classes in ruby too

18:29 hiredman: serjeem: if foo and map are logically associative bags of data, why create new types?

18:29 technomancy: you're supposed to check for supporting the specific methods you're interested in

18:29 hiredman: foo is an associative bag of data with at least an association for :a and :b

18:29 wheeee: Can anyone tell me what ":injections" does in a lein project.clj?

18:30 I'm looking at this: https://github.com/technomancy/leiningen/blob/master/sample.project.clj#L231-L233

18:30 technomancy: wheeee: it's a form that gets included whenever lein evals anything

18:30 ttasterisco: yedi: where at? :)

18:30 clojurebot: Titim gan éirí ort.

18:32 serjeem: hiredman: I’m a very HTDP/design recipe focused programmer, and the first step of that process is describing the data

18:32 yedi: ttasterisco: http://wit.ai

18:32 ttasterisco: yedi: oh, the yc company. nice

18:32 serjeem: when you’re writing production-quality clj, what’s the idiomatic way to say “foo is an assoc. bag containing roughly X Y and Z”?

18:33 hiredman: serjeem: it depends, but generally a function might look at it's arguments and call any number of predicates on them

18:33 wheeee: technomancy: Thanks. Does that mean just when lein first starts up or every time it evals anything? Sorry for asking a daft question.

18:33 hiredman: (doc contains?)

18:33 clojurebot: "([coll key]); Returns true if key is present in the given collection, otherwise returns false. Note that for numerically indexed collections like vectors and Java arrays, this tests if the numeric key is within the range of indexes. 'contains?' operates constant or logarithmic time; it will not perform a linear search for a value. See also 'some'."

18:34 hiredman: serjeem: the schema library will actually do that sort of thing for you, I think, I've never used it

18:34 technomancy: wheeee: it's every time

18:34 wheeee: every time it evals in the project jvm, that is

18:35 wheeee: Ah, thank you.

18:35 hiredman: serjeem: have you looked at the typed clojure stuff at all, it lets you define type aliases for maps with certain keys and that kind of thing

18:36 but it doesn't do the runtime checking, it does static type checking

18:36 akurilin: Random question: do you guys know if there's ever been an effort to support passing the db pool explicitly in Korma?

18:37 Right now it's implicit through the dynamic var you can set

18:37 serjeem: hiredman: For functions, yeah, but if you’re making, say, an IRC server, you’ll have to keep track of your notion of what a “user” is, for instance.

18:37 hiredman: serjeem: why?

18:38 actually we use https://github.com/danlarkin/subrosa at work (an irc server written in clojure)

18:38 serjeem: hiredman: I’ll look into the schema library more, but when I looked at it a few weeks ago it wasn’t 100% what we were looking for. It’ll definitely be a good reference. Last time I looked at typed-clj it didn’t seem production ready.

18:39 hiredman: sure

18:39 we don't use either of those projects at work

18:41 serjeem: hiredman: in terms of why, philosphically, the idea is that your program represents, on some level, in an abstract way, the transformation of information

18:41 hiredman: serjeem: http://www.youtube.com/watch?v=rI8tNMsozo0#t=19m is a nice talk from rich, and around the 19 minute mark he talks a little about types vs values

18:41 serjeem: bits and bytes and users and game characters and server settings

18:42 hiredman: serjeem: exactly, but the types of data we manipulate are finite, mostly associative things

18:42 serjeem: and in order to make sense of the chaos of the universe, we peel away kinds of chunks information into numbers and strings and chars and maps and vectors etc

18:43 and the idea is that when you’re writing actual software, the data that you’re dealing with isn’t just simple languge-provided values

18:43 hiredman: serjeem: the thing is, you can write generic transforms over associative maps easily

18:43 serjeem: not over custom types

18:43 serjeem: but often something that models in some way some kind of facet of the real world, or some abstract value of something

18:43 hiredman: (well, not without haskells type system)

18:44 serjeem: and it makes sense to say, “okay, this think I’m working with is at least conceptually made up of X Y and Z”

18:44 hiredman: serjeem: it doesn't though

18:44 serjeem: you don’t necessarily need like a type system to enforce it, but you should have some way to communicate it to others

18:44 hiredman: serjeem: plenty of simulations and models exist as rows in a spread sheet

18:44 no types for different kinds of things to be found

18:45 simulating the world by mapping it to types is the most primitive type of simulation

18:45 serjeem: those rows most often have, like, labelled columns, right?

18:45 it’s not just rows of arbitrary information

18:45 hiredman: serjeem: sure, and maps have keys and values

18:45 serjeem: see, for instance, the IRC server you linked

18:45 The IRC server you linked, for instance, does this here: https://github.com/danlarkin/subrosa/blob/master/src/subrosa/server.clj

18:46 hiredman: aphyr has a nice post about modeling somewhere

18:46 serjeem: it gives you a description of what it expects users, rooms, user-in-rooms, and the server to be

18:46 hiredman: serjeem: sure, but it doesn't define types, it just says it is some kind of associative thing with these kinds of things in it

18:46 serjeem: yeah! that’s all I’m saying

18:47 hiredman: http://aphyr.com/posts/312-clojure-from-the-ground-up-modeling

18:47 serjeem: the types are just one way to describe the data

18:47 hiredman: they generally are not though

18:48 defrecords are slightly better than other "types" at this

18:48 but generally every type ends up with its own mini-dsl for reading and writing its data

18:49 maps also have a dsl/api, assoc, dissoc, get, but it applies to all maps

18:49 so if you model everything as maps you can use the same api and create truelly generic data transforms

18:51 I am just trying to convey clojure's generally lean, you can do things differently, but you are going to be fighting the language, so why using the language?

18:52 (also I just really like http://aphyr.com/posts/312-clojure-from-the-ground-up-modeling)

18:53 serjeem: (I really like that post, too, thanks for linking it!)

18:53 I also really agree that the map api is _fantastic_ in clojure. all of the core datastructure apis are

18:54 and I very much appreciate that the language is lean, and that it makes it wonderful to work with

18:54 it’s seriously a dream

18:54 hiredman: well, that'll wear off :)

18:54 serjeem: but one of the great things I love about lisps is that you can leverage them and contort them to your bidding when you need to

18:54 :P

18:55 tuft: i always struggle with when and if to defrecords

18:55 or to use protocols for that matter

18:56 cbp: if you're in doubt don't use them

18:56 tuft: always wonder how much it is just to get classes implementing methods at the bytecode level

18:56 yeah, seems like you can get along fine without

18:56 serjeem: after about half a year of using clojure, defrecords seem like the harriest part of the whole langauge

18:56 tuft: also seems like most of the libraries i pick up make use of them

18:57 cbp: protocols are nice for client-facing apis

18:57 hiredman: cbp: the opposite

18:58 cbp: ahhhh?

18:58 tuft: cbp: better than simple generic functions / multimethods? they seem really similar in function

18:58 i assume you're talking about extension points

18:58 hiredman: cbp: they are create for spis, you have a library that can be backed via anything that implements some protocol

18:58 the client api is functions implemented on top of the protocol

18:59 the great for

18:59 they are

18:59 ugh

19:00 a big thing that is missing in clojure is some kind of module/compile time polymorphism, so protocols often get abused for that

19:00 serjeem: +1 to that

19:00 hiredman: something like mls functors

19:01 (I think, I mean, I don't have much experience with those)

19:01 serjeem: If clojure could eat rackets heart, and grow three new limbs (really good macros, module system, better docs), it would take over the world

19:01 [and maybe a fourth limb for non-sucky struct/records :P]

19:01 tuft: is there a benefit to protocols over multimethods beyond performance for that kind of extension point?

19:03 hiredman: protocols group the functions together which is nice

19:03 adu: sounds like ObjC

19:03 hiredman: multimethods bringing in the whole complicated isa? machinery which I've never really seen used

19:04 tuft: hiredman: yeah i guess that's one difference -- it's all or nothing

19:04 hiredman: tuft: actually no, you can selectively implement parts of a protocol

19:04 tuft: oh, hrm

19:04 hiredman: but don't

19:04 amalloy: you're not really supposed to

19:04 it's possible, but not for any good reason

19:05 tuft: it always feels like a little bit of a let-down when the CamelCase symbols creep into your code for non interop purposes

19:05 cbp: >_>

19:06 Lanny: perhaps you mean a letDown

19:06 tuft: heh

19:06 :let-down

19:08 ttasterisco: serjeem: what do you mean by module system?

19:08 hiredman: something like parameterized namespaces

19:09 serjeem: ttasterisco: namespaces on ‘roids, a ‘la i.e. racket http://docs.racket-lang.org/reference/module.html?q=module#%28form._%28%28quote._~23~25kernel%29._module%29%29

19:09 haskell’s got a meh one as well, sml had a fantastic one that programming languages have been trying to emulate for decades

19:11 hiredman: like, if you have a "genric" namespace full of array operations that will work on any type of arrays as long as you give it a 'get and 'set for the given type of array, it would be nice you be able to say foo is an instance of the generic namespace with get and set for long arrays

19:12 and you just call the functions from foo, and there is no polymorphism

19:12 serjeem: oh god if this works I don’t think anyone should ever let me touch a macro again: `(-> ~(keyword typ) str symbol resolve)

19:12 technomancy: serjeem: use "name" instead of keyword+str

19:13 serjeem: technomancy: good point :P


19:14 i am an awful person

19:14 ttasterisco: anyone here using the latest version korma (0.3.2)? I'm getting a really weird bug where (fields ...) isn't filtering the selection but actually adding a repeated field

19:18 (hm, actually happening with all versions > 0.3.0-RC7)

19:18 *>=

19:34 akurilin: Schema question: is it possible to only enforce a certain subset of keys of a map as mandatory and ignore the rest of them?

19:35 aperiodic: akurilin: not really. you can have keys be optional but you have to explicitly list them; any keys not in the schema will cause an error

19:35 akurilin: Ok. Sad.

19:38 aperiodic: akurilin: actually, you can do it with something like {s/Keyword s/String, :required s/String}

19:42 akurilin: What does that do, not sure I can quite figure it out from reading that

19:43 aperiodic: allows any keyword keys in the map, and requires :required to be present. maps will only fail to match it if they don't have :required (or if they have any non-keyword keys)

19:45 TimMc: serjeem: What's an example of something that prismatic/schema didn't have?

19:45 We're using it for a project, so it would be good to know.

19:46 serjeem: TimMc: i could be totally wrong, but t didn’t seem to have a super solid datomic integration story

19:46 which is 1/2 - 2/3 of what we needed out of the schema stuff we wanted to have

19:46 TimMc: Hmm, how so? (I haven't used datomic, so this may be difficult to explain to me...)

19:47 And is extending it not an option?

19:48 akurilin: aperiodic: ah that makes ense, thanks

19:48 serjeem: TimMc: The hole the package I’m writing fills is, “Our program needs to deal with and describe data that we store in Datomic and manipulate with clj”. prismatic/schema has the second half down pat, but it’s muddy on the first

19:48 akurilin: aperiodic: if you don't mind me asking, how do you force schema to check if a val of a key isn't nil? I'm using pred in mine

19:49 serjeem: I could probably extend prismatic/schema, but I figured it’d take me just as long to hack a 200LOC library, while also reconning valuable experience with the SeqEx library and some macro magic for the team

19:51 aperiodic: akurilin: I think a predicate schema is the way do to it. you can (def ButNil (s/pred (complement nil?))) and then use ButNil in your schema, to cut down on the verbosity a bit.

19:52 serjeem: That said, and as a general note, seqex is freaking fantastic

19:52 I hope it doesn’t go the way of the dodo, because it makes writing macros fun again

19:52 tuft: serjeem: i have a similar stack, but i don't quite understand what you mean -- are you having to describe data twice?

19:53 i'm now going to have datomic schema, prismatic/schema and test.check generators. seems like there should be something to unif

19:53 unify

19:53 akurilin: aperiodic: That's a great trick actually, thanks!

19:53 serjeem: tuft: yeah, we have to write everything twice

19:53 which I justify as “double-entry data keeping"

19:54 but really just saves sanity w/r/t db migrations, which is something that would terrify me with a single, non-datomic schema

19:54 tuft: ah hmm

19:54 yeah seems like you should be able to derive one from the other

19:55 .. and of course not everything with a prismatic/schema will be persisted

19:55 serjeem: you can, and https://github.com/Yuppiechef/datomic-schema seems to

19:56 but the idea makes me a little uncomfortable, i dunno

19:56 that said, I wish everything was just protobufs and we’d never have to worry about anything ever again forever~~

19:57 hiredman: I've seen code snippets on github to, uh, I think it was generate core.typed declarations from datomic schemas (it could have been the other way around)

19:57 tuft: yeah i'm using datomic-schema too, incidentally

19:57 serjeem: tuft: has it been working well?

19:58 hiredman: is core.typed production-ready yet?

19:58 hiredman: https://gist.github.com/c-spencer/6569571

19:58 serjeem: I’ve got about 5 files I’d love to move to it

19:58 hiredman: serjeem: I dunno

19:59 tuft: serjeem: i did run into one problem with its strange use of atoms

19:59 hiredman: huh, that is literally storing type information in datomic

19:59 tuft: serjeem: i think it should inspect interned vars instead -- messes up when you're doing redef in the repl

20:00 prismatic/schema and core.typed seem somewhat orthogonal to me

20:01 as in, seems like you'd pick one or the other. static or test driven "type" checking

20:02 serjeem: It’d be nice to get a mix

20:03 I’d like to know that a bunch of important functions are type checked, and my data is all what I expect to be on a type-level

20:03 but I’d also like to have functionality around metadata associated with different fields in a schema

20:04 like in the thing I’m writing, things can get default values, certain fields can have preconditions on them, etc

20:05 which is stuff you can’t get outside of like, agda maybe

21:05 benkay: hey y'all - i'm about to start some capacity analysis of a Ring app i derped out recently, and would like to profile it at the same time. is an acceptably professional approach to implement Timbre and siege the thing on a VPS?

21:12 amalloy: timbre seems silly, use a real profiler

21:12 eg yourkit, jvisualvm

21:13 benkay: timbre:midje::core.test:{jvisualvm,yourkit} ?

21:14 er

21:14 bbloom: amalloy: i haven't used timbre, but instrumented tracing is extremely valuable for many applications

21:15 benkay: timbre:{jvisualvm,yourkit}::midje:core.test ?

22:33 danielcompton: I found timbre not very useful with threaded code

22:44 blaenk: (ns a (:require [clojure.string :as str :refer [replace]]))

22:44 what's the point of :refer there?

22:44 so make it so I can use clojure.string/replace unqualified?

22:44 s/so/to

22:45 if that's the case, then it's like :only?

22:46 oh I think I see, it seems like it is, that way one doesn't have to use :use

22:47 mange: blaenk: Correct. :use/:only is the same as :require/:refer, but (:use x) is the same as (:require [x :refer :all])

22:47 blaenk: thanks mange

22:49 how about translating (:use (clojure zip xml)) to use require, refer, all; would I not be able to use the prefix notation?

22:50 (:require (clojure [zip :refer :all] [xml :refer :all])) ?

22:52 Demosthenes_: hello?

22:52 clojurebot: BUENOS DING DONG DIDDLY DIOS, fRaUline Demosthenes_

22:52 Demosthenes_: am I in the right place?

22:52 Frozenlock: No

22:52 You should leave

22:52 Demosthenes_: What a great community

22:53 dbasch: Demosthenes_: it depends, if you're looking for #clojure then you are

22:54 Demosthenes_: Anyways, I had a reason for coming here. Why does the contains? function not work for in the case (contains? [:a :b :c] :b))

22:54 serjeem: (doc contains?)

22:54 clojurebot: "([coll key]); Returns true if key is present in the given collection, otherwise returns false. Note that for numerically indexed collections like vectors and Java arrays, this tests if the numeric key is within the range of indexes. 'contains?' operates constant or logarithmic time; it will not perform a linear search for a value. See also 'some'."

22:54 Demosthenes_: I know the clojuredocs give the reason that "contains is only for indices" but it doesn't make sense to me

22:54 mange: blaenk: I didn't know it, but apparently (:require [clojure [walk :refer [prewalk]] [test :as test]]) does work. Cool!

22:55 dbasch: Demosthenes_: contains? does not do what you want for arrays

22:55 serjeem: Demosthenes_: the reason is that (contains? c k) looks only at the keys, not the values, of c, and compares them to k

22:55 blaenk: so I guess that's how that would be translated huh

22:56 serjeem: so, e.g. (contains [:a :b :c] 1) works, since 1 is a key in that vector

22:56 Demosthenes_: ah thanks serjeem

22:56 ddellacosta: Demosthenes_: if you want to find a value try something like

22:56 blaenk: (:use (prefix some thing)) becomes (:require (clojure [some :refer :all] [thing :refer :all]))

22:56 ddellacosta: &(filter #(= :a %) [:a :b :c])

22:56 lazybot: ⇒ (:a)

22:56 serjeem: you're probably looking for something more like (first (find #(= v %) col)

22:56 Demosthenes_: what is the %?

22:56 serjeem: ddellacosta: beat me to it!

22:57 ddellacosta: Demosthenes_: it is the argument getting passed to the function. Here's an alternative synta:

22:57 *syntax

22:57 &(filter (fn [v] (= v :a)) [:a :b :c])

22:57 lazybot: ⇒ (:a)

22:57 Demosthenes_: oh I see

22:57 Lanny: is there a syntax for multiple arguments

22:57 Demosthenes_: ty

22:57 Lanny: and how does one google docs for "#()"

22:57 ddellacosta: Demosthenes_: np

22:58 Lanny: yeah, you can do

22:58 &(reduce #(assoc %1 %2 :foo) {} [1 2 3])

22:58 lazybot: ⇒ {3 :foo, 2 :foo, 1 :foo}

22:58 blaenk: Lanny: just search for clojure lambdas or anonymous functions

22:58 ddellacosta: for example

22:58 whoops, backwards

22:58 &(reduce #(assoc %1 :foo %2) {} [1 2 3])

22:58 lazybot: ⇒ {:foo 3}

22:58 ddellacosta: well, that's a dumb function

22:58 but you get the picture hopefully

22:59 cbp: Lanny: http://clojure.org/reader

22:59 dbasch: you could also do

22:59 Lanny: nifty, thanks

22:59 dbasch: ,(filter #{:a} [:a :b :c])

22:59 clojurebot: (:a)

22:59 dbasch: ,(filter #{:d} [:a :b :c])

22:59 clojurebot: ()

23:06 platz: where in the documentation do I find that set can be used as a Fn?

23:07 or just something you learn an memorize

23:08 I mean I know it's on clojure.org somewhere

23:08 but there probably isn't an wasy way to find out via the repl (doc)

23:08 dbasch: platz: http://clojure.org/data_structures#Data Structures-Sets

23:09 platz: dbasch: ah, thanks - reading now

Logging service provided by n01se.net