#clojure log - Feb 15 2015

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

0:23 yogthos: robindunbarr: Luminus is meant to be a light weight batteries included micro-framework like Flask

0:29 robindunbarr: yogthos: I see, thanks.

0:41 devll: Hi,Is there a way to get string value of the stacktrace of a Exception?

0:41 Obviously,I can write one .

0:42 I guess I just should do it.

1:08 justin_smith: ,(apply str (.getStackTrace (Exception. "oops")))

1:08 clojurebot: "sandbox$eval25.invoke(NO_SOURCE_FILE:0)clojure.lang.Compiler.eval(Compiler.java:6768)clojure.lang.Compiler.eval(Compiler.java:6731)clojure.core$eval.invoke(core.clj:3076)clojure.core$eval3$fn__4$fn__14.invoke(NO_SOURCE_FILE:0)clojure.core$eval3$fn__4.invoke(NO_SOURCE_FILE:0)clojure.core$eval3.invoke(NO_SOURCE_FILE:0)clojure.lang.Compiler.eval(Compiler.java:6768)clojure.lang.Compiler.eval(Compiler...

1:09 devll: justin_smith: thanks

1:37 vas: anybody do passwordless logins for their app?

1:49 ping

1:52 justin_smith: vas: no, how would that work?

1:59 vas: justin_smith: been contemplating various approaches, but i think the one i want to use is essentially asking the user just for their email, then sending them a link that they click

1:59 so the only password they need is their email password, not truly "passwordless" but no passwords kept on my end

2:00 ( and the link is their authentication for the session )

2:00 justin_smith: ahh, right - instead you have a mapping of an account (and account data) to a token validated via email?

2:01 vas: precisely so

2:01 or text message, i might use phone numbers eventually

4:34 kaplan: Hi, can anyone tell me what's wrong with this code? https://www.refheap.com/97252

4:36 AimHere: ,(reverse "acca")

4:36 clojurebot: (\a \c \c \a)

4:36 wminor: kaplan: I think you're using the wrong reverse, you need clojure.string/reverse

4:36 kaplan: ah

4:37 AimHere: The 'if' is redundant too

4:37 (if X true false) can be easily reduced to (X)

4:38 kaplan: ah, thanks

4:38 wminor, that worked

4:38 AimHere: (if (if X true false) true false)

4:41 kaplan: wminor, is there any way to shorten the clojure.string part?

4:41 TEttinger: ,(require [clojure.string :as s])

4:42 clojurebot: #<CompilerException java.lang.ClassNotFoundException: clojure.string, compiling:(NO_SOURCE_PATH:0:0)>

4:42 AimHere: You can give it an alias in the require'

4:42 TEttinger: ,(require '[clojure.string :as s])

4:42 clojurebot: nil

4:42 TEttinger: ,(s/reverse "blah")

4:42 clojurebot: "halb"

4:43 TEttinger: kaplan: typically require goes in the ns form, where it looks like (ns mynamespace (:require [clojure.string :as s]))

4:43 note the colon and the no need for a quote

4:44 in the repl, or in the middle of a clojure source file, you can use (require '[whatever]) and need the quote but can't have the colon before require

4:45 wminor: I'm writing an HTTP client for something, and I have a bunch of functions that work in the success case, returning maps representing the json data in the body of the responses. However, I'm having a tough time deciding how to handle errors. What's the idiomatic way to handle failure of the HTTP request in the way that a caller can be informed of the reason for failure?

4:46 TEttinger: there's also (use) but it is frowned upon, especially for clojure.string. use overwrites any functions or vars that are currently defined with the ones in the ns it uses, so you don't need the s/reverse and can just do reverse. BUT you just overwrote clojure.core/reverse

4:46 kaplan: TEttinger, ah, thanks

4:47 TEttinger: wminor, that's a really good question, and I am not qualified at all to answer

4:48 wminor: Sadly, searches for error handling in clojure bring up a really mixed bag, and I've not seen an approach that sticks out as being either particularly nice, or "the clojure way"

4:51 ggherdov: Hello. I'm trying to understand commute vs alter. My book (progr. cloj., oreilly) says about commute that "the commute-d function will be applied again at commit time with the latest value for the commute-d ref".

4:51 I don't understand. Wouldn't this second application of the function need to be in a transaction as well? I mean: the second application of the function may take some time; at the point you have the result, the original ref value might have changed -again-...

4:53 ddellacosta: wminor: if you are just talking about HTTP error responses, seems like that could/should be handled simply by passing the error response back to the client, and handling it as is appropriate there, no? If you are talking about general error handling in the Clojure ecosystem, I'd have to agree with you there

4:54 wminor: ddellacosta: sure, I could just bubble up errors to the caller, but it feels like there should be a better way

4:54 ddellacosta: wminor: you may also want to take a look at liberator, may or may not answer some of your questions: http://clojure-liberator.github.io/liberator/

4:55 wminor: will take a peek, thanks

4:56 ddellacosta: wminor: again, I'm a bit confused about what you are talking about--if you are talking about HTTP responses then I think that should be app-specific. If you are talking about errors/exceptions on the app level that have to be handled in some app-specific way, then that is definitely not something I've seen codified in any way in the Clojure world

4:57 wminor: for example, are you talking about, say, the user passing invalid data to an HTTP route, or the database blowing up because it's out of connections (for example)?

5:06 faveteli_: what am i missing in this simple infix macro? http://lpaste.net/120533

5:08 kaplan: TEttinger, https://www.refheap.com/97253 LightTable instarepl gives me EOF on line 7

5:08 faveteli_: i found the problem need to unquote :)

5:08 TEttinger: need another paren just before line 7, kaplan

5:09 need to end palindrome? fn

5:09 kaplan: TEttinger, ah, damn parens

5:10 TEttinger: heh

5:10 it will get easier!

5:10 also lighttable supports rainbow parens

5:10 which are so nice, in my view, not everyone likes em

5:11 kaplan: TEttinger, I thought I should make my brain used to parens without any aid first

5:11 TEttinger: yeah, I think you will get used to them though, it doesn't take that long

5:13 wminor: ddellacosta: the former I suppose. I think for now I'm happy for the client to explode in exceptional circumstances

5:14 ddellacosta: wminor: in that case, another thing you could take a look at is Prismatic's fnhouse (https://github.com/Prismatic/fnhouse)--we use something different ourselves, but it's worth seeing how much this solves your problem or misses the mark

5:15 wminor: but in general I like the direction the Prismatic folks are going in with most of their libraries

5:16 wminor: ddellacosta: thanks. At this point I'm still very new to clojure, so just happy to find find decent code to read so that I can soak up ideas. I don't yet know enough to evaluate third party code easily

5:17 ddellacosta: wminor: gotcha. Yeah, in general I'd recommend checking out their stuff, I think their libraries represent some of the higher quality and more thoughtfully practical stuff available now in Clojure

5:50 Integralist: Hello, I'm having an issue with a namespace when the app is compiled and/or at runtime: http://goo.gl/At2Jbp -> I've just to use ns-resolve to work around the issue but am still having no luck.

5:54 nicferrier: so I've got two webservers in a single process... they use a lot of core.async... how should I wait on the core.async operations? with a while loop with a thread/sleep?

5:59 muhuk: nicferrier: you mean wait and block everything else?

5:59 nicferrier: muhuk: I mean the go blocks are all async... so if I set them up and do nothing else the program will just quit, no? so I have to wait for them somehow.

5:59 or do I? maybe the main will just hang?

6:00 muhuk: nicferrier: I see what you mean.

6:00 nicferrier: I want to get this right. this is a piece of infrastructure.

6:00 muhuk: I usually set up something like a promise and wait on that

6:00 then you can deliver that promise anywhere else and you should be able to exit that way.

6:00 nicferrier: ah. not a bad idea.

6:00 I could have a signal to the go block to fulfil the promise.

6:18 ggherdov: Can anybody clarify this statement: "The function you give to `commute` will be run at least twice: once to compute the in-transaction value, and again to compute the commit value". It's from "the joy of clojure".

6:18 My question is: why do you bother computing the in-transaction value, if then you're going to do it all over again at commit time?

6:43 muhuk: ggherdov: have you seen the example here https://clojuredocs.org/clojure.core/commute

6:48 ggherdov: @muhuk no I haven't, thanks. Reading.

7:54 nicferrier: doesn't waiting on a promise block the thread? it does right? I'm getting some wierd error about many2many-channels and futures being confused.

7:55 aha. it's not that. I'm confusing a thread and a promise.

7:55 how do I exchange a promise between two threads?

7:56 I want the promise to be delivered in another thread.

7:56 can I return the promise from a thread?

8:34 gah. now I am stuck trying to end my threads.

8:34 :-(

8:34 clojure is great but concurrency is hard.

8:34 muhuk: concurrency is hard, period.

8:34 why do you need to exchange the promise between threads

8:35 nicferrier: I solved that.

8:35 :-)

8:35 muhuk: ok, cool

8:37 nicferrier: I've got a few threads which are sockets and clients... and now they don't end.

8:37 sort of trying to make this usable.

8:38 AeroNotix: nicferrier: stop trying to use 12 different concurrency primitives in the same program.

8:38 nicferrier: but I need them.

8:38 AeroNotix: You think you need them :)

8:38 nicferrier: you think I don't know but you don't know what I'm doing.

8:39 AeroNotix: I know you think you know what you're doing. You always seem to try to mention your many-years experience whenever you're learning something on IRC.

8:39 nicferrier: because I'm not seeking a mentor.

8:39 AeroNotix: But really, there is probably an easier way than using threads, promises and core.async all at the same time.

8:40 I say "probably" because there might be a genuine need.

8:40 nicferrier: yeah.

8:40 AeroNotix: haha!

8:40 go for it dude, knock yourself out.

8:40 nicferrier: you want to know what I'm doing?

8:40 AeroNotix: Nope.

8:40 nicferrier: you're friendly.

8:41 AeroNotix: I am, really.

8:41 nicferrier: not really.

8:41 AeroNotix: but it's clear you don't want help.

8:41 nicferrier: that's right. I'm just chatting.

8:41 chatting helps.

8:41 vas_: hehehe a gem of a back-n-forth

8:41 nicferrier: I use irc for rubber ducking.

8:46 just so you know - that's not friendly and it pisses me off.

8:46 makes me feel unwelcome.

8:46 hope you don't do it a lot.

8:46 AeroNotix: nicferrier: thing is, you are exactly like that yourself.

8:46 #emacs is tyranny when you're active.

8:47 nicferrier: that's not true.

8:47 AeroNotix: Ah! So I'm mistaken.

8:47 oh wait.

8:50 muhuk: Just because someone is rude (or whatever) in another channel doesn't mean we should make belittling comments about them in #clojure.

8:51 AeroNotix: It wasn't belittling. nicferrier made it clear they're just here to complain, not ask for help. Even when nudged in the direction that they might be doing something wrong, the first assertion is that they *need* to do it like that.

8:51 Which is funny, because the previous conversation makes it clear that nicferrier is confused about several primitives.

8:51 nicferrier: AeroNotix: no, but you can't throw bricks at someone without hearing what they're trying to do.

8:51 and I don't think I'm confused.

8:52 AeroNotix: Gotcha.

8:52 muhuk: Implying that he doesn't know what he's doing is belittling.

8:52 nicferrier: and so is passive aggresive behaviour.

8:52 AeroNotix: I implied there might be a better way to do it.

8:52 Bronsa: please, take this somewhere else and don't pollute #clojure with personal issues.

8:52 AeroNotix: Bronsa: agreed. It's gone too far now.

8:57 vas_: hi :) i want to timestamp stuff

8:57 AeroNotix: vas_: what do you mean?

8:57 like generate timestamps?

8:57 vas_: just like unix standard count for tokens i put in a db

8:57 to check that they're <33min fresh

8:58 AeroNotix: vas_: you can get the unix timestamp by doing (quot (System/currentTimeMillis) 1000)

8:58 and then it's simple maths to do the comparison

8:58 vas_: Wow that's awesome. Thanks for the swift answer AeroNotix

8:58 AeroNotix: np

9:00 what's the best guide to getting started with ClojureScript? I know there were a lot of tooling changes recently and I haven't kept up.

9:14 vas_: AeroNotix: works like a charm, thank you kindly ^_^

9:14 AeroNotix: no worries

9:37 cityspirit: in the enqueue macro here http://www.braveclojure.com/concurrency/#4_5__Simple_Queueing, why doesn't (deref ~q) block the main thread, prohibiting further calls to enqueue itself?

9:38 actually, i guess I would rather think the call to ~serialized would be blocking the main thread

9:42 vas_: because "Dereferencing a future will block if the future hasn't finished running" ?

9:47 cityspirit: how does the call to enqueue return a promise to the next call to enqueue without first being block by ~serialized, which is dereferencing a promise

10:05 nonrecursive: cityspirit: this might help https://gist.github.com/flyingmachine/ba9ae6e500896b1d2c78

10:06 that’s not 100% exactly what happens but it should show that all the futures get created before any of the futures get dereferences

10:06 dereferenced*

10:10 mavbozo: nonrecursive: so, if the future is not yet finished, (deref ~q) will block the main thread

10:11 nonrecursive: cityspirit: sometimes it does get blocked but that’s actually ok

10:15 mavbozo: cityspirit: yeah, but that’s ok. Maybe a dumb metaphor will help? Let’s say some unpleasant person has lined up three balls on a table. he wants each ball to get thrown into the air, caught, and then handed to him in the order that they’re lined up. You could go down, one by one, tossing each ball and handing it to this person. Or you could get two of your friends to toss the balls at the same time as you, and you

10:15 hand in each ball, in order, as soon as it’s done being tossed

10:16 in the first case, let’s say the balls take 1 second, 3 seconds, and 2 seconds. It’ll take you a total of 6 seconds

10:16 in the second case, you can hand in ball one after 1 second, then you have to wait 2 more seconds to hand in ball 2. but you can hand in ball 3 immediately

10:17 justin_smith: $mail nicferrier what you want is shutdown-agents when your app is ready to shut down, clojure's main thread will not end until the agent-pools are nicely put to bed

10:17 lazybot: Message saved.

10:17 nonrecursive: enqueue is acting like the second case - the thread does sometimes have to wait, but the task as a whole will only take as long as the longest sub-task

10:18 mavbozy: cityspirit: does that help at all?

10:19 cityspirit: nonrecursive: thanks, for the example and description. the description makes sense, I'm still looking at example. I guess my problem comes with understanding how the macro behaves differently than , e.g. https://www.refheap.com/97267 By the way, I really enjoy your writing style

10:19 mavbozo: nonrecursive: that helps. thx.

10:23 nonrecursive: cityspirit: in that example you deref the first promise before creating the second promise and future. with enqueue, you create all promises and futures before any of the promises actually get dereferenced

10:25 favetelinguis: is the clojure cheat sheet a complete discription of the Clojure language?

10:25 justin_smith: not at all

10:26 gfredericks: ~the clojure cheat sheet is not a complete description of the Clojure language

10:26 clojurebot: Ack. Ack.

10:26 nonrecursive: cityspirit: line 3 and 5 of the gist I linked show a let expression getting deref’d, but those don’t actually have to block until the promise at line 8 is encountered. in the mean time, the futures at lines 2, 4, and 6 have already been created, so that work is done concurrently

10:27 favetelinguis: is there something with the same layout that shows the omplete set of functionallity?

10:27 nonrecursive: cityspirit: also, thanks! :D

10:29 justin_smith: favetelinguis: you could look at the ns-publics of clojure.core and the other core libs, and read doc strings or look them up

10:29 ,(ns-publics 'clojure.core)

10:29 clojurebot: {primitives-classnames #'clojure.core/primitives-classnames, +' #'clojure.core/+', decimal? #'clojure.core/decimal?, restart-agent #'clojure.core/restart-agent, sort-by #'clojure.core/sort-by, ...}

10:30 gfredericks: ,primitives-classnames

10:30 clojurebot: {float "Float/TYPE", int "Integer/TYPE", long "Long/TYPE", boolean "Boolean/TYPE", char "Character/TYPE", ...}

10:30 justin_smith: how handy

10:30 gfredericks: that's my thing-in-clojure-core-I-never-knew-existed-of-the-day

10:31 justin_smith: ,(rand-nth (keys (ns-publics 'clojure.core))) ; random clojure def of the day

10:31 clojurebot: proxy

10:32 gfredericks: clj-http defines a custom map type for headers and it doesn't take metadata o_o

10:32 cityspirit: nonrecursive: ahh ok it makes sense - thanks a lot for the responses!

10:32 nonrecursive: cityspirit: no problem :)

10:34 tcrayford____: gfredericks: I'm sure it saves a bunch of pointers in practice

10:34 (seems like an awful idea too me)

10:35 adgtl: I am tyring to paste following json string in clojure repl

10:35 (json/read-str "{"recenttracks":{"track":[{"name":"Loading...","artist":{"#text":""}}]}}")

10:35 but it fails

10:36 this also fails (json/read-str '{"recenttracks":{"track":[{"name":"Loading...","artist":{"#text":""}}]}}')

10:36 justin_smith: adgtl: neither of those is string syntax

10:36 adgtl: Anyone know how to parse json string

10:36 gfredericks: tcrayford____: which idea is awful?

10:36 tcrayford____: gfredericks: though some of yeller's benchmarks rn spend a significant amount of time in clojure.core/meta (and the calling path from that just leads to `conj`)

10:36 justin_smith: adgtl: you mean how to provide a literal? "{\"recenttracks\":{\"track\"...

10:36 tcrayford____: defining a custom map without meta

10:37 adgtl: justin_smith: I have that string.. I don't want to add \

10:37 basically is there any string sanitizer?

10:37 justin_smith: adgtl: sorry, that's the only way to make the valid clojure string literal

10:37 gfredericks: tcrayford____: I think the point of the custom map was to make it case-insensitive; probably the lacking-of-metadata was just an oversight

10:37 justin_smith: adgtl: unless you use emacs, or another editor that can quote it for your

10:37 adgtl: isn't there any helper to do that?

10:37 justin_smith: *you

10:37 no

10:37 tcrayford____: oh case insensitive maps gosh darnit

10:37 adgtl: justin_smith: I use emacs.. how to make it quote?

10:37 justin_smith: the helper would need to get the string to work on it

10:37 tcrayford____: next thing clojure will get HashWithIndifferentAccess

10:37 justin_smith: what you have is not a string

10:38 adgtl: justin_smith: it's string containing json

10:38 clojurebot: No entiendo

10:38 gfredericks: tcrayford____: hey at least it's not in the language

10:38 tcrayford____: haha

10:38 HashWithIndifferentAccess is in rails

10:38 so it's in the language ;)

10:38 justin_smith: adgtl: there is a tool called string-edit that has a function string-edit-at-point

10:39 you can insert a string into the string-edit buffer and it gets escaped properly

10:39 adgtl: justin_smith: in emacs?

10:39 justin_smith: yes

10:39 you need to require the string-edit package first

10:39 gfredericks: tcrayford____: ruby is the microkernal of the general purpose programming language "rails"

10:39 AeroNotix: paredit quotes literal strings with quotes as well.

10:39 justin_smith: adgtl: the other option is to put the json in a file, and slurp it

10:39 adgtl: justin_smith: can't do that

10:40 justin_smith: adgtl: optionally, you could also call (pr-str (slurp "file.json"))

10:40 and that also gives you the escaped string

10:41 adgtl: you can'

10:41 t install string-edit?

10:42 zapho53: Is there a way of doing something like this (which doesn't work): (apply Integer/parseInt [day month year hour min]) ?

10:42 justin_smith: zapho53: methods are not first class

10:42 #(Integer/parseInt %) will work

10:42 adgtl: hmm

10:42 user=> (def c (json/read-str (pr-str (slurp "seed.json"))))

10:42 #'user/c

10:43 user=> c

10:43 "{\"recenttracks\":{\"track\":[{\"name\":\"Loading...\",\"artist\":{\"#text\":\"\"}}]}}\n"

10:43 that's totally wrong

10:43 justin_smith: no, that's correct

10:43 that's exactly what it should look like as a valid clojure string

10:43 adgtl: I want to convert it to clojure map

10:43 justin_smith: it's properly escaped

10:43 OK, then parse it!

10:43 but now you have the string you can parse

10:43 adgtl: Seee what I am doing json/read-str

10:43 it should parse it too

10:43 justin_smith: no you aren't

10:43 oh...

10:43 that's weird

10:44 clojure.data.json?

10:44 rufoa: you don't need pr-str

10:44 just slurp right into read-str

10:44 zapho53: justin_smith: OK, thanks.

10:44 rufoa: cos its a string

10:44 justin_smith: rufoa: I was suggesting pr-str if he wanted to print the valid escaping

10:44 rufoa: yeah. but now he wants to parse it

10:44 so get rid

10:44 AeroNotix: he?

10:44 rufoa: *she?

10:44 justin_smith: adgtl: rufoa is right, just take out the pr-str if you want to parse straight away, and that will work

10:45 adgtl: I only suggested pr-str if you wanted to get the escaped version (it would print it)

10:46 adgtl: justin_smith: this did the trick (def n (json/read-str (json/read-str (pr-str (slurp "seed.json")))))

10:47 rufoa: that relies on a dodgy assumption about the similarity of clojure map and json map representations

10:47 don't do it

10:47 (def n (json/read-str (slurp "seed.json")))

10:47 justin_smith: adgtl: well, that would do it too, it's also a bit silly

10:48 AeroNotix: A link to clojure.data.json would've solved this ten minutes ago

10:48 rufoa: ^

10:48 AeroNotix: adgtl: https://github.com/clojure/data.json

10:48 justin_smith: AeroNotix: he is using data.json

10:48 AeroNotix: read that, come back if you have problems.

10:48 justin_smith: AeroNotix: the issue is the json literal properly quoted

10:48 AeroNotix: which was solved with putting it in a file, and slurp

10:49 AeroNotix: reading the docs always helps

10:49 adgtl: rufoa: thanks

10:49 corrrected

10:51 doing this now

10:51 (get (get (json/read-str (slurp "seed.json")) "recenttracks") "track")

10:51 two get to just get array back

10:51 rufoa: check out get-in

10:51 in core

10:51 justin_smith: adgtl: (get-in (json/read-str (slurp "seed.json")) ["recenttracks" "track"])

10:52 adgtl: justin_smith: smooth

10:52 AeroNotix: I'm really surprised more APIs don't expose a `get-in`-like function by default

10:52 because it's so useful

10:53 tcrayford____: AeroNotix: got some other examples you want a thing like get-in for?

10:53 apart from update-in/assoc-in

10:53 AeroNotix: tcrayford____: other languages

10:53 justin_smith: AeroNotix: inorite - when I first came to clojure, I had been working on a guile lib to work with json, and I was like "wait, get-in is what I wanted all along"

10:53 AeroNotix: justin_smith: exactly :)

10:53 tcrayford____: oh haha

10:54 AeroNotix: but for clojure-specific stuff, I think I'm missing dissoc-in

10:54 or dissoc-if

11:19 gfredericks: dissoc-if-not-contains?-meta

11:19 dissoc-if-not-contains?-meta-in

11:19 rufoa: haha

11:19 is there a macro version of that

11:22 AeroNotix: Do people use meta a lot? I don't seem to use it all that much

11:22 gfredericks: probably not; it's a weird feature but sometimes useful

11:23 confession: I used it this morning: https://github.com/gfredericks/test.chuck/issues/5

11:25 michaelr`: hi

11:30 I'm writing an application with ClojureScript and Om. I'd like to allow users to deep link into the application screens and then share urls. Such as the following app.com/#/factory/workers/1. The thing here is that when a users gets to this specific page, the application must load not only the data for this specific page, but also all of it's other state - such as to load the "factory" and then to load the "worker".

11:31 Now I'm asking how to architecture for such feature, so as not to make a sphaghetti off of it. :)

11:31 justin_smith: michaelr`: perhaps make a tree that describes the feature dependencies, and a function that can load the code needed for the features?

11:31 michaelr`: almost sounds like component when I put it that way...

11:32 michaelr`: justin_smith: it's less about code, more about state.

11:33 justin_smith: that is the application needs to be brought to a certain state such as if the user has been using it and navigating to this specific screen from the main screen.

11:34 justin_smith: here, he navigates directly to the sub screen...

11:34 justin_smith: michaelr`: component is about state

11:35 I did say "feature" rather than "state" - because big picture what matters is the functionality, and state or not is an implementation detail of that

11:37 regardless, what you need is a way to describe the set of features you need, and then something that can take that discription and build up the state / bindings needed to make those features

11:38 piranha: what could be wrong if compojure doesn't return Content-Type when I serve resources (with `(route/resources "/")`)?

11:39 justin_smith: piranha: so the response to the client has no Content-Type in the headers?

11:39 piranha: justin_smith: yep

11:39 justin_smith: what kind of file is it?

11:39 mavbozo: piranha: have you put content-type middleware?

11:39 michaelr`: justin_smith: ok thanks

11:39 piranha: mavbozo: hm, no, should I?

11:40 I've been looking at compojure sources and it looks like it should still work: https://github.com/weavejester/compojure/blob/master/src/compojure/route.clj#L38

11:40 justin_smith: css file, for example

11:40 justin_smith: michaelr`: something that often happens is that the logic for creating the proper state and bindings is interleaved with the UI workflow

11:40 michaelr`: which can totally work until you want parts of the UI to be directly accessible

11:41 michaelr`: at which point the building of state and bindings needs to be decoupled from UI - so your UI code will likely need to be changed to call the generic "build state and bindings if needed" code

11:42 piranha: there is a wrap-content-type handler that could help you

11:42 piranha: but I thought that was in by default

11:42 piranha: yeah, found it, thanks

11:42 but looking at compojure's code it should've been done already for me :\

11:43 anyway, this one should work

11:43 yep, it helped

11:44 damn

11:44 %)

11:44 justin_smith: except curl -I http://localhost:3000/ now returns application/octet-stream :-)

11:45 justin_smith: piranha: well, you will need to manually add a content-type header if the file-type can't be inferred I think

11:45 piranha: (GET "/" [] (resp/resource-response "index.html")) - how do I add content type here?

11:46 justin_smith: piranha: {:headers {:content-type "text/html"} :body (resp/resource-response "index.html") :status 200}

11:46 piranha: thanks!

11:46 justin_smith: that's if resource-response returns the text of the page

11:46 and not a map

11:47 michaelr`: justin_smith: can you maybe point at a source code anywhere which works like you described?

11:50 justin_smith: michaelr`: a very common, simple example would be the typical "login required" workflow. Instead of having a landing page that you always hit after login, you have a login that intercepts unauthorized access, and after login it sends you back to the resource you initially asked for

11:52 other usages of that pattern will add a more complex map of required features, but have a similar logic - you have a "desired destination" and you have the code that figures out what needs to be built up (load profile from the db? authenticate? load some resource representing your saved session?)

11:54 michaelr`: justin_smith: ok, thanks :)

12:03 justin_smith: i need to make some more thinking.. actually, I might be overthinking it as the current requirements only define one resource that needs to be deep linked within the application, and even then no constraints are set on how the URL should look like. So I'd have to weight seriously on whether there would be a real plus to architecting the whole application for deep linking. Of course that would be really neat, but I'm not

12:03 sure it's a real feature the client needs and wants to pay for :)

12:03 justin_smith: michaelr`: maybe a part of the URL could encode the source of the resource you need?

12:03 well anything beyond what would be specific to a user profile of course

12:04 cddr: I'm trying to add some debugging operations to cider-nrepl but am having a hard time making the tools.jar available to the middlware I'm adding

12:04 justin_smith: cddr: the jvm tools.jar?

12:04 cddr: yes

12:04 justin_smith: with some vms it needs to be explicitly added to your classpath

12:05 it's a 1.7 change iirc?

12:05 cddr: oh

12:05 justin_smith: cddr: and you need the jdk for tools.jar - jre works for most clojure stuff, but you need jdk for that one jar

12:06 cddr: ok, yeah I do have the jdk

12:07 Can a leiningen plugin be dependent on another plugin?

12:08 justin_smith: yeah, but it should specify it as a normal dep

12:08 since the other plugin should be available at its runtime

12:08 cddr: ah, right maybe that's what I was missing

12:08 I was using lein-jdk-tools but it wasn't working

12:08 kaplan: can anyone explain macros in a simple way to me?

12:08 cddr: But didn't have it in the deps

12:08 justin_smith: kaplan: they return the list representing the code that will eventually run

12:09 ,(defmacro two [] (list '+ 1 2))

12:09 clojurebot: #'sandbox/two

12:09 justin_smith: ,(two)

12:09 clojurebot: 3

12:09 justin_smith: haha

12:09 I made a mistake, but I hope it's still clear what that did

12:09 kaplan: the place where it gets interesting, is you can use the full power of the clojure language to construct that list

12:10 kaplan: hmmn, not clear

12:10 justin_smith: and we have tools like ` (aka syntax-quote) and ~ / ~@ (unquote / unquote splicing) that make writing macros much easier

12:10 ,(list '+ 1 1)

12:10 clojurebot: (+ 1 1)

12:10 justin_smith: that returns a list

12:10 which also happens to be valid clojuer code

12:10 *clojure

12:11 ,(defn two-f [] (list '+ 1 1))

12:11 clojurebot: #'sandbox/two-f

12:11 justin_smith: that's a function

12:11 ,(defmacro two-m [] (list '+ 1 1))

12:11 clojurebot: #'sandbox/two-m

12:11 justin_smith: that's a macro

12:11 ,(two-f)

12:11 clojurebot: (+ 1 1)

12:11 justin_smith: ,(two-m)

12:11 clojurebot: 2

12:11 justin_smith: note that they contain the same thing

12:11 but because one is a macro, its result gets evaluated, as if I had typed that in

12:12 kaplan: ahh

12:12 smt-: justin_smith: that was very good

12:12 justin_smith: smt-: thanks :)

12:12 kaplan: What do ` ~ and ~@ do

12:12 justin_smith: kaplan: so you can write code that constructs the code that needs to be run. This is often for developer convenience, making prettier syntaxes.

12:12 ,`(+ 1 1)

12:12 clojurebot: (clojure.core/+ 1 1)

12:13 justin_smith: so first off, ` resolves things to their bindings

12:13 + becomes clojure.core/+

12:13 (def num 42)

12:13 ,(def num 42)

12:13 clojurebot: #<CompilerException java.lang.SecurityException: denied, compiling:(NO_SOURCE_PATH:0:0)>

12:13 justin_smith: hrmph

12:13 ,(defn num [] 42)

12:13 clojurebot: #<CompilerException java.lang.SecurityException: denied, compiling:(NO_SOURCE_PATH:0:0)>

12:13 justin_smith: oh, it's the name

12:13 ,(def num- 42)

12:13 clojurebot: #'sandbox/num-

12:14 justin_smith: ,`(+ num- 1)

12:14 clojurebot: (clojure.core/+ sandbox/num- 1)

12:14 justin_smith: so that resolved the var

12:14 ,`(+ ~num- 1)

12:14 clojurebot: (clojure.core/+ 42 1)

12:14 justin_smith: that "unquoted" the var

12:15 ,`(+ ~@[num- 100 10001] 1)

12:15 clojurebot: (clojure.core/+ 42 100 10001 1)

12:15 justin_smith: and that unquoted, splicing

12:15 so these are all tools for deciding when things should be "unquoted" (evaluated sooner rather than later) and splicing rather than inserting

12:16 ,`(+ ~[num- 100 10001] 1) ; without splicing

12:16 clojurebot: (clojure.core/+ [42 100 10001] 1)

12:17 justin_smith: kaplan: basic idea is that ` / ~ / ~@ can make macro definition much easier

12:19 mavbozo: piranha: i just tried using compojure-app leiningen template and (compojure.route/resource "/") just works and sending the Content-Type

12:19 piranha: :(

12:19 mavbozo: piranha: do you also use `lein new compojure-app ...`?

12:19 piranha: mavbozo: I was doing exactly the same... anyway, wrote a bit of custom code, and it works

12:19 nope, not even close :)

12:19 I had to put compojure inside of an existing system

12:20 mavbozo: piranha: so, you use (with `(route/resources "/")`) . that's new to me

12:21 piranha: the "(with" part was just my words, not clojure's code :)

12:28 gfredericks: none of these routing libs seem to think it might be useful to know what route is going to match while you're running your middleware

12:28 justin_smith: gfredericks: it's tricky - my middleware might want to act differently based on the route that gets matched, but I also might want to use a middleware to change which route gets hit (see friend for example)

12:32 gfredericks: justin_smith: yeah -- I think it should just be easier to do things where you want to do them

12:32 I switched from compojure to polaris to make that easier, but it was still clunky

12:32 justin_smith: gfredericks: let me know if you have ideas for improving polaris btw.

12:33 I still vividly remember the heated discussion as we designed polaris at an indian buffet

12:38 AeroNotix: polaris' image makes me feel nauseous

12:38 especially when scrolling

12:38 justin_smith: haha

12:49 gfredericks: justin_smith: iirc I ended up using polaris to make a middleware that's ordered pretty early, does route matching, adds a key to the req saying what route matched, and a function for doing that route's thing

12:49 then there's a dummy handler at the bottom that just calls the function

12:49 justin_smith: gfredericks: interesting. If that's generally useful we could maybe include that middleware

12:50 gfredericks: it felt pretty weird :/

12:50 justin_smith: gfredericks: why not write the middleware to do things on the request coming out the other side rather than coming in?

12:50 gfredericks: thewhatnow?

12:51 justin_smith: ie. instead of (fn [handler] (fn [request] (handler (foo request)))) you can do (fn [handler] (fn [request] (foo (handler request))))

12:51 the latter lets the handler run first before doing its thing

12:51 gfredericks: the driving use case was wanting all logging associated w/ the request to be able to include which route it was applying to

12:51 justin_smith: ahh

12:52 so the logging could use the latter pattern, right?

12:52 gfredericks: well there's two middlewares involved

12:52 one that does the route matching and one that does logging

12:53 justin_smith: yeah, I'm just saying if you added an assoc of the route at the handler dispatch, the first one isn't even a middleware any more

12:53 and if the logging uses type b (acting after the handler instead of before) it gets all the info it needs

12:54 gfredericks: the logging goes on both sides

12:54 so the route has to be matched beforehand

12:55 justin_smith: what if the first part of the logger attached a lambda to the request

12:55 and the second part ran it

12:55 (with matching route as an arg, if course)

12:55 gfredericks: right, something like that is an option; it feels a little risky/loose to defer logging to after the request

12:56 justin_smith: it's still during the request - just on the tail end after the handler got hit

12:56 gfredericks: and that also presupposes that there aren't any other pre-middlewares interested in logging

12:56 or else you'd have to rewrite all of those too

12:56 justin_smith: right

12:57 gfredericks: it feels like something where there would be an elegant solution

12:57 perhaps it would require route matching vs. route execution to be broken up (which is what you did, in an ad-hoc way)

12:57 gfredericks: yeah

12:57 route matching could return a keyword w/ a params map or something

12:58 justin_smith: polaris should have a function that looks up the handler but not yet calling it

12:58 hmm, yeah

12:58 adgtl: Anyone know easiest way to parse json in clojurescript?

12:58 gfredericks: make the pattern: (def my-routes [...]) (def base-handler (compile-base-handler my-routes)) (def wrap-route-matching (compile-route-matching my-routes)) or so

12:59 adgtl: seems this one is not available clojure.data.json?

13:00 justin_smith: adgtl: I think the easiest way in cljs is to let js do the parsing, and then convert it to clojure data afterward if needed with -js->clj

13:00 adgtl: js->clj?

13:00 justin_smith: yeah

13:00 -js->clj is the underlying protocol method

13:00 but better to use the function, yeah

13:01 https://github.com/clojure/clojurescript/blob/master/src/cljs/cljs/core.cljs#L8676

13:01 adgtl: why can't I do (require '[clojure.data.json :as json])

13:01 justin_smith: clojure.data.json uses java

13:01 which isn't there in the clojurescript runtime

13:01 well, it uses the jvm

13:02 and a javascript runtime's native json reading is very likely better than clojure.data.json could do anyway

13:03 adgtl: justin_smith: but now I have problem.. how can I know that some libraries are there in clojurescript and some are not

13:03 I was assuming all the clojure libs are available for clojurescript too

13:03 justin_smith: adgtl: hopefully the libs will mention if they are cljs compatible

13:03 no, not all work

13:03 adgtl: Any documentation for -js->clj ?

13:04 justin_smith: adgtl: I just linked to it's source, including doc-string

13:04 you would create the js object from the json in the normal way it is done in js

13:04 and then call js->clj on it

13:04 tomjack: cfleming: downgrading to 0.1.44 appears to have fixed my resolution issue

13:05 adgtl: (-js->clj "{}") fails on repl

13:05 justin_smith: that's not a js object

13:05 that's a json string

13:05 adgtl: how to pass js object then?

13:05 justin_smith: something like (js->clj (JSON/parse "{}")) I think

13:05 tomjack: cfleming: oh, no, it didn't, nevermind :(

13:06 adgtl: throws error too (-js->clj {a: "b"})

13:06 justin_smith: adgtl: yes, because you can't just put js literals in cljs

13:06 that's why I suggested using JSON/parse

13:07 adgtl: (js->clj (JSON/parse "{'a': 'awesome'}")) fails too

13:07 justin_smith: it shouldn't

13:07 don't use '

13:07 ' isn't json

13:08 (js->clj (JSON/parse "{}")) will work

13:08 adgtl: okay

13:09 justin_smith: (js->clj (JSON/parse "{\"a\": \"awesome\"}")) also works

13:13 gfredericks: clojurebot: ' |isn't| json

13:13 clojurebot: 'Sea, mhuise.

13:14 adgtl: cljs throwing

13:14 No such namespace: JSON at line 13

13:15 I could do that from repl

13:15 but not from my cljs code

13:15 l3dx: I have a map where each value again is a map. I want to dissoc one of the keys from the inner maps. how would you do that?

13:15 michaniskin: js/JSON

13:15 gfredericks: l3dx: update

13:16 justin_smith: michaniskin: so then would it be (.parse js/JSON "{}") ?

13:16 michaniskin: justin_smith: should be yes

13:16 l3dx: gfredericks: thanks!

13:23 adgtl: Just realized that I can't read files from clojurescript

13:23 so slurp won't work

13:23 justin_smith: but you can serve json files to cljs

13:23 l3dx: hah, nice 404 at clojuredocs :)

13:24 justin_smith: and there is also a #js literal for inline js in clojurescript

13:25 #js {"foo" "bar"} will create a js object directly

13:25 without even needing the json parsing step

13:27 michaniskin: (js-obj "foo" "bar")

13:29 justin_smith: michaniskin: #js reader is just a shorcut for js-obj

13:29 Lewix: https://gist.github.com/6ewis/eb653a3985c5f7feeb30 - what does bottom and size refer to in this example

13:30 justin_smith: Lewix: the arguments to the function

13:30 michaniskin: justin_smith: indeed

13:30 Lewix: justin_smith: no. I mean what do those specific argument represent

13:31 justin_smith: from reading the code, the y of the bottom edge, the x of the left edge, and the width/height

13:31 it generates x/y pairs for a square that is aligned with the cartesian grid

13:32 Lewix: justin_smith: width/height?

13:32 whodidthis: how do i get lein midje to use project.clj's :test profile

13:32 justin_smith: Lewix: yes, the size, in x/y units

13:33 Lewix: justin_smith: it's not intuitive to me

13:34 justin_smith: thanks. I'll think about it

13:34 justin_smith: well, since it is a square, the width and height are the same, right?

13:35 so they are provided as one argument

13:36 Lewix: justin_smith: thanks. i got it now

13:42 How do you think about the parenthesis in clojure?

13:43 like curly braces?

13:52 sveri: Hi, having a list of arbitrary depth and length, how can I check if it contains a certain element?

13:52 smt-: Lewix: in C: foobar(1, 2, "foo"); in Clojure: (foobar 1 2 "foo"). that's how I think about them. they are not the same as curly braces

13:53 rufoa: sveri: do you mean nested vectors? if so flatten them first

13:53 sveri: rufoa: actually I mean seqs :-)

13:53 but flattening sounds good :-)

13:54 Lewix: smt-: you think about them in terms of functions

13:54 sveri: rufoa: thank you, I guess flatten will do the trick

13:54 rufoa: ,(some #{4} (flatten '(1 2 (3 4) 5)))

13:54 clojurebot: 4

13:54 smt-: Lewix: the trick is that everything in clojure is an expression, which means everything returns a value. even an 'if' returns a value. 'if' in C does not, it just branches the execution. once you grok the implications of that, parenthesis suddenly make sense

13:56 Lewix: smt-: I see. so you think about them in terms of expressions

13:56 adgtl: What's the simplest way to do ajax from clojurescript?

13:58 smt-: Lewix: yes. in C you have nested blocks of code, and you control the execution flow. in clojure you have nested expressions but no blocks, hence no need for curly braces

13:58 rufoa: Lewix you might find this illuminating https://en.wikipedia.org/wiki/S-expression#Use_in_Lisp

13:59 Lewix: smt-: thanks

13:59 rufoa: thanks I'll give it a read later

14:02 smt-: adgtl: https://github.com/JulianBirch/cljs-ajax

14:02 adgtl: sveri: thanks :)

14:03 smt-: how about cljs-http?

14:05 smt-: adgtl: I've never used cljs-http so I don't know about that

14:12 adgtl: smt-: ok

14:19 Lewix: (require '[clojure.string :as str])

14:20 why do we need `

14:20 ;`[1 2]

14:20 jjmojojjmojo: Lewix: because clojure.string isn't in the namespace

14:20 Lewix: ;;`[1 2]

14:20 >>`[1 2]

14:21 jjmojojjmojo: Lewix: https://clojuredocs.org/clojure.core/quote

14:21 that's what ' is expaned to in the compiler

14:22 Lewix: How do you guys run clojure code

14:22 here

14:22 mearnsh: ,`[1 2]

14:22 clojurebot: [1 2]

14:22 Lewix: thanks

14:23 ,(type `[1 2])

14:23 clojurebot: clojure.lang.PersistentVector

14:23 Lewix: ,(type [1 2])

14:23 mearnsh: ,`(+)

14:23 clojurebot: clojure.lang.PersistentVector

14:23 (clojure.core/+)

14:23 mearnsh: ,'(+)

14:23 clojurebot: (+)

14:23 Lewix: so jjmojojjmojo it's pretty much the same thing it seems (whenever we use vector)

14:23 mearnsh: syntax quote ` gives you fully qualified symbols

14:23 clojurebot: Cool story bro.

14:24 sundbry: Clojurebot, stop being a dick!

14:24 Lewix: mearnsh: can you be more explicit please

14:24 mearnsh: `str

14:24 ,`str

14:24 clojurebot: clojure.core/str

14:24 mearnsh: ,'str

14:24 clojurebot: str

14:25 Lewix: mearnsh: i understand why it's needed for lists but not so sure about vectors

14:25 jjmojojjmojo: Lewix: it's not though - when you use it in a case like require, you're passing an un-evaluated vector that contains references to things you want to be loaded - if you try (require [clojure.string :as str]) it will break (unless you somehow have clojure.string already loaded)

14:25 mearnsh: is there a context to this question?

14:25 justin_smith: Lewix: in general it namespace qualifies things, and allows selective unquoting

14:25 ` is most useful in macros

14:25 jjmojojjmojo: mearnsh: the initial query was about require

14:26 disclaimer: I am not an expert :)

14:26 Lewix: jjmojojjmojo: ah i see, we are using a function in the vector we're passing

14:26 srruby: How do clojure servers compare with node.js for serving restful apis ? I'm reviewing current web stacks. Some are recommending node,express,mongo,and angular. I'd probably go for clojure and react...

14:27 jjmojojjmojo: srruby: what sort of comparison do you want?

14:27 justin_smith: Lewix: wait, you showed an example using ' and then asked why we need ` right?

14:27 jjmojojjmojo: express != node :)

14:28 Lewix: srruby: my guess is not callback hell and promises craziness anymore

14:28 justin_smith: i meant `

14:28 jjmojojjmojo: srruby: I'm not like the other kids, but I prefer to build my restful stuff without help from frameworks and other distractions - so all I need is something like ring

14:28 justin_smith: ok, because you should not use ` with require

14:29 Lewix: justin_smith: oh apparently it's ' ( i confuse both all the time)

14:29 jjmojojjmojo: Lewix: me too :)

14:29 justin_smith: OK - because it made it look like you were asking a much more complex question than you actually were

14:29 Lewix: jjmojojjmojo: so what's ` for and what's ' for

14:30 justin_smith: most of my questions are probably basic at this point. I don't know clojure

14:30 justin_smith: ' prevents evaluation, ` prevents evaluation, fully resolves symbols in the current context, and allows selective unquoting and splicing

14:30 jjmojojjmojo: Lewix: ^^^ what justin_smith said

14:30 srruby: Thanks everyone. I'll think about how to formulate a better question.

14:30 justin_smith: the features of ` are mostly useful when writing macros

14:31 Lewix: justin_smith: it' sso confusing

14:31 smt-: Lewix: does this help:

14:31 ,(let [x 10 y 20] [x y])

14:32 clojurebot: [10 20]

14:32 smt-: ,(let [x 10 y 20] '[x y])

14:32 clojurebot: [x y]

14:32 justin_smith: srruby: the big difference between clojure and node imho is that clojure takes longer to start up, but it can scale more in a single process. Both can do async within one thread, but clojure has the option of also having mutiple threads

14:32 smt-: ,(let [x 10 y 20] `[x y])

14:32 clojurebot: [sandbox/x sandbox/y]

14:32 Lewix: holycow

14:33 justin_smith: , smt- : I'm not sure i understand `

14:33 it does the same thing as ' + extra stuff

14:34 justin_smith: Lewix: it's useful when writing macros, don't worry about it (and don't use it) until you need it for macro writing

14:34 Lewix: yet we cannot use it as a replacement for '

14:34 justin_smith: no, because it does extra stuff :)

14:34 Lewix: ok I'll leave it at that for now

14:34 justin_smith: A tank does what a truck does, + extra stuff

14:34 but you probably don't want to use it instead of a truck usually

14:35 Lewix: ok fair enough

14:35 am I gonna survive with clojure?

14:35 srruby: justin_smith: Thanks. I think I'll use Clojure when I can in order to preserve my sanity.

14:35 Lewix: I'm losing my motivation to learn it everyday

14:35 justin_smith: Lewix: I think so. Don't be afraid to try things in the repl. Try things that you think should work, and also try things that you think should fail.

14:35 Lewix: srruby: aha tell me about it

14:36 drojas: anyone knows some graph data structure library?

14:36 Lewix: justin_smith: what p languages do you work with?

14:36 justin_smith: Lewix: remember that it doesn't go as deep as other langauges do. You learn some rules and special cases, and relatively quickly you are done. After that it's figuring out the nuances, and how to design things for the most part.

14:37 Lewix: in the past I have used C, C++, OCaml, Scheme

14:37 played around a little bit with java / javascript and a bunch of other stuff

14:37 lot's of shell scripting with vanilla bourne shell/ bash if you count that

14:37 Lewix: justin_smith: I see. thanks for the encouragement

14:38 justin_smith: Lewix: I'd say it's pretty similar to C in terms of the number of special cases you need to learn. Much simpler than eg. C++, Java. A bit more complex than OCaml and Scheme are but not massively so.

14:39 smt-: Lewix: have you written any simple programs in .clj files, or played only in repl?

14:40 Lewix: justin_smith: yea I learned C++ Java back in college (Haven't touch those for an eternity so I barely remember). I also played with C but these days I'm mostly into ruby and javascript in my day to day work

14:40 smt-: justin_smith: btw, does OCaml have persistent data structures?

14:40 justin_smith: smt-: indeed it does

14:41 smt-: it doesn't have a concurrent garbage collector though, so it can't do multi process things as easily as clojure

14:41 Lewix: smt-: I'm playing while learning. It;s just that pesky feeling that you're starting something from scratch and you're not even sure it's worth your time

14:41 justin_smith: usually it is similar to eg. ruby / python / node where you start multiple processes and have them communicate, not as nice as multi threading in clojure

14:41 smt-: justin_smith: how do you like OCaml? I almost began learning it some years ago, but didn't. should I? :)

14:42 justin_smith: smt-: I think it is great. Many of the advantages of Haskell while being much easier to pick up and learn.

14:42 and if you like clojure, most of the ideas cross over (higher order functions, immutable data, etc.)

14:43 smt-: justin_smith: thanks, sounds promising

14:43 justin_smith: but you also get pattern matching, and static typing (for better and every so often worse)

14:44 Lewix: justin_smith: which one do you prefer

14:44 justin_smith: Lewix: I like clojure - because I am doing stuff that works better with real threads

14:44 also, it's easier to deploy in a corporate environment if you are using the jvm

14:45 Lewix: justin_smith: I heard we can use clojure on top of node?

14:45 justin_smith: Lewix: clojurescript, yeah. Though I think node support might still be in progress?

14:45 smt-: Lewix: what kind of applications would you like to do? that way you can figure out if learning clojure is worth it

14:45 Lewix: games? web apps?

14:46 Lewix: smt-: mostly backend for mobile apps

14:46 justin_smith: Lewix: server backend, with multiple clients, is a place where Clojure does very well.

14:46 smt-: Lewix: for that kind of work I find clojure excellent

14:47 Lewix: great. lets see how it goes

15:21 justin_smith: what book do you advise

15:23 whodidthis: how do i insert a vector of longs to a bigint[] column in yesql, i tried "...VALUES (:user_id, :my_vector)" and "VALUES (:user_id, (:my_vector))" but the first one says "insert has more expressions than target columns" and the other "expression is of type record"

15:23 justin_smith: Lewix: Clojure Programming is good

15:25 devll: (inc justin_smith )

15:25 lazybot: ⇒ 4

15:25 justin_smith: devll: it's space-sensitive

15:25 (identity karma karma karma karma chameleon)

15:25 lazybot: karma karma karma karma chameleon has karma 1.

15:26 AeroNotix: (identity AeroNotix)

15:26 lazybot: AeroNotix has karma 5.

15:26 AeroNotix: yay

15:26 TIL

15:26 justin_smith: (identity justin_smith)

15:26 lazybot: justin_smith has karma 186.

15:26 justin_smith: (identity justin_smith )

15:26 lazybot: justin_smith has karma 4.

15:26 AeroNotix: (inc justin_smith)

15:26 lazybot: ⇒ 187

15:26 AeroNotix: 187 skills

15:26 Ckihy

15:27 devll: wow

15:28 AeroNotix: Protected by clojurists with big ideas, Parens, and 187 skills

15:28 justin_smith: ^

15:28 justin_smith: haha

15:29 ncthom91: hi all. Any overtone users in here?

15:32 amalloy: ~anyone

15:32 clojurebot: Just a heads up, you're more likely to get some help if you ask the question you really want the answer to, instead of "does anyone ..."

15:32 AeroNotix: or my favourite variation:

15:32 don't ask to ask, ask.

15:32 amalloy: ~ask

15:32 clojurebot: The Ask To Ask protocol wastes more bandwidth than any version of the Ask protocol, so just ask your question.

15:33 AeroNotix: :|

15:33 (inc clojurebot)

15:33 lazybot: ⇒ 47

15:33 amalloy: that factoid is technomancy's i think

15:33 AeroNotix: (inc technomancy)

15:33 lazybot: ⇒ 162

15:33 AeroNotix: ,scoreboard

15:33 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: scoreboard in this context, compiling:(NO_SOURCE_PATH:0:0)>

15:35 gfredericks: I think there's another element to it, which is that some people might be able to answer your question but aren't willing to admit to arbitrary familiarity with X since who knows what the followup question might be

15:35 amalloy: right, that's my perspective

15:35 AeroNotix: also, the X/Y problem

15:36 amalloy: (not on overtone specifically, since i know i won't be able to answer)

15:45 justin_smith: amalloy: the question asker may think it's an overtone problem, but it turns out to be like their profiles.clj is messed up

15:45 amalloy: things like that happen all the time :)

15:52 ncthom91: anyway, what's your overtone question?

15:54 ncthom91: justin_smith it's about how to route audio buses in overtone. i.e. if I define an instrument with definst, I'm not sure how I would then route the output of that instrument through various fx (i.e. if I want to write a custom waveshaper), and then how I would do things like split the audio bus and route the same channel simultaneously through two parallel effects

15:55 justin_smith: ncthom91: with overtone's model, splitting a bus is just a question of using the same bus in two places

15:55 ncthom91: cool. that parts easy enough then, eh? :)

15:55 justin_smith: ncthom91: regarding routing, it's been a while since I have used this, but it all happens in the supercollider vm - there are commands in the vm to route different "synth groups" to one another

15:56 every instrument is in a synth group, and you can tell the sc vm that the output of one synth group is the input of another etc.

15:56 ncthom91: justin_smith do you know how to do that?

15:56 is it part of hte overtone clojure api? Or do I have to get down in the SC trenches?

15:57 justin_smith: ncthom91: almost everything in overtone is just network commands sent to the sc vm

15:57 all those routing commands are exposed to the network interface, even if overtone doesn't map them they can likely still be accessed in some way

15:59 ncthom91: justin_smith this actually looks close to what I need I think: https://github.com/overtone/overtone/blob/e200075da27375727db1f5ce342e2e1c22ea1dbd/src/overtone/examples/synthesis/fx.clj#L25-L36

16:00 justin_smith: that looks exactly right, yeah

16:00 though I thought it would be a bit more flexible. I guess you could define everything to take a bus in

16:01 and a bus out...

16:01 but yeah, it will at least do what you want

16:01 (right now I am working on a little pixie lang dsl to create a csound score for a musical project)

16:01 ncthom91: justin_smith woah awesome! Is it open source?

16:02 justin_smith: not uploaded yet, I might at the very least upload some of the util libs

16:02 ncthom91: I'm working on a synthesis exploration blog post using overtone

16:02 justin_smith: may or may not upload the composition (it uses a huge audio file...)

16:02 cool

16:03 I tend to like csound as a target lang because it is super trivial to generate code for (it is basically a modified assember syntax)

16:03 or a lisp with no parens, no first class functions, and only one expression per line

16:05 ncthom91: justin_smith hm, I'm rather unfamiliar with csound but I know I've heard of it

16:05 justin_smith: (the syntax supports more than that, but it can be used in that stripped down assmbler style)

16:05 it's a direct descendent of the language max matthews used to program a computer to sing "bicycle built for two"

16:06 not as fancy as supercollider, but it's familiar to me so I use it

16:06 and it's very low overhead for the most part

16:08 ncthom91: to be fair, I never got into SC either. I've always worked in higher level languages like Max/MSP, but in the past few years I've really gotten interested in the math behind hte sound, hence my diving into overtone

16:08 hm that's probably where I've heard of CSound... does Max/MSP have a relation to csound?

16:09 justin_smith: ncthom91: MSP is Miller S Puckett, a student of Max Matthews

16:10 MSP is the author of PD, which you may have heard of

16:10 they all (including supercollider which is the engine for overtone) use the same basic internal model

16:10 but they have various syntax and UI differences

16:11 eg. Max and PD are both point and click visual programming

16:11 but the semantics are identical to the textual ones still

16:12 cfleming: tomjack: Ok, thank - I haven't had a chance to look at your repro case yet, I'll take a look today

16:12 tomjack: *thanks

16:21 ncthom91: justin_smith cool, yea i've used PD a bit

16:23 justin_smith: I've found core.async maps nicely to the part of my brain that knows pd

16:24 ncthom91: justin_smith how do you suppose I could take an audio bus in, duplicate the sound and pitch offset one of the duplicates in the output bus?

16:24 justin_smith: my bigger pd patches were all sends and receives

16:26 so mix audio on an input bus with a pitch shifted verdion of itself?

16:27 ncthom91: justin_smith yea

16:27 justin_smith: the audio sig itself won't be destroyed by pitch shifting, so you can just use the same input twice

16:30 and then sum the regular signal with the shifted one. usually this turns out better if you also adjust the level of the clean and shifted sigs

16:32 ncthom91: justin_smith sweet yea that makes sense. How would you shift the signal? Supposing I'm going to have to calc the FFT here yea?

16:32 justin_smith: it is just like taking two connections from the same in in pd, processing one, and adding that to the other

16:32 ncthom91: right

16:32 sveri: Hi, I have trouble understanding first and rest in a loop recur. In this paste: http://pastebin.com/2d53etiJ I have a vec, doing first on it gives me back a list. Doing rest on it gives me back a list in a list whereas I expect just a simple list too. Why is that?

16:33 justin_smith: ncthom91: there should br a good pitch shift built in

16:33 ncthom91: justin_smith ah, that'd be sweet :)

16:34 hm looks like there's a UGen for it. Suppose I gotta learn how to use UGens then lol

16:36 justin_smith: sveri: do you want second instead of rest?

16:37 sveri: justin_smith: second would work, but I might have more than two seqs in the vec and wanted to use loop / recur with first / rest

16:40 ncthom91: justin_smith any chance you've worked with ugens in overtone? can't seem to find good docs on it

16:41 sveri: jeez, I am so stupid, of course rest returns the rest in a list -.-

16:45 justin_smith: ncthom91: doesn't using a name in a synthdef translate to using that ugen?

16:50 the overtone cheatsheet indicates you can call shift in a synthdef

16:55 ncthom91: justin_smith what do you mean using a name in synthdef translates to using a ugen?

16:57 justin_smith: synthdefs are not normal code

16:57 hey are dsl

16:58 (shift sig) in a synthdef translates to inserting the shift ugen in the def

17:00 emaczen: does anybody here use the luminus web framework/libraries?

17:01 I want to know about the HTML templates that are loading by default

17:01 I would prefer to solely use clojure/clojurescript

17:03 justin_smith: emaczen: you should just be able to add a dep to your preferred templating lib and csll that in your handlers

17:06 emaczen: justin_smith: Do you use the luminus stackk?

17:06 Or the libraries since it is mostly a set of libraries rather than a framework

17:10 justin_smith: I ask because I don't see where to do this -- I see a selmer dependency in handler.clj but it is only called in one place that doesn't seem all that related to what you mention.

17:10 avshalom: emaczen: yes, and i also use "web development with clojure" as a reference

17:11 justin_smith: I don't use it, but chsnging page rendering will just be a question of changing what the handler function returns

17:11 emaczen: justin_smith: Ok, I know where that is then.

17:11 avshalom: Do you use Selmer? Or do you use clojurescript for templating?

17:12 I think the cljs templating is the hiccup library? Is that correct?

17:12 avshalom: not yet, now i am using hiccup

17:12 once i start working with web developers i will probably switch over

17:12 emaczen: avshalom: Do you plan on using Selmer? If so why?

17:13 avshalom: emaczen: i think it would be better for implementing existing stylesheets that were created by webdevs using other technology

17:14 emaczen: avshalom: Yeah, I'm trying to work by myself so it wil be a matter of personal preference for me then :)

17:14 avshalom: emaczen: now, i am just writing boring webpages by synthesizing with hiccup

17:14 emaczen: synthesizing?

17:14 avshalom: programmatically generating

17:14 emaczen: avshalom: I'm new to web-development with a little experience with some JS technologies but I do mostly backend work.

17:15 I also have some Common Lisp experience

17:15 avshalom: emaczen: i'm not a web maven -- i usually do the brains and back end. so, this is new territory, don't know the web lingo

17:15 emaczen: avshalom: Haha, I guess we are in similar boats then...

17:15 But you look like you have the head start :)

17:15 avshalom: emaczen: i would definitely get the "web development with clojure" book/pdf

17:16 emaczen: Sounds like a good idea.

17:16 avshalom: there is also a video series by packt? i think

17:16 emaczen: One quick question for you though.

17:17 avshalom: it's audio is a little crummy, but if you want to get up and going FAST, then it's pretty good

17:17 yes?

17:17 emaczen: Inside the home-page function in home.clj -- how do you render the page with hiccup? By default with luminus there is a line of code: (layout/render "app.html" ...

17:18 This renders the HTML/Selmer template.

17:18 avshalom: dunno, i don't use selmer (yet)

17:18 emaczen: avshalom: I wish to use hiccup

17:19 avshalom: just something like (defroutes "/" [] (home)) i think, with content in home function

17:20 emaczen: Can you link me to those videos by pakt?

17:20 I didn't find anything on goolge

17:20 ahh, I think I found it

17:20 I'm getting antzy I guess...

17:20 avshalom: https://www.packtpub.com/web-development/building-web-applications-clojure-video

17:20 emaczen: Thanks!

17:20 avshalom: yeah, its $35 well spent.

17:21 (defn home [] (layout/common [:h1 "Doo Dah"]))

17:23 emaczen: does web-dev with clojure use hiccup for their layouts?

17:23 I have played with hiccup inside selmer actually

17:23 Wait

17:23 avshalom: iirc, it does both

17:23 emaczen: I mean, I have loaded some selmer templates, and then on top of that used some hiccup

17:26 avshalom: i really want that book on reactive functional programming. i guess i have to wait another month....

17:27 i came from a Fortran / Scientific programming background, and all this stuff is radically different, but i think that i know that i want to do it

17:27 some book on idioms for concurrent programming

17:28 (but in clojure, because i'm not good at clojure or concurrent programming)

17:28 emaczen: avshalom: How much do you know about Lisp dialects?

17:28 avshalom: emaczen: i can do small stuff in elisp

17:29 emaczen: avshalom: Do you know how to use lisp macros?

17:29 avshalom: emaczen: but elisp is not practical enough for "day job" stuff. clojure is practical, though unfortunately, so much maths code is in C and Fortran

17:29 emaczen: avshalom: Maxima is written in Common Lisp

17:29 Clojure is influenced by Common Lisp

17:29 avshalom: emaczen: i know the rudiments of Lisp Macros, but i haven't found a case where i would say "oh, i gotta have a macro instead of a function"

17:30 emaczen: avshalom: I'm new to this as well but I found a pretty cool use case the other day.

17:30 AeroNotix: emaczen: one of the things I really like about Clojure is how un-Common Lisp it is.

17:30 originally Clojure was implemented in CL but Clojure is decidedly not anything at all much like Common Lisp

17:30 aside from being, you know, a Lisp.

17:31 avshalom: emaczen: in fact i came to Lisp through Mathematica (don't shoot, i know mma is not a lisp)

17:31 emaczen: AeroNotix: I don't really know details, but from the languages I have played with, it is most similar to common lisp.

17:31 AeroNotix: emaczen: in what way?

17:31 avshalom: completeness?

17:32 AeroNotix: Oh right we're just making things up. Gotcha.

17:32 emaczen: AeroNotix: multimethods

17:32 generic funciton model instead of message passing mod

17:32 model*

17:32 and it is a lisp dialect, where every other language I know is not.

17:32 AeroNotix: emaczen: multimethods aren't at all like CLOS.\

17:32 emaczen: CLOS has multimethods

17:33 I have not used another PL that uses the generic function model

17:33 AeroNotix: Sure, but it's much richer and actually is a core language feature, rather than being altogether "meh" in Clojure.

17:33 emaczen: If you know a little CL, I think it is a good place to start drawing connections

17:34 Avshalom: Anyway, the use case for macros that I found interesting/fun was a tiny SQL like manipulation for an inefficient list of lists data-table implementation

17:34 AeroNotix: and you only have single dispatch in Clojure.

17:35 m1dnight_: guys, currently I have a printer function (def print [sender & msgs] ..) that I call like (print "me" "foo" "bar")

17:35 emaczen: Avshalom: So I defined 'select' and 'where' as "library" functions and then used them in a macro that would let me type something like: (select (column1 column2) from table where [expressions are true]

17:35 m1dnight_: but now I want to add a second function that takes multiple lists that represent a single line (multithreaded and all that)

17:36 I'm guessing it's not possible since [sender & msgs] will match anything, right?

17:36 avshalom: emaczen: that's cool

17:36 emaczen: that's another book i want, the one on clojure macros

17:37 emaczen: maybe one day when i am a clojure stud, i will write my own dsl

17:37 emaczen: avshalom: if you are interested in macros, I would recommend On Lisp by Paul Graham

17:37 avshalom: or not, because i'm having a blast making money with functions ;-)

17:37 emaczen: avshalom: Yeah, I should spend more time trying to make some money than doing random lispy things :)

17:38 AeroNotix: On Lisp is one of the only very detailed texts on macros. It gets another +1 from me.

17:38 avshalom: emaczen: i will say that i haven't had this much "fun" in years. clojure has been fun!!!!

17:39 emaczen: avshalom: Oh yeah! All Lisp programming is usually fun!

17:39 avshalom: emaczen: and remarkably Mathematica-like. i feel that i can transfer a lot of experience into clojure, and bosses will be satistfied by JVM language

17:39 emaczen: i love using clojure, and watching my 40-core machine shoot to 100% usage.

17:39 AeroNotix: you develop on a 40-core machine?

17:40 avshalom: yeah

17:40 emaczen: I'm jealous!

17:40 avshalom: it's a fucking beast

17:40 250 gig of ram, 200 terabytes of storage

17:40 emaczen: avshalom: I guess you are doing some machine learning / statistics?

17:40 avshalom: (and i have three of them)

17:40 emaczen: With Big Data?

17:40 avshalom: emaczen: yeah

17:40 AeroNotix: Which processor is that?

17:40 avshalom: oh, i dunno. xeon or something

17:41 i also use an ibm p595

17:41 AeroNotix: haha

17:41 ok

17:41 o7

17:41 avshalom: we're getting a new one soon, just that it takes a bit of time to buy a $10 million dollar machine.

17:41 AeroNotix: Roger.

17:41 I'm writing this all down.

17:43 avshalom: emaczen: i'm in the post-big data / machine learning world

17:43 AeroNotix: https://www.youtube.com/watch?v=pnD_51Vvi1I

17:43 avshalom: emaczen: i've gone back to smarter/better models that actually fit the problem

17:43 emaczen: avshalom: What is the post-big data / machine learning world?

17:43 avshalom: more bayesian statistics and markov chain monte carlo

17:43 emaczen: Ahhh cool! I'm just getting into this world really.

17:44 avshalom: emaczen: i.e. there is no universal algorithm (machine learning) that will solve all problems

17:44 emaczen: I wrote a naive bayes classifier with gaussian and bernoulli implementations

17:44 Mostly as a Common Lisp exercise

17:44 avshalom: naive bayes is actually pretty good imo. and a good framework to develop sophisticated models.

17:45 yeah, recur :-)

17:45 m1dnight_: is there a thing like "unlist"?

17:45 I want to pass a list of elements as multiple arguments to a function but i'm not sure how

17:45 I know I've done it before but i can't remember

17:45 avshalom: emaczen: talk to you later, maybe here or on #emacs. i need to go yell at the kids

17:46 take care AeroNotix, i will make you an account once the power 8 arrives

17:46 AeroNotix: m1dnight_: apply

17:46 avshalom: An elephant you say?

17:46 avshalom: :-)

17:46 AeroNotix: m1dnight_: ,(apply + [1 2 3 4])

17:46 ,(apply + [1 2 3 4])

17:46 m1dnight_: yea, but what if + takes more than 1 argument?

17:46 clojurebot: 10

17:46 emaczen: avshalom: haha sounds good, cya later

17:46 m1dnight_: the signature is (def printer [sender & msgs] ..)

17:47 AeroNotix: m1dnight_: TIAS

17:47 ,(doc apply)

17:47 clojurebot: "([f args] [f x args] [f x y args] [f x y z args] [f a b c d ...]); Applies fn f to the argument list formed by prepending intervening arguments to args."

17:48 m1dnight_: ohhhh

17:48 (I had to google TIAS, btw)

17:48 AeroNotix: m1dnight_: :)

17:50 mr_rm: did (fn) always allow you to give it a name, like: (fn foo [_] 42) ?

17:51 Bronsa: mr_rm: yes

17:52 AeroNotix: the alternative is maddening

17:52 mr_rm: Bronsa: ok thanks. it took me quite a while to realize that! i always thought it was purely anonymous and was doing stuff like (let [foo (fn [_] ...)] ...)

17:52 AeroNotix: mr_rm: there's let-fn

17:53 sorry letfn

17:53 mr_rm: AeroNotix: yes, i knew about that. just a stupid example

17:53 AeroNotix: stoopid example

17:53 mr_rm: heh

17:56 m1dnight_: okay I have one more question, if you guys dont mind. (I have googled zip, merge, merge with, zip with, concat with..) but I would like to merge sequences with a value

17:57 like (merge-with [1 2 3] [4 5 6] [-1]) --> [1 2 3 -1 4 5 6]) ?

17:58 AeroNotix: m1dnight_: flatten

17:58 but

17:58 ,flatten

17:58 dammit

17:58 clojurebot: #<core$flatten clojure.core$flatten@99a9fc5>

17:58 AeroNotix: mr_rm: concat

17:58 ~flatten

17:58 clojurebot: flatten is rarely the right answer. Suppose you need to use a list as your "base type", for example. Usually you only want to flatten a single level, and in that case you're better off with concat. Or, better still, use mapcat to produce a sequence that's shaped right to begin with.

17:58 AeroNotix: m1dnight_: ^^

17:59 m1dnight_: that has had some sorting applied, what's the sort there?

17:59 m1dnight_: well, the actual use case is the following: I want to call (debug-msg sendername ["line" " one"] ["line " "two"])

18:00 AeroNotix: and?

18:00 m1dnight_: Since this debugging function is needed for the sake of printing multiline without other threads interleaving

18:00 I need to put it in a single print statement

18:00 so no particular sort, the elements arent even numbers

18:00 AeroNotix: You're talking about printing to the terminal?

18:00 m1dnight_: yes

18:00 AeroNotix: Do you care about logging?

18:01 m1dnight_: it's more debug logging :p

18:01 AeroNotix: ah

18:01 m1dnight_: but I have some "state" I need to print that takes up multiple lines

18:01 AeroNotix: I get you

18:01 use concat

18:01 m1dnight_: and I have multiple threads spitting their state and it gets messy real quick :>

18:02 AeroNotix: this is why when you care about stuff, use a proper logging joint.

18:03 e.g. we use logstash using tools.logging

18:03 and it exports the thread it was running on, so you can drill down into your logs with the thread ID

18:03 m1dnight_: ah, ill have to check that out then )

18:03 thanks for the info, AeroNotix

18:05 AeroNotix: m1dnight_: e.g. http://i.imgur.com/q6lFGDN.png

18:12 What're some cool Clojure open-source projects people are interested in?

19:04 seangrove: $seen bhauman

19:04 lazybot: bhauman was last seen quittingQuit: bhauman 2 hours and 54 minutes ago.

20:27 gfredericks: ,'welp

20:27 clojurebot: welp

20:50 pcn: Is this the right forum to ask cider questions?

20:51 Ah, never mind, I see it now

20:53 justin_smith: ,'narp

20:53 clojurebot: narp

20:58 gfredericks: ,'blelk

20:58 clojurebot: blelk

21:22 brainproxy: happy day for clj devs who are fans of devdocs

21:22 http://devdocs.io/clojure/

21:23 arrdem: cool!

21:40 gfredericks: pop quiz: what's the difference between (def x) and (declare x)?

21:41 justin_smith: oh, wow, that's tricky. def adds metadata that declare doesn't?

21:42 gfredericks: that's basically the exact opposite of the right answer

21:42 justin_smith: oh, haha

21:42 -1 point for me then

21:43 gfredericks: declare is actually just a macro that adds ^:declared

21:43 oh also it can take multiple symbols

22:03 cyy: Hello everybody! I have a question about the multitask on the same JVM. When I type the following three commands in different terminals: "lein ring server" "lein cljsbuild auto" "lein tramponline cljsbuild repl-listen" dose Clojure will setup three different JVMs to execute these commands? If Clojure will do this, could I have a way to force them share the same JVM to execute these task? I found that after executeing these commands my

22:04 --- I found that after executeing these commands my computer memory has been nearly used up, so I want to know whether there is any way to decrease the memory consumption. Thanks!

22:04 justin_smith: cyy: this is lein specific. Check out the "lein pdo" plugin

22:05 pdo will make it do parallel lein tasks in one instance

22:06 arrdem: (inc justin_smith)

22:06 lazybot: ⇒ 188

22:06 arrdem: christ you've been busy

22:07 justin_smith: heh

23:59 ddellacosta: what are folks doing for sharing namespaces for testing utilities between different projects?

23:59 we've got some duplicated code now, but it's also a major pain in the butt to have a separate namespace for testing utility libs

Logging service provided by n01se.net