#clojure log - Feb 27 2015

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

1:05 devll: Hi, how to get current profile name in clojure?

1:06 I can get around by evaluating profile specific value,but is there an elegant way to do this?

1:14 ls

1:14 lazybot: bin dev etc home lib media opt sbin sys var

1:24 tcrayford____: the ring-jetty9 adapter has a new CVE/security fix: https://github.com/sunng87/ring-jetty9-adapter/pull/20

1:24 y'all should upgrade to 0.8.2 as fast as you can

1:47 Kneiva: yay, my first own macro: https://www.refheap.com/97841 Do you have any pointers for improvement?

1:56 sm0ke: so is there a hack to add a folder to lein's classpath?

1:56 justin_smith: Kneiva: why is it a macro?

1:57 sm0ke: the folder contains jar files

1:57 i tried adding to resource-paths , but no lucj

1:57 justin_smith: sm0ke: each individual jar in the folder needs to be added

1:58 sm0ke: i did a ["resources" "lib_managed/*"] justin_smith

1:58 justin_smith: oh, it accepts globs?

1:58 sm0ke: java does

1:58 java -cp "lib/*:..." works

1:59 Kneiva: justin_smith: can I repeat stuff for for's binding vector some other way?

2:02 justin_smith: Kneiva: ahh, right. The function can be written without using a macro, but this approach (generating a binding vector) requires one

2:03 dysfun: tcrayford____: hrm, i wonder if such a thing affects aleph

2:05 justin_smith: sm0ke: I don't doubt that java supports that, I am just not sure that lein implements it. I've never seen it done, and there is no instance of doing it that way in the project.clj.

2:05 *the example project.clj

2:06 Kneiva: hmm, I could probably bind the aseq to a constant so the data does not get repeated in binding vector

2:14 sm0ke: justin_smith: thanks i will verify by adding individually

2:14 `inc` is promised if it works :P

2:16 justin_smith: holy shit!

2:16 justin_smith: wildcard works!

2:16 adding "lib_managed/*" to resource-paths works

2:17 i was adding it to java-source-paths before

2:17 slipset: justin_smith: really enjoyed your conversation with csd_ earlier

2:17 about functions having different responabilities

2:18 justin_smith: slipset: thanks

2:18 slipset: I've been searching for a name to put on this "pattern", but never came up with anything

2:18 the closest I've come is to mention one of the functions as an orchrestator(sp?)

2:19 justin_smith: interesting

2:20 I'm turning in for the night, but I am sure there is a name for this (other than just "functional programming") that is escaping me today

2:20 one keyword would probably be "referential transperency"

2:21 slipset: my thought being that the one organizing the coupling between the logic and the side-effecter is the orchestrator, and it (the orchestrator), as you mention, needs very little testing, since it's logically very simple

2:21 btw, how can you be turning in? my day is just starting?

2:21 justin_smith: ~ugt

2:21 clojurebot: ugt is Universal Greeting Time: http://www.total-knowledge.com/~ilya/mips/ugt.html

2:21 slipset: I know :)

2:22 Interestingly, I was explaining this pattern to a co-worker just yesterday.

2:22 Also, the thing of sending the side-effecting function as a param to the logic-function

2:23 jballanc: anyone know of a library of Clojure form transformations? e.g. I want to refactor a list of calls into a threaded form

2:23 slipset: jballanc: please elaborate?

2:24 jballanc: I often find myself writing something like `(map join (partition 2 (interleave ['a 'b 'c] (some-call))))`

2:24 slipset: so you want the threading macro?

2:24 jballanc: and I'd like to refactor that to `(->> (some-call) (interleave ['a 'b 'c]) (partition 2) (map join))`

2:25 slipset: like -> or ->>

2:25 jballanc: right

2:25 but automatically

2:25 slipset: clj-refactor might have this?

2:25 jballanc: i.e. I built up the first form either in the REPL or in my editor, but once I get 3-4 forms deep I'd like to re-order

2:25 hmm...I'll have a look

2:26 slipset: yepp, it does

2:26 tf :) https://github.com/clojure-emacs/clj-refactor.el

2:26 julianleviston: I have some data. I'd like to look up each entry by one of THREE keys! (and have each entry to have 3 values) Oh, the craziness! Is there a way to do that? I can't think of a way, really...

2:26 slipset: or tl

2:26 jballanc: slipset: ah, indeed...and as I feared its in elisp :-/

2:27 slipset: jballanc: yak-shave for the weekend elisp2clj

2:28 julianleviston: I should say, I want all 3 values out when I look up a key. Should I build a new type of data? I often seem to need n-way maps, actually… not really sure how to go about implementing that.

2:29 slipset: julianleviston: care to share a gist?

2:29 julianleviston: slipset: I don’t have a gist.

2:30 tcrayford____: dysfun: it might have the same vuln, I guess, but that patch is jetty specific. writing http servers is hard :/

2:30 julianleviston: slipset: because I haven’t started to build it yet… I’m currently re-implementing it based on these new requirements… and I’m presently using a map, which is a 1-1 version of this data structure.

2:30 jballanc: slipset: probably just quicker to hand-convert to clj...then I just have to hook it into vim-fireplace somehow

2:33 julianleviston: slipset: I’ll make up a syntax here because there’s no such syntax… (get <:a 1 :b 2 :c 3, :a 5 :b 10 :c 15> {:a 1}) should yield {:a 1 :b 2 :c 3}

2:34 slipset: I *could* just use a set of n maps, but that’s ugly and takes a LOT of overhead to manage, and I don’t like it.

2:35 slipset: the use case is I’d like to be able to say “look in the store for the one where :a is 1, and give me the value of :b”… where :a and :b are arbitrarily any of the keys.

2:37 slipset: julianleviston: but what's the relation between :a and :b?

2:37 raspasov: julianleviston: so you want a value to be "discoverable" by n different keys, and not just one?

2:37 julianleviston: slipset: if you want to know my use case, it’s :dom-id, :database-record-id and :parent-dom-id

2:38 raspasov: yeah :)

2:38 raspasov: is this for Clojure or ClojureScript?

2:38 julianleviston: raspasov: kind of like a map with 2 way lookup instead of 1-way lookup, but actually 3-way.

2:38 raspasov: CLJS

2:38 raspasov: julianleviston: hm ok, does CLJS have STM?

2:38 julianleviston: raspasov: yes

2:38 raspasov: I can't recall

2:38 slipset: so something like (get-by m keys) ...)

2:39 raspasov: I mean the refs

2:39 ro_st: cljs does not have STM

2:39 julianleviston: raspasov: no

2:39 raspasov: it doesn't have the refs, does it?

2:39 julianleviston: raspasov: just atoms

2:39 ro_st: cljs has atom and var. clj has those and ref, agent

2:39 raspasov: yea, with the STM you would be able to have three different maps

2:39 and synchronize them

2:39 julianleviston: raspasov: wow that sounds delicious!

2:39 raspasov: julianleviston: is this irony or you're serious? :)

2:40 julianleviston: raspasov: I’m serious. Sounds neat.

2:40 raspasov: julianleviston: ok :) well you can do it with atoms as well I believe

2:40 julianleviston: raspasov: I’m not sure how tho…?

2:40 raspasov: not sure in CLJS though, since there's no threads...

2:41 julianleviston: raspasov: isn’t the problem to do with structuring the data, not the synchronisation? Or am I missing stuff?

2:41 raspasov: well, I was thinking about a kinda hacky solutions with refs

2:41 slipset: julianleviston: so, do you want all the matches or just the first?

2:41 raspasov: where you copy the data over three (or n times)

2:41 in different maps

2:42 julianleviston: slipset: how do you mean? sorry?

2:42 raspasov: also how big is the data structure you're going to be accessing? I can think of many ways to do this with linear time lookup

2:42 julianleviston: raspasov: well I can build a hacky solution myself. I was asking here because I wanted to know if there’s an actually efficient way to do map-like data structures with n-way lookup

2:43 raspasov: doing it the proper way will prob require some more thought and potentially a new kind of data structure

2:43 julianleviston: raspasov: yeah I can think of those too…

2:43 slipset: say you have a map {:a 1 :b 2 :c 3} and you ask for the keys [:a :b], should the return value be 1, 2 or [1 2]?

2:43 raspasov: yea :)

2:43 julianleviston: raspasov: ah ok… that’s what I was interested in

2:44 raspasov: slipset: from my understanding he wants :a to be discoverable not just by :a but also by n other different keys

2:44 julianleviston: slipset: um… no think of it more like a vector of records all of the same type… which you can look up by any of the values in the records, but that enforces the uniqueness of ONE of the key values

2:44 raspasov: yep.

2:44 slipset: Ah, I see

2:45 julianleviston: slipset: it’s actually a bit annoying, because there can be dupes of the dom-ids and the parent-dom-ids, but not the database-ids

2:46 I guess I should use a relational algebra… probably.

2:46 yeah.

2:47 ok thanks guys!

2:47 raspasov: how about something like (def map-1 {:a atom-1 :b atom-2 :c atom-3})

2:47 and then (def map-2 {:a-1 atom-1 :b-2 atom-2 :c-2 atom-3})

2:47 I mean, it's still hacky

2:47 julianleviston: raspasov: erm… I’m not sure how the associations work there… at all...

2:48 raspasov: also these things will be stored in an atom already, so that’d be like… atoms stored in atoms… seems… bad?

2:48 raspasov: well atom-1 is discoverable by either :a or :a-1

2:48 yes it's not 100% pretty and idiomatic :)

2:48 it's like a ... 50% hack lol

2:48 julianleviston: erm… I think you’ve missed my point really… but it’s cool… nevermind

2:48 I’ll go brush up on my relational algebra like stuffs.

2:49 raspasov: julianleviston: alright :)

2:49 julianleviston: Didn’t occur to me until just now… plus I just can’t remember the functions at the moment.

2:53 be so much easier if there was some kind of pattern matching facility

2:55 dysfun: tcrayford____: once something involves the network, it's time to give up and let someone else do it

3:06 slipset: core.logic?

3:12 dysfun: slipset: what about core.logic?

3:24 julianleviston: dysfun: it was meant for me

3:24 dysfun: oh right

3:24 in that vein, also core.match

3:25 julianleviston: I just meant this: pseudo-relational algebra support for 'relations', which are simply sets of maps - select/index/rename/join

3:25 particularly join...

3:26 dysfun: thanks

3:26 dysfun: i think R can do that, incidentally

3:26 which means incanter probably can

3:26 julianleviston: dysfun: is it effecient over 2000+ item sets I wonder...

3:27 dysfun: they're in memory. if you weren't doing it in your app you'd be doing it in the database which would probably have to read off disk

3:27 so i'd expect it's "fast enough"

3:28 julianleviston: dysfun: maybe. I’m expecting this to be comparable to a map lookup...

3:28 dysfun: because I’m doing like… thousands of these and I’d like it to be very fast.

3:29 dysfun: i expect you probably want some sort of index data structure

3:29 or, y'know, a database

3:29 julianleviston: dysfun: guh. This is a simple data structure.

3:30 dysfun: then you don't have to worry about performance until you've demonstrated a problem

3:30 i can assure you that thousands of operations are not a problem for the combined might of the jvm and a decent machine to run it on

3:31 julianleviston: dysfun: CLJS

3:31 dysfun: client side or server side?

3:31 julianleviston: dysfun: client

3:31 dysfun: why are you doing all of these operations on the client?

3:31 julianleviston: dysfun: it matters. I’ve demonstrated that it slows things down

3:32 dysfun: it’s not a huge amount of operations.

3:32 dysfun: my point… it should be as fast/efficient as map lookup.

3:32 dysfun: because this is a master mapping index of in-memory records. Suggesting I put it in a db is kinda… self-defeating.

3:33 pepijndevos: What are my options for a websocket server? It seems Aleph and http-kit. How do they compare? Both seem to use their own channel-ish things.

3:33 julianleviston: dysfun: I just need it to be able to be looked up by 3 keys, is all.

3:34 zot: just curious: is there another idiom for (mapcat identity coll)?

3:34 dysfun: julianleviston: i think you probably want javascript workers then

3:34 julianleviston: zoldar_: concat ?

3:35 dysfun: errrr… it’s not THAT much work… is it? Not knowing anything about what JS workers are

3:35 dysfun: pepijndevos: aleph is fantastic if you're running websocket-y stuff. http-kit is fantastic if you're doing client-y stuff. i'd probably use aleph for both these days

3:35 pepijndevos: dysfun isn't websockety stuff also clienty stuff?

3:36 julianleviston: dysfun: I *had* a 2 key version which I just used a map-invert when I needed the other direction… but the requirement just changed to having a 3 way lookup, and I’m investigating good ways to implement that…

3:36 dysfun: all good I’m going to try with this join thing first and see what happens after that

3:37 zot: sorry… I mistyped - concat ?

3:37 zot: seeing as mapcat maps a function across a coll, then concats the result… no need to do the map part.

3:37 * ggherdov imagine a kid all happy about his new program using reducers, all ready to tame his 24 cores with the power of ForkJoin. Then, suddenly, java.lang.StackOverflowError

3:38 dysfun: pepijndevos: sorry, i meant "http client" here, so if you're wanting to *initiate* connections

3:38 pepijndevos: ah

3:40 zot: julianleviston: apply concat would be the same i suppose

3:40 i was curious if there's a completely standardized idiom for it

3:40 and identity is *such* a long word :)

3:42 hyPiRion: Wish it was named `id`

3:43 julianleviston: (def id identity)

3:43 pretty easy

3:43 dysfun: i'd use 'apply concat'

3:43 julianleviston: zot: given the source of mapcat USES apply concat, I think what you want is silly… just write your own function if you don’t want to repeat yourself

3:44 zot: lol. point taken :)

3:44 julianleviston: (defn catty [& args] (apply concat args))

3:44 I have loads of these shortcuts of my own… and a lot are in contrib...

3:47 zot: sorry I didn’t mean to be rude. Shouldn’t have used the word silly… “trivial” might have been a better word. :)

3:48 zot: julianleviston: no worries dude, i'm a big boy, and didn't take any offense in the first place. but it's great to see you speak up; not enough adults act like it, these days :)

4:42 Glenjamin: ~mapply

4:42 clojurebot: You have to do something like (defn mapply [f & args] (apply f (apply concat (butlast args) (last args)))), which just goes to show why unrolled keyword args are a bad idea

4:43 Glenjamin: zot: ^ is that the scenario?

4:45 zot: Glenjamin: not really. but your suggestion has a bonus: seeing 'butlast' for the first time :)

5:03 dysfun: what's the library that has a reloader for lein repl called?

5:07 pepijndevos: wut... my Aleph websocket is closed instantly.

5:08 zot: dysfun: https://github.com/stuartsierra/reloaded ?

5:09 noncom|2: Raynes ping

5:09 Raynes: sup brotha

5:09 dysfun: zot: no, there's another module i'm thinking of. that does a quick scan of changed files. although i'm using reloaded workflow so i should probably figure out reloaded repl

5:10 noncom|2: i've just got a cery strange error within conch

5:10 Raynes: That's a shame

5:10 zot: dysfun: if you figure it out, please share :) i've had mixed luck w/ reloaded

5:11 noncom|2: i use lein 2.x and when i don't say :aot [main.namespace], it works ok (except that lein complains that i should be explicit). when i do say than, an exception comes up: https://www.refheap.com/97846

5:11 the line that causes the exception is marked in the source sample

5:12 i think this is not conch error, but it is so strange one..

5:12 why would that happen?

5:12 (sorry for typos)

5:13 Raynes: That's something wrong with your environment.

5:13 I see ci related stuff in there

5:13 Does this happen in a repl?

5:13 noncom|2: no, a teamcity ci agent runs the jar

5:14 it works ok, if i remove the explicit :aot clause in project.clj.. but afaik lein does just that automatically if i don't say it.. the main ns also has the (:gen-class) ns parameter..

5:15 and how drop-last is different from any other clojure.core function... ?

5:17 dysfun: zot: hrm, i've just gotten reloaded repl working, but working is a strong thing to say because the moment i get an error, my repl module drops out of usability and i can't call the refresh function

5:18 zot: dysfun: sounds like exactly the fun i've experienced :)

5:20 dysfun: well i can figure out how to get around that. I just need to hook it into cider and bind a keycombo to eval (require '[clojure.tools.namespace.repl :refer [refresh]]) (refresh)

5:21 i wonder what other horrors it has lurking

5:21 zot: i copy gladly. i had other issues with it (namely files w/ protocols always breaking, and sometimes having it run alllllll unit tests, despite my best efforts).

5:21 i haven't spent enough time to understand it better

5:21 pepijndevos: Hmmmm it seems closing a manifold closes the whole chain. How do I stop this?

5:22 I'm trying to do something like this: https://www.refheap.com/97849

5:24 dysfun: pepijndevos: pass downstream? false to connect

5:25 pepijndevos: dysfun thanks

5:25 dysfun: yw

5:25 pepijndevos: as a keyword, or just like that?

5:26 dysfun: you pass a map as the last arg if you want to provide some

5:26 and keyword

5:26 (s/connect foo bar {:downstream? false})

5:27 pepijndevos: cool

5:27 dysfun: what are you building, out of interest?

5:28 pepijndevos: dysfun, connecting a Game Boy to the internet.

5:28 dysfun: cool!

5:28 how does that work then?

5:32 pepijndevos: dysfun, with a teensy and a WebRTC connection. Quite tricky. https://www.youtube.com/watch?v=0X6RxmUK6jA

5:33 dysfun: oh wow

5:34 'TCPokemon' heh

5:34 pepijndevos: I'm now making the Chrome app that talks to the Teensy a little more robust.

5:34 Yea, that's what it's called for now, kinda cheesy, but hey.

5:35 So I'm using Aleph to do chat and initiate the peer connection

5:35 dysfun: nice

5:35 why are you doing it in browser though?

5:36 i suppose you could build a gameboy social trading network

5:36 pepijndevos: because that is the only platform that has easy access to USB hardware AND peer to peer connections.

5:36 dysfun: 'easy access to usb hardware' wouldn't be my first guess :)

5:37 pepijndevos: think again https://developer.chrome.com/apps/hid

5:37 dysfun: cool

5:37 daniel`: anyone can point me to the easiest way of getting a headless cljs setup with repl?

5:38 lein template of some kind

5:38 pepijndevos: If there was a good HID lib and WebRTC lib for clojure.... I'm not that big of a fan of chrome and webdev.

5:39 dysfun: pepijndevos: well actually, i might be able to help you there

5:39 pepijndevos: i've been using

5:39 libwebkitgtk+ to embed webkit. so you can have the same apis through gobject introspection

5:40 i haven't tried the clojure bindings myself because JNI is horrible

5:40 well, the java bindings

5:40 also i'm building something that wouldn't benefit terribly from the jvm

5:52 pepijndevos: dysfun, I don't know. I think a chrome app makes sense and is not terrible. I'm not sure if some webkit hack is worth the effort

6:00 dysfun: it is for me because i find javascript enormously tedious and clojurescript leaves a little to be desired on the 'instant feedback' front

6:00 and i won't ever need to provide it over the web

6:39 pepijndevos: staartuuuupp tiiiiimeeeee! (I can type this whole mesage between lein run and something happening)

6:40 noncom|2: probably we could rewrite lein in python to make it faster..

6:40 (joke :) )

6:43 dysfun: wow, tetrisql looks cool :)

6:43 https://github.com/zilti/tetrisql

7:05 noncom|2: when creating an app with luminus template, what advantage is of http kit over the default ring-server do i get if i specify +http-kit ?

7:10 in other words, what is the difference between using ring and httpkit?

7:17 dysfun: httpkit is asynchronous so you can handle more connections concurrently

7:18 in theory, anyway

7:18 * dysfun uses aleph (netty)

7:19 samflores: noncom|2: I think you wanna know the diff between *jetty* and httpkit, right?

7:20 noncom|3: samflores: oh, i know that: jetty is java io server, which makes a thread for every connection, and httpkit (i looked at the sources) uses java nio, correct?

7:21 so that's the only difference, looks like using httpkit is the better option anyway

7:26 dysfun: or you can use aleph, which uses jetty's asynchronous features

7:26 samflores: well, I wouldn't say it *is* the better option, but as dysfun said, it theoretically can handle more concurrent connections

7:26 I tend to use http-kit due to its WebSocket support

7:27 dysfun: aleph also supports websockets :)

7:28 pick the one you like the sound of better, tbh. they're both written by smart people

7:29 samflores: true that

7:29 dysfun: i quite like ztellman's other libraries which integrate quite nicely with aleph

7:30 i also use a lot of ptaoussanis' modules, but they're fairly silo'd

7:33 samflores: it was ptaoussanis' sente that led me to http-kit :p

7:33 now it works with immutant too. I need to try that

7:35 dysfun: sente is cool, been meaning to play with it

8:35 Eremox: Is a function which references a global but immutable variable considered referentially transparent? And not if mutable?

8:36 justin_smith: Eremox: that sounds about right. Also, if it captures the variable at time of definition it can be pure even if the variable was mutable.

8:37 Eremox: sometimes you can change a clojure function from pure to impure by changing fn-name to #'fn-name because the later is always delayed to be looked up at runtime. This can be useful when redefining things during development.

8:38 Eremox: U mean a closure? But what if is a ref then I would have to capture the value not the ref

8:38 justin_smith: Eremox: all clojure vars are mutable

8:38 that's what I mean

8:39 Eremox: Do you OK sorry I misunderstood but I get it

8:40 And do you mean I define the fn with #'name or that I call (#'name)?

8:40 justin_smith: the latter

8:41 in normal code, vars will be looked up at runtime, but if you bind something as a function arg or in a let block you need the #'foo form for runtime lookup, otherwise you capture and close over a value

8:42 Eremox: Thanks for the info ;)

8:43 justin_smith: of course code which changes vars during a normal run isn't idiomatic. During dev you want to change vars though.

8:44 Eremox: Do you know a good article i can read to understand the reader. And what happens behind the scenes?

8:45 justin_smith: Eremox: have you looked at the clojure.org docs for the reader? http://clojure.org/reader

8:46 mavbozo: Eremox, there's a video How Clojure Works https://www.youtube.com/watch?v=8NUI07y1SlQ

8:46 Eremox: Yeah was reading now. Great I will watch that video. Thanks.

9:23 ila1222221: In cls I'd like to make objects implement ISeqable...

9:23 How do I find out what the methods are to override?

9:23 clojuredocs has no entry for it

9:23 (ISeqable)

9:24 puredanger: the only method is (seq [this])

9:25 julianleviston: ila1222221: http://swannodette.github.io/2015/01/12/lazy-contracts/

9:25 has an example of implementing it

9:26 dnolen: ila1222221: it's not documented anywhere, another good idea for a community maintained wiki page though!

9:27 ila1222221: ok... so what is the path to discover the methods of any arbitrary protocol. is it something that can be done at runtime, or do you go through cljs or clj source code?

9:33 ila122221: blech crash.

9:37 justin_smith: ila122221: protocols are implemented in clojure code, which means you can use clojure.repl/source to see their code

9:37 puredanger: Seqable is a Java interface. you will probably inevitably have to look through the Clojure source itself for the details of everything.

9:37 justin_smith: also you can use clojure.repl/doc to see just the doc string

9:37 puredanger: there is also a great scaffold generator …. looking

9:37 justin_smith: puredanger: ahh yeah, fair point.

9:37 puredanger: https://gist.github.com/semperos/3835392

9:38 that's a pretty useful tool for this

9:38 justin_smith: so, pedantically you can see "the source for an arbitrary protocol" but ISeqable isn't a protocol :)

9:38 (inc puredanger)

9:38 lazybot: ⇒ 32

9:38 justin_smith: that's cool

9:38 * justin_smith makes a local copy of that for reference.

9:39 puredanger: you also may find this tool to be good for exploring the internal class structure of the Clojure impl https://github.com/stuartsierra/class-diagram

9:41 ila122221: oh wow that tool is awesome. i tried source and doc in a lein repl and it gives me nil, maybe a lein setting? i'll probably prefer stuarts lib though.

9:41 justin_smith: ila122221: source and doc work for protocols

9:41 ila122221: but ISeqable is not a protocol, it is an interface

9:41 ila122221: ah duh the I ok.

10:30 trideon: does anyone know what is wrong with this code? http://pastebin.com/KpcMVZyD

10:34 justin_smith: trideon: get does not work on lazy-seqs

10:34 ,(get (range 10) 2)

10:34 clojurebot: nil

10:34 justin_smith: you would need nth

10:34 ,(nth (range 10) 2)

10:34 clojurebot: 2

10:35 trideon: thanks

10:36 justin_smith: the NPE happens in the > call (getting a value that is nil thanks to get)

10:36 ,(> nil Math/PI)

10:36 clojurebot: #<NullPointerException java.lang.NullPointerException>

10:37 justin_smith: also, as a style thing, you might like (pos? (mod % p)) better than (not= (mod % p) 0)

10:37 but that's six / half-dozen

11:37 mmitchell: Is there a default timeout value for deref?

11:38 stuartsierra: mmitchell: no, it will block forever

11:38 mmitchell: ok thanks stuartsierra

11:42 justin_smith: mmitchell: but deref does take a timeout arg optionally of course

11:43 (I frequently forget this)

11:43 mmitchell: yeah nice feature

11:43 Glenjamin: (doc deref)

11:43 clojurebot: "([ref] [ref timeout-ms timeout-val]); Also reader macro: @ref/@agent/@var/@atom/@delay/@future/@promise. Within a transaction, returns the in-transaction-value of ref, else returns the most-recently-committed value of ref. When applied to a var, agent or atom, returns its current state. When applied to a delay, forces it if not already forced. When applied to a future, will block if computation not complete. When applied to a promise

11:43 Glenjamin: (inc justin_smith)

11:43 lazybot: ⇒ 198

11:44 Glenjamin: i'd never noticed that before

12:02 mmitchell: anyone here familiar with http-kit's :timeout option?

12:02 client

12:14 pepijndevos: What is the key for in add-watch?

12:16 Glenjamin: pepijndevos: it's just a name

12:16 you can use it to replace a watch

12:16 or remove-watch

12:18 pepijndevos: thanks

12:22 justin_smith: mmitchell: it cancels the request if the server takes too long to respond. Do you have a more specific question about it?

12:25 mmitchell: justin_smith: yeah, just that it doesn't seem to behave consistently. I have a test server setup that blocks for 5 seconds. I set the :timeout option to 3000, and wrap that with the time macro.

12:25 My test server blocks for 5 seconds, and I get the response successfully

12:25 justin_smith: oh, weird

12:25 mmitchell: the time macro reports just a little over 5 seconds

12:25 yeah it is

12:26 justin_smith: mmitchell: oh, are you using conn-timeout or socket-timeout?

12:27 because socket-timeout is a socket pool option (for pooling client connections for reuse)

12:27 mmitchell: good question. I'm not sure. it's just the :timeout option.

12:28 justin_smith: and the timeout logic may be more about timing out on initial handshake, rather than timing out on getting the result

12:28 mmitchell: yeah that would make sense

12:28 justin_smith: mmitchell: I don't even see a unqualified "timeout" key being used https://github.com/dakrone/clj-http/blob/master/src/clj_http/core.clj#L207

12:30 mmitchell: and as you can see here, all the client methods are just calls to that request function https://github.com/dakrone/clj-http/blob/master/src/clj_http/client.clj#L838

12:30 mmitchell: justin_smith: oh this is http-kit - http://www.http-kit.org/

12:30 sorry

12:30 justin_smith: argh, I'm sorry

12:30 mmitchell: no worries!

12:34 xemdetia: MORE SORRY

12:37 justin_smith: mmitchell: and this is an async request? because the docs for clj-http.client/request suggest that for synchronous requests you should instead use deref with the optional timeout args

12:38 mmitchell: yeah, this is using http-kit's "request" function. It has a :timeout option here - https://github.com/http-kit/http-kit/blob/master/src/org/httpkit/client.clj#L135

12:38 justin_smith: mmitchell: right, that's the doc I am reading

12:38 it suggests using deref for sync

12:38 and :timeout for async

12:39 mmitchell: ahh I see. The deref w/timeout works as expected (sync)

14:02 fellipebrito: [noob/starting here] Reading The Joy of Clojure yesterday. On a single example the guy moved things inside the main defn as much as he could.

14:02 It is completely the opposite of OO, when you try to use few lines inside your method, and organize it better with the principle of a method executes only one action.

14:03 agarman: @fellipebrito functions should do one thing only

14:03 @fellipebrito just like methods in OO

14:03 fellipebrito: I've studied and pushed my team to write a great code, following best practices and tons of other things that are out there on the ruby community.

14:03 agarman: @fellipebrito beginner books don't always demonstrate the best examples up front

14:04 fellipebrito: @agarman sure thing

14:04 @agarman maybe I'm too raw, I will keep reading the book, but would ike to hear from you guys

14:04 agarman: btw, what page are you referencing?

14:06 fellipebrito: @agarman I will look for it later and get back to you

14:07 @agarman thank you!

14:08 By the way. I have the book Clean Code here. How you guys see it being applied to Clojure?

14:10 agarman: @fellipebrito I like Agile PPP in C# by same author. SOLID & YAGNI apply to well written programs.

14:13 justin_smith: fellipebrito: some things that are slightly different with Clojure - for immutable data (which is what most things should be), there is less benefit for making it private or encapsulating. So well written idiomatic Clojure code will often pull things out of a private or closed over scope to be an immutable global.

14:14 fellipebrito: @justin_smith Thank you! For me it is still a "huge mess". I love the code as data idea, but everytime I open a file It takes some minutes until I feel comfortable reading the code. I'm used to read any well-written ruby code in seconds.... I will keep studying and pushing hard to get the 'clojure-way'

14:15 justin_smith: fellipebrito: also, because the clojure compiler demands that definitions be declared or bound before being accessed, the quickest way to read a normal namespace is usually from the bottom of the file to the top

14:16 agarman: ,(declare maybe)

14:16 clojurebot: #'sandbox/maybe

14:16 justin_smith: every once in a while you will see code that is organized top to bottom with declare

14:16 but that's rare in practice

14:16 so you should not expect it as a reader of code

14:17 fellipebrito: @justin_smith I will buy some mangas alongside my new clojure books :)

14:17 justin_smith: haha

14:17 TimMc: "declare" usually means "lots of mutually recursive code ahead"

14:17 justin_smith: it's just a rule of thumb that works well for me when I decide to read clojure code - I take a peek at the top, and most of the time the next step is to jump to the bottom of the file and scroll up

14:17 agarman: yep, declare is a spaghetti crossing sign

14:17 fellipebrito: I do not want to write "ruby code" in clojure. I am trying to "get the groove"... the community helps a lot. Thank you guys

14:17 justin_smith: if I see a nice big comment block at the top of the file, and / or usage of declare, then I read top down

14:18 TimMc: fellipebrito: IRC convention doesn't use the @ sign, by the way.

14:18 fellipebrito: thanks TimMc

14:18 agarman: @TimMc I started that above...my bad :-p

14:18 TimMc: If you leave it off, people are more likely to be notified by their IRC clients that you're talking to them.

14:18 hah

14:19 fellipebrito: TimMc you see... you started above, but if I read bottom - top, I will not see the error and I will start the right way.

14:19 pepijndevos: Can I somehow auto--reload an Aleph app? the startup time is killing me. I could have written another app in Java it the time spent waiting.

14:19 fellipebrito: Thank you justin_smith agarman and TimMc

14:19 TimMc: justin_smith: I usually read from the top when I'm reviewing code, although I don't know that that's really the most efficient approach.

14:20 agarman: pepijndevos: can't you just recompile files into running app?

14:20 pepijndevos: agarman, maybe? How?

14:20 justin_smith: TimMc: often there are one or two functions that are kind of "the reason this namespace exists", and it helps me to see those defs before looking at the details, and they are very likely to be at the bottom of the file

14:21 agarman: pepijndevos: I just reload file through emacs

14:21 Glenjamin: thats my biggest bugbear in clojure, that i have to read from the bottom of the file

14:21 pepijndevos: uh... emacs?

14:21 justin_smith: pepijndevos: if you have a repl open, (require 'some.ns :reload)

14:21 Glenjamin: not that it's a big issue really

14:21 agarman: pepijndevos: if your in Intellij, using Cursive, you can do the same thing

14:21 pepijndevos: I see...

14:21 agarman: pepijndevos: or exactly what justin_smith said

14:22 justin_smith: pepijndevos: most editors have some "reload project" function, but it's just going to call that one liner I posted anyway

14:22 pepijndevos: :)

14:22 agarman: pepijndevos: or :reload-all if there's a whole lot of changes

14:22 justin_smith: yes, that's a good point too

14:23 agarman: in my own web app, I (stop) (require 'core.stuff :reload-all) (start)

14:23 justin_smith: I should have said "reload namespace" rather than "reload project" above

14:23 TimMc: which is great until there are defrecords or protocols or multimethods :-P

14:23 justin_smith: hello, component

14:23 agarman: yeah TimMc got some of those and it super not fun

14:23 TimMc: justin_smith: ssshhhhh

14:23 agarman: yep

14:23 TimMc: ssshhhh

14:24 (One of these days I will get around to using that.)

14:24 agarman: same

14:24 still less time wasted than would probably take to migrate everything into component or similar

14:46 fellipebrito: Any of you guys trying to use clojurescript + Phonegap (or something like that) = nativeapps?

14:58 dysfun: lighttable is a native app using node-webkit. but i'm guessing you meant for phones. the phonegap desktop stuff is... a little sketchy

14:58 nkoza: fellipebrito: if you google "clojurescript phonegap" you can see some examples

14:59 fellipebrito: there is also ongoing work to integrate Clojurescript with React Native, so you can use iOS/Android from CLJS

14:59 fellipebrito: dysfun nkoza my main goal are iphone and android native apps, but not using only a webview... you know apple hates it.

15:00 dysfun: there's a clojure->ios thingy

15:00 nkoza: fellipebrito: check this: https://code.facebook.com/videos/786462671439502/react-js-conf-2015-keynote-introducing-react-native-/

15:00 fellipebrito: and this: https://github.com/omcljs/ambly

15:00 fellipebrito: nkoza Praise the lord

15:01 dysfun: ooh, nice

15:10 ToxicFrog: Does pprint have the same guarantee as prn in that it emits something the reader can consume?

15:13 gfredericks: eehch

15:17 chouser: ToxicFrog: prn doesn't have that guarantee either, as far as I know.

15:17 ,(pr-str (Object.))

15:17 clojurebot: "#<Object java.lang.Object@7799cdd5>"

15:17 amalloy: prn produces something the reader can consume when it can

15:17 chouser: ,(read-string (pr-str (Object.)))

15:17 clojurebot: #<RuntimeException java.lang.RuntimeException: Unreadable form>

15:17 ToxicFrog: chouser: (doc pr) says it does

15:17 justin_smith: ,(doc pr)

15:17 clojurebot: "([] [x] [x & more]); Prints the object(s) to the output stream that is the current value of *out*. Prints the object(s), separated by spaces if there is more than one. By default, pr and prn print in a way that objects can be read by the reader"

15:18 ToxicFrog: I mean, obviously this isn't universally possible, but it guarantees that it will if it can

15:18 So I know I can throw a map full of keywords and strings at it and get something that I can read back in later.

15:19 chouser: Yeah. I think that should work approximately as well with pprint as with prn

15:20 mikerod: Does it matter if type-hints are Symbols representing classes or actual Class objects themselves?

15:20 amalloy: mikerod: they should be symbols

15:21 hexa: Hi, I have this weird problem if I do like (do (map println '(1,2,3))) with lein-exec plugin , nothing prints out.... , without map all is fine,,, ideas??

15:21 lazybot: hexa: Definitely not.

15:21 amalloy: ~lazy

15:21 clojurebot: lazy is hard

15:21 amalloy: er

15:21 ~map

15:21 clojurebot: map is hard

15:21 amalloy: sure

15:21 justin_smith: hahaha

15:21 hexa: map is lazy

15:21 hexa: haaaa domap...? or similar

15:21 justin_smith: doall

15:21 hexa: righ thx!!

15:21 mikerod_: ,(-> #'str meta :tag type)

15:21 clojurebot: java.lang.Class

15:21 hexa: I was getting crazy since it worked ok on the repl hehe

15:22 justin_smith: hexa: or dorun since you likely aren't using the return value

15:22 mikerod_: amalloy: this seems inconsistent

15:22 justin_smith: hexa: right, printing forces laziness

15:22 mikerod_: I thought it should be symbols too

15:22 but I see a mix

15:22 hexa: :)

15:22 justin_smith: (and Print is the P in rePl)

15:23 mikerod_: ,(-> #'realized? meta :arglists first first meta :tag type)

15:23 clojurebot: clojure.lang.Symbol

15:23 mikerod_: I'm guessing the compiler is dealing with symbols and classes interchangably

15:24 it is always awkward in situations where you have to chose which one is right for a type hint, if you are doing something like writing a macro.

15:24 amalloy: mikerod: the hints on arglists are not the same as hints on vars. the compiler does not treat them the same; i wouldn't try comparing them

15:24 mikerod_: it is very easy. always choose a var

15:24 er, a symbol

15:24 mikerod_: amalloy: I see... :)

15:25 I see some places in the compiler explicitly referring to `tag` fields with type Symbol, so that does seem to be the wise choice

15:25 amalloy: the :tag metadata on vars may be symbols, it may be classes, who cares - the important thing is that in the *source code* the compiler reads, it should be symbols

15:26 hiredman: strings

15:26 mikerod_: oh

15:26 amalloy: well. sure. that's fine too i guess

15:26 but a human being can type a string or a symbol into source code, and they can't type a Class object out and save it in their .clj file

15:26 the compiler is supposed to consume stuff you could have typed

15:28 hiredman: ,((fn [^foo/String x] (.toString x)) "Foo")

15:28 clojurebot: #<CompilerException java.lang.IllegalArgumentException: Unable to resolve classname: foo/String, compiling:(NO_SOURCE_PATH:0:0)>

15:29 hiredman: ,((fn [^foo/java.lang.String x] (.toString x)) "Foo")

15:29 clojurebot: #<CompilerException java.lang.IllegalArgumentException: Unable to resolve classname: foo/java.lang.String, compiling:(NO_SOURCE_PATH:0:0)>

15:29 mikerod: amalloy: I'm able to not fail though with classes

15:29 like (eval (let [sym (with-meta 'a {:tag String})] `(let [~sym "a"] (-> '~sym meta :tag type))))

15:29 I'd think that would break

15:29 its fine, I'll stick to symbols

15:29 I'm just curious how it keeps working out for me to use embedded classes instead

15:29 amalloy: mikerod: sure, some things work. you can add #_#_#_#_#_3 anywhere in your source code and it works fine

15:30 likewise (eval (fn [])) works, but you're not supposed to do it

15:31 gfredericks: (defn set-foo [x] (def foo x)) also works fine and you're also not supposed to do it

15:32 FSVO "supposed"

15:32 hiredman: fsvo of works fine

15:32 mikerod: :D

15:32 justin_smith: gfredericks: also, (System/exit 42) can replace any program

15:33 it's a proven fact

15:33 chouser: (swap! x prn) ; fsvo works fine

15:33 mikerod: all good points

15:33 hiredman: e.g. if people do that expecting scheme's local defines, that doesn't work

15:33 gfredericks: yeah true

15:34 hiredman: if you do that, and expect clojure to still throw an error compiling forms that reference foo because you haven't run the function yet, that doesn't work

16:02 oskarth: Using secretary, is there something I have to do server-side in order to get dispatch to work when changing the URL? Adding `(defroute foo "/bar" [] ...)` and clicking a link `href="#/bar` doesn't do anything, but running `dispatch!` manually in browser-repl works.

16:18 problem was with listening to 'navigate' event

16:25 augustl: is there a canonical setup for using clojurescript to develop code for running in node.js?

16:44 nuwanda_: oskarth: yeah, I've only used secretary on a small project and i didn't have time to figure out what I was doing wrong so I simply had those links directly dispatch

16:45 I'm sure there's another (proper) way to do it though

16:55 augustl: emacs indents clojure like in "actual.clj". How do I make it indent the way it is in "want.clj"? :) https://gist.github.com/augustl/7b028e1cadc498809e56

16:55 I don't want nested data structures to align to the opening symbol, I want it to indent like normal code

17:00 justin_smith: augustl: hanging open symbols aren't very popular in this language family

17:00 *open delimiters

17:00 amalloy: your "want" is weird as heck. it doesn't look like "normal code"; normal code in clojure looks like actual

17:01 augustl: is it really that weird? The code is from David Nolen's leiningen templates

17:02 I found the extra spaces that emacs added when I indented the generated project.clj pretty unhelpful

17:03 the rule seems pretty simple to me, indent nested data structures the way builtins like "do", "if", etc are indented

17:03 justin_smith: augustl: that's not what it is though. It's indenting based on trailing open delimiters C style

17:04 hiredman: gross

17:04 TimMc: Here's a thing I think I'd like to be able to do: https://www.refheap.com/97878

17:04 amalloy: augustl: do you have a link to whatever code from dnolen you copied?

17:04 TimMc: Basically, "footnotes" in functions so that I can attach logging statements and the like unobtrusively.

17:05 augustl: amalloy: sure, https://github.com/swannodette/mies-node-template

17:05 specifically https://github.com/swannodette/mies-node-template/blob/master/src/leiningen/new/mies_node/project.clj

17:05 amalloy: that is really weird. i don't know why he is writing it that way

17:06 augustl: perhaps it's an intellij thing or something

17:06 TimMc: The syntactic transform would look like this: https://www.refheap.com/97879

17:08 amalloy: TimMc: it's less featureful/flexible, but for simple cases flatland.useful.debug/? does similar stuff

17:09 turbofail: i feel like that indentation style does make some amount of sense for maps

17:09 augustl: turbofail: not sure what's not to like about it :)

17:09 turbofail: it's nice to be able to keep the keys and values together without having them push too far to the right

17:10 that said i still use the emacs default style

17:11 and i don't know if there's any straightforward way to make emacs do that

17:11 TimMc: amalloy: The forms I'm looking to attach do all sorts of things: Logging, debug printlns, metrics, debug response headers... basically, I want to get all that crap out of the main control flow and logic.

17:12 amalloy: TimMc: it sounds kinda like you are looking for haskell's where instead of let?

17:12 TimMc: I know that dire does some of that, but it only applies at var boundaries.

17:12 Tell me about this "where".

17:12 amalloy: TimMc: it's just a let with the bindings after their use instead of before it

17:13 TimMc: Nah, I want to be able to intercept values within an expression and have the intercept logic be all shoved down to the end of the fn.

17:14 hiredman: I do something like that in my raft implementation

17:14 amalloy: TimMc: but like, your example is just defining a function named † and calling it

17:14 hiredman: https://github.com/hiredman/raft/blob/master/src/com/manigfeald/raft/rules.clj#L101-L115 bindings at the end

17:15 amalloy: with the definition of † at the end of your "primary" function instead of at the beginning

17:15 TimMc: amalloy: Ah! The transformed version, yeah.

17:15 hiredman: oh, nope

17:15 (I just saw "haskell's where")

17:17 TimMc: My coworkers might kill me if I put non-ASCII in our source files.

17:17 amalloy: as well they should

17:18 they might symbolically leave a flaming 💩 on your doorstep

17:19 TimMc: hah

17:19 Oh man, this looks so much nicer, though.

17:19 (defmacro essentially [& args] `(let ~(last args) ~@(butlast args)))

17:21 https://www.refheap.com/97879 so good

17:21 amalloy: TimMc: that is *definitely* just where

17:21 TimMc: yeah

17:21 amalloy: which is fine, where is cool

17:21 TimMc: I *could* do *1, *2, *3 and so forth, even though it shadows clojure.core stuff.

17:22 Those don't get used in main source, right? And they're lexical, so there's not even a warning.

17:22 amalloy: you'd get a warning from eastwood

17:22 TimMc: What doesn't.

17:52 amalloy: Not quite good enough, upon further reflection. This doesn't give me the ability to use the lexical scope of the places the spy expressions are referenced. What I really want to do is inject aspects...

17:53 Am I reinventing Spring? Please tell me if I'm reinventing Spring. I don't want to be that kind of person.

18:50 crazydiamond: Hi. How to check what kind of value I'm dealing with? E.g. is it map, vector/list or scalar-like? I tried like (instance? (class {}) v), but failed 'cause (not= clojure.lang.PersistentHashMap clojure.lang.PersistentArrayMap)

18:50 justin_smith: crazydiamond: map?

18:50 ,(map? {})

18:50 clojurebot: true

18:50 crazydiamond: yep :)

18:50 thanks

18:50 amalloy: crazydiamond: but don't use list?

18:51 crazydiamond: amalloy, why?

18:51 justin_smith: ~list?

18:51 clojurebot: excusez-moi

18:51 amalloy: crazydiamond: seq? is a function that does what you actually *want* list? to do, whereas list? does something that is not useful

18:51 Bronsa: ,(list? (cons 1 nil))

18:51 clojurebot: true

18:51 justin_smith: ,(list? (list 1 2 3))

18:51 clojurebot: true

18:51 Bronsa: ,(list? (cons 1 ()))

18:51 clojurebot: false

18:52 crazydiamond: yep, I see

18:52 ,(list? [])

18:52 clojurebot: false

18:52 crazydiamond: thanks!

18:52 aperiodic: ,(seq? [])

18:52 clojurebot: false

18:52 crazydiamond: oops

18:52 aperiodic: ,(sequential? [])

18:52 clojurebot: true

18:52 crazydiamond: :)

18:52 aperiodic: ,(sequential? (list 1 2 3))

18:52 clojurebot: true

18:53 aperiodic: ,(sequential? (cons 1 nil))

18:53 clojurebot: true

18:54 aperiodic: oh and also ##(vector? [])

18:54 lazybot: ⇒ true

18:57 aperiodic: crazydiamond: you should probably study the "type tests" subsection of the "collections" section of the clojure cheatsheet: http:///conj.io

18:57 crazydiamond: aperiodic, thanks. I believe I should study the whole

19:39 coventry: Does anyone here use scala with emacs? Does it have anything like cider? I've been playing with ensime, just started looking at sbt-mode.

19:56 jodaro: coventry: i think M-x sbt-start does something similar

20:22 crazydiamond: Hi. Is there shorter way to write (fn [x] x)?

20:22 justin_smith: #(do %)

20:22 crazydiamond: thx

20:22 'cause #(%) is trying to call the arg

20:22 justin_smith: of course you can always do (def i identity) and then just use i

20:23 right

20:23 amalloy: the shortest way to write something is not usually the best way

20:23 justin_smith: can't get shorter than a one letter function name

20:23 amalloy: excellent point

20:23 amalloy: justin_smith: new programming language: features 0-character identity function, implicitly added before every value

20:24 justin_smith: hahaha

20:24 amalloy: analysts amazed that this is indistinguishable from previous languages

20:25 justin_smith: oooh - you could define a unicode composing character, so when you call it on a value it shows up above or below the first letter of the arg, instead of as a separate word

20:25 crazydiamond: amalloy, well, in my case I asked that only for experiments in REPL

20:25 justin_smith: not that this would confuse anyone at all!

20:26 amalloy: justin_smith: ẍ is (identity x) in this groundbreaking new language

20:28 justin_smith: right

20:29 we could use the little tail that Spanish puts on the letter ç for deref (it would be a little tail on the first letter of the binding's name of course)

20:29 crazydiamond: if ẍ doesn't matter

20:29 I mean, if ẍ is a funciton

20:29 so x itself doesn't matter

20:31 amalloy: justin_smith: spanish doesn't use the cedille for anything, you're thinking of french

20:32 justin_smith: oops

20:32 amalloy: although apparently it used to, though

20:32 calling it cedilla

20:34 justin_smith: ahh, used in Portugese too I see

20:34 I misremembered which one semester middle school foreign language class had introduced that letter

20:34 nuwanda_: definitely portuguese too :p çç

20:35 rpaulo: yup..

20:36 justin_smith: "used in Portuguese" is incorrect. It still uses it and will continue to use it for the foreseable future

20:36 justin_smith: ugh, I misread.

20:36 justin_smith: rpaulo: I meant the present case

20:36 it's OK

20:37 * rpaulo probably doesn't want to see Clojure methods using ? :)

20:37 rpaulo: ?

20:37 looks like my IRC client can't even display it

20:37 justin_smith: doesn't send it it looks like

20:38 crazydiamond: ç

20:38 äåéëþüúíóöáßðïœø朩®bñµç

20:39 seems it's displaying fine

20:39 rpaulo: ç

20:39 ok, I was using the JIS encoding

21:31 codesine: Hi all, looking for guidance regarding ring or compojure.

21:32 I want to start with learning ring to do webapp development, and have been going through this resource: https://brehaut.net/blog/2011/ring_introduction

21:32 Are there any recommendations (possibly more up to date items?)

21:33 justin_smith: codesine: I don't see anything out of date there, anything else usually is built on ring

21:33 and a lot of people still use compojure

21:33 codesine: oh cool, so i can go by that

21:33 justin_smith: it's definitely a good starting point yeah

21:34 codesine: see I'm confused as to where ring and compojure stand, is ring just a third party library the same as compojure?

21:34 justin_smith: ring is an api that wraps various web servers with a common interface

21:34 compojure is a routing lib

21:34 codesine: ah got it

21:34 Yeah, I was looking at this luminusweb item, but, I get confused because it seems to be doing things for me

21:35 amalloy: codesine: but yes, it is also a third-party library, not associated with clojure the language

21:35 codesine: Ah ok.

21:35 justin_smith: people write various adaptors so that you can use eg. aleph, or jetty, or http-kit or tomcat but via the ring api

21:35 codesine: is there something in clojure core that does http serving etc?

21:35 justin_smith: no

21:35 codesine: ok gotcha both

21:36 justin_smith: codesine: since the jvm is so "batteries included" and there are so many libs for java that are easy to use via interop, clojure's core tends to be abstract stuff

21:36 codesine: ah

21:36 justin_smith: libs for specific pragmatic things will be adaptors or wrappers that are not part of hte core lang

21:36 typically at least

21:36 codesine: Yeah, see, I am worried to use luminusweb or compojure -- because I think that it will allow me to take things for granted

21:37 so it _is_ ok to start with ring, and do a pure web app in ring

21:37 justin_smith: so clojure.core is all about data types and protocols etc.

21:37 codesine: like a todo list to get my feet wet

21:37 justin_smith: right

21:37 I think that's a good idea

21:37 eventually how ring does things will matter

21:37 (unless you use one of those rare web libs for clojure that don't use ring)

21:37 codesine: yeah when i looked at the dependencies for luminus and compojure I made :/ face when it was a buncha libraries i'm not familiar with lol

21:38 ah

21:38 so i'm thinking if I were to do a todo list that would interface with mongodb

21:38 justin_smith: codesine: luminus is just making a bunch of good default library choices for you

21:39 codesine: I'd just need something like monger

21:39 and ring

21:39 and i can do sessions in ring anyways

21:39 justin_smith: sure

21:39 codesine: ok

21:39 nothing else i might need right?

21:39 I'm just not confident lol

21:39 justin_smith: but looking at the default luminus project.clj, there's nothing in there I have not had to use, and nothing I totally hated. So that's cool.

21:39 codesine: i will look at the dependencies, and learn some of them little by little

21:40 justin_smith: you can use monger and ring, sure. As long as you understand the pitfalls of mongodb of course :)

21:40 codesine: I've always used sql, i just finished one of the 10gen courses

21:40 lol

21:40 figured i might as well put myself out of my comfort zone

21:40 monger ring and selmer (:

21:40 justin_smith: codesine: after you get your bare bones server running, take a moment to look at the github project (at least the readme) for each luminus dep. They are all useful for a backend web stack.

21:41 for the bare bones you can even leave out selmer, but you still probably want compojure (or some routing lib)

21:41 unless you want a case statement with regexes and the :uri key of the request or something

21:41 codesine: in the lazy sequence blog it details how to do routing with ring

21:41 justin_smith: follow the guide from brehaut, it is decent

21:42 codesine: i figured i'll make it hard on me and do it manually from the request mapping

21:42 (<

21:42 justin_smith: codesine: that's not ring, that's compojure, from what I see

21:42 codesine: at the very top

21:42 it is ring

21:42 then he shows how to do mustache

21:42 and compojure

21:43 justin_smith: oh, OK, at the very very top

21:43 yeah, you are right

21:43 codesine: ya!

21:43 ob_: i really enjoy sql for its proximity to the data. is clojure similar in that regard?

21:43 justin_smith: instead of his usage of moustache, you can swap in selmer

21:44 ob_: clojure has a very data-first philosophy yes

21:44 codesine: yeah i heard moustache wasn't used as much?

21:44 justin_smith: codesine: that may be the one out of date thing in this intro

21:45 codesine: yeah i'm gonna primarily use only the ring part, and do the routing myself for a learning experience (tedious, but just to instill it more firmly heh)

21:45 high5 justin_smith

21:45 justin_smith: best of luck, I do back end web stuff in clojure as my full time job, and I love it

21:45 it's a great stack

21:45 codesine: I do python and django, so i've been just spending 2 hrs a day trying to pick this up

21:46 I'm doing that there brave clojure tutorial

21:46 I do have the 2nd edition of joy of clojure

21:46 but it's over my head

21:46 justin_smith: I don't think many of the web-specific parts will be new or surprising if you do django already

21:46 codesine: D:

21:46 justin_smith: but have fun with the clojure stuff :)

21:46 codesine: oh and 4 clojure

21:46 justin_smith: yeah joy of clojure is not introductory level material for most people

21:46 codesine: thanks

21:46 i have the other 2 yr old book, clojureprogramming from oreilly

21:47 justin_smith: yeah, 4clojure is good too, especially if you look at solutions from more experienced users after you solve it yourself

21:47 codesine: but damn me if i can focus enough to read 600 pages

21:47 ya!

21:47 justin_smith: haha

21:47 codesine: exactly

21:47 there was some really terse solutions

21:47 then i realize

21:47 wtf

21:47 this is really short but unreadable

21:47 then i realized there is code golfing...

21:47 D:

21:47 justin_smith: well, a lot of it is more readable once you know the style / idioms

21:47 and yeah, some people are golfing (4 is a pun on fore)

21:48 codesine: haha

21:48 yeah i could understand it

21:48 but i realized, it was abusing a trick

21:48 to be shorter

21:48 amalloy: justin_smith: the name 4clojure is totally not related to the fore in golf

21:48 justin_smith: oh? never mind then

21:48 amalloy: i've never heard anyone make that connection before, actually

21:48 justin_smith: I totally thought it was a pun

21:48 codesine: no i think he means

21:48 amalloy: justin_smith: it's a pun on foreclosure

21:48 codesine: 4 as a pun on fore

21:49 read 4clojure as foreclosure

21:49 foreclosure on a home lol

21:49 justin_smith: right

21:49 amalloy: but the golfing features were added later on, by a different person than the one who named the site

21:49 codesine: it's cool some solutions of people i follow (those who answered all 156 questions)

21:49 code how i think

21:52 bashed: Is it possible to import a java class without loading it? It seems like clojure does that. I need to reference some java classes that depend on that.

21:53 codesine: I'm a clojure beginner but I think (require) does that

21:53 maybe someone else can correct me if i'm wrong

21:53 justin_smith: codesine: require is for namespaces / clojure code

21:53 amalloy: no, that is not consistent with how classloaders on the jvm work

21:53 codesine: ohh... so i'm wrong

21:53 idk bashed, justin prob knows (<

21:54 justin_smith: codesine: import is for jvm level classes (usually java code, but maybe also a record or deftype sometimes)

21:54 or amalloy :)

21:54 codesine: oh ok, so i'll use import if i ever want to do what bashed does

21:54 justin_smith: amalloy: is there a behavioral difference between using import or not using import and just using the fully qualified package name?

21:55 amalloy: justin_smith: no

21:55 justin_smith: that's what I thought, just double checking

21:55 amalloy: does referencing a class in a function that gets compiled force some initialization then?

21:56 amalloy: justin_smith: it causes the class to be loaded when the function is compiled (if it wasn't loaded already), which runs the class's static initializers

21:57 justin_smith: aha, yeah, I can see where that would be an issue for badly designed classes

21:58 codesine: I wonder if it's advisable to make an attempt to read o'reilly's clojure programming back to back with coffee as fuel (:

21:58 justin_smith: you'd probably learn more if you went slower and did things in the repl to test what you think you are learning

21:59 codesine: yeah i've done it with clojure for the brave and true

21:59 just hand typed everything

21:59 justin_smith: clojure is very repl freindly - more than most languages the interaction in the repl really follows all the same rules as code in files

21:59 codesine: ok thx for everything

21:59 i'll try to be a regular here from now on xD

21:59 hiredman: http://dev.clojure.org/jira/browse/CLJ-1315

22:00 codesine: i just discovered (clojure.walk/macroexpand-all)

22:00 this helped me with some questions i had in my head

22:00 justin_smith: that's a helpful one

22:01 codesine: how'd you start when you were a clojure padawan

22:01 since you do it for work now

22:01 justin_smith: me? I got hired because an old friend knew I was into FP.

22:01 and I learned it on the job.

22:01 codesine: come to think of it for every language i've learned i've never read a book front to back

22:01 justin_smith: I was mostly using OCaml and Scheme until I got hired

22:01 codesine: scheme is cool

22:01 justin_smith: indeed

22:02 codesine: esp that gambit scheme

22:02 justin_smith: ml and scheme turned out to be a great combo of things to make learning clojure easier

22:03 the jvm part took me longest

22:03 codesine: -_-;;;;;; i started with ansi c and then python

22:03 i never learned java tho

22:03 i can use the interop with just googling so not worried -- mostly just interested in idiomatic clojure stuff

22:03 justin_smith: but with some c and python experience, at least the javadoc for the included libs with the jvm should be readable

22:03 codesine: so this stuff really busts my head

22:03 yeah

22:04 justin_smith: for idiomatic clojure, another thing is to read code by people who know the language well

22:04 codesine: i take peek at random github repositories and try to understand what i can or the solutions on 4clojure

22:05 justin_smith: amalloy_: (for example the flatland/useful lib) or seancorfield (who also hangs out here, he works on clojure.java.jdbc among others), stuartsierra

22:05 sorry, didn't mean to tag amalloy_ there, just listing him as someone with good code to read

22:05 codesine: i've saved this irc buffer so i don't lose anything

22:06 justin_smith: hiredman also has some good stuff on github to learn from

22:06 heh

22:06 (I've definitely been there)

22:06 codesine: where i'm at? nonsense

22:06 justin_smith: codesine: getting suggestions and then just deciding to save the whole irc transcript to go through later? yeah, done that a few times

22:07 codesine: this is the second time i've used irc, never realized it was so helpful, this is not clojure related but if it'sok to ask, irc just let's you key in a handle and it joins the room with the handle, what's to keep another person from logging in with your name

22:07 yeah, in another saved buffer in emacs heh

22:07 justin_smith: codesine: register with nickserv

22:08 codesine: kk

22:08 ty

22:08 justin_smith: via nickserv you can boot someone using your handle without permission

22:08 and people can check if you are registered with nickserv (though how often someone actually does that is another question)

22:09 codesine: i've just registered

22:09 justin_smith: codesine: another caveat about that brehaut article - I wouldn't use Korma or ClojureQL

22:10 codesine: kk

22:10 oh crap forms and sessions

22:10 i'll figure it out (will prob check luminus dependencies and learn one of those)

22:11 ok going to study some more now

22:11 *waves all*

22:11 justin_smith: oh, haha, luminus uses korma. I mean it's not totally terrible, but...

22:11 codesine: i don't wanna use korma

22:11 i just wanna use mongodb

22:11 prob that monger thing

22:12 do you have a recommendation for postgres then?

22:12 justin_smith: I like yesql but have not used it in anger

22:12 it compiles regular sql files into clojure code you can call

22:12 clojure.java.jdbc is totally usable

22:13 codesine: justin_smith: got it -- bbl and thanks for all

Logging service provided by n01se.net