#clojure log - May 05 2015

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

0:02 jhn: why does (get {:a "1"} :a :z) => :z

0:03 but (get {:a "1"} :a (throw (Exception. "woops"))) => Exception woops user/eval786 (NO_SOURCE_FILE:1)

0:03 I thought that last expression would only execute if the key is not missing?

0:04 justin_smith: jhn: it's not a macro

0:04 jhn: so all the args are evaluated

0:05 it would be easy to make the macro version that does what you want, of course

0:05 jhn: ah, interesting, that makes sense.

0:08 so I ran into this ^ at https://github.com/jhn/clojure/blob/master/src/clj/clojure/gvec.clj#L458

0:09 and according to this: http://dev.clojure.org/jira/browse/CLJ-1705 it's better to throw a more informative exception

0:09 so my simple solution is this

0:09 https://gist.github.com/jhn/b6d3e86f521ac903316f

0:10 is this good /idiomatic enough?

0:23 justin_smith: jhn: that's how I would do it if I wanted that behavior. Except for the indentation being a little off

0:24 also the idiomatic version of ^{:private true} is ^:private

0:24 jhn: justin_smith: I let vim do it for me :-/ what would be proper?

0:24 justin_smith: :long lining up directly under :int

0:24 as in the first version

0:25 for the metadata, the ^{:something true} version is only needed if you are setting two or more keys

0:26 jhn: what do you mean setting two or more keys?

0:26 the original version https://github.com/jhn/clojure/blob/master/src/clj/clojure/gvec.clj#L458 is not setting anything

0:26 but it has ^{:private true}

0:26 justin_smith: it's setting the :private key to true in the metadata map

0:27 that's only one key, so it can be replaced with ^:private

0:27 jhn: oh I see, so Rich's style is just outdated? :-)

0:28 justin_smith: now if you had ^{:private true :doc "this is a thing"} then you are setting two keys

0:28 jhn: richhickey authored on Apr 26, 2010

0:28 i see

0:28 justin_smith: jhn: yeah, that's old code, probably had no reason to update it to the newer style

0:28 but for new code, you should use the current style

0:28 jhn: cool. will remove it then.

0:30 updated: https://gist.github.com/jhn/b6d3e86f521ac903316f

0:31 justin_smith: ,(meta ^:foo [])

0:31 clojurebot: {:foo true}

0:32 justin_smith: jhn: yeah, that looks good

0:33 jhn: justin_smith: thanks!

0:37 the ticket in question says "Affects Version/s: Release 1.4, Release 1.6" — does this mean that I'd have to checkout the respective tags from the git repo and apply my changes in each one separately?

0:37 http://dev.clojure.org/jira/browse/CLJ-1705

0:43 ed-g: hello everyone. how can I return a binary stream (protocol buffer) as a Ring response?

0:56 ok I've figured that out.

0:58 next question. how do I read a binary file into a byte[] array?

1:07 TEttinger: ed-g: there isn't a way in clojure's core lib, but you have access to all of java's core lib too, which includes https://docs.oracle.com/javase/8/docs/api/java/nio/file/Files.html#readAllBytes-java.nio.file.Path-

1:07 well there probably is a way with clojure's core lib, but it wouldn't be much simpler than that

1:08 (java.nio.file.Files/readAllBytes "myfile.bin")

1:11 hm crap

1:11 that takes a Path not a string

1:13 (java.nio.file.Files/readAllBytes (java.nio.files.Paths/get "path/to/file"))

1:13 ed-g, that should work

1:52 lvh: Is it idiomatic clojure to not use a kw as a fn and instead use get, when you want an early exception if a key is missing?

1:58 ed-g: TEttinger, thank you!

1:58 TEttinger: woo!

1:59 lvh, IIRC using a kw as a fn actually still allows the default arg

1:59 ,(:not-there {} :default)

1:59 clojurebot: :default

2:00 ed-g: (inc TEttinger )

2:00 lazybot: ⇒ 4

2:00 TEttinger: thanks ed-g, the space after my name there thanks you

2:00 (identity justin_smith )

2:00 lazybot: justin_smith has karma 9.

2:01 TEttinger: huh, my bonus-space karma is going up at a faster rate than justin_smith's bonus-space karma despite the actual karma being different

2:01 (identity justin_smith)

2:01 lazybot: justin_smith has karma 250.

2:01 ed-g: TEttinger, oops. I thought the bot would tokenize

2:01 TEttinger: it's an odd one

2:01 it actually allows complex stuff, strange things

2:02 (inc #_)

2:02 lazybot: ⇒ 1

2:02 TEttinger: (inc #_ )

2:02 lazybot: ⇒ 1

2:02 TEttinger: (identity #_)

2:02 lazybot: #_ has karma 1.

2:03 TEttinger: for the record, #_ does deserve more karma, it's quite useful in let bindings

2:04 lvh: TEttinger: I don't want the default, I want the exception

2:05 TEttinger: (:x m) is equivalent to (get m nil), not (get m)

2:05 TEttinger: ahhhh

2:05 ,(:not-there {})

2:05 clojurebot: nil

2:05 lvh: err, (get m :x nil) and (get m :x) of course

2:05 TEttinger: ,(get {} :not-there)

2:05 clojurebot: nil

2:05 TEttinger: uh

2:06 you sure?

2:06 lvh: huh, I got an NPE

2:07 oh, wait; sorry, I switched between -> and ->>

2:07 I probably messed up the order there

2:07 is there a way to do map access that eagerly complains?

2:37 TEttinger: Raynes: did something change in refheap's API? I just got a paste error

2:37 failed to paste: peer not authenticated

2:40 sm0ke: any library for code formatting? sql, groovy etc

3:48 dfletcher: Man, I really appreciate how much clojure reads out like English sometimes. Two neat ones from this file I'm looking at: (.load fxml stream) (.lookup node "#HBox") both doing exactly what they say :)

3:51 Sizur: i'm really happy that there is a resurgence of homoiconic languages

3:52 dfletcher: it affects my naming of things a bit. "node" was a better choice than "root" so resulting code reads much nicer. and "fxml" instead of "loader" similarly.

3:52 (.load root "#HBox") is a little less informative and more misleading. not loading any root anything here ;)

3:54 err. .lookup not .load. 1am prob time for bed hehe.

4:05 Hmm. Bed or put on a movie and write clojure 'till 4am? I think we all know where this is going.

4:08 I decided to go with this neat thing for parsing command line opts https://github.com/clojure/tools.cli .. does anyone think it's a terrible idea to re-def a global after parsing args and let rest of program read that? else pass it around everywhere?

4:10 after init time it would ofc be treated entirely as a constant. seems a bit nicer to me than passing config into everything.

4:14 I guess the example does pass the results down into everything. Hmm. Alright nevermind talked myself into it I'll go as clean as possible.

4:22 chipf0rk: Hi! Can someone explain to me why `recur` requires >= 2 args for functions with one arg + optionals?

4:28 irctc: Can someone explain what is going on here (first (first (map #(do '(%)) (range)))). It returns p1__4908#. Probably it has something to do with lazy seqs. If i do not wrap the % in a list it works as expected.

4:33 chipf0rk: you're quoting the list containing the unique symbol that clojure generated to use instead of %. if you want to construct a list, use list. for this specific way of doing things, you could use syntax-quote with splicing instead:

4:34 #(do `(~%))

4:34 nothing to do with lazy seqs; you're just getting a symbol instead of the value you want because you quoted the entire expression

4:35 irctc: nice it works now

4:35 what is the better solution (list ) or ~

4:35 chipf0rk: definitely list

4:36 ~ requires syntax quoting which most of the time is not what you want

4:36 clojurebot: Ok.

5:31 zot: what's really happening when using :exclusions in a project.clj? are the named things just "dropped" with the assumption that some other dependency fulfills the need?

6:07 dysfun: what's the easiest way to slurp a java.io.File?

6:11 oddcully: (slurp thefile)?

6:12 hyPiRion: zot: Or with the assumption that you will never use said dependency

6:12 dysfun: doesn't do that :/

6:12 oddcully: ,(slurp (java.io.File. "/etc/passwd"))

6:12 clojurebot: #error{:cause "denied", :via [{:type java.lang.SecurityException, :message "denied", :at [clojurebot.sandbox$enable_security_manager$fn__887 invoke "sandbox.clj" 69]}], :trace [[clojurebot.sandbox$enable_security_manager$fn__887 invoke "sandbox.clj" 69] [clojurebot.sandbox.proxy$java.lang.SecurityManager$Door$f500ea40 checkRead nil -1] [java.io.FileInputStream <init> "FileInputStream.java" 135] [c...

6:22 milanj: hi

6:23 simple questio

6:23 anyone has idea why `(1 2 3) is of type Cons

6:23 and not List

6:23 if '(1 2 3) is List this looks discrepantly

6:28 Bronsa: milanj: the only guarantee you have is that () will return a seq no guarantee on the concrete type

6:30 milanj: but ` and ' should expand to similar things ?

6:30 and thus create the same type ?

6:32 Bronsa: no they don't

6:32 it's an implementation detail anyway

6:37 milanj: well, probably, for someone with php experience (not saying it's you)

6:37 everything is "implementation detail"

6:38 oddcully: that's the reason why ` does something else than ' in php... scnr

6:39 milanj: hah, not saying it's me anyway, just that mindset

6:39 Bronsa: milanj: not sure I understand what you're implying here.

6:39 milanj: "it's implementation detail"

6:39 shouldn't be in this case

6:40 Bronsa: why?

6:40 clojurebot: why is Why

6:40 Bronsa: milanj: there are tons of concrete seq implementations in clojure

6:40 (class (seq []))

6:40 ,(class (seq []))

6:40 clojurebot: nil

6:40 Bronsa: ,(class (seq [1]))

6:40 clojurebot: clojure.lang.PersistentVector$ChunkedSeq

6:40 Bronsa: ,(class (seq {1 1}]))

6:40 clojurebot: #<RuntimeException java.lang.RuntimeException: Unmatched delimiter: ]>

6:40 Bronsa: ,(class (seq {1 1}))

6:40 clojurebot: clojure.lang.PersistentArrayMap$Seq

6:40 milanj: not connected

6:40 ' and ` should expand to same "sequence" construct code

6:40 Bronsa: except ' and ` do differnt things

6:41 '`()

6:41 ,'`()

6:41 clojurebot: (clojure.core/list)

6:41 Bronsa: ,''()

6:41 clojurebot: (quote ())

6:42 milanj: of course they do different things

6:42 Bronsa: then why do you expect them to expand to the same code?

6:43 but the most important question is -- why do you care what concrete implementation is returned? again, there's no mention on the doc about the returned class

6:59 noncom|2: can anyone suggest a good code editor for clojure on android?

7:05 drguildo: is there a way of maintaining access to functions like clojure.repl/doc when switching ns inside a cider repl?

7:06 without having to specify the full path to it

7:06 justin_smith: drguildo: you can require clojure.repl in the new ns, or use vinyasa https://github.com/zcaudate/vinyasa

7:07 drguildo: sorry should have said i meant automatically

7:07 i'll take a look at vinyasa though thanks

7:07 justin_smith: my preference is to switch back to user for that stuff, then back into some app namespace only as needed

7:07 but that's not at all automatic of course

7:09 drguildo: is there a quick way to switch between namespaces in cider?

7:09 i.e. a keybinding

7:10 justin_smith: if you eval code in some file (eg. C-M-x to load a defun) it will be evaluated in that ns

7:10 chipf0rk: C-c M-n to switch to the ns of the current file

7:10 justin_smith: without changing the ns of your repl

7:12 nilern_: milanj: clojure prefers programming to interfaces over concrete types, i.e. ISeq and also encourages us to do so

7:13 chipf0rk: Can someone explain to me why `recur` requires >= 2 args for functions with one arg + optionals?

7:13 i.e. (fn [x & xs] ... (recur (inc x))) is invalid code

7:14 justin_smith: "' and ` should expand to same "sequence" construct code" - yeah, citation needed for that "should"

7:18 mpenet: nilern_: yes! It also expands to libraries/apis, sadly not everybody thinks that way, even people you would expect to do so

7:20 I was recently bit by an (assert (vector? arg)) in a *very* popular lib and the author rejected a patch using sequential?

7:20 justin_smith: chipf0rk: Bronsa understands the why of this better than I do, but recur targets don't use varargs normally.

7:20 mpenet: weird

7:21 mpenet: was the arg being used for indexed lookup?

7:22 mpenet: nope

7:23 the lib is component

7:23 chipf0rk: So this is known and "intended" behaviour? I'm aware that this isn't standard coding style, but it made for a really succinct reimplementation of `trampoline` in 4clojure challenges

7:23 And I kind of expected it to work regardless :)

7:24 mpenet: I was surprised by the answer, to say the least: https://github.com/stuartsierra/component/pull/27

7:24 justin_smith: chipf0rk: coding to concrete type is almost always wrong in clojure

7:25 chipf0rk: sorry, not sure what you're saying?

7:25 justin_smith: chipf0rk: for example {:a 0} returns a PersistentArrayMap and if you assoc enough keys onto it you get a PersistentHashMap back. If you coded against those types, it would be a pain in the ass

7:26 but instead, you can code against the interfaces / protocols (like clojure.lang.Associative), and it's not an issue

7:26 zoldar: justin_smith: I think you are adressing the wrong person :)

7:26 chipf0rk: I'm aware, I think you're confusing my convo with milanj's here

7:26 justin_smith: oops

7:26 sorry

7:26 TEttinger: hehe

7:26 chipf0rk: np

7:26 justin_smith: chipf0rk: recur doesn't do varargs

7:27 and yes that's known and I would assume intended

7:31 chipf0rk: It does seem to work as long as the varargs part consists at least of one argument

7:31 which is odd

7:31 If it didn't work with them at all I wouldn't be surprised

7:31 justin_smith: Bronsa: so what's the deal with recur and varargs again?

7:33 chipf0rk: the args need to be there, but the vararg destructuring is not done ##((fn [a & args] (if (empty? args) a (recur (conj a (first args)) (rest args)))) nil 1 2 3)

7:33 lazybot: ⇒ (3 2 1)

7:34 justin_smith: or, I should say structuring - they should be provided in their "post listified" form

7:35 Bronsa: justin_smith: I actually don't remember exactly. had to do with avoiding the need for apply-recur

7:35 justin_smith: OK

7:36 yeah, I'it's definitely

7:36 err

7:36 zoldar: chipf0rk: here's a bit dated but probably still accurate explanation of handling varargs in the context recur by Michal Marczyk: http://programming.nullanswer.com/forum/1377301

7:36 justin_smith: I'd assume it's much easier to implement recur without adding the varargs logic to it

7:38 zoldar: that site ***umes much about substrings

7:38 lol

7:38 zoldar: :)

7:41 chipf0rk: had to think about this for a moment, so you're saying this only works because we're using `rest` and thus providing something that is already a list as pseudo-varargs?

7:41 that makes sense. thanks for the link too :)

7:41 justin_smith: chipf0rk: exactly

7:41 oddcully: well or more likely the original http://stackoverflow.com/questions/3670010/apply-recur-macro-in-clojure/3670343#3670343

7:42 justin_smith: (inc oddcully)

7:42 lazybot: ⇒ 7

7:42 chipf0rk: what is it with these sites that are just restyled stackoverflows

7:42 oddcully: if you rip other pages, get the code formatting right

7:42 justin_smith: there are sites that do it with irc too

7:42 if I search for justin_smith I find a lot of it

7:43 zoldar: harvesting content from other sites -> dodgy seo -> cash from ads

7:43 justin_smith: well, there's lots of people with my name, but throw clojure in there too

7:43 chipf0rk: well it seems to work... sadly

7:44 oddcully: yeah or just a malware catapult

7:44 chipf0rk: justin_smith: haha, is (inc ...) the way of giving out karma here?

7:45 justin_smith: chipf0rk: yessir

7:45 chipf0rk: love it

7:45 justin_smith: oddcully: speaking of, the other day I was reading about a mail anonymizer, where on their home page had a link to a cracked copy of the app (normally cost $200+). The cracked copy was a trojan that added your computer to their mailer relay botnet.

7:46 the fact that they went ahead and said "here's the cracked version if you don't want to pay for it" on their own site is hilarious

7:48 mpenet`: technically it's not a "cracked" version

7:48 justin_smith: sure, but that's what they called it

7:50 http://www.net-security.org/malware_news.php?id=3030

8:16 Confusionist: justin_smith, they could have been upfront about that feature (that is now considered a trojan) and just called it the 'payment-in-kind edition'

8:24 justin_smith: heh

9:00 status402: Is there a way to integrate with Java that doesn't involve Leiningen subsuming the whole project? I'm wondering if I could just sort of stick the Clojure project in a subdirectory.

9:02 agarman: when integrating with a large Java application, I added necessary changes to the pom.xml

9:03 using a project.clj would result in having to maintain dependencies in two files…

9:15 status402: agarman: So leiningen would work off a pom.xml where no project.clj is present+

9:16 *?

9:16 clojurebot: * is just for when you are lazy and sloppy

9:20 TimMc: status402: There are plugins for Maven.

9:20 status402: TimMC: Thanks. I'll look into it.

9:21 TimMc: status402: https://github.com/talios/clojure-maven-plugin I think

10:41 J_Arcane: Can anyone here who's used Monger tell me what a find-one-as-map returns if the item isn't found? Because the docs sure don't seem to.

10:41 {}?

10:50 TimMc: PUrely from the name, one would expect nil...

10:50 Check the source.

10:53 chipf0rk: well, I would expect {} purely from the name. so it's already worth of documentation

10:53 worthy*

10:54 J_Arcane: yes, {} seems to do the trick, or at least, it returns something that checks true with empty?

10:55 chipf0rk: (empty? nil)

10:55 is also true, but if that's enough of a safeguard in your case, good

10:56 J_Arcane: Yeah.

10:58 TimMc: J_Arcane: com.mongodb.DBCollection/findOne yields a DBObject, which monger then converts into a clojure-y thing.

10:59 findOne fails to document the behavior when not found, but I bet it returns null.

11:00 The question then is what monger does with nil...

11:16 kaiyin: i have a 0.1M by 20M matrix that i want to store on harddisk but also make it accessible from clojure without needing to read the entire thing into ram, could anyone suggestion a solution?

11:18 nkoza: kaiyin: http://docs.oracle.com/javase/7/docs/api/java/nio/MappedByteBuffer.html

12:31 lvh: How does sqlingvo compare to korma compare to honeysql? They all seem extremely similar.

12:35 sobel: I'll gladly recommend against DSLs to write DSLs at runtime

12:35 (SQL is already a DSL)

12:35 wasamasa: ^

12:35 also, the clojure jdbc wrapper is surprisingly good compared to the original

12:36 sobel: it's so easy to write a clojure function to wrap sql, leave it at that

12:36 when you have horrible data structures (e.g. objects, reflection) forcing you into complex marshalling systems, maybe. but not in clojure.

12:37 the clojure jdbc wrapper is indeed good. i am pretty sure it covers everything i ever did with Spring JDBCTemplates

12:38 lvh: sobel: I'm not sure why it's more constrained to runtime than plain old SQL?

12:40 sobel: lvh: it's less about runtime than about stacking DSLs

12:40 lvh: sobel: OK. Why's that bad?

12:40 sobel: I could see why it falls down if you want to express something in the bottom DSL that the top one can't express.

12:40 sobel: lvh: fundamentally, it's a leaky abstraction

12:40 the bottom isn't the only place it leaks

12:41 briefly, trivial data access patterns are already pretty dang portable, and complicated rarely get/need porting and tend to defy ORMs anyway

12:43 lvh: ok, yesql-ghosts convinced me that maybe it's not the worst idea

12:43 I'll give it a try; thanks for the suggestion

12:44 sobel: I'm assuming that you'd recommend yesql in particular as a way of just using SQL?

12:46 sobel: lvh: not sure why you'd assume that. i see little reason to isolate application queries into files and use that defquery macro to integrate them. i don't see that as valuable.

12:46 lvh: sobel: OK. What do you suggest instead?

12:46 sobel: Just strings in clj files that hold SQL queries?

12:46 sobel: lvh: isolate queries into a domain-specific library

12:47 lvh: yeah. don't create unnecessary work

12:47 lvh: That seems orthogonal to...

12:47 OK

12:49 sobel: here's the thing. you already have a jdbc library. you won't reuse any part of the domain access library. it will need modification as your schema grows/changes. or maybe reimplementation if the data system changes significantly.

12:53 wasamasa: lvh: yesql is ok, but even that exposes the leakiness

12:53 lvh: wasamasa: why's that?

12:53 wasamasa: lvh: like, it's fixing the order of arguments

12:53 lvh: you also add a level of indirection by using a separate file and defqueries

12:54 lvh: which had me hunting a bug for half a day because I didn't know about purging the REPL namespaces :D

12:55 sobel: what's the benefit of keeping queries in a separate file?

12:55 wasamasa: you have syntax highlighting!

12:56 sobel: srsly!

12:56 wasamasa: yes

12:56 and it feels cleaner of course

12:56 sobel: o/~ feelings o/~

12:56 wasamasa: but overall I'm not impressed with it, a clear API over your database adaptor delivers pretty much everything else you need

12:56 sobel: anything tangible besides syntax highlighting?

12:57 lvh: sobel: The tools are a bit nicer than just syntax highlighting, but sure

12:57 tatut: other tools can read .sql files and work with them

12:57 lvh: sobel: You can share the .sql files between projects.

12:57 sobel: i have design input based on those concerns

12:58 if you really find that syntax highlighting is that useful, either your sql-fu is insufficient or the size of query you are cramming into the application adapter is too big. you should probably consider a stored proc or view to keep that under control. the bigger the query, the more likely it tightly couples your app to the schema and that coupling is something you need to manage.

13:00 if you really find that you need to share sql between projects, you might consider that either your sql-fu is insufficient or the size of the query you are cramming into the app...blah blah blah...implement a remote facade pattern to share useful access patterns you want to expose to applications. if they are really sharing access patterns, let them share a library too. a sql file isn't a great way to share code though.

13:02 tatut: syntax highlight is evidence of *-fu? I use syntax highlighting in all langs I work with :)

13:02 of low *-fu I mean

13:02 sobel: oh, i do too, but i don't sweat it for one-liners embedded in clojure

13:03 IOW i have clojure syntax highlighted but the sql is just a string, and i don't let those get out of hand

13:03 tatut: SQL is language... not "just a string" in my opinion

13:03 sobel: i did not say or mean to imply using syntax highlighting is evidence of low skill, so much as if it's necessary to have it for the tiny bits of sql in your application interfaces

13:04 embedded SQL in Clojure is just a string, in the sense that it is a String

13:04 tatut: I much prefer having longer queries than doing stored procs

13:04 you have to manage and version those sprocs too

13:04 sobel: yup, they're code too

13:05 tatut: and another thing to deploy in your CI pipeline

13:05 wasamasa: btw, there are programs that can syntax-highlight multiple languages at once :P

13:05 pandeiro: does anyone have experience using session cookies with single page apps that do CORS requests to a different host or port? my api server is returning the Set-Cookie header but it seems like the browser (Chrome) is ignoring it

13:05 sobel: if you don't already test your schema in CI the process is deficient

13:06 so the "more work" argument holds no weight with me. if you have a database and don't test it you're missing a spot.

13:06 tatut: fair enough

13:07 sobel: there's also the simple fact that applications can't always be trusted with db access, and we have to implement remote facades just to protect from malicious queries

13:07 tatut: I'll still keep my longer queries instead of stored procs tho

13:08 sobel: you can do that, and you can rip them out of clojure to edit them in a syntax-aware buffer. it's not that hard but it's harder than keeping my stuff in adapter code simple, since my scope includes all the sprocs anyway

13:08 wasamasa: http://soft-dev.org/pubs/html/diekmann_tratt__eco_a_language_composition_editor/

13:08 ruhe: how do you construct your yesql-based code (or any other similar framework) if you need to translate complex query from complex search form into SQL? Are there examples of such code on github?

13:09 sobel: yesql still uses SQL

13:09 wasamasa: it's just wrappers you'd write around SQL anyways

13:10 mavbozo: pandeiro, i tried it quite some time ago, and i find that my server can not set cookie for different domain other than its own domain

13:11 maybe things change now

13:11 tatut: I'm still not quite sold on the benefit of "remote facades", why wouldn't you trust the app you code with db access?

13:12 sobel: tatut: because it's an unnecessary risk which, in practice, has proven untrustworthy

13:12 acyed: is anyone here a physics major?

13:13 sobel: tatut: ask any DBA at a finance agency how many times the max loan size trigger has been tripped by an app gone haywire, attempting to create loans for untold millions. if i hadn't seen it in person i wouldn't be such a proponent of using databases as full safety backstops.

13:13 acyed: I know that's kind of random, but I've done some modeling in clojure and I need a second set of eyes

13:14 tatut: sobel: but as both the app and the sprocs are code, both must be tested... why is sproc code inherently safer than app code?

13:14 sobel: tatut: it's entirely possible for an application to become compromised in a way that can be mitigated by appropriate role restrictions and data constraints in the database

13:14 tatut: bugs can be in either

13:14 tbaldridge: a nice thing about using sprocs is that it allows the DBAs to completely re-write the structure of tables under an app, and the app will never know

13:15 sobel: tatut: because it runs in the database. and constraints are pretty rigorous code to reuse.

13:15 tbaldridge: if apps use sprocs and views, the DB structure is essentially abstracted from the app

13:16 sobel: tbaldridge: where you say sprocs and views i say remote facade

13:16 tbaldridge: exactly, I'm agreeing with you. :-)

13:16 sobel: outside of the security issues, remote facades let you decouple your schema from the app. that is valuable.

13:16 ruhe: that's why i liked to use spring jdbc along with stored procedures. it provided really nice API over sprocs

13:16 sobel: tbaldridge: yes, yes )

13:16 :)

13:16 hiredman: man, I wish we had a dba to restructure this mess

13:17 TimMc: hahaha DBA

13:17 sobel: i really liked writing remote facades, testing with PGTap, and deploying extremely reliable code a couple jobs back

13:17 tatut: I get the abstraction part, that could be useful... but I still don't get the security part

13:17 TimMc: The only place I've worked with a true DBA there was so much territoriality about the DB.

13:18 amalloy: acyed: better to ask your actual question, and hope someone qualified sees it, than to ask for volunteers to help with an unknown task

13:19 tbaldridge: TimMc: eh, it can depend on the Job. One place I worked, I was basically the DBA, and all that meant was I handled all sproc implementations and optimizations. Why? Because I was good at it, the only reason.

13:20 No reason for the entire team to learn all the ins and outs of a query engine, just tell one guy (or two or three), and let him spend the time to get it all working properly.

13:20 sobel: tatut: you can harden data access in the database in ways you cannot harden it in the application.

13:20 TimMc: tbaldridge: Who ended up designing the data layout?

13:20 tatut: how, exactly? or are we getting too deep into specifics

13:20 sobel: TimMc: bad DBAs aren't an argument against DBAs. sorry you had a territorial twerp on your team. ;)

13:20 tbaldridge: TimMc: myself, another DB guy, and the main software architect

13:21 TimMc: sobel: Oh, they weren't necessarily *bad* -- for all I know, they were defending the DB from people who wanted to abuse it. I was front-end on that job, so I don't know the specifics.

13:21 but it seemed like a situation ripe for conflict over control

13:22 When I said "hahaha DBA" I was thinking about how lots of places don't *have* them.

13:24 sobel: tatut: it's a great question you can get fully fleshed out on #postgresql but the short version is, databases have a scope-limited duty that makes them a good target for enforcing relations and constraints. then there are some things only a sproc can do (upsert for one popular example)

13:25 TimMc: gotcha. in my experience DBAs are always presiding over some nominal conflict for control.

13:25 my current job has what seems to be the blasted-out remains of a battle not even valiantly fought over control of the db

13:25 (java devs won)

13:26 TimMc: I have some trouble understanding who would manage the data layout if there's a DBA because it's so intricately coupled with the code.

13:26 Having the DBA as an optimizer and advisor makes a lot of sense to me.

13:27 VFe: The problem I see with (some) DBAs, is they focus on very abstract optimizations well ignoring practical ones.

13:27 sobel: they either have one dev that feels empowered/comfortable taking it over as a dev duty, or they just don't change much

13:27 VFe: i.e. this structure in theory runs great! except for on this hardware it doesnt

13:28 tatut: thanks guys, good talk :)

13:28 sobel: VFe: their manager should be telling them what their deliverable goal is, performance, or ...

13:28 tatut: likewise, i'm running off to lunch myself now

13:28 VFe: Though honestly that’s a problem well beyond DBAs, and has more to do with how CS educating is constantly abstracting away performance :)

13:28 sobel: no, that's squarely in the DBA role duties

13:28 acyed: http://pastebin.com/AeT1MYc9 This is a program I've written to model the trajectory of a 105mm howitzer round side fired from a C-130 to predict the impact point of the bullet. I'm having a hell of a time getting the solution right (I have a ballistics table that gives me the gun depression and lag angles for most altitudes and airspeed). This is more of a physics question, not a clojure question, but I've been working on it for two we

13:29 and the guys in #physics don't know clojure

13:29 sobel: er, sorry, i don't think CS is abstracting away performance. ask michael stonebraker if he's eschewing CS to make kickass databases. ;)

13:30 acyed: http://imgur.com/3YaI6wI this is a plot of what that program outputs.

13:30 VFe: As a CS educator I’d disagree, I consistently see programs that graduate people with no understanding of low level performance(and how high level abstractions utilize(or dont) it)

13:31 And I see that repeated throughout the industry as a result(people who have a firm understanding of logical performance but no grasp of why it may not work on real metal)

13:31 sobel: what do you expect from a 4yr program not in the eng. dept?

13:32 i had more than 8yr experience before i started to have a rational clue about i/o and complexity

13:32 VFe: I see it in PhDs more than 4yrs, 4yrs dont even learn the basics anymore XD

13:33 sobel: performance is not as critical as it used to be, either. at 100MHz you just don't have the cycles to burn.

13:33 some laziness is just atrophy

13:33 VFe: Correct, though in some domains (particularly DBs) it’s still super relevant

13:34 sobel: i've always been told to view college as a generalist's certification, though. you're talking about fairly applied topics.

13:34 VFe: and I was just commenting that I see a lot of the fighting between devs and DBAs in my experience, stems from the mismatch of their ideas on performance

13:34 sobel: ...DBAs have ideas, devs don't? :)

13:34 VFe: That’s clearly not what I said.

13:35 sobel: the way i figure, most the DBAs i worked with could and have done the regular dev job. but the converse is not true.

13:35 VFe: In my experience most DBAs graduate from the system admin role more than the dev side of things.

13:35 sobel: so when it comes to a question of merits, i seem to side with DBAs culturally. but that is a simple misapprehension of the choice made. it's political hell for me, though.

13:36 VFe: It’s not uncommon for many of my clients to have DBAs with very light programming experience.

13:36 sobel: VFe: i've been lucky/choosy/sheltered in working with a lot of DBAs rooted in the developer side of the shop

13:36 but regardless of the background, perf is perf

13:37 and lunch is lunch. catch you later.

13:59 Natane: So if i want to eval a single sexp that's inside a function, what's a convenient way to do that using cider?

14:00 My repl works and all, it's just that arguments to that function can't be resolved

14:00 (for an obvious reason)

14:00 i was wondering if i can go around that

14:06 amalloy: Natane: i mean, the arguments to that function don't exist, you can't eval the sexp without them. how do you eval (+ x 2)?

14:06 you can only eval it in an environment that contains a binding for x

14:07 which could be ((fn [x] (+ x 2)) 5), as your function is usually called, or you could eval (let [x 5] (+ x 2)) if you want to eval a subsection of it selectively

14:09 Natane: yeah but say there is a long function that i wanted to debug without writing extra code anywhere

14:10 what would be the most ninja way to insert an argument?

14:10 justin_smith: Natane: write smaller functions

14:10 or user something like cursive or recent cider that lets you do step debugging

14:11 amalloy: the most ninja way would be with some kind of sword, and climbing boots. but i presume you are looking for a software-developer way

14:11 Natane: cider can do that?

14:12 sounds fun, thanks ^_^

14:12 justin_smith: recent versions claim to have that feature

14:12 but ugrading cider can be an epic challenge

14:13 Natane: yeah my emacs broke and i just had to do that recently D:

14:13 justin_smith: yeah, cider will test your emacs-fu skills

14:13 and your patience sometimes

14:14 Natane: i still couldn't embed cider repl in my program!

14:14 a normal repl works just fine

14:15 wait, ninjas have climbing boots?

14:15 justin_smith: for wall climbing

14:15 amalloy: well climbing slippers, or something. they climb walls

14:16 Natane: they do? i thought they just throw shurikens

14:16 TimMc: they strap squirrels to their feet

14:16 Natane: and conceal tantos in their mouths

14:17 i mean how do you run up a wall with a knife in your mouth, that's insane

14:17 justin_smith: well, if we really knew with any accuracy what ninjas were doing, they wouldn't be good ninjas

14:17 Natane: so ninjas are like lisp functions?

14:17 that makes sense

14:18 TimMc: ninjas: non-serializable

14:18 Natane: D:

14:38 amalloy: ,(apply *' (range 1 10))

14:38 clojurebot: 362880

14:40 Natane: what's *'? :D

14:41 justin_smith: (doc *')

14:41 clojurebot: "([] [x] [x y] [x y & more]); Returns the product of nums. (*) returns 1. Supports arbitrary precision. See also: *"

14:41 justin_smith: arbitrary and capricious

14:42 Natane: (doc *)

14:42 clojurebot: "([] [x] [x y] [x y & more]); Returns the product of nums. (*) returns 1. Does not auto-promote longs, will throw on overflow. See also: *'"

14:42 Natane: what's auto promotion?

14:43 actually nvm, found an article

15:16 underplank: Hi all. I’ve got the following code. https://www.refheap.com/100457

15:18 The issue is that if an exception is thrown somewhere in the let block then the cleanup that happens on the last two lines dont happen. Which when running with auto-refresh means all the other tests fail. I imagine that I need to use a (try (…) (finally)) block. but thats difficult as if I put it outside the let, then then finally doesnt have lexical scope, and If i put it within, then I can catch the whole thing. Im not sur

15:18 how to get around this issue. Any ideas?

15:28 lnostdal: hi, i keep getting "not a nrepl dict object: ..." when doing auto-completion via tab key .. i have company-mode enabled

15:29 JDShu: lnostdal: are you using cider?

15:30 Cust0dian: Anyone here has OP in #clojurescript? Getting spammed there.

15:30 w4ffles: wow, that's annoying

16:20 justin_smith: $mail underplank define a promise in an outer let block, wrap try/catch/finally around the inner and deliver to that promise, clean up the thing delivered to the promise in the finally, but only if (realized? p) returns true

16:20 lazybot: Message saved.

16:20 justin_smith: lnostdal: do you heave the clojure-complete nrepl middleware?

16:21 I think cider's nrepl middleware (delivered via the cider-nrepl plugin) may give you that though?

16:34 lnostdal: justin_smith, uhm, sorry, i had to go afk for a bit there ..it turned out to be a version problem; my cider in emacs was too new

16:35 justin_smith: ahh, so it didn't match the middleware you had

16:50 kaiyin: I really hate the fact that the order of function definition matters in clojure, is there a way around this? I know I can use (declare ...), it's still tedious.

16:53 sritchie: kaiyin you could make a special defn macro that walks code and automatically declares any symbols in the fn position that it can’t find in the environment?

16:54 kaiyin: sritchie: ok, i see, i will think about it when i start learning macros.

16:54 sritchie: kaiyin: in the meantime… just use declare :) or write stuff in order of use.

16:54 kaiyin: yeah.

16:56 amalloy: sritchie: that sounds super duper hard

16:56 sritchie: haha, first one or second one

16:56 amalloy: like you'd probably need to use tools.analyzer or something

17:02 tbaldrid_: tools.analyzer.jvm may work quite well

17:02 there's a hook that it calls when it wants to find a var, just have that fn create the var, and you're done

17:03 Pixie does that (creates vars on demand) and it's a blessing and a curse

17:04 misspell a var name an you now have a undefined var lying around

17:04 amalloy: yeah, but like...you don't want to do that just to allow you to write files in backwards order

17:16 TimMc: Just set Emacs to display and edit files in character reverse order.

17:23 uris77`: I actually like that clojure forces you to define the functions before you use them. It is how I tend to think in other languages also, so haven't found it to be much of a problem.

17:35 shem: one starts to look at a namespace from the bottom of the file, going upwards. from the general to the specific

17:38 Jaood: the joys of a one-pass compiler

17:38 joelkuiper: Hey, I'm trying to use/make a rudimentray type hierarchy in ClojureScript. The problem I hope to solve is the following: I have a series of (reagent) components that I want to be of a certain "type", such that when a user add a component I can make sure it's of the right type (and filter option lists with isa? or decendants). However, I'm not sure multimethods are appropriate, and I'm also not sure how

17:38 to use the build-in type hiearchy on something other than ::stuff (things are defined in different namespaces)

17:40 Would it be possible to somehow "annotate" functions or maps with the (derive x y)?

17:42 tomjack: I'm not sure that "when a user add a component I can make sure it's of the right type" actually describes a problem

17:45 joelkuiper: tomjack: yea, you're right. It's more explained in this blog post https://joelkuiper.eu/knowledge; but in short there are a bunch of UI components that can be nested, however they can only be nested at certain places. For example a Markdown block is a Text block, but so is a plain text one. Similarly a sliders is a Number input, but so is a Number field. There is a hierchy of types that I wish to expre

17:45 ss as different (Reagent) components

17:48 TimMc: ~LISPers |always| turn to the back of the book first to see how it ends

17:48 clojurebot: Alles klar

17:51 joelkuiper: Ah, I guess I can just do some book keeping somewhere on the namespace-qualified symbols. Might not be pretty, but I guess it would work

17:57 tomjack: I mean, I just don't understand why you'd want to "make sure it's of the right type"

17:58 clojure style is to let them make the mistake, and then let a random exception or bug pop up :)

17:58 oh, you mean a user user, huh?

18:01 do you already know you can do ::foo/bar where (:require [com.example.foo :as foo])?

18:01 not sure what "things are defined in different namespaces" means

18:01 joelkuiper: tomjack: yep, that really helps!

18:02 tomjack: well I didn't know that a minute ago, but now I do ;-)

18:03 never really used the namespace qualified symbols, nor the hierarchy things

18:03 somehow they feel a bit weird, but I guess I'll get used to it

18:04 tomjack: and yeah a user, it's a UI feature...the term type is perhaps a bit confusing

18:15 justin_smith: is there a trick to using core.async with component? ava.lang.ClassCastException: clojure.core.async.impl.timers.TimeoutQueueEntry cannot be cast to clojure.core.async.impl.timers.TimeoutQueueEntry

18:16 I guess for now I won't use :reload-all when requiring my top level namespace in the repl

20:53 ambrosebs: ,(meta '^:foo a)

20:53 clojurebot: {:foo true}

22:10 l1x: hi

22:11 what is the best way to use reduce to apply the more computation to the output of the previous function? (map #(clojure.string/replace (.toLowerCase "test string") (first %) (second %)) '([#" " "_"] [#"\?" "_"] [#"\%" "_"]))

22:42 justin_smith: ,(reduce (fn [acc [a b]] (clojure.string/replace acc a b)) (.toLowerCase "Test ?%¥") [[#" " \_][#"\?" \_][#"\?" \_]])

22:42 clojurebot: #error{:cause "java.lang.Character cannot be cast to clojure.lang.IFn", :via [{:type java.lang.ClassCastException, :message "java.lang.Character cannot be cast to clojure.lang.IFn", :at [clojure.string$replace_by invoke "string.clj" 67]}], :trace [[clojure.string$replace_by invoke "string.clj" 67] [clojure.string$replace invoke "string.clj" 106] [sandbox$eval25$fn__27 invoke "NO_SOURCE_FILE" 0] [c...

22:43 justin_smith: ,(reduce (fn [acc [a b]] (clojure.string/replace acc a b)) (.toLowerCase "Test ?%¥") [[#" " "_"][#"\?" "_"][#"\?" "\"]])

22:43 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading string>

22:44 justin_smith: ,(reduce (fn [acc [a b]] (clojure.string/replace acc a b)) (.toLowerCase "Test ?%¥") [[#" " "_"][#"\?" "_"][#"\?" "\\"]])

22:44 clojurebot: "test__%¥"

22:47 l1x: thanks justin_smith

Logging service provided by n01se.net