#clojure log - Oct 14 2015

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

2:24 Seylerius: What's the string-formatting function in Clojure? If I need to take an int and turn it into a zero-padded string out to four digits?

2:25 Nevermind, found it.

2:33 sobel: did you use Formatter?

2:33 (java class)

2:37 Seylerius: sobel: http://clojuredocs.org/clojure.core/format

2:41 sobel: ah cool

2:41 beats pasting with str, which was my most recent solution to computing a chunk of text

2:52 elg: What would you call this? And/or is there a better way to do it? (defn thread-reduce [val f coll] #(reduce f val coll))

2:56 sm0ke: elg: dont get why you have an unnecessary function there

2:57 (partial reduce f val coll) is what you could also do if you want to return a function

2:57 elg: oops, I don't want to return a function. my bad - (defn thread-reduce [val f coll] (reduce f val coll))

2:58 sm0ke: or just #(reduce f val coll) should also be fine

2:58 ook

2:58 elg: what are you trying to do with it?

2:59 elg: user=> (-> {} (thread-reduce (fn [m k] (assoc m k 42)) [:foo :bar :baz]))

2:59 {:foo 42, :bar 42, :baz 42}

2:59 sm0ke: ,(reduce (fn [m k] (assoc m k 42)) {} [:foo :bar :baz])

2:59 clojurebot: {:foo 42, :bar 42, :baz 42}

3:00 elg: yes, but I want to continue the threading (->)

3:00 sm0ke: ,(doc as->)

3:00 clojurebot: "([expr name & forms]); Binds name to expr, evaluates the first form in the lexical context of that binding, then binds name to that result, repeating for each successive form, returning the result of the last form."

3:01 sm0ke: ,(as-> {} $ (into $ :a 1) (merge {:b 2} $))

3:01 clojurebot: #error {\n :cause "Don't know how to create ISeq from: java.lang.Long"\n :via\n [{:type java.lang.IllegalArgumentException\n :message "Don't know how to create ISeq from: java.lang.Long"\n :at [clojure.lang.RT seqFrom "RT.java" 535]}]\n :trace\n [[clojure.lang.RT seqFrom "RT.java" 535]\n [clojure.lang.RT seq "RT.java" 516]\n [clojure.core$seq__4116 invokeStatic "core.clj" 137]\n [clojure.co...

3:01 sm0ke: ,(as-> {} $ (assoc $ :a 1) (merge {:b 2} $))

3:01 clojurebot: {:b 2, :a 1}

3:01 sm0ke: you dont need to have contived function just so you could use ->

3:03 elg: cool, that's the sort of thing I was hoping to find. Thanks!

3:03 sm0ke: np

7:08 Wabsta: Hello, anyone here with experience in clojure for android?

7:41 novak`: I have a problem with installing a Java library using Leiningen. I have added [org.kie.modules/org-apache-commons-math "6.3.0.Final"] to my project.clj but lein can't find it on Maven with a message "Could not find artifact org.kie.modules:org-apache-commons-math:jar:6.3.0.Final in central (https://repo1.maven.org/maven2/)" but the lib obvious is present https://repo1.maven.org/maven2/org/kie/modules/org-apache-commons-math/

7:47 ordnungswidrig: jonathanj: I've added a smalish HAL example to a project of mine. I was pretty easily done with liberator and the halbrowser was happy with it. Unfortunately I cannot release the source and maybe I will bild another public example.

7:48 novak`: no, there's no 6.3.0 jar, just a file called org-apache-commons-math-6.3.0.Final-tests.jar

7:58 novak`: ordnungswidrig: absolutely right. Thanks

8:01 snowell: novak`: It looks like they don't have actual jars in maven central, just poms. I would try adding `:extension "pom"` to that dependency and see if that resolves it

8:02 [org.kie.modules/org-apache-commons-math "6.3.0.Final" :extension "pom"]

8:02 jonathanj: ordnungswidrig: i'd be quite interested to see a public example

8:05 snowell: novak`: Or just depend on [org.apache.commons/commons-math "2.2"] directly, as that seems to be the only thing the one you found brings in

8:30 noncom: i am experimenting with clojure.tools.analyer, the example: (ast/children (analyze '(do 1 2 :foo))) returns [], what am i doing wrong?

8:31 i should also say that the "analyze" function cannot be defined as in the example above since "create-var" is not found, so i am using ana.jvm/analyze instead

10:33 sdegutis: Is there a list of all the libraries that map a Ring request to a function I can define and map to a given path?

10:42 justin_smith: (filter is-ring-router? every-possible-function)

10:58 bja: sdegutis: are you looking for a list of ring routing libraries?

10:59 yenda: How would you use ansible from clojure ? With (sh) ?

11:00 sdegutis: Sort of, I guess? I'm looking for libraries that let you map paths to functions (both of your own choosing), and can create a single Ring handler from them.

11:01 I've been using Compojure, but Compojure uses function composition (oh! hey! that's probably where it gets its name from!) which is a very problematic approach. I'm looking for similar alternatives, but which don't use function composition.

11:03 justin_smith: sdegutis: the router I work on (and use in production) is polaris, it uses a data structure driven approach (the router can take functions, or keywords that get resolved when routing, or multimethods)

11:04 sdegutis: Oh right, we talked about this didn't we?

11:04 That's right. I think I was going to use weavejester's underlying library to just find a path that matches, and do it that way.

11:05 justin_smith: and I was griping that polaris uses that lib, and if it were up to me it would use a trie based approach

11:05 sdegutis: Oh right!

11:06 And then you explained what tries were and I got confused.

11:06 Man, those were the days.

11:06 justin_smith: wasn't your reason for preferring tries just efficiency?

11:07 justin_smith: and a deep suspicion of regex, yes

11:07 yenda: anybody here tried to use ansible from clojure or it doesn't make sense ?

11:07 justin_smith: like, with a regex based approach you create a separate matcher automata for each route, while with a trie you have a single automata that finds all the routes

11:12 mmg: so I thought I could alter string representations of records by overriding toString but it looks like clojure tools logger doesn’t try toString first? any thoughts on what method it’s calling and how I can better override it?

11:12 https://gist.github.com/philip-doctor/5cbf329ae6f69bb33058

11:12 justin_smith: mmg: check out the multimethod print-method

11:12 mmg: justin_smith: thanks!

11:12 justin_smith: ,(print-method :a)

11:13 clojurebot: #error {\n :cause "Wrong number of args (1) passed to: core/fn--4784/fn--4785"\n :via\n [{:type clojure.lang.ArityException\n :message "Wrong number of args (1) passed to: core/fn--4784/fn--4785"\n :at [clojure.lang.AFn throwArity "AFn.java" 429]}]\n :trace\n [[clojure.lang.AFn throwArity "AFn.java" 429]\n [clojure.lang.AFn invoke "AFn.java" 32]\n [clojure.lang.MultiFn invoke "MultiFn.java" ...

11:13 justin_smith: oops!

11:13 ,(print-method :a *out*)

11:13 clojurebot: :a

11:13 sdegutis: justin_smith: why not rewrite the internals of polaris so that it uses tries?

11:13 justin_smith: some day

11:17 ,(print-method (java.util.Date.) *out*)

11:17 clojurebot: #inst "2015-10-14T15:17:33.414-00:00"

11:17 justin_smith: ,(str (java.util.Date.))

11:17 clojurebot: "Wed Oct 14 15:17:40 GMT 2015"

11:17 justin_smith: that's a great example of the difference

11:19 sdegutis: No it's not

11:19 justin_smith: ?

11:20 sdegutis: I thought print-method chooses between str and pr-str based on whether *pretty-print* is truthy.

11:20 justin_smith: pr-str uses print-method

11:20 sdegutis: Oh. Well then the other way around.

11:20 Oh okay yeah.

11:20 Never mind me.

11:21 justin_smith: sdegutis: take away point being - define print-method to control how pr outputs, define toString to control what str creates

11:22 zarkone: Hi all! Did anyone use leiningen-jenkins plugin? Always get "Could not find or load main class clojure.main" error, a bit wierd...

11:22 sdegutis: yeah

11:23 wait, that's not what component uses?

11:23 Oh wait yeah it does.

11:23 https://github.com/stuartsierra/component/blob/master/src/com/stuartsierra/component.cljc#L183

11:40 yenda: zarkone: do you have a main class in your project ? is it defined in the project.clj file ? do you have (:gen-class) in your namespace definition in core.clj ?

11:40 zarkone: you have all of these when you create a project with lein new app yourproject

11:40 but not when you call lein new yourproject

11:42 justin_smith: yenda: why would that lead to a "cannot find or load main class clojure.main" message?

11:43 yenda: I build and run uberjars without any aot - I get warnings that no main class was compiled, but I can still run the jar via clojure.main, which is aot compiled and will be in an uberjar

11:46 zarkone: yenda: hey! if i run the command genearted by plugin on my local machine, i've got something like "project.clj not found"

11:52 sdegutis: hold on a second

12:04 justin_smith: sdegutis: continuing to hold

12:05 sdegutis: ok never mind

12:09 justin_smith: select count(fucks) from given; => 0

12:11 xemdetia: I wonder if given is fully normalized

12:12 justin_smith: haha

12:14 yenda: (let [given {:fucks 0 :potatoes 1000 :bananas 42}] (:fucks given))

12:15 ,(let [given {:fucks 0 :potatoes 1000 :bananas 42}] (:fucks given))

12:15 clojurebot: 0

12:15 justin_smith: well look who's potato rich

12:15 mister potato trump over there

12:16 yenda: But I'm sad, I want to use pallet and it looks like a dead project :( I would give many potatoes to save it

12:16 clojure automated deployment would be awesome

12:16 justin_smith: last updated august 12th?

12:17 other projects in that group updated this week even

12:17 not so bad

12:17 yenda: it's just the aws module

12:17 but the main module it broken because jclouds updated and one of the api call is deprecated

12:17 justin_smith: ouch

12:18 when did this happen?

12:18 n/m see the github issue now, opened by some guy named "yenda"

12:19 yenda: looks like me

12:19 * yenda ?

12:25 visof: ,(partition 2 '(1 2 3 4))

12:25 clojurebot: ((1 2) (3 4))

12:26 justin_smith: ,(partition 2 '(1 2 3 4 :missing))

12:26 clojurebot: ((1 2) (3 4))

12:26 visof: ,(for [x (partition 2 '(1 2 3 4)) y '(partition 2 '(5 6 7 8))] [x y])

12:26 clojurebot: ([(1 2) partition] [(1 2) 2] [(1 2) (quote (5 6 7 8))] [(3 4) partition] [(3 4) 2] ...)

12:26 justin_smith: ?

12:27 visof: justin_smith: i want to get [(1 2) (5 6)] [(3 4) (7 8)]

12:27 sm0ke: ,(partition-all 2 [1 2 3 4 :missing])

12:27 clojurebot: ((1 2) (3 4) (:missing))

12:28 sdegutis: ,(())

12:28 clojurebot: #error {\n :cause "clojure.lang.PersistentList$EmptyList cannot be cast to clojure.lang.IFn"\n :via\n [{:type java.lang.ClassCastException\n :message "clojure.lang.PersistentList$EmptyList cannot be cast to clojure.lang.IFn"\n :at [sandbox$eval145 invokeStatic "NO_SOURCE_FILE" 0]}]\n :trace\n [[sandbox$eval145 invokeStatic "NO_SOURCE_FILE" 0]\n [sandbox$eval145 invoke "NO_SOURCE_FILE" -1]\n ...

12:28 sdegutis: ,[([()])]

12:28 clojurebot: #error {\n :cause "Wrong number of args (0) passed to: PersistentVector"\n :via\n [{:type clojure.lang.ArityException\n :message "Wrong number of args (0) passed to: PersistentVector"\n :at [clojure.lang.AFn throwArity "AFn.java" 429]}]\n :trace\n [[clojure.lang.AFn throwArity "AFn.java" 429]\n [clojure.lang.AFn invoke "AFn.java" 28]\n [sandbox$eval169 invokeStatic "NO_SOURCE_FILE" 0]\n [sa...

12:28 visof: ,(for [x (partition 2 '(1 2 3 4 :missing)) y '(partition 2 '(5 6 7 8 :missing))] [x y])

12:28 clojurebot: ([(1 2) partition] [(1 2) 2] [(1 2) (quote (5 6 7 8 :missing))] [(3 4) partition] [(3 4) 2] ...)

12:28 sdegutis: ,#{[()]}

12:28 justin_smith: ,(partition 2 (interleave (partition 2 [1 2 3 4]) (partition 2 [5 6 7 8]))

12:28 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

12:28 #{[()]}

12:28 justin_smith: ,(partition 2 (interleave (partition 2 [1 2 3 4]) (partition 2 [5 6 7 8])))

12:28 clojurebot: (((1 2) (5 6)) ((3 4) (7 8)))

12:28 justin_smith: visof: that's what you wanted, right?

12:29 visof: Yep

12:29 what interleave do?

12:29 luma: visof, you have an extra quote in your code

12:29 after y

12:29 justin_smith: ,(interleave [1 2] [3 4])

12:29 clojurebot: (1 3 2 4)

12:30 visof: ah

12:30 great

12:30 thanks justin_smith

12:30 luma: yeah seems

12:31 sm0ke: is anyone planning to maintain https://github.com/piranha/ring-undertow-adapter ?

12:49 yenda: anyobdy here used the amazonica library ?

13:05 sdegutis: Okay.

13:05 I figured it out.

13:06 I'm only using a single component, https://github.com/weavejester/ring-jetty-component

13:06 The rest of my services are idempotent and don't have start/stop.

13:07 Each of my services are something that have a live version and an in-memory version, like an email-service, or a database-service.

13:08 So nothing belongs in a Service except if it has multiple versions, one for the test system and one for the live system. And even then, it must be limited to only the methods that differ between these two implementations.

13:08 /Everything else/ must be a regular old function that takes a system as its first argument. That way it's friendly to code-reloading!

13:32 visof: hi guys

13:33 how can i make this line nicer: (map #(partition n %) (map #(apply interleave %) (map (fn [x] (map #(partition n %) x)) (partition n grid)))) ?

13:36 sdegutis: So that's solved.

13:36 taylan: visof: is that real code? O_o I'd give all the functions good names.

13:37 when in doubt, name more things

13:37 name helper functions, name intermediate values by let-binding them before passing them to another function

13:42 snowell: visof: Example, you define #(partition n %) twice. That's a good candidate for let

13:43 visof: snowell: (let [pn (fn [x] (partition n x))]) ?

13:43 snowell: Yeah, that would work

13:43 visof: snowell: you meant this?

13:46 justin_smith: (let [pn (partial partition n)] (map pn (map (partial apply interleave) (map (partial map pn) (pn grid))))) ; maybe something like this

13:48 snowell: I'd probably use ->> to pretty that up further

13:50 sdegutis: I always try to avoid anonymous functions as much as possible. That helps me to refactor messy algorithms into something cleaner and much easier to understand.

13:50 And snowell is right, ->> is amazing for describing a progressive transformation of data in its logical order.

13:50 I probably use ->> at least once an hour.

13:58 taylan: visof: ideally, a more descriptive name than "pn". something that actually tells the reader what the function does in the problem domain of the program, and not just in Clojure's semantics.

13:58 visof: I know sometimes it's very hard or impossible to find such a name though

14:00 pilne: man, the lein/repl/code development cycle with clojure is so.... smooth

14:09 justin_smith: ,(let [stupid-seq #(try (seq %) (catch Throwable _))] (remove stupid-seq (tree-seq stupid-seq seq {:a 0 :b #{1 2 3} 'hello "world"})))

14:09 clojurebot: justin_smith: excusez-moi

14:09 justin_smith: haha

14:10 anyway, that is stupidly amazing, or maybe the inverse

14:13 pilne: are those states mutually exclusive?

14:13 justin_smith: stupidly amazing, and amazingly stupid? oh there's likely an overlap there :)

14:53 kungi: yogthos: I am using reagent-forms. I would like to display a "Save" Button every time form input is changed. Can I somehow add an on-change handler for the whole form?

14:58 pvinis: if i have (+ (reduce + (map :a [{:a 3} {:a 2} {:a 1}])) (reduce + (map :a [{:a 3} {:a 2} {:a 1}]))), is clojure smart enough to calculate the reduce part once? or do i have to be smart enough to write it in a better way? (like *2, or with let or something)

14:59 justin_smith: pvinis: you need a let, though hotspot may or may not be smart enough to optimize that, I wouldn't count on it, and clojure definitely won't optimize that

14:59 pvinis: aha

14:59 justin_smith: thanks

14:59 justin_smith: it's easy to test if hotspot optimizes it with criterium actually

15:00 (one moment, now I'm curious and I have a repl with crit at the ready)

15:00 pvinis: yea, but i mean in the general case, not in that very specific case

15:00 but sure :)

15:00 pilne: justin_smith CRITS code for >>stack overflow<<

15:00 pvinis: please tell me. im sure you will be faster than me googling how to do that :p

15:01 justin_smith: pilne: pvinis: it's a lib called criterium that you can put in profiles.clj so you can have it in all your repls

15:01 pilne: i was making a "crit" joke like a critical hit in a game or something (:

15:02 justin_smith: haha

15:02 pvinis: so whats the result?

15:02 justin_smith: I thought it was a weirdly formatted request for info about crit before searching on stack overflow to see how to use it

15:02 pvinis: criterium is not that fast, still running

15:03 pvinis: oh

15:03 *waits patiently

15:03 justin_smith: pvinis: part of what makes criterium good is that it runs enough times in a loop to make sure hotspot optimizes everything it ever would in production

15:03 * pvinis tris that again

15:03 justin_smith: because hotspot can be reluctant to do some optimizations

15:03 pvinis: aaa nice. i will look into crit

15:04 justin_smith: got done with the naive version, now running the version with let

15:12 pvinis: is it still running?

15:12 justin_smith: oops, got distracted by my day job where I get paid to do clojure :P

15:13 pvinis: haha thats cool

15:13 keep working then. no worries

15:13 justin_smith: pvinis: so yeah, the version with let is twice as fast, just about exactly https://www.refheap.com/110621

15:13 kungi: yogthos: found it :-)

15:14 justin_smith: pvinis: nah, I just wasn't watching the terminal, but it's not like it's an interactive thing to run it, no worries

15:16 pvinis: justin_smith: cool so its x2 faster

15:17 justin_smith: yup, within a pretty close threshold

15:18 pvinis: but i guess the let way would be a normal way to write it anyway. thank for answering my question though, in a nice way :D

15:19 pilne: i take it that refheap is the preferred pastebin?

15:19 justin_smith: it's the one I like, and it handles clojure nicely

15:20 snowell: And it is, I believe, written in clojure

15:20 justin_smith: indeed

15:20 pilne: well, considering how you are probably gonna be the yoda to my luke, i think i can handle using it

15:20 pvinis: and has persona, which is the first site i see that

15:20 pilne: although "vader jr." sounds so much cooler than luke

15:21 justin_smith: something something try has an implicit do block something yoda


15:21 >.<

15:22 clojure syntax hilighting seems to use far less colors than any other syntax i've worked with

15:23 justin_smith: we don't have much syntax

15:23 sobel: there's a reason

15:23 less is more

15:23 pilne: amen

15:23 looks good in the attempt at sublime's syntax scheme that i'm using in atom

15:24 rainbow brackets from vim would be excellent, but the atom plugin for that is glitchy and borderline deprecated

15:24 depreciated

15:25 i love the use of parenthesis for structuring, i just get a bit lost in the nesting on occasion >.<

15:26 oddcully: pilne: showmatch + paredit

15:30 pilne: hrm, the paredit for atom is not working, throwing errors like a rapper in a strip club throws out 20s

15:32 oddcully: pilne: i meant in vim

15:33 pilne: yeah, i'll probably get vim all setup nice and pretty

15:34 i use atom when i'm doing tutorials and such, but when i'm in the zone, vim and i are like best buddies (:

15:36 celwell: Hi, how could I retrieve the value of a local variable (from a "let") that is within a (try) and get it in the (catch) statement?

15:37 justin_smith: celwell: sadly I have not found an elegant way to do this, the closest I get is (let [x (promise)] (let [... _ (deliver x val) ...] ...) (catch Exception e (report @x)))

15:38 celwell: justin_smith: interesting

15:38 justin_smith: oh I missed the try between the let blocks :P

15:38 but I think you get the idea

15:39 the idea being that you can use deliver to get an idea back out of a let block, without worrying about weirdness or side effects (because promises are weak, compared to other reference types)

15:39 s/idea back out/value back out/

15:43 mikerod: What's the chances of http://dev.clojure.org/jira/browse/CLJ-1224 still getting into clj 1.8, now that beta1 is out without it?

15:43 just curious, I guess I could ask on the mailing list post

16:17 {blake}: Do you guys CRUD?

16:19 TEttinger: {blake}: I have enough CRUD in my chest that I had a CT scan to see if a fungus is causing it. other than that, not especially

16:19 {blake}: TEttinger: That's a lot of crud.

16:19 TEttinger: you only have two lungs in one life!

16:19 {blake}: Just wondering if I should do this CRUD app in Clojure or just punt.

16:19 Two lungs: One life

16:19 TEttinger: sure, there are some good choices I think

16:19 is it SQL-based?

16:21 justin_smith: (def lives (/ lungs 2))

16:21 {blake}: Yessir.

16:28 pilne: i <3 my ecig

16:58 {blake}: TEttinger: Any thoughts on those choices?

16:58 puredanger: mikerod: clj-1224 is still in the queue for 1.8

16:59 TEttinger: {blake}: I would take a look at the clojure toolbox to see what's recommended

16:59 http://www.clojure-toolbox.com/

16:59 mikerod: Thanks for the update on it puredanger

16:59 (inc puredanger)

17:00 TEttinger: you have SQL Abstraction and SQL Clients as two sections, oddly

17:00 {blake}: Yeah, I'm not crazy about either. =P

17:01 Well, the clients are low-level. Gotta use one of those, I guess.

17:02 cloj_dev: can clojure have mutually recursive functions?

17:03 justin_smith: cloj_dev: within letfn, or indirectly via trampoline, yes

17:03 TEttinger: {blake}: you may want YesQL then

17:03 justin_smith: cloj_dev: there are also hacks using resolve (but of course, like most things using resolve, they are ugly hacks fighting the language)

17:04 TEttinger: yesql doesn't involve translating SQL queries to any other syntax, you keep them as normal SQL

17:04 hiredman: cloj_dev: the answer is yes, but likely you want mutually recursive functions that don't grow the stack, and the answer to that is still yes but slightly more complicated (there is a function trampoline for trampolining)

17:05 {blake}: I tried yesql for my last project; ended up just passing direct SQL. I don't think Clojure has what I'm looking for. But it could, so maybe I'll do that...

17:05 hiredman: for global names, you'll have to at least declare a name bfore you use it

17:05 for local functions you can use letfn

17:06 letfn being similar to letrec elsewhere but restricted to function values

17:07 cloj_dev: {blake}: try honeysql

17:08 {blake}: cloj_dev: I may. I'm more interested in getting from the DB =to= the front-end.

17:10 IOW, given a DB entity, give me a front end for it.

17:12 cloj_dev: oh like views

17:12 or something

17:13 {blake}: yeah, or something. =P

17:13 cloj_dev: cool idea

17:24 sobel: do you have to write a JSON interface to your server and a separate frontend web app, or what?

17:25 {blake}: No, I can do whatever. I can direct link. I could probably get away with a desktop app, but I'd prefer web.

17:25 sobel: so web arch, but bundled as desktop, basically?

17:25 or will you deploy a multiuser server

17:27 because i gotta offer OpenRESTy as a possible solution for the server part. it makes the JSON interface really easy to write.

17:44 kavkaz: whattup Clojure fam

17:46 {blake}: sobel: This is about as pure crud as it can be. Front end with minimal calculations hooked to a SQL Server database. I could probably do it all in ClojureScript, come to think of it (although I have no idea how to hook cljs to a backend DB.)

18:21 sobel: {blake}: i don't think it supports mssql. generally mapping CRUD to REST is pretty straightforward.

18:21 then making clojurescript talk to your REST server is mostly straightforward

18:23 {blake}: sobel: Yeah, I do that sorta thing pretty regularly.

18:24 sobel: too bad about no support from openresty. it's really the simplest pattern for getting the web to the database

18:24 imo

18:25 {blake}: no support for...Clojure or MSSQL?

18:25 sobel: mssql

18:26 neveretheless there are lots of restful service solutions

18:26 justin_smith: you don't want to connect to the db from cljs directly anyway because if cljs can use your db, the client can too...

18:27 sobel: justin_smith: it sounded like the env would allow for what is normally dangerous

18:27 i still go for the n-tier arch because nothing that starts simple ever stays that way in my experience

18:27 {blake}: Well, I'd be okay with that, but I'm sure security wouldn't. They sweat bullets over internal apps getting CSRFed.

18:28 I'm fine with the n-tier, too. I just don't wanna do all the stupid boilerplate.

18:29 sobel: i don't know the go-to solution in clojure. but i bet there's a good one.

18:29 {blake}: sobel: Seems like there oughtta be. One of my former co-workers said he had something worked out where you pass EDN and get an interface.

18:30 But he wasn't sure he could share it.

18:30 sobel: it should be pretty doable.

18:31 {blake}: Yeah, that's what I was thinking. If he won't share, I'll roll my own, in the manner of the LISPers.

18:36 TEttinger: {blake}: you may want seesaw if you're doing a desktop GUI

18:36 seesaw makes swing actually nice to use

18:38 {blake}: TEttinger: I think we discussed that very thing yesterday.

18:39 Although that was Seylerius who brought it up.

18:41 TEttinger: I really like seesaw

18:42 {blake}: I did a little seesaw, then for my class I went to using straight Swing and, yeah, I really like seesaw, too.

18:52 ianhedoesit: TEttinger: did you have previous experience building GUIs in Java before using seesaw?

18:53 TEttinger: ianhedoesit, nope

18:54 ianhedoesit: have you built anything reasonably complex with seesaw?

18:54 (esp. that's public)

18:54 TEttinger: I've seen people try to use visual designers to make GUI dev easier, but they're really just churning out boilerplate

18:54 nothing terribly complex

18:56 ianhedoesit: my problem with it (last time I tried using it, and it was a really simple UI - ~15 buttons and two labels - it was pretty easy, but I quickly became concerned that if I was wanting to build something more complex it would get messy fast. mainly, I think, because there's not many examples or documentation for it.

18:56 TEttinger: I have a little "The R in CRUD" app that takes hideous FDA data on foods and displays it filtered and sorted for people with restricted diets, who can't have certain nutrients above certain amounts (like my grandmother, for instance, had limited phosphorus and magnesium intake, as well as protein)

18:59 ianhedoesit: TEttinger: is it public?

18:59 TEttinger: it's one of the first clojure things I made, so it's really awful style-wise

19:00 ianhedoesit: hm

19:00 TEttinger: https://github.com/tommyettinger/nutrition-searcher

19:06 {blake}: TEttinger: Kidney problems?

19:06 TEttinger: yep

19:07 {blake}: My dad had kidney problems, too.

19:08 TEttinger: she never drank enough fluids, her whole life, and that ended up causing really serious kidney problems. those caused fluid buildup, fluid worsened existing heart disease, she went from rather healthy to no longer with us in about 5 years

19:08 {blake}: Whoa. Yeah.

19:09 TEttinger: it was made somewhat worse by the fact that she was so outrageously tough. she never complained about pain, even really serious pain (she had dying tissue in her large intestine, which must have been absurdly painful, but she never acknowledged it to anyone, so doctors couldn't treat it until they finally realized what it was)

19:10 {blake}: Ha...my dad did the same thing...with gangrene. I still don't know how he got away with that.

19:11 TEttinger: cut out about half of her large intestine and linked the two living parts together. she came back from the hospital losing her hair from ICU psychosis, apparently being without exposure to the outside world for a week or more makes people go crazy

19:12 gangrene causes joint pain, right?

19:12 that sounds agonizing

19:12 especially if totally untreated

19:32 pilne: i'm still trying to grasp what the ' "does"

19:33 ianhedoesit: ,(doc quote)

19:33 clojurebot: Gabh mo leithscéal?

19:34 ianhedoesit: well that wasn't what I wanted.

19:35 pilne: worked in repl

19:35 ianhedoesit: quoting a symbol yields the unevaluated form. so '(1 2 3) is (1 2 3). This is important because without the quote:

19:35 pilne: ty

19:35 ianhedoesit: ,(1 2 3)

19:35 clojurebot: #error {\n :cause "java.lang.Long cannot be cast to clojure.lang.IFn"\n :via\n [{:type java.lang.ClassCastException\n :message "java.lang.Long cannot be cast to clojure.lang.IFn"\n :at [sandbox$eval49 invokeStatic "NO_SOURCE_FILE" 0]}]\n :trace\n [[sandbox$eval49 invokeStatic "NO_SOURCE_FILE" 0]\n [sandbox$eval49 invoke "NO_SOURCE_FILE" -1]\n [clojure.lang.Compiler eval "Compiler.java" 6943]...

19:36 pilne: i gotta remember that the inbuilt documentation on clojure is fucking fantastic

19:39 justin_smith: pilne: well, not always, sometimes it's kind of weird. But we do have some nice tools for investigating things in the repl. Also see http://conj.io

19:39 pilne: nice

19:40 well, all the examples i have make good use of the docstring, and are well-commented, i've always been a "clear variable name" and "well-commented" guy (maybe not *while* coding, but definitely in a cleanup pass), and will definitely continue on that given the inbuilt resources of clojure

19:43 sdegutis: nice

19:57 pilne: i *like* the inbuilt data structures, however i am still working on "just knowing" their syntax >.< lol

19:58 ianhedoesit: they're pretty straight forward. there's only lists, maps, sets, and vectors.

19:59 pilne: yep, it is just getting my head around their # or specific brackets, commas or not, and how the ' alters how they are passed, i'll *get* it soon, just not quite yet (2 days in coming from mostly racket and ruby the last month with a bit of haskell)

20:00 ianhedoesit: none of them need commas. commas are whitespace.

20:00 pilne: so they are for readability if needed

20:00 ianhedoesit: commas are whitespace everywhere

20:00 yes.

20:01 pilne: beautiful

20:01 ianhedoesit: (def,foo,5) and (def foo 5) are exactly the same

20:01 pilne: i'm starting to like the double entendre (sp?) that "functional elegance" has in regards to clojure

20:02 ianhedoesit: ' is the same for everything, and doesn't have anything inherently to do with different collections. I think I figured it out by thinking "this quote means nothing will happen."

20:04 pilne: yeah... it will pass it "literally"

20:05 ianhedoesit: right.

20:05 pilne: sweet

20:06 ianhedoesit: racket, in face, has the same syntax for quoting.

20:06 s/ce/ct/

20:09 pilne: hrm... you are right... but the clojure tutorials i've seen are fare more aggressive in their early introduction of the idea

20:10 ianhedoesit: hm, I don't know why. it's really not a very important idea for beginners, imo.

20:11 well, I don't know. it's a very important idea, but it's also not very helpful if you just want to learn how to do things.

20:11 pilne: this tutorial seemed to be very keen on showing mutability vs immutability, and in a way, that is a way to make something immutable in certain circumstances

20:11 (is what i got from the author)

20:11 ianhedoesit: hm, not exactly.

20:13 pilne: yeah, but sorta, and that is what the author stressed too

20:13 ianhedoesit: in fact, typically if you're using quoted forms it's in a macro, which is more meta than clojure's focus on immutability.

20:13 sdegutis: bbl

20:18 pilne: i'm not quite that far in yet, but i do understand that macro is far more meta

20:19 this tutorial kinda paints the picture that a macro is generally a last resort if something "native clojure or java" doesn't work as needed.

20:19 ianhedoesit: you're familiar with the C preprocessor?

20:19 #DEFINE FOO 5 nonsense

20:20 pilne: i know c from a distance, i'm mostly a hobbyist with a little formal education in c++ and java

20:20 ianhedoesit: which literally just replaces any text instance of "FOO" in the file with "5"

20:20 well it's the same with C++, but it's not too important.

20:21 but basically, a macro in Clojure, at it's most simple form, allows you to replace some text with some other text.

20:21 pilne: yeah, i have a little experience with preprocessing, and the way macros have been presented, it is like preprocessing but using the native syntax of the language

20:22 justin_smith: unlike c macros, a clojure macro can't alter its caller

20:22 eg #DEFINE FOO ); somethingElse(

20:23 which changes its caller by changing the arg count

20:23 (and giving the stolen args to somethingElse)

20:27 ianhedoesit: pilne: I think a simple example in clojure is `or`.

20:27 ,(source or)

20:27 clojurebot: Source not found\n

20:28 pilne: that's what the tutorial used as a macro example

20:28 ianhedoesit: ,(clojure.walk/macroexpand-all '(or 4 5))

20:28 oh

20:28 clojurebot: #error {\n :cause "clojure.walk"\n :via\n [{:type java.lang.ClassNotFoundException\n :message "clojure.walk"\n :at [java.net.URLClassLoader$1 run "URLClassLoader.java" 366]}]\n :trace\n [[java.net.URLClassLoader$1 run "URLClassLoader.java" 366]\n [java.net.URLClassLoader$1 run "URLClassLoader.java" 355]\n [java.security.AccessController doPrivileged "AccessController.java" -2]\n [java.net.U...

20:28 ianhedoesit: ,(use 'clojure.walk)

20:28 clojurebot: nil

20:28 ianhedoesit: ,(macroexpand-all '(or 4 5))

20:28 clojurebot: (let* [or__4226__auto__ 4] (if or__4226__auto__ or__4226__auto__ 5))

20:29 ianhedoesit: ,(eval (macroexpand-all '(or 4 5)))

20:29 clojurebot: 4

21:10 pilne: i do like the use of "true" as a way to use and to do a few functions after each other (:

21:10 ianhedoesit: hm?

21:18 pilne: ,(eval (macroexpand-all '(and 4 5)))

21:18 clojurebot: #error {\n :cause "Unable to resolve symbol: macroexpand-all in this context"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to resolve symbol: macroexpand-all in this context, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6704]}\n {:type java.lang.RuntimeException\n :message "Unable to resolve s...

21:19 pilne: hrm, i thought i did an example

21:19 where as long as they were "true" multiple things would be done after an "and"

21:22 TEttinger: ,(and 4 5)

21:22 clojurebot: 5

21:22 TEttinger: ,(and 4 5 (not (print "hey! ")) 6)

21:22 clojurebot: hey! 6

21:27 pilne: i have much to learn

21:27 these clojure koans are making it fun though

21:29 TEttinger: ,(or (print "hey! ") (print "you! ") (print "get off of my cloud! ") 9)

21:29 clojurebot: hey! you! get off of my cloud! 9

21:29 TEttinger: but if you omit 9, then what?

21:29 ,(or (print "hey! ") (print "you! ") (print "get off of my cloud! "))

21:29 clojurebot: hey! you! get off of my cloud!

21:30 TEttinger: still has side effects, but returns false I think

21:30 ,(true? (or (print "hey! ") (print "you! ") (print "get off of my cloud! ")))

21:30 ianhedoesit: it returns nil, I believe.

21:30 clojurebot: hey! you! get off of my cloud! false

21:30 TEttinger: ,(nil? (or (print "hey! ") (print "you! ") (print "get off of my cloud! ")))

21:30 clojurebot: hey! you! get off of my cloud! true

21:31 TEttinger: ianhedoesit is correct!

21:31 I'd inc you but we're down one lazybot

21:32 ianhedoesit: that's okay

21:32 it's the thought that counts

21:32 pilne: hrm, not sure what exactly they are looking for here though:

21:32 https://www.refheap.com/110631

21:33 the __ is supposed to be something to make it pass as a test

21:33 ianhedoesit: ,(or true (println "foo"))

21:33 clojurebot: true

21:34 pilne: right, or short circuts on the first true

21:34 ianhedoesit: pilne: what will the try block end up returning?

21:34 pilne: "No Dice"

21:34 ianhedoesit: well, "No dice!" but yeah

21:36 arslania: Anyone could explain to me why: (re-matches #"(cat*)" "mytical cat crweatures") returns nil ?

21:37 justin_smith: arslania: re-matches needs to match the entire string

21:37 arslania: oh, that's a good explanation :p, thanks

21:37 justin_smith: ,(re-find #"(cat*)" "mytical cat crweatures")

21:37 clojurebot: ["ca" "ca"]

21:38 justin_smith: as you see, re-find is not limited in that manner

21:39 arslania: Ya, that's the one I want

21:39 thank you

21:42 TEttinger: ,(re-seq #"cat*" "mytical cat crweatures")

21:43 clojurebot: ("ca" "cat")

21:43 TEttinger: ,(re-find #"cat*" "mytical cat crweatures")

21:43 clojurebot: "ca"

21:43 TEttinger: the grouping in the regex makes re-find return both the first found value and the full match, which happens to be the same

21:44 ,(re-find #"(cat*)" "cat-like mytical crweatures")

21:44 clojurebot: ["cat" "cat"]

21:44 TEttinger: ,(re-find #"(ca)t*" "cat-like mytical crweatures")

21:44 clojurebot: ["cat" "ca"]

21:45 arslania: Ah, I was wondering why it was not gicing me ["ca" "cat"]

21:45 pilne: waigt.......... i can slice vectors?????

21:46 i think i just had a codegasm

21:46 ianhedoesit: pilne: hm?

21:46 pilne: first tutorial didn't mention slicing vectors (:

21:47 ianhedoesit: as in using subvec?

21:47 arslania: @TEttinger So if I want all captured groups, re-seq will give me a sequence of [fullMatch groupX]?

21:48 ianhedoesit: ,(subvec [4 5 6 7 8 9] 1 4)

21:48 clojurebot: [5 6 7]

21:49 pilne: is the backtick used much in clojure, i'm having anger issues towards my bracket matcher right now due to it duplicating anything even vaugely similar to a () pair >.<

21:50 ianhedoesit: no, that's for syntax quoting

21:51 pilne: your editor automatically closes a ` with another `?

21:51 TEttinger: pilne: are you using paredit?

21:51 you may want to disable it if it's causing more hassle for now

21:51 pilne: the only working bracket matcher i found does, i'm turning it off now, no, i'm using atom for now, when i'm tabbing between an editor and a tutorial i use atom, vim for solo stuff

21:52 TEttinger: paredit is a mode that's in a few editors

21:52 originally in emacs, I think light table has it as an option, it's a checkbox in nightcode

21:52 ianhedoesit: https://atom.io/packages/paredit

21:53 pilne: it threw an exception and disabled itself for me

21:53 TEttinger: arslania: if you want all matches to a regex, you probably want something like re-seq. if there are groups involved, things are a bit screwy

21:53 ianhedoesit: pilne: maybe try lisp-paredit instead?

21:54 meh, it doesn't really matter.

21:54 pilne: hmmm

21:54 ianhedoesit: but anyway

21:54 pilne: it is working now

21:54 TEttinger: ,(re-seq #"a+" "aardvarks are animals, aaaa!")

21:54 * pilne goes back to coding

21:54 clojurebot: ("aa" "a" "a" "a" "a" ...)

21:54 pilne: ty

21:55 TEttinger: ,(re-seq #"(a+)" "aardvarks are animals, aaaa!")

21:55 clojurebot: (["aa" "aa"] ["a" "a"] ["a" "a"] ["a" "a"] ["a" "a"] ...)

21:55 TEttinger: the group is more useful when you want the word and the match

21:56 ,(re-seq #"(aa+)\w*" "aardvarks are animals, aaaa!")

21:56 clojurebot: (["aardvarks" "aa"] ["aaaa" "aaaa"])

21:58 TEttinger: so in that last case, we actually have a seq of vectors containing strings. the number of strings, if I remember it right, is equal to the number of groups in the regex + 1 (for the whole match to the regex, even stuff not in a group)

21:59 ,(re-seq #"(aa+)\w*(!)" "aardvarks are animals, aaaa!")

21:59 clojurebot: (["aaaa!" "aaaa" "!"])

21:59 TEttinger: two groups, two groups that can match, but only one additional match to the whole regex

21:59 ,(map first (re-seq #"(aa+)\w*" "aardvarks are animals, aaaa!"))

21:59 clojurebot: ("aardvarks" "aaaa")

22:00 TEttinger: that's often what you want if your groups are there for some reason other than re-find and re-seq behavior

22:00 ,(map first (re-seq #"(a)\1+" "aardvarks are animals, aaaa!"))

22:00 clojurebot: ("aa" "aaaa")

22:01 TEttinger: the case of \1 , for first group's match, is a good one

22:02 ,(map first (re-seq #"([aeiou])\1+" "vacuums are not animals, aaaa!"))

22:02 clojurebot: ("uu" "aaaa")

22:02 TEttinger: that example would be, uh, difficult without groups

22:02 err, nvm

22:03 but there are things like that that involve repeated matches to something that aren't exactly repetition

22:03 arslania: hum, ya, I think I need to familiarise myself with the capturing group some more

22:03 TEttinger: they act a bit weirdly in clojure's re- fns

22:04 in the meanwhile, (?:something) will match something but not group

22:04 ,(re-seq #"(?:aa+)\w*" "aardvarks are animals, aaaa!")

22:04 clojurebot: ("aardvarks" "aaaa")

22:04 ianhedoesit: is there any way to use a character literal as a key for a map?

22:04 TEttinger: ,{\a 1 \b 2}

22:04 clojurebot: {\a 1, \b 2}

22:04 ianhedoesit: oh wow

22:04 ...

22:05 I don't know what I was thinking

22:05 TEttinger: I'd guess the answer is yes

22:05 hehe

22:05 justin_smith: ,(->> (all-ns) (mapcat ns-publics) keys (map name) (filter #(.startsWith % "re-")))

22:05 clojurebot: ("re-groups" "re-seq" "re-pattern" "re-matcher" "re-find" ...)

22:05 justin_smith: ,(->> (all-ns) (mapcat ns-publics) keys (map name) (filter #(.startsWith % "re-")) (clojure.string/join " "))

22:05 clojurebot: "re-groups re-seq re-pattern re-matcher re-find re-matches re-quote-replacement"

22:05 justin_smith: notice I used no regexes to do that though I could have :P

22:06 ianhedoesit: ,(keyword " ")

22:06 clojurebot: :

22:07 TEttinger: ,(->> (all-ns) (mapcat ns-publics) keys (map name) (filter (partial re-find #"re-")) (clojure.string/join " "))

22:07 clojurebot: "re-groups future-call re-seq future-done? re-pattern compare-and-set! re-matcher future-cancelled? *clojure-version* ensure-reduced re-find re-matches clojure-version future-cancel re-quote-replacement"

22:07 TEttinger: interesting!

22:07 ,(->> (all-ns) (mapcat ns-publics) keys (map name) (filter (partial re-find #"^re-")) (clojure.string/join " "))

22:07 clojurebot: "re-groups re-seq re-pattern re-matcher re-find re-matches re-quote-replacement"

22:07 TEttinger: notice how I used no anonymous fns to do that though I could have :P

22:08 or whatever #() is called

22:09 justin_smith: heh

22:11 TEttinger: ,(keyword"  \t")

22:11 clojurebot: :  

22:11 TEttinger: ,(keyword"  \t\n\r\a")

22:11 clojurebot: #<RuntimeException java.lang.RuntimeException: Unsupported escape character: \a>

22:11 justin_smith: hey, that's Mjolnir

22:11 TEttinger: ,(keyword"  \t\n\r\b")

22:11 clojurebot: :   \n

22:11 TEttinger: it is runic

22:12 ,(+ 1 2 3 4)

22:12 clojurebot: 10

22:13 arslania: ,(re-matches #"(^[A-z]+).+ ([A-z]+$)" "first middle last")

22:13 clojurebot: ["first middle last" "first" "last"]

22:13 arslania: ,(re-seq #"(^[A-z]+).+ ([A-z]+$)" "first middle last")

22:13 clojurebot: (["first middle last" "first" "last"])

22:14 arslania: ,(re-find #"(^[A-z]+).+ ([A-z]+$)" "first middle last")

22:14 clojurebot: ["first middle last" "first" "last"]

22:15 TEttinger: ,(+ 1 2 3 4)

22:15 clojurebot: -10

23:12 rhg135: how can I go from {:a [1] :b [2 3] :c [4 5 6]} to [{:a 1 :b 2 :c 4} {:a 1 :b 2 :c 5} ...]?

23:37 TEttinger: rhg135: interesting question

23:38 ,(def rhg-data {:a [1] :b [2 3] :c [4 5 6]})

23:38 clojurebot: #'sandbox/rhg-data

23:39 rhg135: actually these are observables, not vectors. I think I found a solution but it's very icky

23:39 state everywhere

23:53 TEttinger: ,(def rhg-data {:a [1] :b [2 3] :c [4 5 6]})

23:53 clojurebot: #'sandbox/rhg-data

Logging service provided by n01se.net