#clojure log - Jan 30 2014

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

0:01 akurilin: bbloom: not 100% sure what you're referring to

0:01 bbloom: (def ^:private cleanup-process (future (let [cleanup myns/cleanup] (loop [] (when (= cleanup myns/cleanup) (cleanup) (recur)))))

0:01 er stick a @ on that

0:01 or rather no @ sorry ignore me

0:02 the future won't run w/o somebody demanding it, right? so you need to spin up a thread somewhere

0:02 can also just use stupid agents:

0:03 (def cleanup-agent (agent nil)) .... (send-off (fn rec [_] sleep (cleanup) (send cleanup-agent rec)))

0:03 make that (Thread/sleep whatever)

0:03 and send vs send-off i always forget

0:03 but the idea is the same

0:04 rely on the agent thread pool

0:04 uses the agent as a trampoline for tail recursion

0:04 akurilin: Brain's melting a little bit.

0:05 I think I'm going to roll with the var version first

0:09 elarson: are there any tutorials or anything that provide a good overview of testing in clojure using emacs, clojure test mode and cider?

0:09 this is based on a lein new app based project

0:10 technomancy: elarson: apart from recommending the starter kit, the clojure-doc emacs tutorial is pretty good http://clojure-doc.org/articles/tutorials/emacs.html

0:10 or at least it was last I checked

0:11 elarson: technomancy: I'm pretty sure I'm doing something pretty similar to the starter kit. my emacs config is a bit to personalized (IMHO) to start from scratch

0:11 that said, I'll will take a closer look

0:11 technomancy: yeah, that's a good thing =)

0:12 elarson: assuming I did use the starter kit though, is C-c , the only way to run the tests?

0:12 technomancy: no, just the quickest

0:12 you can always invoke them manually in the repl with (run-tests)

0:12 elarson: in python I used my pytest.el mode which did the test run in a compile buffer so I was able to jump through the trace, so I didn't know if there was something similar

0:12 ah

0:12 that is good to know

0:13 technomancy: is it normal that you have to re-eval the clojure files in order to get the tests to find changes in the tests and/or file being tested?

0:14 technomancy: yeah, run-tests does not reload things for you

0:24 gtrak: hrm... any chance we can get file info from cljs-repl eval? it seems to have line, but not file.

0:28 dnolen: gtrak: you would need to give the repl file info, the repl doesn't know

0:29 gtrak: I'm looking at the impl of cljs.repl

0:30 akurilin: If I want to atomically look at the value of a var and decide whether I want to update it or not, returning what exactly I did, should I use a ref rather than an atom?

0:30 gtrak: seems like it's gotta bootstrap from some manner of source files... looking at 'assoc in the analyzer output.

0:30 akurilin: Doesn't look like swap! has semantics to inform the caller whether anything was done to the atom or not.

0:33 dnolen: gtrak: I don't know what leads you to think this

0:33 gtrak: dnolen: not sure :-), just scratching the surface of how it bootstraps a repl..

0:33 dnolen: gtrak: anyways, evaluate-form take an optional filename

0:34 gtrak: was surprised to find no file info for builtins

0:34 dnolen: gtrak: you have to *give* it

0:37 gtrak: huh odd. seems like it oughta work, then, rhino repl calls load-file with "cljs/core.clj", calls load-stream, which calls evaluate-form with same

0:38 core.cljs, sorry

0:39 I will trace it through at some point

0:42 dnolen: gtrak: where are you expecting :file info? on the meta of a form or something?

0:43 gtrak: in the analyzer env, there's a :file key for assoc but it's got a nil value.

0:43 (-> env :cljs.analyzer/namespaces (get 'cljs.core) :defs (get 'assoc) :line)

0:43 oddly it's got a line number, :file is nil

0:45 dnolen: gtrak: k I follow now, yeah that is weird

0:45 gtrak: I'm hacking piggieback to get to this... I can investigate more in the morning, good to know you think it should work.

0:47 dnolen: gtrak: actually looks like a simple problem

0:47 gtrak: line 242 in analyzer.clj

0:47 gtrak: we check *cljs-file* instead of first checking that :file isn't present env

0:49 gtrak: hrm, actually *cljs-file* should be bound, dunno, something subtle going on

0:51 gtrak: maybe it's bound to nil? :-)

1:05 dnolen: nothing's actually calling analyze-source, from what I can tell.

1:07 rhino-setup calls repl/load-file directly, but repl/repl actually calls analyze-source which populates the path info.

1:11 piggieback doesn't call repl/repl either

1:13 so... I think I can hack something together now.

1:53 sm0ke: hello anyone know of a sane ctags file for clojure syntax?

3:21 hmm its awfully quiet today in here

3:34 quizdr: interesting article that suggests coffescript is the most expressive of the major languages. clojure and haskell close behind: http://www.infoq.com/news/2013/03/Language-Expressiveness

3:49 TEttinger: quizdr, I saw that. not sure how effective their metrics are.

3:51 cark: that's pretty stupid, javascript is actually very expressive

3:52 this measure the habits of a population rather than the languages

3:55 fredyr: expressiveness is a really weird metric isn't

3:55 it

3:56 cark: yes

3:59 atyz: Is anyone here familiar with core.async? I have a function for validating entities (that calls an external service) however it takes the same amount of time as if I was doing it synchronously. I feel like I"m missing something. https://www.refheap.com/29715 . Any guidance would be greatly appreciated

3:59 dsrx: using LOC to measure anything, especially across languages, is absurd

4:00 quizdr: am i thinking correctly that having an explicit recur form is actually a win for clojure, rather than tail recursion being automatic? reading scheme, for example, the syntax for optimized tail recursion (iterative recursion) vs. linear recursion (memory-consuming) are not different, therefore you must look more closely to see if scheme will actually optimize it

4:03 cark: i seem to remember ritch saying that even if we had TCO he would keep recur in the language

4:03 might be wrong tho

4:04 i kinda disagree there

4:04 you learn to see tail recursion at a glance

4:04 if you can't see that, you certainly didn't understand the function at all

4:05 so you might as well just not read it !

4:05 =)

4:05 quizdr: if you use recur at least you know that, if it works, you have used it properly. if you had normal TCO you could still have a working function, even if it wasn't optimized, due to an error of logic

4:06 cark: atyz: i don't even understand how that would run, isn't <!! supposed to be in a thread block or something ?

4:07 quizdr: seriously, there is no added cognitive load with tail recursion, and i say that as a fairly limited person =)

4:07 atyz: cark: I think you can run that ona channel

4:08 cark: you'll get bitten by it once or twice as a newbie, then never again

4:08 atyz: however, I'm very lost at the moment

4:08 d11wtq: Have to agree. Having previously done Scheme and Erlang, TCO is just something you learn.

4:08 deadghost: I like clojure because it is very good for cognitively challenged people like myself

4:09 d11wtq: A deadghost would be fairly cognitively challenged, one would assume :)

4:09 cark: atyz: hum but you're blocking your full thread aren't you ? i'm usually using <! myself (single !) that must go in a go block

4:09 hum wrong person

4:09 atyz: cark: it seems that way.

4:10 are you suggesting (go (<!! (async/into [] validated)))?

4:10 cark: nope

4:11 atyz: sorry (go (<! (async/into [] validated)))

4:11 cark: i'd put the while thing in a go block ... but this is not his problem i think

4:12 quizdr: what's coming in the assets parameter ?

4:12 what's in this collection ?

4:12 and what does f ? is it just a predicate?

4:13 quizdr: cark: not sure what you are talking about

4:13 atyz: cark: this is just a collection of entitys '({:some :key :anoter :key}). The function would be something that validates that collection. in this case. valid-asset? which acceps an asset

4:14 cark: atyz: that's not how it works

4:14 you should first map your collection of entities to a collection of channels

4:14 lvh: so, are there any decent string interpolation things that do *NOT* work at compile time? I am interpolating some templates only available at runtime.

4:14 (They're markdown templates.)

4:15 atyz: Oh. so you want a channel for each entity?

4:15 lvh: I am aware of format, but I'd like something with named parameters, and hopefully also code eval.

4:15 cark: atyz: then you may filter it with filter<

4:15 atyz: yes

4:15 atyz: your goal is to have those requests done in parallel ?

4:15 atyz: cark: yep

4:16 Sec, just looking up something in the api

4:16 cark: don't use map< that's not it

4:16 atyz: So filter only takes one channel at a time

4:17 I will have to doseq over every channel and call filter on that?

4:18 cark: atyz : nope you can do it declaratively ...f

4:18 first you need a function that initiated a request, returning a channel that will contain the requested data

4:18 initiates*

4:19 let's call it request-chan

4:19 then you can do this : (map request-chan assets)

4:20 that will give you the list of channels

4:20 that's the standard clojure map

4:20 atyz: Ok

4:21 cark: then i *think* you need to use (async/map identity asset-chans)

4:22 and finally you can filter like you did, only using a simple predicate

4:22 atyz: https://www.refheap.com/29715

4:22 Something like that

4:22 ?

4:23 cark: i don't see where you initiate your request in there

4:23 you would do that in request-chan

4:23 atyz: Oops it was meant to be to-chan

4:24 cark: let me fork and write soemthing

4:24 atyz: So if you look now, request chan will take an asset and add it to a chan

4:27 quizdr: Is there anyway to somehow save or dump all the various definitions including functions that you've created while working at the repl?

4:27 atyz: quizdr: http://clojure.github.io/clojure/clojure.core-api.html#clojure.core/ns-publics

4:28 Would that be what you're looking for?

4:28 you could also probably use ns-map

4:29 cark: heh I keep killing my repl :\

4:29 cark: atyz: https://www.refheap.com/29723

4:29 quizdr: atyz: well, except that the mapping only shows function names, not contents; I guess the funcitons are immediately compiled and don't exist as code any more, unlike a data type which can be printed exactly the same way as you'd need to recreate it

4:30 cark: atyz: there might be a sinpler way to do that async/map part

4:31 quizdr: i guess one potentially bizarre but maybe useful workaround would be to have a macro that i'd use to define functions; you pass the function body etc as normal and the function is created, but the source for your function is also stored to an atom or something. you could then print out the atom to get all the source you came up with for various improvised functions, and then read them back in

4:31 cark: atyz: ah indeed looks like async/merge will do it

4:33 atyz: there you go https://www.refheap.com/29723

4:34 atyz: cark: sorry this is a dumb question, but I'm not sure what the initiate request function is doing?

4:34 cark: at some point you need to call your service

4:34 i don't know how you do it, you didn't say

4:34 atyz: that would be done through a library I've written that is encapsulate int eh validate-function

4:35 so the function I'm passing (f) encapsulates all of that

4:35 cark: well, that's bad style =)

4:35 atyz: Might I ask why?

4:35 cark: what does that function return ?

4:35 atyz: Its part of a library I've written

4:35 It returns true or false

4:36 cark: well, it "complects" doing the request and validating it

4:36 or rather validating the result

4:36 these are 2 different concepts : 1 network request, 2 data validation

4:37 if your service is doing the validation, you may put it all in request-chan

4:38 let me do it

4:38 zoldar: anybody working with cloact/reagent here?

4:38 cark: your function returns a chan ? or does it use a callback ?

4:39 or is it blocking ><

4:39 atyz: I suppose I see that, its that this library is being used in several places and I dont liek the idea of moving teh service network request to this file. However I suppose I could this async code into the library

4:39 It would be a http request

4:39 So blocking

4:39 cark: well then, there is you bottleneck

4:39 let me fix that

4:40 atyz: Yeah its a huge bottleneck

4:40 zoldar: I have an issue where I'm rendering a component being a table row (tr). The problem is, I want to conditionally render additional row in the the same component. Reagent seems to require the subcomponents being wrapped in another component, however I can't nest tbody inside already existing tbody.

4:41 React.js itself is perfectly fine with putting components in a simple array, whereas Reagent seems to always require a component at the top level. Maybe I'm missing something.

4:44 cark: atyz: https://www.refheap.com/29723

4:44 atyz: actually it's not bad style if it's the service doing the validation

4:44 zoldar: my temporary workaround for that is using mapcat instead of map a level higher and wrap the rendered component in a vector.

4:45 atyz: cark: I"m confused. filter returns the channel?

4:46 There is nothign on any channels?

4:46 cark: hum

4:46 what does your validation function return exactly ?

4:46 is it a boolean ?

4:47 atyz: it is

4:47 cark: https://www.refheap.com/29723

4:49 assuming my-lib-validation-func is blocking, the validate function would return a serie of filtered maps all having :valid? true

4:49 atyz: It is

4:49 cark: merge is async/merge

4:49 map is clojure.core/map

4:49 filter< is async/filter<

4:49 atyz: async/merge takes a collection of source channels

4:50 But we're not creating any?

4:50 cark: map creates a collection, right ?

4:50 atyz: It does

4:50 cark: the request-chan function creates a channel, right ?

4:50 atyz: no?

4:50 clojurebot: no is tufflax: there was a question somewhere in there, the answer

4:50 atyz: OH wait

4:50 Thread returns a channel

4:50 cark: the thread macro returns a channel, that will contain the result of the body, then close it

4:51 atyz: Ahh I understand

4:51 I just have to move some code around then I'll give this a shot!

4:52 cark: heh good luck

4:52 atyz: Thanks so much - I feel like I understand this better

4:52 cark: cool!

4:52 atyz: So if I was to take this a step further? What shoudl I look at?

4:53 cark: well you have to get the data out of this channel, and do something with it =)

4:53 maybe just print it at firsty

4:53 atyz: can't I use (async/into [] result-of-filter) ?

4:53 cark: test it with some valid and invalid data

4:54 atyz: I have those tests setup already for when it was working "synchronously)

4:54 *"synchronously"

4:54 cark: well no

4:55 into will give you a channel with a collection of maps ....just what you had before

4:55 atyz: Thast what I need

4:55 cark: ah let me show you

4:55 second

4:59 atyz: https://www.refheap.com/29723

5:00 atyz: *looks up take*

5:00 cark: forgot the recur ...but you get the drift

5:01 https://www.refheap.com/29723

5:03 atyz: why are both the as-you-wanted and print-results calling the validate function?

5:03 cark: that's 2 ways to do about the same thing

5:05 that's how you get the data out of the chan in the end

5:05 atyz: Oh wow

5:05 This is like 100 times faster

5:05 cark: ahwell... must not be working then =)

5:06 atyz: And I understand how its working!

5:06 cark: great ... i'll go back to AFK then =)

5:06 good luck !

5:06 atyz: thank you! :)

5:12 SNBarnett: cs

5:17 tim_: hi, i'm new to emacs http://elpha.gnu.org seems to be unavailable for at present, is there an alternative repo apart from marmalade as trying to install cl-lib-0.3?

5:24 no7hing: binding apparently only works in the lexical scope - is there a way to use a binding in calls to other functions without using alter-var-root?

5:24 cark: no7hing: that's not true

5:25 no7hing: then i must've made a mistake

5:26 cark: it works in the dynamic scope

5:26 that means in all the functions that are called inside the binding form, and the ones called by those

5:27 but you might want to declare you var this way : (def ^:dynamic myvar "hello")

5:28 your*

5:29 also there are a few gotchas with lazy sequences

5:33 no7hing: thatoh

5:33 looking into this, as then binding stops working some function calls deep

5:34 cark: are you returning a sequance out of the binding form ?

5:34 sequence*

5:37 no7hing: actually yes

5:38 cark: that's a common problem

5:38 use doall on those sequances that will go out

5:38 sequences* ..

5:38 no7hing: is there a way so solve/circumvent it?

5:38 i'll try that

5:39 now i got it, sorry for being so thick

5:39 cark: np

5:48 doody1: how does one reload changed code referenced from checkouts folder in repl? Is restart necessary?

5:50 cark: require and :reload-all

5:54 doody1: can this be automated?

5:55 cark: i guess, that's not part of my workflow .... usually i edit a file, then evaluate it from my editor, which knows how to send it to the repl

6:01 doody1: hmm, I edit a referenced source (the doc of a ns) and evaluate it in cider, but it seems repl does not see it

6:02 cark: hum did you start the repl with cider-jack-in ?

6:03 doody1: hmm using emacs live, there's nrepl not cider, i did connect to a running repl

6:03 cark: mhh i can't help at all with emacs-live. never tried it

6:03 doody1: thanks

6:07 its the same thing with nrepl instead of cider

6:08 ahh interesting, when I change the doc for a function it does show the changed doc

6:08 but not so with the doc of a ns expression

6:27 AeroNotix: what's that error handling library?

6:27 slugger?

6:27 something like that

6:29 slingshot!

6:35 noncom: doody1: namespaces are strange in clojure

6:35 they are different from everything else

6:40 silasdavis: how can I pass an unbound var as a function argument?

6:40 I should say a possibly unbound var

6:43 CookedGryphon: silasdavis: do you mean so if the var changes the function changes with it?

6:43 just wrap it in (var my-defnd-fn)

6:43 and it'll look up the var every time, var implements ifn

6:47 noncom: i am trying to parse xml with clojure.data.xml/parse and i get this exception: https://www.refheap.com/29786

6:47 what am i to do with that?

6:54 gko: what's the equivalent of clojure.contrib.repl-utils.show in 1.5.1?

6:54 rurumate: how to do a 'select distinct' in cascalog?

6:57 ok found it, it's (:distinct false)

6:57 vijaykiran: gko: http://stackoverflow.com/questions/5821286/how-can-i-get-the-methods-of-a-java-class-from-clojure

6:58 gko: vijaykiran Thanks!

7:04 bordatoue: hi just a quick question why does (= 1 1.0) return false in clojure

7:04 (= 1 1.0),

7:05 clgv: ,(== 1 1.0

7:05 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

7:05 clgv: ,(== 1 1.0)

7:05 clojurebot: true

7:05 clgv: ,(doc ==)

7:05 clojurebot: "([x] [x y] [x y & more]); Returns non-nil if nums all have the equivalent value (type-independent), otherwise false"

7:06 bordatoue: clgv: what is difference between = and == in clojure

7:06 thanks clgv

7:07 clgv: numerical comparison is ==

7:08 $source ==

7:08 lazybot: == is http://is.gd/XeIlE5

7:08 bordatoue: clgv: but in the doc it says = can be used for numerical comparison

7:08 clgv: translates to (. clojure.lang.Numbers (equiv ~x ~y)) when used as call

7:09 bordatoue: well it works if they have the same type. the docs should be more specific there

7:09 usually it is no good idea to compara floating point numbers via equals

7:10 bordatoue: clgv: when it says comapres numbers what are they actually refering to

7:11 clgv: bordatoue: there are also known bugs in clojure <=1.5.1 with respect to comparisons of big integers or big decimals

7:12 bordatoue: will be fixed in 1.6 afair

7:12 bordatoue: could you please explain when it says in the document it compares numbers what kind of numbers are is it mentioning

7:13 Bronsa: bordatoue: with = you can only compare integer types with integer types (Integer, Long, BigInts) or floating types with floating types (Float, Double, BigFloat)

7:13 clgv: integers

7:13 Bronsa: with == you can compare integers with floating types too

7:13 clgv: right, what Bronsa said ;)

7:14 bordatoue: I'm getting confused it says in the doc in a type-independent manner

7:14 for "="

7:14 clgv: bordatoue: as I said, the docs should be more specific there

7:15 bordatoue: so clgv, with "=" we can compare numbers in a type dependent manner is it correct

7:15 clgv: bordatoue: maybe there is a jira issue for that otherwise you should create one, since it is documentation only chances should be good for inclusion in 1.6

7:16 yeah

7:16 Bronsa: actually looks like with = you cannot compare a Float/Double with a BigDecimal

7:16 bordatoue: ok, thanks very much

7:16 Bronsa: ,(= 1.2M 1.2)

7:16 clojurebot: false

7:16 clgv: Bronsa: thats a bug being fixed in 1.6 though

7:16 bordatoue: Bronsa: they are different type

7:17 lvh: Hi! could someone review my couple of lines? I'm afraid I might be committing Abominations Unto Rich: https://github.com/lvh/fomp/blob/master/src/fomp/core.clj#L12

7:17 Bronsa: clgv: nope

7:17 lvh: (ignore make-body; I know it's broken)

7:17 Bronsa: clgv: at least, hasn't been pushed yet

7:18 clgv: Bronsa: damn, I remembered some dicussion about it...

7:18 Bronsa: yeah clgv the bug has been fixed for ==

7:18 clgv: but you are right it is not in the current changelog

7:18 bordatoue: clgv: Bronsa , are you saying with version 1.6 it would be possible to compare different type using "="

7:19 lvh: I'm also thinking that maybe recipients should be part of params :)

7:19 clgv: bordatoue: no probably not

7:19 bordatoue: I jsut stated you could try to get the docs adjusted

7:20 Bronsa: clgv: ok looks like it's expected behaviour as BigDecimal is considered in the decimal category, not in the floating

7:20 bordatoue: clgv: you mentioned to Bronsa it is an issue fixed in 1.6 (= 1.2M 1.2)

7:21 Bronsa: bordatoue: he was mistaken

7:21 sm0ke: can i lauch lein repl with some jvm properties ?

7:21 -Dxyz=1

7:21 bordatoue: ok thanks guys

7:21 clgv: bordatoue: yeah, but that was an error. the discussion I remembered was obviously around ==

7:21 bronsa corrected me

7:21 Bronsa: bordatoue: https://github.com/clojure/clojure/blob/master/test/clojure/test_clojure/numbers.clj#L68-L79

7:22 the comment there explains nicely how = is supposed to work for numbers

7:23 pyrtsa: ,[(== 11/10 1.1) (== 1.1 1.1M) (== 1.10M 1.1) (== 1.10M 1.1M)]

7:23 clojurebot: [true true true true]

7:23 pyrtsa: Oh, so that got fixed as well. (Returns [true true true false] on Clojure 1.5.1.)

7:23 emlyn: sm0ke: add :jvm-opts ["-Dxyz=1"] to project.clj

7:24 sm0ke: emlyn: is there another way

7:24 changing file is not very friendly

7:25 deadghost: so if I'm reading this right

7:25 emlyn: sm0ke: I'm not sure, sorry

7:25 deadghost: I shouldn't be using jquery with cljs

7:25 or maybe I should

7:26 sm0ke: emlyn: i think i can set JVM_OPT

7:27 clgv: ,*clojure-version*

7:27 clojurebot: {:interim true, :major 1, :minor 6, :incremental 0, :qualifier "master"}

7:27 clgv: pyrtsa: ^^

7:28 pyrtsa: clgv: Thanks, I knew that. Just didn't know how = and == behave in 1.6.0.

7:29 emlyn: sm0ke: yes I think that should work too

7:32 pyrtsa: Numbers in Clojure are a mess. I think Clojure should've done something to help those poor programmers who believe that comparing equality of a Double against a BigDecimal is an okay thing to do. :/

7:33 ,(BigDecimal. 1.1)

7:33 clojurebot: 1.100000000000000088817841970012523233890533447265625M

7:33 clgv: pyrtsa: that only bytes you when comparing nested data structure, afaik

7:34 when you really care for numbers in computation then you have them "in hand" and compare them via ==

7:35 deadghost: hmm so there's domina, dommy, jayq for dom manipulation

7:35 pyrtsa: ,(doc ==)

7:35 clojurebot: "([x] [x y] [x y & more]); Returns non-nil if nums all have the equivalent value (type-independent), otherwise false"

7:35 pyrtsa: ,(nil? false)

7:35 clojurebot: false

7:35 deadghost: are any of them the generally recommended choice?

7:38 clgv: deadghost: arent there plenty blog posts on that topic - I feal as if the people using clojurescript were really chatty about the technologies in the last half year

7:39 lvh: is there an easy way to turn abitrary strings into something that looks like an easy to type keyword

7:39 ie a valid keyword literal?

7:40 I have a CSV file with a header that has a bunch of stuff in it like single quotes and spaces that don't work for keywords

7:41 clgv: lvh: you could use clojure.string/replace for conversion

7:41 lvh: clgv: Cool, thanks :)

7:45 The compiler appears to be complaining about: [:require clojure-csv.core :refer [parse-csv]] ; saying Exception :only/:refer value must be a sequential collection of symbols clojure.core/refer (core.clj:3840)

7:45 I don't understand why [parse-csv] doesn't count

7:47 llasram: lvh: You need [:require [clojure-csv.core :refer [parse-csv]]] -- one more set of nesting

7:48 lvh: oh, derp. okay :)

7:56 atyz: Hey all. so I'm doing some work wiht core.async but its not behaving as I would expect. Many of the results I'm receiving are nil and it seems to be giving me a random subset of correct answers and I suspect this is because the channel has been closed. https://www.refheap.com/29811

7:58 sobel: what's a zipper?

7:58 i find myself more lost in clojure land than most languages because it doesn't have much baggage from java OR native libs typically bound to python/perl/ruby wrappers

7:59 nomenclature-lost. the language is fine. :)

8:13 locks: sobel: a zipper is a functional data structure http://en.wikipedia.org/wiki/Zipper_(data_structure)

8:17 AeroNotix: does cider support "find callers of this function" ?

8:17 kind of like the reverse of M-.

8:22 hyPiRion: AeroNotix: So functions calling the function, essentially?

8:23 AeroNotix: hyPiRion: yep

8:29 sobel: well, i wasn't quite getting it until wikipedia explained it in terms of decategorification. seems my feeble math background still pays off.

8:29 thx locks, that pretty much hit the spot

8:33 what's the clojure idiom for coalasce? i'll get a value or a nil from a function, and i'm hoping/assuming there's a common expr/macro for "value or default-if-nil"

8:34 gtrak: cemerick: I nearly got file/line working yesterday, but I think piggieback needs a fix, any thoughts? https://github.com/clojure/clojurescript/blob/master/src/clj/cljs/repl.clj#L181 repl/repl calls analyze-source, which calls analyze-file, which is where the file info comes from in the first place, but piggieback never makes it through that part of the code.

8:34 sobel: better question: is 'if' the best idiom for value-or-default?

8:34 llasram: ,(or nil :default) ;; sobel

8:34 clojurebot: :default

8:35 sobel: ah ok

8:37 cemerick: gtrak: isn't it just a matter of analyze-path being truthy?

8:38 gtrak: it needs to be given the file path to the core.cljs somehow

8:38 yea, analyze-path is the key

8:41 marcschwartz: Anyone have any advice on the best way to find freelance Clojure developers?

8:43 goodger: they probably all hang out here, marcopol_

8:43 doody1: how to jump to definition of a function in emacs

8:43 goodger: by which I mean marcschwartz

8:43 doody1: if its in another namespace

8:44 or file

8:48 marcschwartz: goodger: Thanks. I'll just put the description of the project on the web somewhere and post the link here every couple days.

8:49 mdrogalis: marcschwartz: You have a PM. :P

8:51 stuartsierra: doody1: M-. if the Clojure code has been loaded by CIDER.

8:51 silasdavis: how can i get the name of a var?

8:52 as in (declare foo), (name-of (var foo))

8:53 stuartsierra: silasdavis: indirectly, via (meta (var foo))

8:53 noncom: is there any ready tool to count top-level forms in clj files allover my project?

8:53 silasdavis: stuartsierra, is that the way to do it?

8:53 the only way?

8:53 noncom: just wanna estimate how much unit testing be pain in the ass

8:54 doody1: stuartsierra: connected to lein repl via nrepl in emacs, i guess that does not count as being loaded by CIDER

8:54 stuartsierra: doody1: Compile/load the file you're looking at with C-c C-k and it should work.

8:55 silasdavis: strange that Vars aren't Named

8:59 quizdr: in general is it better to look up a key in a map using the key or the map as the function?

8:59 Anderkent: quizdr: key, it works with nil maps then

9:00 stuartsierra: quizdr: If the key is a keyword literal, use that as the function.

9:00 If either the key or the map could be nil, use `get`

9:00 quizdr: i suppose one reason to use the collection as the function is then it would be more general in case you use a vector instead of a map and search on key of index

9:01 Anderkent: Well yes if your keys arent literal keywords then use get or the collection

9:02 quizdr: Andrekent if the map has nothing in it (is nil?) then it still seems to work whether you search by key or map -- or are you saying that if you search by key you can specify the default return value?

9:02 Anderkent: quizdr: no, if someone passes nil as the map trying to use it as a function will NPE

9:03 ,(let [mp nil] (mp :foo))

9:03 clojurebot: #<NullPointerException java.lang.NullPointerException>

9:03 quizdr: ah i see. regarding keys that aren't keyword literals, using a symbol as a function for a map seems to also work fine

9:03 Anderkent: uh that depends on what the symbol 'points to'

9:04 ,(let [key :keyword] (key {:keyword :yes}))

9:04 clojurebot: :yes

9:04 quizdr: ,('a {'a 5})

9:04 clojurebot: 5

9:04 Anderkent: ,(let [key 3] (key {3 1}))

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

9:05 Anderkent: oh you mean a literal symbol. I didn't know that

9:05 lvh: hi, is there a standard for clj docstrings

9:05 quizdr: yeah

9:10 maps must do some sort of implicit lexical binding or something if you use them as a function, right? for example:

9:10 ,(let [bbb 5] ({bbb 6} bbb))

9:10 clojurebot: 6

9:10 quizdr: obviously the keyword is overriding the binding of bbb to 5

9:11 Anderkent: quizdr: that's just equivalent to ({5 6} 5)

9:11 quizdr: oh i see. the bbb form is evaluated prior to its insertion in the map

9:43 mdrogalis: stuartsierra: Vagrant set up you posted is nice. There's some good stuff in there.

9:43 stuartsierra: mdrogalis: thanks!

9:43 mdrogalis: Especially the Emacs24 thing. It's a pain every time you gotta do it.

9:44 cemerick: dnolen: I ran into some difficulty trying to use :as to bind the result of an :or match; I expected either of the first expressions to work, and was surprised that the third did. Bug, or are :or and :as not necessarily supposed to work together? https://gist.github.com/cemerick/6b7bb333293fd11855d9

9:44 lvh: I have a bunch of n-vectors; what's the idiomatic way to filter out all the ones where all the elements are empty strings

9:46 I guess I want (all (map empty? vec)) where all is reduction with and? (is that a core function?)

9:46 stuartsierra: lvh: `remove` and `every?` should do it

9:48 dnolen: cemerick: interesting open a ticket though I can't say when I'll get to that. patch welcome

9:49 lvh: stuartsierra: Thanks!

9:49 cemerick: dnolen: Will do. I may take a whack at a patch, depends. What *should* happen?

9:49 stuartsierra: lvh: you're welcome.

9:50 dnolen: cemerick: the first one looks like sugar to me, so I don't really care whether that works or not.

9:50 cemerick: the other 3 should all work

9:51 cemerick: dnolen: thanks

9:54 lvh: Can I do destructuring def?

9:54 I guess I don't really need it

9:55 stuartsierra: lvh: def does not support destructuring

9:56 octane--: stuartsierra, mdrogalis: could you please repeat that about the vagrant setup?

9:57 Anderkent: lvh: not without a non-core macro. (let [[x y & rest] (def x x) (def y y) (def rest rest)) kinda works, but i'd avoid it if at all possible

9:57 stuartsierra: octane--: https://github.com/stuartsierra/devbox

10:04 edbond: cemerick, changed lein-cljsbuild to 1.0.2 and got NPE - https://www.refheap.com/29856 1.0.2-SNAPSHOT works fine.

10:09 cemerick, to reproduce -> "lein new mies-om ommm", change lein-cljsbuild version to "1.0.2" in project.clj and "lein cljsbuild once"

10:09 cemerick: edbond: I think you've somehow gotten a stale cljsbuild dependency in there; try `rm -r ~/.m2/repository/lein-cljsbuild/cljs-compat`, and rerun lein

10:10 edbond: cemerick, yes, that helped. Thanks a lot!

10:10 (inc cemerick)

10:10 lazybot: ⇒ 15

10:11 cemerick: edbond: thanks for the report, I'll make it so that won't happen again

10:12 edbond: now I can switch to 1.0.2 without SNAPSHOT. Nice.

10:16 noncom: is there a simple way to know if a string can be parsed into a, say double or integer, without try-catch or regexps?

10:21 fredyr: ,(doc re-matches)

10:21 clojurebot: "([re s]); Returns the match, if any, of string to pattern, using java.util.regex.Matcher.matches(). Uses re-groups to return the groups."

10:21 octane--: stuartsierra: lovely, thank you.

10:21 fredyr: noncom: oh, misread

10:22 noncom: so nvm me

10:23 noncom: i think try-catch is the way

10:23 noncom: i better go with regexps then :)

10:25 fredyr: hah

10:27 john2x: what could cause clojure.walk to not be found? https://www.refheap.com/29863

10:28 stuartsierra: john2x: If the namespace being loaded uses clojure.walk without requiring it.

10:31 john2x: indeed.. a bug in revise? strange, I tried the same version in another project a few days ago and didn't get the issue.

10:31 wei__: anyone know a good method for specifying config variables through a file? kind of like leiningen's profiles.clj, but it has to work when running from an uberjar

10:32 Anderkent: wei__: edn? is the config file supposed to be *in* the uberjar or not? (depending on that, read it as a resource or filesystem url)

10:32 wei__: Anderkent: good question. it's supposed to be outside the uberjar

10:32 but in the same directory (on the classpath)

10:33 Anderkent: wei__: if you'd rather not have your config file be lisp syntax (picky users), you can use java.util.Properties. to parse a java properties file and then read that into a map

10:33 I'm not sure if the current directory is actually guaranteed to be on the classpath

10:34 wei__: "slurp" seems to always check in the current directory

10:34 i think java properties will work, thanks!

10:34 (inc Anderkent)

10:34 lazybot: ⇒ 6

10:35 Anderkent: wei__: check out https://github.com/michaelklishin/propertied

10:36 wei__: perfect. it's clojurewerkz too, which i know writes good stuff

10:40 noncom: what would be the regexp to check if a string can be parsed into a double?

10:41 Anderkent: noncom: (try (Double. str) (catch NumberFormatException)

10:42 edbond: noncom, (if (re-find #"\." s) :double :integer)

10:42 Anderkent: edbond: "asdf.fdsa"?

10:42 fredyr: and ".5" and "1e-1000"

10:42 etc

10:43 Anderkent: in short - why regex, who needs two problems?

10:43 edbond: it's quite complicated, consider localization (, . etc)

10:43 fredyr: it can easily get kinda hairy

10:44 edbond: ,(Double/parseDouble "1e-100")

10:44 clojurebot: 1.0E-100

10:44 edbond: ,(Double/parseDouble "123")

10:44 clojurebot: 123.0

10:45 Anderkent: if you don't want integers as doubles (but why not?!), you can do (try (Integer. str) (catch NumberFormatException (try (Double. str) (catch NumberFormatException (throw+ :nope

10:51 noncom: thanks!

10:51 lvh: hi

10:52 Im trying to use atoms and failing :(

10:52 https://gist.github.com/8711482

10:52 interesting function starts at 13

10:52 so I am returning an atom and a function closed over it from that function at line 13

10:52 when I call the returned function with 2 args, itcomplains that I'm only calling it with 1

10:53 fomp.core-test> ((second test-send) :a :b) -> ArityException Wrong number of args (1) passed to: ...

10:53 Anderkent: lvh: you're using swap wrong

10:53 lvh: it should be (swap! sent #(into % [recipients body]))

10:53 swap gives your function one argument - the current value of the atom

10:53 you don't need to reference the atom inside of your function

10:55 lvh: oh, okay; that actually makes more sense. Swap takes a function that maps the current value to the next one?

10:57 `cbp: If I use a var from another namespace and properly qualify it do I still have to require the namespace?

10:57 It seems to work without requiring it

10:57 most of the time..

10:58 Anderkent: lvh: yeah

10:58 luxbock: hello, I want to create a function that takes a vector of ints, e.g. [3 2 2] and creates a sequence between [1 1 1] and the input vector based on the following rule: try to increment the leftmost number until it matches the one in the input vector

10:58 Anderkent: `cbp: yes you do. It will work if some other already laoded namespace required the one you refer to, but there's no reason to depend on that

10:58 luxbock: so with my example the first steps would go: [1 1 1] [2 1 1] [3 1 1], then reset back to 1 and increment the second leftmost number: [1 2 1], and now continue incrementing the leftmost number again until we hit a limit: [2 2 1] [3 2 1] [3 3 1] etc. until we reach the input vector [3 2 2]

10:59 but I can't think of how to do this, any help?

10:59 Anderkent: luxbock: I'd try a recursive solution. First think of a function that will take the current vector and the 'max' values, and generate the next entry

10:59 then wrap that in a lazy-seq

11:00 ooor you can just use for

11:01 luxbock: how would for work for that? the order of the sequence matters

11:01 Anderkent: just reverse the order in for

11:02 llasram: I think `iterate` is the way to go

11:02 Anderkent: ,(for [z (range 1 3) y (range 1 3) x (range 1 4)] [x y z])

11:02 clojurebot: ([1 1 1] [2 1 1] [3 1 1] [1 2 1] [2 2 1] ...)

11:02 Anderkent: that looks right to me?

11:03 luxbock: yeah that's right, but I would also like it to work for an input vector of any size

11:03 llasram: Actually, more state is nice -- an explicit lazy-seq is probably better

11:04 Anderkent: yeah, for arbitrary length vectors a lazy-seq would probably turn out nicer

11:04 TimMc: "more state is nice"

11:04 ~guards

11:04 clojurebot: SEIZE HIM!

11:04 llasram: heh

11:04 luxbock: how does the call to lazy-seq look like if the fn that creates a new vector is called myinc ?

11:04 llasram: TimMc: I didn't say *mutable* state :-p

11:04 TimMc: Oh! OK.

11:05 ~unguards

11:05 clojurebot: Titim gan éirí ort.

11:05 Anderkent: (def vector-seq [cur limit] (cons cur (lazy-seq (vector-seq (my-inc cur limit) limit))))

11:05 then just a wrapper fn that gives [1 1 1] for cur

11:05 (or you know, arities)

11:05 luxbock: cool, thanks

11:08 noncom: yea, try catch seems more versatile for doubles parsing from strings

11:12 llasram: ,((fn [v] (->> v (map-indexed vector) (mapcat (fn [[i x]] (map #(-> [i %]) (range 2 (inc x))))) (reductions (fn [v [i x]] (assoc v i x)) (vec (repeat (count v) 1))))) [2 1 4])

11:12 clojurebot: ([1 1 1] [2 1 1] [2 1 2] [2 1 3] [2 1 4])

11:13 Anderkent: llasram: nah, it should reset to [1 1 2] after [2 1 1]

11:13 ambrosebs: ,(def foo (fn [] `bar#))

11:13 clojurebot: #'sandbox/foo

11:13 llasram: Oh, I missed that

11:13 Anderkent: also, I find the lazy-seq version much easier to read / reason about

11:14 ambrosebs: ,(def foo (fn [] `bar#))

11:14 clojurebot: #'sandbox/foo

11:14 ambrosebs: (foo)

11:14 ,(foo)

11:14 clojurebot: bar__49__auto__

11:14 ambrosebs: ,(foo)

11:14 clojurebot: bar__49__auto__

11:14 Anderkent: ambrosebs: sounds like you want (gensym)

11:14 ambrosebs: Bronsa: does tools.reader have that behaviour with syntax quote?

11:14 Anderkent: nvm :)

11:15 ambrosebs: Anderkent: well I assumed they were interchangeable..

11:15 Anderkent: hm, I think `# runs on read time

11:16 ambrosebs: Anderkent: yes. I assumed it expanded to (let [gsym (gensym bar)] `~bar)

11:17 rather ##(let [gsym (gensym 'bar)] `~gsym)

11:17 lazybot: ⇒ bar11970

11:17 jazzorn: (+ 1 2)

11:17 clojurebot: 3

11:17 jazzorn: ;-)

11:17 Anderkent: of course you have to be careful about manually using gensyms

11:18 ,(let [goal (gensym "f1")] (loop [s (gensym "f")] (if (= s goal) [goal s] (recur (gensym "f")))))

11:18 clojurebot: [f1123 f1123]

11:18 Bronsa: ambrosebs: yes

11:18 ambrosebs: Bronsa: do you know if it's by design?

11:18 Bronsa: the gensym is done at read-time, not run-time

11:21 ambrosebs: Bronsa: could the run-time behaviour be implemented?

11:22 a reader macro can emit code as well, right?

11:22 Bronsa: it most definitely could, sure

11:23 ambrosebs: Bronsa: ok.

11:24 Bronsa: ambrosebs: you could implement it as a tagged literal if you need it

11:24 ambrosebs: Bronsa: I just want to fix syntax-quote for everyone.

11:25 Anderkent: I still don't see how it's broken

11:25 llasram: ambrosebs: Why do you want autogensyms to emit code instead of read-time gensyms?

11:25 Bronsa: ambrosebs: making run-time gensym the default behaviour of `a# would be problematic

11:26 ambrosebs: Bronsa: I haven't thought about it. Go on.

11:28 llasram: I assumed that's how syntax-quote worked.

11:28 llasram: haven't thought of an example which it makes a difference, but it still disturbs me.

11:29 llasram: ambrosebs: Interesting. I've definitely always thought of it as read-time behavior, and the thought of it generating new symbols on subsequent evaluation disturbs me :-)

11:29 ambrosebs: Bronsa: the biggest problem I can see is the implementation burden of bookkeeping the current gensyms for the same syntax-quote expression.

11:29 Bronsa: suppose you are doing `(let [a# 1] (some-macro a#)). with the current read-time behaviour you'd get (let [a__whatever 1] (some-macro a__whatever 1))

11:30 with the run-time, you couldn't even bind the let

11:31 ambrosebs: Bronsa: I guess I mean macroexpand time then?

11:32 Bronsa: ambrosebs: that doesn't do it for special forms

11:32 ambrosebs: Bronsa: ok.

11:32 jph-: anyone know if i can get a request uri from within a (selmer) template?

11:32 Bronsa: (let [(macro) 1]) the call to macro won't get macroexpanded

11:33 ambrosebs: I'd guess there could be a way to make it work, just not as simple as just expanding to a run-time call to gensym

11:33 noncom: ,(= 100 100.0)4

11:33 clojurebot: false

11:34 noncom: why is not 100 == 100.0 ?

11:34 llasram: noncom: It is

11:34 noncom: how do i check properly

11:34 llasram: ,(== 100 100.0)

11:34 clojurebot: true

11:34 noncom: oh

11:34 llasram: It just isn't the case that 100 = 100.0 :-)

11:34 noncom: ))

11:35 Anderkent: eh, isn't = supposed to be type-independent for colections and nums?

11:35 ,(doc =)

11:35 clojurebot: "([x] [x y] [x y & more]); Equality. Returns true if x equals y, false if not. Same as Java x.equals(y) except it also works for nil, and compares numbers and collections in a type-independent manner. Clojure's immutable data structures define equals() (and thus =) as a value, not an identity, comparison."

11:35 Anderkent: i'd call that a bug

11:35 ,(= 100.0f 100.0d)

11:35 clojurebot: #<NumberFormatException java.lang.NumberFormatException: Invalid number: 100.0f>

11:35 Anderkent: oups

11:36 llasram: (doc ==)

11:36 clojurebot: "([x] [x y] [x y & more]); Returns non-nil if nums all have the equivalent value (type-independent), otherwise false"

11:37 Anderkent: I guess it's just a documentation error?

11:38 llasram: ,[(= (int 100) (long 100)) (.equals (int 100) (long 100))]

11:38 clojurebot: [true false]

11:49 BobSchack: is there a good technique or collection to get the neighbors of an element (the elements to the left and right of it)?

11:50 sdegutis: BobSchack: I can't figure out how that question would make sense.

11:51 bbloom: Bronsa: you mean you have a sequence and want to have a cursor in to that collection and move left or right?

11:51 sdegutis: Like, you're never *in* a collection. You always just have some data-path that you're using to access deep within a collection. In which case, sure, you can adjust that.

11:51 bbloom: BobSchack: whoops, that was for you, not Bronsa

11:51 BobSchack: bbloom: yes

11:52 Anderkent: Biohazard: something like

11:52 ,(let [f (fn [pre cur next] [pre cur next]) cl [1]] (map f (cons nil cl) cl (concat (next cl) [nil])))

11:52 clojurebot: ([nil 1 nil])

11:52 Anderkent: woups

11:52 wrong name

11:52 BobSchack: that's for you

11:52 gfredericks: Anderkent: it's just subtle; = is type-independent for numbers, but won't compare exact with inexact

11:52 bbloom: BobSchack: two man choices: 1) hold on to the pointer to the root of the collection and pair it with an index or path or whatever

11:52 BobSchack: I should get a new name :)

11:52 gfredericks: Anderkent: e.g., ##(= 3 3N)

11:52 lazybot: ⇒ true

11:52 Anderkent: gfredericks: yeah I looked inton Numbers/equal and saw the category() calls

11:53 bbloom: BobSchack: 2) alternatively, use something like a zipper (look it up, but not necessary the clojure.zip api)

11:53 gfredericks: Anderkent: it's perhaps similar to why #(= [1 2 3] (sorted-set 1 2 3))

11:53 BobSchack: Yeah I'm looking at zippers right now

11:53 gfredericks: &(= [1 2 3] (sorted-set 1 2 3))

11:53 lazybot: ⇒ false

11:53 Anderkent: hah.

11:53 BobSchack: bbloom is there a good zipper non clojure.zip zipper impl out there?

11:54 bbloom: BobSchack: not general purpose, but the reason i say to study zippers & not necessarily the API is b/c for a sequence, zippers are trivial

11:54 for example if you have [1 2 3 4 5] and you have a "zipper" at 3, then you can define it simply as [(3 2 1) (4 5)]

11:55 BobSchack: but generally just use an index: [[1 2 3 4 5] 2] ; would be at the three

11:55 or better yet: {:vector [1 2 3 4 5] :index 2} ; this is all you need

11:56 BobSchack: Well I'm trying to implement the borderline sequence of Fortune's algorithm (http://blog.ivank.net/fortunes-algorithm-and-implementation.html)

11:57 drorbemet: Hi, can clojure.data.xml be used to roundtrip xml, or has it some unresolved issues?

11:57 It is based on stax parser that's nice.

11:57 But I am getting an error when trying to partition large xml file into chunks of smaller xml files

11:57 XMLStreamException Prefix cannot be null

11:57 com.sun.xml.internal.stream.writers.XMLStreamWriterImpl.writeAttribute (:-1)

11:58 BobSchack: which calls for getting a point in a sequence and it's neighbors quite frequently

11:59 drorbemet: I am back in about 10min

12:00 Anderkent: BobSchack: sounds like you maybe want a different structure than a list?

12:00 bbloom: BobSchack: clojure's data structures don't get you out of the business of considering and creating your own data structures.... it simply delays that so far that often you don't have to do it :-)

12:01 BobSchack: get the algorithm working (however slowly) with the dumbest thing that can work, then decide if you need to tune and whether or not that tuning requires custom data structures

12:01 BobSchack: bbloom: thats what I figured. I was hoping someone knew a clojure corner I didn't

12:01 I'll go do the naive impl first then go back later thanks everybody.

12:04 zoldar: is there a library similar to flatland/ordered but for clojurescript? I need a map that maintains insertion order

12:05 lvh: hi

12:05 to do autocomplete in emacs, should I get ac-cider-compliment or ac-nrepl

12:07 drorbemet: I am back in about 60min

12:10 sdegutis: devn: I'd love to see how we could use Julia types to represent token types in the lexer and parser. That might be really cool.

12:11 gfredericks: is compojure the most egregious violation of halloways "data-model > API > DSL" pyramid in the clojure-oss-world?

12:14 now I know why ratios auto-convert to bigints

12:15 ,(= 3 (clojure.lang.Ratio. (biginteger 3) (biginteger 1)))

12:15 clojurebot: false

13:09 sdegutis: Someone should name their next project Dragicorn.

13:09 That'd be pretty sweet.

13:28 aaronj1335: hey folks, is there a way to drop into a clojure repl in the middle of a program?

13:28 kinda like `import pdb; pdb.set_trace()` if you're familiar w/ python...

13:31 bbloom: aaronj1335: there are a few things in that category around...

13:31 aaronj1335: this seems like it might b the thing i'm thinking of: http://georgejahad.com/clojure/debug-repl.html

13:36 stompyj: #clojurecorner

13:36 love it

13:37 aaronj1335: stompyj yea? sounds like #clojure but in a leisure suit

13:37 (which sounds awesome)

13:38 stompyj: haha someone wrote clojure corner up in the chat earlier, and that sounds awesome. If I give a talk on clojure, I'm going to call it the #clojurecorner

13:38 srruby: How do I send commands via the Linux command line to a clojure repl or nrepl ? I want to do something like $ echo "(+ 1 1)" | ???? to pipe some commands to the repl process

13:39 technomancy: srruby: grenchman does that

13:39 there might be a python thing too maybe?

13:39 SegFaultAX: srruby: Plus the nrepl protocol isn't that complicated. It's described on the github project page.

13:40 Yea, there is a Python impl of the nrepl protocol.

13:40 technomancy: ocaml's so much cooler than python though

13:41 SegFaultAX: technomancy: Lots of things are cooler than Python.

13:41 srruby: Thanks.

13:43 sdegutis: technomancy: I've heard great things about Haskell from many people but not OCaml. Have you done a comparison of them on your blog?

13:44 hyPiRion: sdegutis: no, but I'm sure bitemyapp would help you with that

13:44 Oh, he's not here

13:44 sdegutis: callen's gone.

13:44 technomancy: sdegutis: probably the biggest difference is you can learn ocaml in a week no problem

13:44 llasram: sdegutis: Forever?

13:44 technomancy: it's really simple

13:44 stompyj: I have a buddy who's a huge haskell guy. We gently argue about who's made the right choice. :)

13:45 sdegutis: technomancy: Haskell isn't as simple?

13:45 technomancy: sdegutis: ocaml is more like clojure in that it has facilities for imperative programming when necessary

13:46 sdegutis: I see.

13:46 llasram: Probably.

13:46 SegFaultAX: sdegutis: Why?

13:46 I know Chris IRL but I haven't been around much since I've been on vacation. Did something happen?

13:46 sdegutis: SegFaultAX: No. He's fine.

13:47 He just moved on from Clojure.

13:47 stompyj: that sounds ominous :)

13:47 sdegutis: Sorry to phrase it poorly at first.

13:47 SegFaultAX: Oh, probably switching to Haskell full time.

13:47 sdegutis: He's in #haskell, you can ask him.

13:48 I'm writing a terrible admin section in Hiccup right now. No idea what I'm doing.

13:48 Kinda wish I could just write native apps. I'm sick of "web as a platform". It's so easy to mess something up catastrophically.

13:48 technomancy: sdegutis: it's actually a lot nicer than clojure at isolating side-effects since the type system will ensure they're all returning unit

13:49 sdegutis: technomancy: OCaml?

13:49 Sweet.

13:49 technomancy: haskell goes further by requiring side-effects run in a monad, but I find that OCaml's approach is a really pleasant middle ground

13:50 yazirian: the "web as a platform" is an elaborate plot to prevent programmers from taking over the world

13:50 technomancy: (inc yazirian)

13:50 lazybot: ⇒ 2

13:50 yazirian: why else would it be so awful?

13:50 stompyj: don't say that on hacker nes

13:50 news*

13:50 or bye bye karma

13:51 yazirian: lucky for me i don't say anything there, and in fact dumped the RSS feed even just last week!

13:51 i prefer more linear jerks

13:51 sdegutis: yazirian: we so could have done it by now if not for CSS/JS :'(

13:51 SegFaultAX: yazirian: LtU

13:51 yazirian: I think so!

13:51 sdegutis: stompyj: speaking of which

13:51 What IRC would look like in 2014: https://news.ycombinator.com/item?id=7147396

13:52 the only difference being that there are no chanops

13:52 llasram: Is submitting links to hacker news to hacker news a new meme or something?

13:52 sdegutis: llasram: no, I just invented this idea just now.

13:53 stompyj: hahahahahahahahah

13:53 sdegutis: llasram: (well, 20 hours ago)

13:53 technomancy: sdegutis: check out the free book at http://realworldocaml.org if you want to dig in; I find it a great fit for small native distributables that clojure is bad at

13:54 sdegutis: well, not always small, according to your blog

13:54 technomancy: right, if size is a priority you have to choose your libs carefully

13:54 hyPiRion: yeah

13:54 `-import core async` and then bam

13:54 * sdegutis places bets on when technomancy's "in which" streak will end

13:55 technomancy: the author of the book told me they were working on improved tree-shaking for an upcoming version that would solve that

13:55 sdegutis: nevar

13:55 yazirian: which reminds me again of the web as a platform and the horror of a cljs/pedestal/om 'hello world' app downloading over a megabyte of js to run

13:55 sdegutis: technomancy: it had a beginning, it must have an end

13:55 technomancy: sdegutis: I will take it with me to the grave

13:55 hyPiRion: sdegutis: so uh, you're betting on when technomancy will... die? =/

13:56 oh, he beat me to it too, argh

13:56 sdegutis: hyPiRion, technomancy: i doubt http://technomancy.us/ will even be a valid URL in 15 years

13:56 technomancy: sdegutis: what with the fall of the US?

13:57 *impending fall

13:57 sdegutis: and im assuming by then we'll be using XAML or something instead of html/css/js

13:57 TimMc: LaTeX

13:57 stompyj: clojure is the first language I've worked in where I feel like i could use a tutor at times

13:57 TimMc: LaTeX everywhere

13:58 * sdegutis cries "nooooo!!!" into the streetlit rain

13:58 bbloom: sdegutis: latex scares you but xml-based object initialization syntax is A-OK?

13:58 ToxicFrog: LaTeX \o/

13:58 sdegutis: anyway, in all seriousness, i think https://news.ycombinator.com/item?id=7147396 is actually a pretty good joke

13:58 bbloom: there are some brilliantly designed bits of WPF, but the decision to use XML for XAML was political & brain dead

13:58 yazirian: sdegutis: it'll be Dart, and the runtime will inject ads into your source

13:59 sdegutis: bbloom: im not that picky about syntax tbh

13:59 yazirian: of course, how else will chromium os make its money?

13:59 technomancy: Sergei gots to eat, son.

13:59 bbloom: sdegutis: xml's verbosity is only half the problem. the other half is that it has horribly broken semantics that clash with the desired semantics for UIs

14:00 sdegutis: oh?

14:00 bbloom: can you cite a paper demonstrating this please?

14:00 bbloom: sdegutis: no b/c i haven't written such a paper yet :-P

14:00 sdegutis: (i only read papers these days, it's the only way i can sleep at night now that i have a HN account)

14:01 stompyj: hey bbloom I missed the last clojure meetup where you gave your talk. is the video online?

14:01 bbloom: stompyj: http://www.hakkalabs.co/articles/clojure-software-dendrology

14:01 sdegutis: (that joke came out wrong, i meant it to be a joke about how HN is fine with random articles on the web, not a description of how i fall asleep)

14:01 stompyj: much appreciated!

14:06 sdegutis: ,[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]

14:06 clojurebot: [[[[[[[[[[#]]]]]]]]]]

14:07 sdegutis: wat

14:07 hyPiRion: ,*print-depth* ;; I guess

14:07 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: *print-depth* in this context, compiling:(NO_SOURCE_PATH:0:0)>

14:08 hyPiRion: ah, *print-level* it is

14:10 sdegutis: ##[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]

14:10 lazybot: ⇒ [[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]

14:11 egghead: why does edn make a distinction between vector and list?

14:11 technomancy: egghead: because it's secretly clojure

14:11 sdegutis: ##(repeat 500 nil)

14:11 lazybot: ⇒ (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil ni... https://www.refheap.com/29927

14:11 technomancy: don't tell anyone

14:11 sdegutis: neat.

14:11 ,(repeat 500 nil)

14:11 clojurebot: (nil nil nil nil nil ...)

14:11 sdegutis: okay, lazybot it is

14:12 egghead: technomancy: it seems like for edn that would make sense as a tagged literal

14:13 technomancy: egghead: I'm not entirely convinced EDN is anything but a sneaky way to get people to write datomic libs for other platforms

14:13 sdegutis: Clojure's destructuring is probably the number one feature I miss in other languages. Some of them get kinda close, but not nearly as convenient as Clojure.

14:13 (In other high-level languages, i.e. Ruby and Python)

14:13 egghead: sdegutis: sml? :p

14:14 OH

14:14 hyPiRion: OCaml's good at that. And Erlang, although it lacks both map and sets, which is super annoying.

14:14 technomancy: that's funny; destructuring just seems so limited compared to pattern matching

14:14 hyPiRion: oh, right. that's pattern matching, not destructuring.

14:15 sdegutis: technomancy: i.e. OCaml?

14:15 technomancy: sdegutis: or any FP language that isn't clojure, basically

14:15 sdegutis: Ah.

14:15 egghead: ya technomancy

14:16 sdegutis: I started using a pattern of functions that update the database returning [db val], and functions that update an entity taking [db val] as their first argument.

14:16 That way I can do chaining with ->, i.e. (-> (create-episode ...) (set-episode-title ...)) etc

14:17 Pretty handy for carts when writing tests: (-> (open-cart db user) (add-license-to-cart ep1) (receive-stripe-payment ...))

14:18 That's where I'm loving destructuring the most right now. I can access either the db or the val in a let block in my tests without using an extra (first ret-val) line.

14:18 srruby: technomancy: Is there a 32 bit version of grenchman? I'm on Linux wheezy

14:19 CaptainLex: So I see there is no true literate programming engine for Clojure. Is this because a) true literate programming is overrated? b) true literate programming is not as useful for FPs? or c) language-agnostic FP tools are good enough?

14:19 llasram: Do they still make 32-bit computers?

14:19 technomancy: srruby: no, sorry;

14:19 sdegutis: CaptainLex: what does literate programming mean to you?

14:19 technomancy: all the precompiled stuff is 64-bit

14:20 CaptainLex: sdegutis: The kind of thing described by Knuth, with compile-time reordering of content, macro-substitution, &c &c

14:20 hyPiRion: CaptainLex: most likely it's because noone has bothered to make one yet.

14:20 sdegutis: CaptainLex: I haven't found a need for one.

14:20 CaptainLex: sdegutis: It's mostly useful when making a large codebase that many people will have to poke around in

14:20 sdegutis: Well-written Clojure reads like English to me.

14:20 hyPiRion: Whether that is the cause of a, b, c or some unknown x I'm unsure of.

14:20 CaptainLex: i.e. where documentation is the most important part of the software

14:21 dkinzer: llasram: I've seen plenty of 32-bit VMs

14:21 TimMc: CaptainLex: I don't see what FP has to do with it.

14:21 sdegutis: llasram: we bought a 32-bit PC from a local shop for like $100 last year

14:21 it has MS-DOS 6.22 on it

14:22 CaptainLex: Oops, C was supposed to read "language-agnostic LP tools"

14:22 sdegutis: my son's been trying to make games using QBasic on it

14:22 CaptainLex: TimMc: Well, maybe FPs are more readable. Not really, though :P

14:22 TimMc: ah

14:22 sdegutis: <3

14:22 CaptainLex: I was just imagining responses from the peanut gallery, and I could see someone saying "Well, literate programming is mostly useful for spaghetti code" or some such a thing

14:24 devn: hmmm, anyone in here know anything about iota and reducers?

14:25 I want to use iota in combination with clojure.data.csv. What's the best way to go about doing something like this? Perhaps extending the Read-CSV-From protocol to iota.FileVector?

14:25 technomancy: CaptainLex: I would suspect it might be because people value a literal and clear mapping of files on disk to namespaces.

14:25 devn: Is this a foolish thing to do in any case?

14:25 technomancy: people are rightly suspicious of anything that gets in between them and the compiler

14:26 devn: clojure.data.csv just doesn't work for the size of files I'm dealing with

14:26 CaptainLex: technomancy: Makes sense. I haven't written any LP stuff, but it sounds interesting!

14:27 drorbemet: XMLStreamException Prefix cannot be null

14:27 I think I found the cause of the error

14:27 I don't declare namespaces in the new xml file in which I copy the xml chunks

14:27 I read about a repairing mode in

14:27 http://jira.codehaus.org/browse/WSTX-170

14:27 can I use repairing mode with clojure.data.xml/emit?

14:28 tmciver: If anyone is interested in a Clojure job in Framingham, Massachusetts, feel free to PM me.

14:28 CaptainLex: tmciver: Were that it were five months from now!

14:29 llasram: devn: Are you sure that's the problem? data.csv should be producing a lazy sequence of the rows in your CSV input file

14:29 devn: Are individual rows too large to fit into memory?

14:29 shep-werk: tmciver: got anything in Pittsburgh? ;-)

14:29 tmciver: shep-werk: sorry, no. :(

14:29 shep-werk: tmciver: time to open a remote office

14:30 * TimMc waves to tmciver

14:30 tmciver: Hey, man!

14:30 o/

14:30 TimMc: \o

14:30 tmciver: Missed you at the last Boston Clojure meet up.

14:30 TimMc: Oh! Yeah, things have been busy.

14:31 I have too many projects and too much ADHD.

14:31 tmciver: Tell me about it.

14:31 Going to the next meet up?

14:32 TimMc: ^

14:33 TimMc: I hope so.

14:34 I've been getting into electronics, so reading up on circuits has been occupying me some nights.

14:35 tmciver: Cool. Yeah, I have an Arduino project in my basement collecting dust.

14:35 technomancy: TimMc: what kind of projects?

14:37 devn: llasram: hmmm, maybe I was mistaken? I think I know the issue. walk/keywordize-keys across my data.

14:38 llasram: Yeah -- that's probably forcing full realization in memory

14:40 tjd: philosophical question: (map some-f some-seq), if some-f throws an exception, what ought happen? swallow it and map to nil? raise the exception?

14:43 technomancy: exception hiding is pretty evil

14:43 shep-werk: tjd: mu

14:44 hyPiRion: tjd: Whenever the value is calculated, the exception is thrown.

14:45 so for example ##(do (map #(< 10 %) (concat (range 1 100) [nil])) nil) will not throw

14:45 lazybot: ⇒ nil

14:45 hyPiRion: but ##(map #(< 10 %) (concat (range 1 100) [nil])) will.

14:45 lazybot: java.lang.NullPointerException

14:45 sdegutis: technomancy: evil is such a strong word. how about "malutile"?

14:45 hyPiRion: (because it attempts to print the value)

14:45 technomancy: sdegutis: maybe "reprehensible"

14:45 sdegutis: actually im gonna coin malutile.

14:46 technomancy: more power to you

14:46 sdegutis: technomancy: that phrase is so malutile

14:46 devn: llasram: is there anything decent that i can do with iota to deal with that? basically I want to create a map out of every row, by zipmapping the headers across all of the rows, and keywordizing the keys on those maps

14:46 mmitchell: stuartsierra: I've been playing around with your component lib/idea. Question... for web apps, how are you getting the "system" into your handlers? Or are the handlers reaching out the the "system" var?

14:47 llasram: devn: I don't know iota, but that isn't anything you shouldn't be able to do with lazy seqs. The headers are just the first row, right?

14:51 stuartsierra: mmitchell: construct the handlers when you start your app

14:51 Compojure makes this awkward but still doable.

14:52 devn: llasram: yeah, im trying it out, doesn't seem to make much of a difference with reducers and iota

14:53 mmitchell: stuartsierra: Right, so (GET _ #(my/handler system %)) etc.?

14:53 devn: i find it a bit annoying clojure.data.csv keeps read-cell and so on private fns

14:53 TimMc: technomancy: I want to build a Joule Thief or five, and then start playing with high-power LEDs.

14:54 llasram: devn: So data.csv returns a lazy seq of the rows, right? So you get (let [rows ...] ...) at some point. Then you just: (let [headers (map keyword (first rows)), data-rows (map (partial zipmap headers) (rest rows))] ...)

14:55 Then data-rows is a lazy sequence of your keyworded maps

14:55 technomancy: TimMc: cool

14:55 stuartsierra: mmitchell: no, don't use defroutes at all. Do something like (defn make-app [… service components …] (routes …)) and call it from your app component's start method.

14:55 The handler functions are no longer top-level defns.

14:55 llasram: devn: Any processing you do on that sequence, including reducers, you just need to make sure you don't realize the whole thing into memory at once

14:55 TimMc: technomancy: I'd really like to make my own LED grow light, but to get to the point of making the necessary constant-current mechanisms I need for learnin'.

14:55 s/for/more/

14:56 mmitchell: stuartsierra: Ahh I see. Is there any example of this (a ring web app) somewhere?

14:56 stuartsierra: mmitchell: no

14:57 But it's not hard.

14:57 mmitchell: OK, I'll give it a try

15:08 dobry-den: i have a user-upload avatar system that saves avatars to "/public/avatars/custom/{{user-id}}.{{gif/png/jpg}}". even though i cache the path, i'm having trouble figuring out performance without the cache.

15:08 is it faster to try 42.gif, 42.png, 42.jpg and pick the one it finds. or is it faster to search the file-seq for a match on 42.png/gif/jpg?

15:09 Raynes: gf3: You live outside the snapchats!

15:09 gf3: Raynes: YOU HUSH


15:10 * Raynes shooshes his mouth, raynes

15:11 mdrogalis: Man, the last time you guys were talking about Snapchatting, there was a helicopter incident involved.

15:14 AeroNotix: how likely is it that Clojure would get fully preempted user space threads?

15:16 sobel: like Java's?

15:16 mdrogalis: AeroNotix: What does that mean?

15:17 lvh: I'm having some problems with clj-postal; it's reporting success with or without metadata (so SMTP server info) and in no case is any mail actually getting sent.

15:17 sdegutis: lul i trull u

15:17 sobel: given the clojure concurrency model, i am not really seeing why or how it makes sense to use a preemptive process model in clojure

15:18 AeroNotix: sobel: like Go's

15:18 sobel: Java doesn't have user space threads anymore

15:18 afaikt

15:18 llasram: AeroNotix: You mean like core.async then?

15:18 AeroNotix: llasram: no, that's cooperatively scheduled.

15:19 llasram: In what sense?

15:19 sshack: So what libraries are people using to do graphs in their web apps?

15:19 AeroNotix: llasram: you know what preemptive scheduling is, right?

15:19 sobel: sshack: http://d3js.org/

15:19 AeroNotix: If I make a go block which literally blocks, it blocks that thread completely.

15:20 ToxicFrog: llasram: basically he wants preemptive greenthreads rather than preemptive kernel threads or coroutines.

15:20 AeroNotix: ToxicFrog: exactly

15:20 sshack: sobel: Ahh, so you're just emitting json and letting the fronted take care of it?

15:20 ToxicFrog: AeroNotix: what does that get you over just using kernel threads?

15:20 sobel: sshack: bingo

15:20 AeroNotix: ToxicFrog: a lot

15:20 ToxicFrog: kernel threads are not cheap, for one.

15:20 ToxicFrog: AeroNotix: I've never used greenthreads before, so I don't know the implications

15:21 sobel: they're cooperatively scheduled

15:21 AeroNotix: e.g. in Go/Erlang a green thread is very, very small.

15:21 sobel: we've been saying this

15:21 but the preemptive scheduling is what does it

15:21 does it for me *

15:22 since it means you have no real rules about what a thread can do

15:22 sobel: are they green threads or process threads?

15:22 one is preemptive and one depends on the language vm

15:22 lvh: can someone please explain what the difference is in this example between send-message2 and send-message3? (this is a clj syntax question) https://github.com/drewr/postal/issues/22#issuecomment-5220583

15:22 AeroNotix: sobel: right, I'm asking how likely is it that clojure could have this

15:22 sobel: these things are baked into languages, so they're not trivial things to implement overnight.

15:22 llasram: AeroNotix: It's not clear to me that go employs any sort of preemptible user-level threads. Reference?

15:23 sobel: unless you are speaking strictly from the VM perspective, then i guess you can call green threads preemptive with the VM as the preemptor but i don't get the use case for making that distinction

15:23 AeroNotix: llasram: They're coming

15:23 ToxicFrog: sobel: java (and thus clojure) already supports process/kernel threads. The question is about support for green threads with preemptive scheduling, which it doesn't currently have. Java used to, but it was dropped from the JVM in 1.2, IIRC.

15:23 llasram: AeroNotix: Reference?

15:23 sobel: AeroNotix: i more than get the 'baking in' aspect.

15:23 AeroNotix: llasram: second

15:23 ToxicFrog: sobel: the distinction is that you can treat them like preemptive threads and not have to worry about whether the preemption is handled by the kernel or the VM.

15:23 stuartsierra: AeroNotix: Not exactly what you're asking, but some of the latest Fork/Join thread pools can detect blocked threads and expand the thread pool. That combined with core.async can prevent a real blocking action in a `go` block from blocking other work.

15:23 AeroNotix: llasram: https://code.google.com/p/go/issues/detail?id=543

15:24 llasram: not perfect preemption, but a start.

15:24 ToxicFrog: sobel: whereas with coroutines scheduling is handled by the coroutines themselves

15:24 AeroNotix: stuartsierra: gah what's the point of a pool (limited, bounded etc) when you just grow it?

15:25 stuartsierra: AeroNotix: I assume there are still limits, it's just slightly more flexible than a fixed-size pool.

15:25 AeroNotix: Go has a similar tactic for IO fwiw

15:25 when a goroutine blocks on IO, another kernel thread starts. AFAICR

15:26 stuartsierra: the point is, core.async isn't exactly perfect

15:27 stuartsierra: nobody said it was

15:27 AeroNotix: stuartsierra: I know :)

15:27 bbloom: it's kinda amusing to me to watch language VMs reinvent OS stuff, even when the VM designers are OS people :-)

15:27 hyPiRion: AeroNotix: I would guess that's a limitation with the JVM. (Disclaimer: I know how hard it is to predict when IO will block the thread)

15:27 sdegutis: Some days, I want to just quit programming for 20 years and come back when everything's not so insane.

15:28 AeroNotix: hyPiRion: therein is kind of my question, really. How hard does the JVM make preemption of user-space threads?

15:28 bbloom: sdegutis: add a zero

15:28 AeroNotix: bbloom: what's the alternative?

15:28 bbloom: we all just use threads?

15:28 sdegutis: bbloom: 020 years? I don't know octal.

15:28 bbloom: sdegutis: :-P

15:28 llasram: AeroNotix: Reading that issue, I believe that you have somewhat mistaken ideas about what Go is changing, and what is possible. What mechanism do you see allowing for user-level threads engaged in blocking kernel operations to be preempted?

15:28 sdegutis: Oh, 020 = 16.

15:29 stompyj: (inc bbloom)

15:29 lazybot: ⇒ 26

15:29 sdegutis: Right, that makes sense. Only 8 digits, so 8 * 2

15:29 AeroNotix: llasram: it's just a better tactic for preempting goroutines

15:29 before they were preempted just on chan blocks

15:29 sdegutis: lulul i truuul u

15:29 * sdegutis is avoiding working with some jQuery sorting stuff right now.

15:31 llasram: AeroNotix: That's my reading as well. Which is where I'm confused as to where you're getting this user-level preemptive threading thing from. If code makes a system call which blocks the kenel thread, then there's nothing you can do to preempt it

15:31 AeroNotix: llasram: it's better than just requiring everything use channels everywhere

15:31 sobel: sdegutis: it will be insane in 20 years, too.

15:31 AeroNotix: sobel: probably moreso

15:32 sobel: if the past 20 are any sort of a blunt hint

15:32 ToxicFrog: llasram: typically this is done at the VM level - the VM knows when you're making a blocking call and replaces with an asynchronous call and reschedule under the hood

15:33 sobel: my time-travel fantasy is pretty much limited to delivering a MacBook Retina to my 12 year old self

15:33 ToxicFrog: Or it just doesn't make synchronous IO available at all, or does so with a "this will break greenthreads" caveat

15:33 sobel: loaded with software, patents, stock charts, MLB scores...

15:33 sdegutis: sobel, AeroNotix: I'm not so sure of that. Professional OSes are moving towards really good architectures, the only thing holding them back is backwards compatibility, which isn't that hard a problem to solve when you have virtualization.

15:34 AeroNotix: sdegutis: which are the professional OSes/

15:34 ?

15:34 sobel: with WinXP as my example, i disagree that virtualization the problem of backward compatibility holding OSes back

15:34 sdegutis: AeroNotix: Windows 8, Mac OS X, etc

15:34 sobel: solves

15:34 technomancy: lol

15:34 AeroNotix: sdegutis: how do you know anything about their architectures?

15:35 sdegutis: Also Ubuntu.

15:35 AeroNotix: I dunno. Programming?

15:35 AeroNotix: sdegutis: but it's not kernel level hacking though is it

15:35 sdegutis: not usually, no

15:36 so?

15:36 AeroNotix: So how do you know what their architecture is like?

15:36 sdegutis: AeroNotix: I dunno. Programming?

15:36 AeroNotix: sdegutis: you keep saying that

15:36 sdegutis: No, you keep saying that.

15:36 Notte: troll...

15:36 llasram: AeroNotix: Friendly reminder: IRC is not a contest

15:36 AeroNotix: llasram: I know this

15:37 sdegutis: AeroNotix: I don't care about the kernel, I wasn't talking about the kernel.

15:37 AeroNotix: I was talking about userland libraries and available tools.

15:37 AeroNotix: sdegutis: you mentioned architecture, usually this is used with kernels. Never mind then friend.

15:37 sdegutis: AeroNotix: Also I really liked the paper I read on MS's Singularity.

15:37 dobry-den: I'm running a Compojure app behind Nginx with proxy_pass. How do you prevent the runaway spiral of users f5'ing when load is high?

15:38 sshack: sobel: So, coming from Mathematica, D3 is an utter nightmare. two pages of code to do a bilevel partition pie chart that takes one in Mathematica.

15:38 AeroNotix: dobry-den: have you had this problem already?

15:39 bbloom: sdegutis: for all the things i hate about browsers, they do provide an opportunity to escape the backwards compat nightmare when coupled with virtualization

15:40 sdegutis: at least at the user application level

15:40 sdegutis: AeroNotix: When I made my comment, I was mostly thinking of LightTable. While I kinda like the app in itself, I think it's insane that HTML/CSS/JS is the best we can do for cross-platform GUI programming right now.

15:40 dobry-den: AeroNotix: yeah. and so far my comical solution is to `sudo service nginx stop` until server catches up

15:40 AeroNotix: sdegutis: there's Qt, I've had great success with that

15:40 sshack: dobry-den: Does nginx have rate limiting?

15:41 AeroNotix: dobry-den: so what's your load? Req/s?

15:41 sdegutis: AeroNotix: True, I did have a hello-world in Qt that I haven't seriously investigated yet.

15:41 sshack: A hack, yes, but sometimes simple solutions are the best.

15:41 sdegutis: Although they dropped Qt-Jambi, which means Clojure integration won't be so pleasant.

15:41 AeroNotix: sdegutis: I used pyqt mostly, very nice. Moved some stuff to C++ from Python if you can believe it.

15:41 sdegutis: bbloom: They're their own backwards compatibility nightmare in terms of browser support.

15:42 dobry-den: AeroNotix: nginx reports 50 req/sec.

15:42 AeroNotix: dobry-den: and it dies on 50/s/?????

15:42 can anyone confirm that this is all Compojure can do?

15:42 dobry-den: yeah, there's a bottleneck i'm working on

15:43 sdegutis: llasram: yes it is and i win

15:43 * AeroNotix looks up benchmarks

15:43 sshack: dobry-den: Is it io constrained on a DB or something?

15:43 dobry-den: AeroNotix: it's a dynamic website. doesnt really have much to do with compojure

15:43 sdegutis: I also think we could do a lot better with IPC. I was impressed by Singularity's solution for a simpler and faster IPC model.

15:44 AeroNotix: dobry-den: but like.. 50/s, that's pretty poor.

15:44 sdegutis: It might make it a little more feasible to have Clojure running in the background and a C app just communicate with it over nREPL or something, for use with scripting.

15:44 dobry-den: sshack: i've found the bottleneck, i just dont want the server to get stuck in a cpu-load spiral every time

15:44 AeroNotix: yeah, well, the idea is to optimize as i go

15:44 AeroNotix: hmm ok

15:45 dobry-den: the bottleneck is actually the use of a swap! on the homepage

15:46 AeroNotix: dobry-den: huh, what for?

15:47 sdegutis: bbl

15:47 dobry-den: AeroNotix: my introspection skills are pretty poor, but it seems that my naive use of noir.util.cache will make everyone halt on the homepage when any of the cache! are invalidated

15:48 i've been replacing it with a simpler atom where a cache recomputed in another thread (scheduled)

15:48 AeroNotix: dobry-den: what are you caching?

15:49 dobry-den: AeroNotix: it's a forum homepage. so the latest-post of each forum, forum stats, total-posts in each subforum.

15:49 AeroNotix: dobry-den: ever heard of memcached?

15:49 or redis

15:49 dobry-den: well, that's unnecessarily complexity that doesn't address this particular problem

15:50 AeroNotix: Oh I assure you it will

15:50 dobry-den: i believe the problem is that the recalculation function is inside the swap! that the user has to wait on

15:51 i've fixed it by scheduling the swap myself and letting all users simply deref it, which is how it should be for such trivial cache

15:52 AeroNotix: dobry-den: what's the calculation?

15:53 dobry-den: it makes a db call and there seems to be some sort of blocking contention when multiple people land on an invalidated homepage

15:54 AeroNotix: dobry-den: depending on the application you can forgo atomic changes, if the later calculations don't depend on the previous ones...

15:54 e.g. "latest forum post"

15:54 stompyj: Is it terrible practice to have a configuration namespace where you declare vars that other namespaces may need?

15:54 AeroNotix: you'd just use memcache and overwrite a key

15:54 stompyj: (trying to get myself out of circular dependency hell)

15:54 AeroNotix: and cache the ARSE out of that

15:55 because you only need to invalidate the cache when new posts are created, I'd have middleware on the routes which create posts to invalidate caches.

15:55 because if you're using TTL, it's just stupid

15:55 hiredman: yes

15:56 stratify your code

15:56 dobry-den: AeroNotix: right, i invalidate the cache on new posts. but it seems better to swap the new latest-post myself instead of make users trigger it

15:56 dsrx: move your code into the highest strata - rewrite it in Haskell

15:56 dobry-den: but i dont see how it matters if i use memcached, redis, or an atom.

15:57 AeroNotix: dobry-den: then test it

15:57 dobry-den: I don't see anywhere where you mentioned testing

15:57 dobry-den: well, i didnt even mean to talk about the issue because it actually turns out i dont need to cache it (the cache introduced a block). i was just asking about nginx

15:59 sdegutis: gfredericks: you guys ever file that speclj bug?

16:00 dobry-den: AeroNotix: funnily enough, the only reason i hastily cached it (incorrectly) was because i was hastily trying to resolve a load issue that was actually caused by -- wait for it --- running lein-ring in dev mode

16:00 AeroNotix: ah

16:00 dobry-den: which i dont recommend

16:01 AeroNotix: i didnt even know dev mode was a thing

16:02 arohner: is there a library/trick for generating ring session cookies, for use w/ clj-http cookie-store?

16:03 I would like to directly add cookies to clj-http, that look like they've been signed by ring

16:04 hiredman: isn't the whole point of signing cookies to avoid that?

16:07 akurilin: For my integration tests I just have a couple of hardcoded cookies lying around

16:08 AeroNotix: same

16:08 akurilin: I think there might be an issue with generating cookies procedurally on machines that don't get a lot of entropy

16:08 my dev boxes can get stuck waiting for entropy for something like 10s

16:09 stuartsierra: akurilin: This can be a problem in virtualization containers.

16:10 akurilin: stuartsierra: what's an example?

16:10 stuartsierra: akurilin: dunno, just heard that as conventional wisdom

16:11 akurilin: I remember filing a bug against ring about those stalls back in the day and weavejester pointed out it was nothing he could do on his end.

16:11 I still need to come up with a way of bypassing this issue in my integration test suite :(

16:11 stuartsierra: fair enough

16:14 So, mixing dosync and clojure jdbc transactions can be potentially a bad idea, huh?

16:14 stuartsierra: akurilin: Yes. JDBC is a side effect. Don't put side effects in dosync transactions.

16:15 akurilin: I have a shared map in memory that I want to run some checks against and then runthe transaction (which can also fail)

16:15 meaning that ideally I could roll back both

16:15 shep-werk: akurilin: if you can guarantee that that machine is only used for tests, you could probably set a kernel option to use a PRNG instead of a crypto-hard one

16:15 which might be easier in a virtualized env

16:16 akurilin: shep-werk: this is pretty much exclusively on my dev machine which is on bare metal, I think the issue is that I might not have enough network traffic to it to generate enough entropy

16:16 arohner: hiredman: this is for integration tests. I want to set up the ring session in a certain state, and then bang on the server

16:16 akurilin: shep-werk: but yeah that's a good idea, I'll try that perhaps

16:17 arohner: hiredman: looks like it's not too hard to reach into the ring middleware, I was just checking if there was a lib to do this already, because I remember a few ring / clj-http testing libs

16:18 akurilin: Regarding the dosync / jdbc transaction issue: it seems that the least error prone way would be to start a JDBC transaction, do all the DB operations without committing, then run the dosync and use the result of it to decide whether to rollback JDBC or not.

16:18 Which sounds incredibly convoluted, but probably isn't.

16:20 stuartsierra: akurilin: yes that should work

16:21 shep-werk: akurilin: if it's your dev machine i'd be surprised - I'd expect keyboard / mouse input to also go into entropy pool

16:21 unless you enter code by force of will ;-)

16:24 akurilin: stuartsierra: thanks for confirming, apprecaited.

16:24 *appreciated

16:25 shep-werk: yeah I really need to find time to drill deeper into what exaly is stalling in the process, have yet ot figure out how to "break" in clojure

16:25 to see what's waiting

16:26 shep-werk: akurilin: just do a JVM thread dump :-)

16:27 akurilin: shep-werk: any particular tools you'd recommend?

16:28 shep-werk: TBH, I haven't done much specific to Clojure, but I'd start with just sending a SIGQUIT to the JVM when it's slow and browse the result

16:29 or use something like (J)VisualVM and attach to it

16:30 gfredericks: sdegutis: not that I know of

16:30 sdegutis: my coworker writes it, so i may be able to help get the ticket some attention

16:32 gfredericks: sdegutis: okay, I'll probably pull one together

16:33 sdegutis: it would basically involve reverting an earlier accepted PR

16:33 sdegutis: gfredericks: make sure to put in the explanation for what bug it caused

16:33 he's understanding, but very skeptical and untrusting of anyone but himself.

16:34 (he said this himself; i am not slandering)

16:34 in other words, be sure to give a good argument that it really did cause the bug you saw

16:34 gfredericks: oh I wonder if that approach means running with an old version of clojure?

16:38 indeed it does

16:38 how does that not damn it all by itself?

16:41 oh technomancy commented on the original PR

16:49 technomancy: "technomancy will yell at you unless you revert this commit" <- good argument?

16:49 ddima_: depends on how badly you can yell

16:49 sdegutis: technomancy: doubtful, unless you also wag your finger

16:49 in which case maybe

16:49 gfredericks: sdegutis: https://github.com/slagyr/speclj/issues/7

16:49 E

16:49 um

16:49 https://github.com/slagyr/speclj/issues/78

16:50 is what I failed to paste somehow

16:50 sdegutis: Thanks.

16:50 technomancy: sdegutis: I can do M-x look-of-disapproval if that helps

16:51 sdegutis: gfredericks: most excellent, theophilus. thank you.

16:51 AeroNotix: technomancy: so lame, I have that on C-x M-l d

16:51 brehaut: hiredman: what was the aphyr video you were talking about yesterday?

16:51 technomancy: AeroNotix: hehe

16:51 sdegutis: AeroNotix: why not just have it auto-run inside init.el and save time

16:52 AeroNotix: SERIOUSLY though (= (+ :clj-refactor :cider-mode) :omfg-amazing)

16:52 sdegutis: one needs to do it on demand

16:52 sdegutis: AeroNotix: i'd try it but my setup is pitifully fragile

16:53 AeroNotix: sdegutis: Why?

16:53 I *do* spend a lot of time on my .emacs stuff

16:53 https://github.com/AeroNotix/dotfiles/blob/master/.emacs

16:54 sdegutis: AeroNotix: why is mine fragile?

16:54 technomancy: if it were scheme I'd recommend switching all your parens to []

16:54 more structurally stable

16:56 sdegutis: AeroNotix: last time i tried to upgrade a dep from melpa, it broke and was a pain to revert. this is cuz melpa builds off master, which is a bad idea. so i stopped using melpa and froze my dependency graph in fear of breaking anything else.

16:56 AeroNotix: sdegutis: yes

16:56 sdegutis: put your .emacs/.emacs.d into a repo

16:56 I regularly just rm -r elpa/* stuff just to see what breaks

16:56 sdegutis: AeroNotix: also, any time i touch my init.el i get sucked in for hours. constantly changing, reverting changes, trying new things, etc. its a black hole of experimentation.

16:56 AeroNotix: sdegutis: Yes, this is emacs.

16:57 sdegutis: its in a repo already.

16:57 but i took it off github cuz no one wants to see that stuff. its like underwear.

16:57 AeroNotix: sdegutis: nah, the guys at work usually steal stuff from mine, and I theirs.

16:58 technomancy: sdegutis: melpa is fragile by design

16:58 sdegutis: AeroNotix: i have no "the guys at work". nobody knows about my github repos. im the only employee in this company, i work from home, sole developer on this project.

16:58 technomancy: yes.

16:58 technomancy: do not want

16:58 sdegutis: the only dependency manager ive seen done well is whatever leiningen uses.

16:59 AeroNotix: technomancy: it's better than what it was

16:59 technomancy: sdegutis: aether still screws up version ranges pretty badly

16:59 but that's relatively easy to avoid

16:59 well... it took a couple years, but we mostly squashed the issues

16:59 sdegutis: ive had a lot of trouble with pip and bundler. havent used npm so cant say much there.

17:00 and i refuse to use cocoapods on principle (its not ruby dangit, its objc!)

17:00 AeroNotix: one must say that I'm postively happy about lein. It Just Works.

17:00 end of story.

17:00 sdegutis: only one i havent had trouble with is whatever leiningen uses (nobody knows what its called)

17:00 AeroNotix: Coming from Erlang/Rebar+Python/PIP it's a whole new world.

17:00 jacortinas: sdegutis: Maven?

17:01 sdegutis: no, clojars

17:01 or whatever

17:01 zerokarmaleft: npm got a lot of things right

17:01 technomancy: jacortinas: Maven and Leiningen both use Aether

17:01 jacortinas: ah ok

17:01 sdegutis: oh, aether.

17:01 insamniac: make up your mind!

17:01 sdegutis: why not name it Dragicorn?

17:01 technomancy: zerokarmaleft: having JS modules be first-class data structures helps a lot there

17:01 (the one thing JS does better than clojure)

17:02 sdegutis: http://bit.ly/1nrYLp0

17:02 insamniac: This channel makes me feel dumb all day.

17:02 sdegutis: insamniac: isnt it awesome?

17:02 technomancy: sdegutis: you can suggest a rename: https://bugs.eclipse.org/bugs/buglist.cgi?query_format=specific&order=relevance+desc&bug_status=__open__&product=Aether

17:02 insamniac: It's refreshing, but I kind of like feeling like a hero at work all day too.

17:02 sdegutis: cant.

17:03 technomancy: sdegutis: you can if you believe in yourself

17:04 * sdegutis walks away

17:04 insamniac: You forgot to drop the mic.

17:04 sdegutis: ha

17:04 back to manipulating the DOM directly via clojurescript

17:05 * sdegutis glares at modern technology

17:05 * sdegutis winces as modern technology glares back

17:05 technomancy: modern technology is getting to the point where it can glare back

17:05 dammit

17:05 sdegutis: ha

17:05 insamniac: anyone here use parkour?

17:05 we have some hadoop project coming up

17:06 bbloom: technomancy: javascript's modules are only first class because javascript doesn't have anything even approaching modules

17:06 technomancy: it's easy to make something first class if it's also practically useless :-P

17:07 ddima_: insamniac: no idea about parkour, but another solid alternative would be cacalog

17:07 err, cascalog

17:07 rhg135: modules are maps there

17:07 technomancy: bbloom: well, there's a silver lining to that cloud

17:07 insamniac: i like caca log

17:07 ddima_: it's the best

17:07 insamniac: i just mean i like the typo. never heard of it!

17:08 I won't be able to sell anyone on using anything but Java probably anyhow.

17:08 ddima_: i knew you meant the typo :)

17:08 insamniac: i knew you knew i knew

17:08 ddima_: insamniac: once they see what a job of moderate complexity looks like in java they will at least go for pig probably

17:09 one could use cascading though, but then jumping to cascalog is not a big step anymore. It's not that pig is much easier to grasp than some clojure dsl.

17:12 * seangrove sighs

17:12 seangrove: Wish there was a gofmt for clojure

17:12 erm, and cljs

17:14 hyPiRion: but there is

17:15 seangrove: alias cljfmt='emacs --batch -l ~/.emacs.d/init.el --eval='(clojure-mode)' --eval='(indent-region (point-min) (point-max) nil)' -f save-buffer'

17:15 locks: and I bet it’s even customizable

17:15 seangrove:

17:15 hyPiRion: Clever. But not all the way there

17:16 * xuser needs to learn the powez of emacz

17:16 seangrove: Also looking to enforce things like "one line of separation between defs"

17:18 technomancy: knowing where to add \n can be tricky too

17:18 sshack: Are there any tutorials.examples of web apps using friend with an sql backend?

17:18 arkh: anyone know what causes the following on perfectly valid ns syntax: "ArityException Wrong number of args (2) passed to: namespaces$import-fn clojure.lang.Compiler.macroexpand1 (Compiler.java:6473)"

17:19 in one project, it give me that error but in another project, essentially the same syntax, it doesn't error

17:19 *gives

17:21 turbofail: it'd probably help if you showed us the syntax

17:22 arkh: (ns foo.bar.baz (:use [vertigo.structs]))

17:23 from 'lein repl', if I (load-file "src/foo/bar/baz.clj) I get that error but not in another project

17:23 sorry ... long day and it makes no sense

17:35 hiredman: brehaut: it was basically a recap of his strangeloop presentation, with a little more focus on cassandra

17:35 brehaut: hiredman: thanks

17:38 bbloom: dnolen: do you know of a handy list of X where there exists a CLP(X) ?

17:39 dnolen: bbloom: hmm, I don't - and people implement new domains fairly regularly

17:39 bbloom: dnolen: i figured that they did, but i was hoping to see a list of like "here's ones that people agree are generally worth studying or knowing of"

17:40 tbaldridge: CLP(all-the-things)

17:40 bbloom: a friend of mine is doing some procedural generation for a game & he's trying to improve the uniqueness of the results without creating totally alien impossible things

17:41 i was wondering if CLP of some sort might be helpful

17:44 * sdegutis was going to do a coin toss to figure out whether learn Haskell or OCaml, but then thought, why not both?

17:44 seangrove: Who's generally taking care of clojars these days? I suppose it's not the same burden as npm given it's able to ride off of maven repos, but it still seems like npm struggles *a lot* more

17:45 bbloom: seangrove: npm struggles for a few reasons 1) a totally unscalable design 2) massive abuse of a central repository (seriously people, host your own packages for production) 3) crazy unjustified popularity of javascript ... etc

17:46 stompyj: I think the difference is that clojars is written in clojure, and npm is written in node *cough*

17:46 jk

17:46 bbloom: stompyj: lol but no seriously, you're not that far off

17:46 technomancy: bbloom: no, it is

17:46 it's the difference between couchdb and nginx

17:47 brehaut: couchdb O_O

17:47 bbloom: technomancy: sure

17:47 technomancy: actual downloads of packages don't hit any dynamic code in either case

17:47 brehaut: it actually makes mirroring really easy

17:47 but no one uses mirrors because it's easier to just hammer the central repo

17:47 brehaut: technomancy: win!

17:50 sdegutis: technomancy: btw, have you seen that guy's response to your response to my response on HN about the problem with Marmalade?

17:51 https://news.ycombinator.com/item?id=7114490

17:51 technomancy: sdegutis: somehow I remain unconvinced =)

17:52 actually that's crap anyway; with marmalade you try to get teh original authors to submit too

17:52 sdegutis: seems like a major flaw to me, that anyone can push to any given marm package

17:52 technomancy: yeah, if someone squats on a package with a fork and the original author comes along, the marmalade guy will give them the name

17:53 sdegutis: oh

17:53 bbloom: #3 is totally right on

17:54 in it self it just mystifies me

17:54 bbloom: i mean, node has its (limited) uses & i'm glad it exists and is maturing

17:54 i'm just glad that other suckers are trying to build scalable infrastructures on it so that my puny use cases for it aren't problematic

17:55 seangrove: bbloom: Hrm, what're your use cases?

17:55 * seangrove remains skeptical

17:55 technomancy: the npm guys don't really understand couch all that well either

17:55 brehaut: technomancy: being one of the people melpa crapped on, i agree with your position ;)

17:55 technomancy: they were putting password hashes in unprotected fields for years, and then also http://writing.jan.io/2013/12/19/understanding-couchdb-conflicts.html

17:55 bbloom: seangrove: pretty much just builds for front end code

17:56 seangrove: bbloom: Ah, so compilation tooling, more or less?

17:56 technomancy: well, they didn't understand it when they originally designed it. they probably understand it better now.

17:56 bbloom: seangrove: primarily, which also includes to a limited extent something like react-page

17:56 seangrove: https://github.com/facebook/react-page

17:56 seangrove: but there are alternatives that are preferable there: like clojure + clojurescript

17:57 sdegutis: brehaut: you mean you were bit by it too?

17:57 brehaut: sdegutis: i was part of the stream of people technomancy helped because i had melpa in my config when i didnt want it

17:57 sdegutis: :)

17:57 was this back when Magit broke?

17:57 technomancy: "My Emacs is broken" / "Are you using melpa?" / "Yes" / "Well then."

17:58 sdegutis: i was bit hard by that.

17:58 technomancy: ^ basically a weekly theme either in here or #emacs

17:58 brehaut: technomancy: followed by "what is melpa?"

17:58 technomancy: brehaut: those are the worst, yeah =/

17:58 brehaut: technomancy: sorry :(

17:58 technomancy: brehaut: not your fault

17:58 sdegutis: Another reason I don't touch my init.el is because I'm afraid of breaking muscle memory.

17:58 technomancy: brehaut: it's people putting "just copy/paste this snippet into your config" in their readme without explaining it

17:59 sdegutis: For example, newer versions of Magit changed the shortcuts, so it's doing all sorts of things I don't expect or even want.

17:59 brehaut: technomancy: weell, i should know by now not to just cargo cult

17:59 sdegutis: brehaut: cargo-culting is a legitimate and time-honored way to get started with emacs

17:59 deadghost: cargo culting is a good way to begin in a lot of things

17:59 brehaut: sdegutis: and still wrong ;)

18:00 technomancy: I think it's feasible to limit the cargo-culting to "install this set of packages"

18:00 sdegutis: brehaut: it's impractical to start learning everything about how emacs works when you're just getting started. You just copy bits/pieces from other people's configs that make your stuff work right, and learn why afterwards.

18:00 technomancy: if you install packages one at a time, you'll have a better chance of understanding what each one does

18:00 deadghost: 1. start using something 2. decide it sucks 3. recur

18:01 sdegutis: Speaking of deleting repos, does anyone want to fork https://github.com/sdegutis/LVReplClient ?

18:01 technomancy: deadghost: catch StackOverflowException -> become a carpenter

18:01 AimHere: Maybe there should be an emacs-from-scratch install, where it just gives you the lisp interpreter and the minimal set of lisp things and tells you to built it yourself from then on

18:01 technomancy: AimHere: no, start with SKI

18:01 or maybe logic gates

18:01 brehaut: technomancy: SKI is for lazy people. Start with SK

18:02 sdegutis: I really want to see an Emacs Reboot.

18:02 technomancy: brehaut: touché

18:02 sdegutis: Like, a minimalist program with a similar language to Emacs Lisp, and a similar API for handling text, but with less 1980s baked in.

18:02 seangrove: sdegutis: It's pronounced "LightTable", I believe

18:02 bbloom: lol

18:03 seangrove: sdegutis: It just needs another decade or so to fully form

18:03 technomancy: sdegutis: rms goes back in time and prevents his past self from writing a lisp-2, creating an alternate timeline in which elisp is actually not a terrible language for doing FP

18:03 except there are romulans and stuff

18:03 turbofail: needs moar borg

18:03 deadghost: I'd watch that movie

18:03 sdegutis: seangrove: Something about compiling Lisp into JS and running it inside a WebView just makes me feel all weird inside.

18:03 brehaut: technomancy: how could you tell which is evil RMS though? the tiny beard is going to be lost in wild hill man beard

18:04 or does the beard have a beard?

18:04 technomancy: brehaut: mind_blown.gif

18:04 AimHere: RMS is beard all the way down

18:04 seangrove: sdegutis: Well, give it time

18:04 sdegutis: seangrove: I thought the ClojureScript route was only for prototyping, and then it suddenly became the official thing. That confused me.

18:05 technomancy: sdegutis: it sounds like embracing the madness of the modern stack instead of staunchly insisting on DTRT

18:05 sdegutis: seangrove: Plus I'm very skeptical of any API design. But simpler always seems better, and LT's API seems complex right off the bat.

18:05 technomancy: problem is that staunchly insisting on DTRT leads you to either loper-os or opengenera

18:05 dnolen: sdegutis: it's actually an incredibly simple system.

18:06 sdegutis: dnolen: Oh? Can you recommend a specific write-up describing it?

18:06 dnolen: sdegutis: http://www.chris-granger.com/2013/01/24/the-ide-as-data/

18:06 sdegutis: writing a hello world plugin is ridiculously easy

18:06 sdegutis: dnolen: Sweet.

18:07 dnolen: sdegutis: all the hard stuff is interacting with Node, WebKit, CodeMirror

18:07 sdegutis: My only other objection was arrogance (I didn't write the IDE myself) and that one has to go cuz it ain't founded in any kind of sanity.

18:07 arkh: I finally have my problem down to the simplest case: 1) do a 'lein new baz' 2) in your new project.clj, add as dependencies [aleph "0.3.0"] and [vertigo "0.1.1"]. 3) make this the contents of your src/baz/core.clj "(ns baz.core (:require [vertigo.structs :as vs]))" 4) breaks when loaded

18:07 sdegutis: dnolen: That sounds kinda painful. I've been writing ClojureScript interacting with the DOM this afternoon and it's not pleasant at all, even with Dommy.

18:08 seangrove: sdegutis: It also seems like ibdknox's approach of allowing plugins to fundamentally change anything means it'll grow along the lines of emacs

18:08 technomancy: drracket might qualify on the "staunch dtrt" front actually

18:08 reading about racket's approach to image handling just made me sad about quil

18:08 dnolen: sdegutis: Dommy doesn't really try to fix anything, nor does LT fundamentally

18:08 sdegutis: try React, Reagent, or Om for something more sensible

18:08 sdegutis: dnolen: Sounds like it needs some good third party wrapper APIs.

18:08 Oh.

18:09 Thanks for the recommendations, I'll check them out dnolen.

18:09 TEttinger: arkh, what kind of breaks?

18:09 arkh: TEttinger: ArityException Wrong number of args (2) passed to: namespaces$import-fn clojure.lang.Compiler.macroexpand1 (Compiler.java:6473)

18:10 seangrove: We should probably find someone local who can talk on reagent

18:10 Then we can divide the next meetup into three talks: React, Om, Reagent

18:10 arkh: Tettinger: I did a (load-file "src/baz/core.clj") at a repl

18:10 dnolen: Hoplon looks cool too, though I haven't looked at it closely enough to understand how you model components or if the model more less obviates them

18:11 insamniac: s/re le/re or le/

18:12 sdegutis: technomancy: dtrt = do the right thing?

18:12 TEttinger: arkh, I'll try to reproduce

18:12 arkh: Tettinger: awesome!

18:12 sdegutis: technomancy: opengenera exists!?

18:13 technomancy: yeah

18:13 clojurebot: DTRT is do the right thing

18:13 clojurebot: In Ordnung

18:13 technomancy: opengenera ... mostly exists?

18:16 TEttinger: arkh, I can reproduce.

18:16 ztellman: arkh Tettinger: this is my fault?

18:16 TEttinger: I am guessing it's a problem in a lib

18:17 ztellman, is vertigo yours?

18:17 ztellman: yup

18:17 TEttinger: I guess I should have checked the google ads

18:17 arkh: ztellman: I was going to try to contact you next : )

18:17 ztellman: vertigo is one I haven't used in a production context yet

18:17 arkh: TEttinger: thank you for trying it

18:17 ztellman: just a sec

18:17 TEttinger: no prob arkh

18:19 ztellman, it looks like you need a new version! https://github.com/ztellman/vertigo/compare/0.1.1...master

18:20 ztellman: TEttinger: coming to that conclusion, yeah

18:20 TEttinger: or could arkh use the snapshot, is it published?

18:22 ztellman: 0.1.2-SNAPSHOT should be there, but it's also marginally out of date

18:25 aperiodic: technomancy: what were you reading about racket's image handling that made you sad about quil?

18:25 technomancy: aperiodic: the first chapter of htdp.org, oh man

18:26 it starts with numbers and how to do arithmetic

18:26 then it goes on to strings and how to append them, upper-case them, etc

18:26 but how they're all just values you call functions on

18:26 then it's all «oh yeah, and you can do "arithmetic" with images too»

18:27 they're first-class values that display in the repl; you can compose them like data

18:27 quil is all "here's a function to draw a line on the screen" or whatever; very imperative and primitive =\

18:27 hiredman: overloading math :(

18:27 technomancy: hiredman: it doesn't overload the actual symbols

18:28 it's just a way of saying "these are all values you can do things with"

18:28 aperiodic: yeah, i understand pragmatically the motivation to build on top of processing, but it's basically impossible to escape its imperative paradigm

18:29 everything you do is a side-effect on a graphics buffer

18:32 sdegutis: "oh, camel! you so silly!"

18:32 arkh: ztellman: looks like vertigo 0.1.2-SNAPSHOT does the same. I'll just have to wait for the next version! Thank you

18:32 sdegutis: I don't think there's actually a topic for this channel, right? It's just kind of like, in-general programming-ish, right?

18:33 technomancy: sdegutis: maybe you're thinking of #emacs

18:33 this was the "argue about haskell" channel until like a week ago

18:33 sdegutis: When will it be the argue-about-ocaml channel?

18:33 arkh: I thought that was just that one guy, instigating problems

18:33 technomancy: arkh: well yes

18:35 TimMc: eternal haskember

18:36 * technomancy glances at the /topic

18:37 TimMc: hahaha

18:40 I should really have irssi write my logs file-per-day

18:40 My log for this channel is over 1000000 lines long.

18:41 xuser: so bitemyapp finally ditch clojure for haskell?

18:42 `cbp: I believe he uses clojure at work

18:43 sdegutis: But Haskell is more fun.

18:43 `cbp: ~guards

18:43 clojurebot: SEIZE HIM!

18:44 sdegutis: I started reading Learn You a Haskell, and so far it's just Clojure, but without parentheses, and everything is wrapped in an implicit (fn ...)

18:45 Raynes: You haven't read much then.

18:45 sdegutis: Oh right, it also does static typing.

18:54 AeroNotix: sd

19:04 ztellman: arkh: try vertigo 0.1.3

19:04 0.1.2 was tragically lost in a dependencies mishap

19:11 TEttinger: same error ztellman

19:11 ztellman: !

19:11 TEttinger: I'll try cleaning first?

19:12 it's an arity issue still.

19:12 ArityException Wrong number of args (2) passed to: namespaces$import-fn clojure.lang.Compiler.macroexpand1 (Compiler.java:6473)

19:12 ztellman: why is the test suite not catching that

19:12 ok, back to the drawing board

19:14 TEttinger: oooh

19:15 ztellman, if I use the ns that requires vertigo.structs (might have spelled it wrong): Exception namespace 'vertigo.primitives' not found clojure.core/load-lib (core.clj:5380)

19:15 ztellman: ...

19:16 I mean, it's there

19:16 that's also something which uses import-fn, so maybe it's related

19:23 arkh: ok, figured out your issue, which wasn't the one I was tracking down

19:23 add [potemkin "0.3.4"] to your depdnencies

19:23 `cbp: Man I thought compiling c was hard but then i stumbled upon clojurescript

19:23 ztellman: or exclude potemkin from the aleph dependencies

19:24 mikerod: Haskell is just like Clojure, without all of the awesome

19:25 `cbp: without all of the java? ;)

19:25 mikerod: i.e.: (remove the-awesome Clojure) ;= Haskell

19:25 egghead: huh...

19:25 mikerod: just joking, I don't know enough to say that :)

19:25 technomancy: (remove NullPointerException Clojure)

19:25 brehaut: remove the-awesome Clojure #= haskell ;)

19:25 egghead: mikerod: clojure is just like haskell.. without all the types?

19:25 mikerod: technomancy: that was a good one. haha

19:27 tjd: i'm looking for a way to "map

19:27 "map" a hash map, something like (defn f [k v] [k (+ v 1)]) then (map f {:a 1 :b 2}) and have the result be {:a 2 :b 3}

19:28 `cbp: Am I missing something? I can't seem to find docs for cljs compiler options

19:31 TEttinger: tjd, I think that's kvmap?

19:33 tjd: TEttinger: i can't find taht in standard library

19:34 TEttinger: yeah I was confused

19:34 you can map over hashmaps, it just has entries

19:34 tjd: ##(letfn [(f [[k v]] [k (+ v 1)])] (map f {:a 1 :b 2}))

19:34 lazybot: ⇒ ([:a 2] [:b 3])

19:35 tjd: yeah, and i can reconstitue the result of that map into a hashmap, its just kind of a pain in the butt

19:35 TEttinger: tjd: ##(letfn [(f [[k v]] [k (+ v 1)])] (into {} (map f {:a 1 :b 2})))

19:35 lazybot: ⇒ {:a 2, :b 3}

19:35 whilo: `cbp: have you had a look at: https://github.com/clojure/clojurescript/wiki/Quick-Start ?

19:36 mikerod: ,(into {} (map (juxt key #(inc (val %))) {:a 1 :b 2}))

19:36 clojurebot: {:a 2, :b 3}

19:36 mikerod: (into {} (map (juxt key (comp inc val)) {:a 1 :b 2}))

19:37 ,(into {} (map (juxt key (comp inc val ) {:a 1 :b 2}))

19:37 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

19:37 whilo: ztellman: at euroclojure we talked briefly. with critical theory and frankfurt school i meant especially http://books.google.de/books?id=l-75zLjGlZQC&printsec=frontcover&hl=de#v=onepage&q&f=false

19:37 TEttinger: you could just declare a function that does this. (fn [f coll] (into {} (map #(f (first %) (second %)) coll)))

19:37 mikerod: ,(into {} (map (juxt key (comp inc val)) {:a 1 :b 2}))

19:37 clojurebot: {:a 2, :b 3}

19:37 whilo: don't know if you know it, just for reference

19:38 TEttinger: ,(defn map-map [f coll] (into {} (map #(f (first %) (second %)) coll)))

19:38 `cbp: whilo: yeah. I still can't figure out how to add .js libraries though

19:38 clojurebot: #'sandbox/map-map

19:38 tjd: awesome!

19:38 i learned something

19:38 `cbp: (even though they're supposed to work with closure)

19:38 TEttinger: ,(map-map + {1 10 2 20})

19:38 clojurebot: #<ExceptionInfo clojure.lang.ExceptionInfo: Don't know how to create ISeq from: java.lang.Long {:instance 11}>

19:38 TEttinger: uhhhh I might have screwed up

19:39 mikerod: tjd: my example was just trying to use all built ins to do the job

19:39 whilo: `cbp i am not very experienced. the easiest i found was to include the js somewhere on the html page, use whitespace compilation and exploit the fact that symbols are not munged, so you can reference js objects just by their name

19:40 if your js library supports google closure you can compile it in, there was fairly little information on that. the easiest is to grab (or create) some extern file for your library, reference that once you move from whitespace compilation to optimized js

19:40 mikerod: ,(reduce (fn [m [k v]] (assoc m k (inc v))) {} {:a 1 :b 2})

19:40 clojurebot: {:b 3, :a 2}

19:41 sdegutis: AeroNotix: Yes?

19:43 mikerod: or maybe (->> clojure :features (remove awesome?))

19:43 tjd: thank you mikerod and TEttinger. i'm still learning and stuff like this really helps. cheers.

19:43 mikerod: sdegutis: indeed :P

19:46 TEttinger: ah, here we go.

19:46 ,(defn map-map [f coll] (into {} (map (fn [[k v]] [k (f v)]) coll)))

19:46 clojurebot: #'sandbox/map-map

19:46 TEttinger: that one takes a function and a map, calls the fn on each value of the map, and keeps the same keys

19:47 there's a way to do that with juxt too, but it's uh not as easy

19:47 devn: suggestions on how to do this more efficiently: https://gist.github.com/devn/cf948a57216bb8eb83c6

19:48 the ref need not be there, fwiw

19:48 this is a CSV file that is around 200MB

19:48 I want to very quickly find all distinct values for each column within that file

19:49 TEttinger: devinus, hm? (dosync (alter r assoc header-name distinct-vals)) is at the last line, and r is the ref?

19:49 ^ devn

19:49 devn: r is the ref there, yes

19:49 but i mean, try and use reducers, whatever

19:49 TEttinger: oh ok

19:49 devn: i dont care how i do it, but i've been playing with solutions and am hitting a roadblock

19:50 I think maybe loading this into a database is a requirement

19:50 llasram: devn: Do you known that all distinct values for all columns will fit into memory?

19:50 TEttinger: well are you sure of what the core.data.csv fns return?

19:50 devn: llasram: I do not.

19:50 My motivation for writing this is: I have 100 CSV files, from 1k to 1.2GB

19:51 I know for a fact there are relationships between the data, but they are fuzzy connections

19:51 llasram: devn: Also, trying to create a lazy seq which holds on to resources and releases them when the seq is exhausted pretty much guarantees that you'll have resource leaks

19:51 devn: the column names do not match, for instance

19:52 so I want to accrete all the discrete values for each colum, and when the number of discrete values for a column is more than 90% of all values found for a column (excluding empty? vals)

19:52 so I can try and test whether or not they're related CSV files

19:52 to find a common unique value between them

19:52 to basically sniff out "ID"-esque columns

19:53 llasram: yeah, im finding this out. again, looking for suggestions on a good approach

19:54 TEttinger: I'm not realizing the core.data.csv result

19:54 I'd have to do (doall ...) around it to realize it

19:54 im running with Xmx2g and -server

19:54 TEttinger: I actually wrote my own (tab) separated value parser not long ago.

19:55 it wasn't hard

19:56 devn: yeah, it really isn't, but i've looked at core.data.csv and it looks fine

19:56 i dont think that's where the problem is

19:57 llasram: devn: Actually taking a look at your code, you are definitely forcing the whole CSV to be realized in memory at once

19:58 You bind the CSV to `rows`, then in the `doseq` iterate by column. After you finish the first column, `rows` can't be cleared (because you need it for the next column), but has been fully realized (because you've walked all the rows)

19:58 devn: llasram: that used to be a for

19:59 the doseq

19:59 llasram: Same problem

19:59 You still need to realize the entire CSV in order to produce the results for a single column

19:59 devn: right, because i need distinct values

19:59 llasram: You need to structure your code so that you walk the CSV row-wise, holding only a single row at once, and accumulating the results for all columns at the same time

19:59 devn: ah, i see

19:59 right that makes sense

20:00 so i should reduce over it maybe

20:00 and check whether i have that value or not

20:00 and then continue walking

20:00 llasram: Or just add to sets

20:00 devn: yeah, good idea

20:00 thanks llasram. much appreciated.

20:00 llasram: np and good luck

20:04 ztellman: whilo: thanks, I'll give it a look

20:04 kristof: All this talk about walking csv's feels eerily familiar

20:07 turbofail: also make sure you don't hold on to the CSV sequence's head anywhere. if it's in a local variable, that will force the whole thing to remain in memory

20:07 devn: kristof: :)

20:08 kristof: devn: Was that you?

20:08 A few days ago, maybe a week ago

20:08 devn: kristof: i have a TON of legacy data I'm trying to form relationships between

20:08 kristof: Legacy code SUCKS, YUCK

20:08 devn: kristof: perhaps. i've been mucking around with csv transformations

20:08 kristof: it's kind of fun FWIW

20:08 just daunting

20:08 which is why i want to write a tool to do this

20:09 kristof: devn: Give me an example of what you're doing

20:09 devn: a.csv is a 500MB file of information, like first name, last name, a, b, c, d, e, etc.

20:10 e is actually concatenated from a c d, it serves as a key

20:10 in all other tables, i want to check to see if the value in e exists, and if it does, i want to form a relationship to that table from my table+column, to its table+column

20:11 kristof: ^

20:11 safety: is there a way to get a running total of a vector without using loop? e.g. [1 2 3] -> [1 3 6]

20:12 devn: safety: reductions

20:12 safety: not sure how to reduce to a vector

20:12 kristof: into

20:13 er

20:13 turbofail: ##(into [] (reductions + [1 2 3]))

20:13 lazybot: ⇒ [1 3 6]

20:13 kristof: "reducing to a vector" makes no sense. reduce is a mapping from a collection of a's to an a

20:13 or some b, actually

20:13 ah right reductions

20:13 technomancy: whut

20:13 safety: turbofail: thanks!

20:13 kristof: technomancy: where's the what coming from

20:13 devn: ,loop

20:13 clojurebot: #<CompilerException java.lang.RuntimeException: Can't take value of a macro: #'clojure.core/loop, compiling:(NO_SOURCE_PATH:0:0)>

20:13 devn: whoops

20:13 ,([] [1] [1 2] [1 2 3] [1 2 3 4] [1 2 3 4 5])

20:13 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (5) passed to: PersistentVector>

20:14 devn: ahhh!

20:14 ,(reductions (fn [res x] (conj res x)) [] [1 2 3 4 5])

20:14 clojurebot: ([] [1] [1 2] [1 2 3] [1 2 3 4] ...)

20:14 technomancy: "reduce is a mapping from a collection of As to an A"

20:14 kristof: technomancy: corrected in the subsequent statement since the return value can be of any type, the point being that it's always a single value

20:14 turbofail: a single value that might be a sequence of values

20:15 kristof: I can't think of a scenario where you reduce over something and end up with a collection

20:15 technomancy: I literally just did that a few hours ago

20:15 kristof: what was the scenario?

20:15 technomancy: well, it was erlang

20:16 kristof: still relevant

20:16 technomancy: it was in order to map and filter in a single pass

20:16 brehaut: ,(reduce conj () [1 2 3])

20:16 clojurebot: (3 2 1)

20:16 devn: brehaut: i like to keep it verbose :)

20:16 technomancy: but I reduce into maps in clojure fairly frequently

20:16 kristof: brehaut: I meant something useful :P

20:17 technomancy: oh, that's a good point

20:17 I think I was just thinking of lists and vectors

20:17 devn: kristof: if you never ended up with a collection

20:17 why would reduce-kv even exist?

20:17 i suppose that's /over/

20:17 nevermind

20:17 * kristof shrugs

20:17 devn: but yeah, i build collections all the time with it

20:17 it's not uncommon at all

20:18 kristof: hmmm

20:18 oh, related: is there an unfold/unreduce in clojure?

20:18 devn: not that im aware of

20:19 hyPiRion: kristof: I think the confusion is partially coming from the reduction definition in parallel programming terms is usually considered to be to a single A.

20:19 devn: yeah, that's a good point

20:19 kristof: hyPiRion: yeah

20:19 devn: and frankly, i remember learning reduce

20:19 the canoncial example was reduce + [1 2 3 4 5 6]

20:19 brehaut: kristof: if you discard returning collections from reduce you have just made map, filter… a lot harder to write

20:20 kristof: brehaut: Are those implemented in terms of reduce? I had no idea!

20:20 devn: it's a building block

20:20 brehaut: kristof: well they can be. i think they may be a big squirrly maze for performance reasons

20:20 kristof: reduce is just 'primative recursion' abstracted as a function

20:21 jajaja: Anyone using Clojure on a VM with 1GB RAM or less?

20:21 brehaut: jajaja: yes

20:21 devn: filter isn't written in terms of reduce

20:21 jajaja: Wondering how pared down you can get the JVM if tuned properly

20:21 brehaut: jajaja: i run two clojure apps on a VPS with only half a gig

20:21 turbofail: devn: it could be

20:21 brehaut: theres room to spare

20:21 devn: turbofail: sure

20:21 im just saying it isn't

20:21 i believe the same is true for map

20:21 because it defers to applyTo

20:21 jajaja: brehaout Great! I'm new and had my doubts

20:21 devn: inside apply

20:22 jajaja: brehaout Also room for db and mailserver?

20:22 brehaut: jajaja: i have no idea about mailserver because im not crazy / have copious spare time but yes. ive run postgres and couch concurrently with those two apps

20:22 devn: brehaut: 16g is a lot

20:23 err, jajaja

20:23 jajaja: brehaout Did you need to tune your JVM a lot?

20:23 brehaut: jajaja: i didnt tune it even a bit

20:24 it'll obviously depend on your app / load whether thats necessary

20:24 jajaja: surely your irc client autocompletes nicks?

20:24 jajaja: brehaout What's the first thing that happens when a JVM runs out of memory?

20:24 brehaut: i dont know. its never run out of memory

20:25 jajaja: brehaout Does it handle the situation gracefully?

20:25 turbofail: it throws an exception

20:25 brehaut: how would i know this

20:25 turbofail: and then dies

20:25 jajaja: turbofail So not quite so graceful

20:26 kristof: jajaja: Why don't you try it?

20:26 turbofail: i don't think any system really handles running out of memory gracefully

20:26 if you can't garbage collect anymore, what else are you going to do?

20:26 devn: monit

20:27 that's what you do in that case

20:27 monitor it and fire an alert

20:27 jajaja: Swap to disk?

20:27 turbofail: jajaja: well you can do that by just giving java a max heap size larger than your physical memory and enabling swap in the OS

20:27 devn: jajaja: load test it

20:27 jajaja: turbofail That could be handy to know

20:28 Better than dying, maybe

20:28 devn: give it an order of magnitude more queries/connections/whatever, and run some tests

20:28 turbofail: that said without an SSD (or maybe even with an SSD) relying on swap is probably not going to be a great experience

20:28 jajaja: devn Will do

20:29 turbofail Thinking more of a last resort, obviously

20:30 devn: taking the time to verify your stuff works in production under load is so important when you get an alert that's like: "OMG I'm dying!"

20:30 `cbp: whilo: hi, just read your comment. Yeah I think I need to make an extern file. Need to figure that out somehow. I'm trying to compile react + om with advanced optimizations. Thanks for your help

20:31 aperiodic: you can definitely run two clojure webapps, postgres, and a mailserver all with less than a gig of RAM

20:31 In fact, this box is running four clojure webapps, postgres, a mailserver, and irssi

20:31 devn: aperiodic: depends on the traffic

20:31 jajaja: aperiodic Good to know. I have a number of clients who run everything on VMs with 1GB RAM

20:32 aperiodic: devn: yeah, none of them get very much traffic. YMMV

20:32 devn: aperiodic: i've run lots of stuff on a tiny VPS before

20:32 but i've also watched kingdoms crumble when GC limits got hit

20:32 more time spent in reclamation than performing tasks

20:33 turbofail: look upon my heaps, and despair!

20:33 devn: :D

20:33 jajaja: aperiodic devn: I read somewhere that beyond the startup memory allocation the JVM is more efficient under load than, say a Rails app because it doesn't have to spawn a new process for every request

20:34 turbofail: hm, looks like i left out "ye mighty"

20:34 kristof: devn: Is there an implementation strategy for really, really large applications where you almost entirely decouple two big chunks of a program and garbage collect them separately?

20:34 ...I think I just described distritubed computing.

20:34 aperiodic: devn: did you ever explicitly set the max heap size and have the JVM die on OOM?

20:37 that's what we used to do when we were running HBase on AWS machines with crappy disks at my old job, and it really helped to avoid instances getting bogged down in GC

20:45 quizdr: I can't understand why (map #(-> (% 2 4)) '(+ - *)) doesn't simply return the value of the function (-> (% 2 4)) for each fn in the map, as you'd expect a map to do.

20:45 ,(+ 2 4)

20:45 clojurebot: 6

20:45 quizdr: ,(map #(-> (% 2 4)) '(+ - *))

20:45 clojurebot: (4 4 4)

20:49 quizdr: i'd have expected 6 for the first value in the map's return, for example

20:51 aperiodic: quizdr: i can't understand either. i suspect it has something to do with the fact that you're mapping over symbols, since ##(map #(% 2 2) [+ - *]) does what you'd expect

20:51 lazybot: ⇒ (4 0 4)

20:52 aperiodic: quizdr: and so does ##(map #((resolve %) 2 4) '(+ - *))

20:52 lazybot: java.lang.SecurityException: You tripped the alarm! resolve is bad!

20:53 quizdr: hm, that's interesting. very curious why that happens.

20:53 aperiodic: but i don't understand what exactly is going on in the example you provided

20:54 sdegutis: This is a weird client.

20:55 aperiodic: quizdr: ##(map #(% 1 2 3) '(+ - *))

20:55 lazybot: clojure.lang.ArityException: Wrong number of args (3) passed to: Symbol

20:57 hyPiRion: quizdr: It's because symbols are ifns themselves

20:57 It's a weird thing

20:57 ,('foo 'a 'bar)

20:57 clojurebot: bar

20:58 quizdr: what is "ifns" ?

20:58 * aperiodic has hazy memories of discovering this in the past

20:58 hyPiRion: Well, I say "weird". They work just like keywords.

20:58 quizdr: ,('+ 4 5)

20:58 clojurebot: 5

20:58 hyPiRion: ifns are values which are also functions. E.g. sets, maps, vectors, keywords and symbols are all IFns.

20:58 turbofail: ,('+ {'+ 8} 5)

20:58 clojurebot: 8

20:59 quizdr: so what exactly is happening with '+ as the operator?

20:59 turbofail: quizdr: see above

20:59 hiredman: '+ is the quoted symbol +

21:00 turbofail: it's roughly similar to (get 4 '+ 5)

21:00 hyPiRion: quizdr: it tries to look itself up in the first argument, and if the first arg is not a map or doesn't contain the symbol, it returns the second value (or nil, if none is passed).

21:00 yeah, turbofail got it

21:00 quizdr: ah

21:00 the final value is the "if not found" value

21:00 hyPiRion: yes

21:01 quizdr: ok that explains, man, thanks a lot. that was going to bother me all day

21:01 (inc hyPiRion)

21:01 lazybot: ⇒ 32

21:01 hyPiRion: :D

21:06 quizdr: (inc turbofail)

21:06 lazybot: ⇒ 1

21:15 fortruce: is there a clean idiomatic way to re-bind a local based on a predicate without dealing with dynamic, it seems like there should be an easy way to accomplish this (https://gist.github.com/fortruce/8725445) without repeating '(format)' in an if

21:17 brehaut: 'rebind' a local?

21:18 you cant rebind a local, clojure is a single assignment language (for locals). you can shadow it however, but thats practically identical to introducing a new local

21:18 ztellman might have a library for you though

21:19 fortruce: i'm sure my terminology is off, if you look at my gist, i am wondering if it is necessary to repeat my format command

21:19 brehaut: fortruce: however, you could simply move your let and if inside the format (or bind s' outside)

21:19 llasram: fortruce: Are you looking for `cond->` ?

21:19 alandipert: fortruce: https://www.refheap.com/30118 is another way

21:19 llasram: (or `as->`)

21:20 brehaut: what alandipert just said

21:20 fortruce: alandipert: thats exactly the easy solution I can't believe I missed, thanks

21:21 brehaut: fortruce: fwiw a pluralizer without an optional plural form is broken by design ;)

21:22 fortruce: brehaut: thats a good point, i'll add another arity to let you specify the plural form :p

21:22 brehaut: yup

21:22 english is to wacky to be cattered to by simple functions

21:24 fortruce: thanks for the help

21:25 Bronsa: fortruce: or you could just use cl-format

21:26 ,(clojure.pprint/cl-format nil "~r car~:p" 1)

21:26 clojurebot: #<ClassNotFoundException java.lang.ClassNotFoundException: clojure.pprint>

21:26 Bronsa: ,(require 'clojure.pprint)

21:26 clojurebot: nil

21:26 Bronsa: ,(clojure.pprint/cl-format nil "~r car~:p" 1)

21:26 clojurebot: "one car"

21:26 Bronsa: ,(clojure.pprint/cl-format nil "~r car~:p" 2)

21:26 clojurebot: "two cars"

21:30 fortruce: Bronsa: I'll keep that in mind, the docs for it are a little overwhelming atm

21:30 ztellman: cl-format is such a clown car

21:32 sobel: is nil a value?

21:33 brehaut: clojurebot: cl-format is such a clown car

21:33 clojurebot: In Ordnung

21:33 sobel: i want to say no, since there is a special function to test for it

21:33 brehaut: ~cl-format

21:33 clojurebot: cl-format is such a clown car

21:33 llasram: sobel: But then what of `zero?`

21:34 sobel: llasram: wait until you see my code for ... `seven?`

21:35 all seriousness aside, zero? is syntax-sugar, right?

21:35 llasram: heh

21:35 But how is it less so than `nil?`?

21:35 Or more so

21:35 Whatever

21:35 sobel: i guess it works out the same if nil? is shorthand for (= % nil) (i may have butchered that expression...new at clojure)

21:36 but the reason i asked, is it's really handy for nil<>nil

21:36 brehaut: ,(source nil?)

21:36 clojurebot: Source not found\n

21:36 brehaut: (source nil?)

21:36 sobel: i use this in SQL land a lot

21:36 i am translating nil as NULL

21:36 llasram: ,(= nil nil)

21:36 clojurebot: true

21:37 sobel: in theory, null is not a value. = is not defined on not-a-value. the result is not a value.

21:37 (relational)

21:38 llasram: Yeah, that's not the case on the JVM or in Clojure

21:39 sobel: well, it's complicating my recursive sexpr :)

21:39 llasram: Oh?

21:39 fortruce: brehaut: https://www.refheap.com/30125

21:39 sobel: i'm sure it's nothing interesting, i'm just doing 4clojure tutorials

21:39 thinking like a sql guy

21:40 brehaut: fortruce: sure

21:40 sobel: buuuut this is functional not declarative, so i'm sorta grappling

21:40 brehaut: who said functional isnt declarative?

21:40 the terms arent mutually exclusive

21:42 sobel: fair nuff

21:51 * talios gaks at leiningen - sure, go use ~/.m2/repository - and ignore ~/.m2/settings.xml's <localRepository> setting

21:52 technomancy: ...?

21:53 would you expect zsh to look in .bashrc?

21:54 talios: no - but if you're going to put things in "the local maven repository", that's not a hard coded value.

21:54 arkh: ztellman: thanks! I'll try that tomorrow

21:54 technomancy: talios: of course not

21:54 just set :local-repo in your user profile

21:54 talios: does that eval environment variables?

21:55 or... can it?

21:55 I'm doing dynamically located local repositories.

21:57 mmm, I guess I can get around it with symlink love actually

21:58 technomancy: you can use ~(System/getenv "STUFF"), sure

21:59 there is no aether-wide config file though

22:01 talios: mmm, actually - I don't need to. I misread arbscht's code review comment.

22:02 getting jenkins to do adhoc pipelining of builds based on the gerrit review branch/topic

22:02 working quite well. will need to do the :local-repo thing at some point I suspect tho.

22:15 hola_: Really basic question about immutable data: if in a large app some part can modify a data structure what does it matter whether a new copy is created or the original is mutated?

22:16 You can still end up with unexpected changes whether via re-bindig or mutation

22:19 brehaut: i think you are going to have clarify your question a lot.

22:20 hiredman: hola_: it depends on what you mean, but if you have an immutable structure, and it is immutable, someone else can do whatever, but your structure is fine

22:22 hola_: As I understand it Clojure's immutable data structures are a bit like git commits ie. the latest version is the earlier version plus the last change, no?

22:23 Rich Hickey is selling the advantages of immutable data structures based on retaining historicity but as I understand you can only ever reference the current version of a Clojure data structure, not earlier versions

22:23 hiredman: hola_: but if you want to keep the old versions, you can, but for example, with a mutable hashmap, if you put a new value in, you have destroyed the old version

22:23 hola_: You can't roll back, say, a few changes to a vector once you've added something to it

22:24 hiredman: ,(let [x {:a 1} y (assoc x :a 2)] [x y])

22:24 clojurebot: [{:a 1} {:a 2}]

22:24 hiredman: ,(let [x (doto (java.util.HashMap.) (.put :a 1)) y (doto x (.put :a 2))] [x y])

22:24 clojurebot: [{:a 2} {:a 2}]

22:26 hola_: I'm aware there are data structures to handle mutability (eg. records). It's just that I don't quite undertand how the basic immutable data structures in Clojure save you from all the unintended consequences Rich claims they circumvent.

22:28 brehaut: hola_: perhaps you need to suggest some specific examples that you dont understand rather than waving an abstract cloud of "all" around? its hard to refute or discuss a vaguery

22:28 hola_: If I add an element to a vector, for example, and don't rebind it to a new variable I end up, effectively, with the same result as an assignment in a non-functional programming language

22:28 john2x: how do I update my dependencies, other than visiting each project's page to check if my they're are up to date?

22:29 brehaut: if nobody else holds a reference to the original vector thats true

22:30 hiredman: john2x: don't update deps unless you need to

22:30 brehaut: hola_: however, that vector cant be changed at a later date by a black box function you call at a later date, whereas if it were an arraylist it could

22:32 its always up to you if you discard your old state, not a callee you need to pass that state too

22:33 hola_: (def arr [1 2 3 4]) (def arr (cons 5 arr))

22:33 brehaut: hola_: def is a dev time feature; you dont rebind vars as part of the operation of a running program

22:33 srruby: What are the advantages of using zippers vs postwalk? So far I've just been using postwalk.

22:35 hola_: brehaut I can save prior state in any language if I choose to by creating new variables so what's the big win with Clojure? See my example.

22:36 brehaut: what example

22:37 hola_: I'm not trolling. The penny just hasn't dropped as to how immutable data structures automatically save you from anything.

22:37 brehaut: hola_: nevertheless, what example are you talking about

22:37 hola_: (def arr [1 2 3 4]) (def arr (cons 5 arr))

22:37 The end result is just the same as mutating a variable in, say, Ruby

22:38 brehaut: hola_: that is not remotely idiomatic clojure. dont use def for storage.

22:39 even with (let [a [1 2 3 4] b (conj a 5)] …) its not the same as in ruby

22:39 because functions you call cannot mutate that vector

22:39 hola_: arr = [1, 2, 3, 4] ; arr.unshift 5

22:40 brehaut There are plenty of tutorials using def for storage

22:40 brehaut: (let [a [1 2 3] _ (any-function-ever a)) (= a [1 2 3])) ;; true. its completely invariant

22:40 hola_: .. and books

22:40 dsrx: arr = [1, 2, 3, 4]; arr2 = arr; arr.unshift 5

22:40 brehaut: hola_: then there are plenty of tutorials that are wrong

22:41 hola_: its useful in a tutorial to explain repl exploration (as i said previously, dev time) but that is in no way how you write a program

22:41 fortruce: using def to set up initial state for an example is a lot different than using def to change state in the middle of code...

22:42 hola_: I can understand if it's idiomatic but what I'm getting at is that the language itself, ie. immutable data structures, doesn't protect you from unintended consequences as Rich Hickey claims. What you're saying is .. only if you know how to write idiomatic Clojure

22:42 chippie: Can I use (iterate ...) to create a finite lazy-sequence? I have an extremely large sequence of dates, but it is not infinite. Aside from using lazy-seq directly, would the idiomatic way to do this in Clojure be to use (iterate ...), but return nil (or some other "end" marker) once the sequence end is reached, then wrap that with something like take-while? (take-while (complement nil?) (iterate ...))

22:42 brehaut: hola_: consider the following JS: var a = [1, 2, 3]; any_function_ever(a); a == [1, 2, 3]; // no way to know if this is true or false

22:43 hola_: go ahead, write all your programs with mutable global storage. its no skin of my nose.

22:44 hola_: brehaut If you insert my example in the middle of this in Clojure the result would be the same

22:44 dsrx: hola_: nobody should or would write code the way you did in that example

22:44 brehaut: hola_: no, it wouldnt. i used let. let introduces local, signal asignment bind. there is exactly no way in which you could change it

22:44 s/signal/single/

22:44 anyway its 4:30 on a friday. why am i on the computer

22:44 hola_: If you didn't use let it would blow up just the same

22:45 brehaut: no it wouldnt

22:45 hiredman: people coming from scheme often think def and let must do the same thing, but in clojure they are very different

22:45 brehaut: you are welcome to disagree of course, but you'll be wrong

22:46 alandipert: chippie: i find take-while+iterate pretty common, and use this myself: https://www.refheap.com/30149

22:46 chippie: alandipert: Thanks! :)

22:47 alandipert: Ah nice pattern

22:48 alandipert: chippie: i guess it's the same as (take-while pred (iterate f x)), which is a little more straightforward

22:49 chippie: Nobody really talks about design patterns in functional languages (or at least, there's not a lot of literature out there about them), but they clearly exist.

22:51 quizdr: I'm getting a null pointer exception on this little code snippet, don't know why: https://gist.github.com/quizdr/8726329

22:53 if r is nil, then using (r) as a cond should not run that branch in the cond, right?

22:54 alandipert: ,(nil)

22:54 clojurebot: #<CompilerException java.lang.IllegalArgumentException: Can't call nil, compiling:(NO_SOURCE_PATH:0:0)>

22:55 alandipert: ,(let [x nil] (x))

22:55 clojurebot: #<NullPointerException java.lang.NullPointerException>

22:55 quizdr: oh my

22:55 ok, thanks

22:55 whoops

22:56 alandipert: np

22:57 quizdr: lol I fixed it by doing (not (nil? r)) before realizing that just r by itself would suffice

23:01 gtrak: anyone know elisp here? #emacs is no help.. . trying to debug a cider thing. read-from-string seems to inexplicably kill further execution.

23:30 johnjelinek: hihi all, how's it goin'?

23:31 quizdr: keeping it real, johnjelinek

23:31 johnjelinek: way to be :)

23:31 dsrx: i'm keeping it complex, personally

23:31 johnjelinek: had a question -- are you familiar with clojure.tools.namespace.repl/refresh?

23:31 quizdr: dsrx well at least you aren't imaginary

23:32 johnjelinek: I get errors when I try to do (clojure.tools.namespace.repl/refresh)

23:33 here's a pastebin of the error: http://pastebin.com/BYxuEB9M

23:33 does that look familiar to you?

23:34 seangrove: Hrm, I'd like to write an html parser in ClojureScript

23:35 Actually, I'd like to use an html parser written in ClojureScript, but I haven't seen any

23:35 Any recommendations for writing a parser in cljs?

23:44 dsrx: (defn parseHtml [s] (.parseFromString (DOMParser.) s "text/html")) :P

23:44 er parse-html

23:44 ack

23:47 seangrove: dsrx: Yeah, but I don't want to instantiate any html objects, I only want clojure data structures

23:49 dsrx: seangrove: ah, i see. there's hickory as well but in cljs it just uses DOMParser internally I think, but only ever returns clojure data structures

23:50 seangrove: dsrx: Ah, interesting, that looks like exactly what I'd like, but skipping the DOMParser bit. I wonder how the jvm-clj side it handled. Thanks!

23:53 Ah, Jsoup. Damn.

23:58 cark: parsing html isn't easy considering most of it is malformed

23:59 seangrove: cark: Yeup. But we'll approach it iteratively

Logging service provided by n01se.net