#clojure log - Aug 13 2014

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

0:23 shriphani: hi I was wondering if anyone has any experience with aleph. I am trying to talk to an aleph tcp server from a java client and calling readLine on the socket's inputstream causes it to block (while a clojure client is able to speak to the server).

0:27 codygman: xeqi: Thanks.

2:34 supreme__: I am new to clojure. would you say Clojure is good (perfect) for building scalable REST based API's? Since clojure have macros and is scale well making it the perfect DSL creator?

3:47 r4vi: supreme__: I think any/most languages would be fine for building a REST API; just a matter of preference

4:14 bajabongo: hi, I'm learning ClojureScript and I'm curious about "special" form (js* string), but I cannot find where and how it's implemented

4:15 could anybody provide info where can I find it's definiotion?

4:19 bryanmaass: What's cooler than how clojure maps are implemented?

4:22 clgv: bajabongo: probably in the clojurescript compiler

4:23 wink: supreme__: ever seen http://www.techempower.com/benchmarks/#section=data-r9 ?

4:24 bajabongo: clgv: well, probably :), but I was looking for "js*" string and, actually, did not find any definiotion

4:24 *definition

4:24 clgv: it's used frequently, but nowhere I can find a definition

4:25 clgv: bajabongo: https://github.com/clojure/clojurescript/blob/4ba56712274d67b592cff5160bb2a6aea397c72d/src/clj/cljs/analyzer.clj#L1284

4:26 bajabongo: clgv: hm, looks like I didn't notice that since as for now, I don't know what "defmethod" is,

4:26 clgv: thanks, I'll look around

4:27 clgv: bajabongo: oh well so you are just a beginner? then do not try to find that source ;)

4:27 supreme__: wink: nope, thanks!

4:27 clgv: bajabongo: js* just emits literal javascript as far as I read

4:27 bajabongo: clgv: yeah, started learning Clojure(Script) a few days ago :)

4:28 clgv: yes, and that's what I exactly needed to understand, how ClojureScript handles "this" in JS

4:28 clgv: bajabongo: is there some docstring for (doc js*)?

4:28 wink: supreme__: but take it with a grain of salt. I think you can build a reasonably scalable api in most languages. Only the top top end, server costs or speed of development matter as hard facts

4:28 supreme__: I saw there was a video series of rick hickey about learning clojure for a java programmer. they are from 2012, still relevant? waiting for my book to drop in the mail anyday so thought I could look at thoose while waiting. cool that the creator has done the videos himself

4:29 clgv: bajabongo: yeah well the javascript passed to js* will just show up in the non-optimized javascript output

4:29 bajabongo: it turned out there's macro (this-as), but it just makes a binding and uses (js*) internally, and that's the reason I wanted to know more about (js*)

4:29 clgv: bajabongo: there is probably some information in one of the tutorial series

4:30 supreme__: wink: what webframeworks are clojure that are on that list?

4:30 bajabongo: clgv: I've got no idea, but looking for "this in clojurescript" yields this http://stackoverflow.com/questions/15531261/accessing-this-in-clojurescript

4:30 ener2: is there something like cons in cl that will create pair instead of treating second value as a sequence?

4:31 bajabongo: clgv: which is nice, but I actually don't see why I cannot just use (let [this (js* "this") ...]) by myself

4:31 supreme__: wink: found the abbrevation now

4:31 wink: supreme__: there's a column where you see 'clj' - but most people use libraries and ring middleware to combine stuff, not use a full stack framework, altough there's pedestal and a few more

4:35 bajabongo: clgv: anyway, thanks for providing an exact line :)

4:38 clgv: bajabongo: wont help you much though, since you need to understand clojure pretty well and maybe need some cljs compiler knowledge

4:41 bajabongo: clgv: it's OK, after a few days I have a vague idea how it may work; mostly I just wanted to know how to handle "any" JS

4:41 clgv: bajabongo: I guess, you should use js* seldomly anyway

4:41 supreme__: wink: are you familiar with the rick hickey videos learning clojure for a java programmer? are they still relvent

4:42 ?

4:43 clgv: supreme__: the general ideas yes. some syntax has change meanwhile

4:45 bajabongo: clgv: sure, it's just I now know, that I have yet another way to refer to JS

5:02 xfel: Hi. Has there been non-trivial changes to the syntax/etc in Clojure since version 1.4 and/or 1.3?

5:02 llasram: ener2: just using a 2-element vector is generally the idiomatic way to represent a pair.

5:03 xfel: Not really. 1.4 added reader tagged literals, but everything else and since has pretty much been bug fixes and standard library features

5:03 xfel: See https://github.com/clojure/clojure/blob/master/changes.md for the details

5:05 xfel: llasram: Ok, thanks. (Asked because I picked up a book from 2012 which seemed nice, Clojure Programming by Chas Emerick, and would be a bit silly spending time on "old material")

5:06 llasram: Good choice. And yeah, anything covering 1.3 or later should be pretty much still relevant.

5:39 thesaskwatch: Hi, anyone knows how to encode url when using clj-http?

5:42 karls: thesaskwatch: i've used java.net.URLEncoder with success before

5:42 thesaskwatch: karls: thanks

6:21 martinklepsch: anyone experience using nth-child selectors with garden? I can't require garden.selectors that contains some nth-child related things

6:34 ener2: what am I doing wrong here?

6:34 (let [trgs (.split com.badlogic.gdx.graphics.g2d.TextureRegion texture tw th)]

6:34 I get No matching method found: split for class java.lang.Class

6:35 why is it getting java.lang.Class instead of com.badlogic.gdx.graphics.g2d.TextureRegion ?

6:36 broquaint: ener2: If it's a static method then com.badlogic.gdx.graphics.g2d.TextureRegion/splot should work IIRC.

6:36 rolfb: broquaint: s/splot/split ?

6:36 broquaint: That too :)

6:36 ener2: I get

6:36 CompilerException java.lang.RuntimeException: No such namespace: .com.badlogic.gdx.graphics.g2d.TextureRegion, compiling:(simvivor/loader.clj:37:22)

6:37 with

6:37 (let [trgs (.com.badlogic.gdx.graphics.g2d.TextureRegion/split texture tw th)]

6:37 broquaint: Drop the leading dot.

6:37 ener2: ah okay thanks

6:37 hmm

6:38 No matching field found: length for class [[Lcom.badlogic.gdx.graphics.g2d.TextureRegion;

6:38 you can't query java arrays same way?

6:39 broquaint: The same way as?

6:39 ener2: well

6:39 array.length

6:39 (.length array)

6:39 broquaint: ,(let [a (int-array '(1 2 3))] (.length a))

6:40 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: No matching field found: length for class [I>

6:40 broquaint: ,(let [a (int-array '(1 2 3))] (alength a))

6:40 clojurebot: 3

6:41 broquaint: http://clojure.org/java_interop

6:42 ^^ Should have all the answers :)

6:49 llasram: ener2: Yeah, the property-like query for array length is a Java syntax feature vs a JVM feature. Clojure distinguishes between them, I assume due to dynamism -- otherwise w/o full type information, you'd have this weird special case in the Clojure compiler for any attempt to access a property named `length`

6:50 ener2: ah alright

6:50 hmm is (for [foo (range x)] (...))

6:50 0 based or 1 based?

6:51 llasram: ~tias

6:51 clojurebot: Try it and see! You'll get results faster than asking someone in #clojure to evaluate it for you, and you'll get that warm, fuzzy feeling of self-reliance.

6:51 llasram: :-)

6:51 ener2: because it ignores the whole thing if I have (range 1) ...

6:51 llasram: ,(range 1)

6:51 clojurebot: (0)

6:53 * clgv did not know that shortcut^^

6:53 ener2: http://pastebin.com/4VRzr1QW

6:54 it nevers gets into that (let [array (nth trgs i)] block

6:54 even if range returns ä0)

6:54 *(0)

6:56 Bronsa: ener2: for is lazy

6:56 clgv: ener2: you misunderstood `for`. `for` is lazy and its body is only executed if elements are requested or the whole lazy sequence is forced

6:56 ener2: I found this is how you do for loops in clojure....

6:56 Bronsa: ener2: use (dotimes [i times] ..) rather than (for [i (range times)] ..)

6:56 clgv: ener2: that's wrong. `for` constructs a lazy sequence, so for each "loop" you get an element in a lazy sequence

6:57 ener2: in your example you want to replace it with `reduce`

6:57 Bronsa: ener2: also struct maps have been deprecated in favour of records for years

6:57 llasram: Aaaand the `conj` onto `output` is treating it like something mutable, when instead it will yield a new persistent value each time, never accumulating anything

6:58 ener2: llasram: yeah forgot setting

6:58 clgv: ener2: llasram comment is the reason why you want a `reduce` there ;)

6:59 llasram: And destructuring -- your highest-level `let` could be written as `(let [[symbol path tw th ft] pair] ...)`

6:59 In fact, you could ditch the `let` entirly and stick the whole binding form in the `doseq`

6:59 ener2: hmm you can't set! into let variable?

6:59 llasram: Oh dear no

6:59 ener2: I come from CL background so...

6:59 llasram: We are polite and functional around here

6:59 ener2: well that is all and dandy but not all the time :)

6:59 clgv: ener2: yeah you should forget how you' program in the "mutable world" for now ;)

7:00 llasram: As clgv suggested, a `reduce` is probably what you want, "mutating" via iterative application to successive return values

7:01 ener2: hmm, unless closure has yield...

7:01 llasram: Also, you can directly iterate over arrays -- no need to access by index

7:01 ener2: OOC what resource/s are you learning from?

7:02 ener2: llasram: google and right now finished watching https://www.youtube.com/watch?v=7mbcYxHO0nM

7:03 how will reduce help in this case?

7:03 I need to basically flatten array of arrays into list

7:04 llasram: I'd suggest checking out one of the introductory books (like the O'Reilly one -- there are others, but I can vouch for that one). Even if you have a Lisp background, introducing the functional stuff can be helpful

7:04 Well, we were saying `reduce` because of the accumulation you have in the most-nested form form of your loops, but

7:05 ener2: in lisp I would accumunalte into list, either with setf into it or loop append/loop collect ...

7:05 llasram: You may just want to directly accumulate a lazy seq...

7:05 What is trgs? A 2-dimensional array?

7:05 ener2: yes

7:05 2-dimensional java array

7:06 llasram: Try replacing the whole thing with (mapcat seq trgs) :-)

7:08 ener2: hmm interesting

7:08 it seems to work

7:09 I guess (seq java-array) returns list containing that array content?

7:12 clgv: ener2: almost it returns a specialized sequence but it only matters that it is a sequence

7:14 ener2: you can checkout http://www.braveclojure.com/

7:15 ener2: clgv: thanks

7:15 I am really fond of common lisp (even made thesis about it) but I have to work in java in company, so I am trying some crazy things (like this :P)

7:19 clgv: ener2: well clojure fits perfectly in this scenario ;)

7:22 CookedGryphon: can anyone think of a neat way to express "first of the following statements to fulfil this predicate", ideally short circuiting like and/or

7:23 and i want the value of the thing, not the value of the predicate

7:23 opqdonut: I often have (defn find-first [p s] (first (filter p s)))

7:24 CookedGryphon: yeah, I have that option or a load of nested ifs, neither of which I'm 100% happy with

7:24 as if the first one matches, I shouldn't have to calculate the second

7:27 ener2: CookedGryphon: well I don't know about closure but it is possible in lisp so it might be

7:27 if you find how, you can wrap it in macro for something easier to use

7:28 you nca use throw/catch

7:28 *can

7:28 and build macro around it

7:30 john2x_: CookedGryphon: I think opqdonut's suggestion does what you need? filter is lazy, so it it will just calculate up to the first match

7:30 CookedGryphon: john2x_: yes, but I have fewer than 32 items in the list and each is expensive to compute individually

7:30 and so laziness gives me no benefit

7:31 it doesn't matter, I'll just take the hit and if it's a problem rewrite it with if-lets

7:31 ener2: kinda shame clojure does not have function exist as in return-from <block> value ...

7:31 *exits

7:31 opqdonut: CookedGryphon: can't you call seq to unchunk the sequence?

7:32 clgv: CookedGryphon: expensive item calculation where you possibly dont need each item is exactly one of the shining use cases for lazy sequences ;)

7:32 opqdonut: err, no, I'm raving

7:33 but anyway, use a non-chunked sequence

7:33 see e.g. seq1 in http://stackoverflow.com/questions/12412038/in-clojure-are-lazy-seqs-always-chunked

7:33 clgv: CookedGryphon: you should avoid chunked sequences though, e.g. no (range n) but you can use (take n (iterate inc 0))

7:34 CookedGryphon: I think I have a better solution,

7:34 I'm just going to rewrite my predicate to return the value or nil

7:34 and then use or

7:35 which looks neat, conveys the intention properly, and has no lazy sequence overheads or chunking uncertainties

7:35 clgv: but wasnt part of the problem that you have more than 4 items?

7:38 IceD^: question - I have clojure app (http api) handling ~150K rps, each request in the end will consume some amount of some resource - {:r1 100 :r2 200 :r3 100500} - there are ~10K resources. request processing code will build list of resources that could be consumed and will try to consume each of them sequentually till success (e.g. request can [[:r1 200], [:r2 10]])

7:40 so question is - what to use to handle this mutable state - e.g. refs, external kv, ...?

7:42 on typical load most "popular" resources can be accessed ~10K tps

8:05 danielszmulewicz: ,(clojure.walk/macroexpand-all '(-> (read) (eval) (println) (loop-forever)))

8:05 clojurebot: #<ClassNotFoundException java.lang.ClassNotFoundException: clojure.walk>

8:06 danielszmulewicz: ,(require 'clojure.walk)

8:06 clojurebot: nil

8:06 danielszmulewicz:

8:06 ,(clojure.walk/macroexpand-all '(-> (read) (eval) (println) (loop-forever)))

8:06 clojurebot: (loop-forever (println (eval (read))))

8:06 danielszmulewicz: ,(macroexpand '(-> c (+ 3) (* 2)))

8:06 clojurebot: (* (+ c 3) 2)

8:07 danielszmulewicz: ,(clojure.core/macroexpand '(-> c (+ 3) (* 2)))

8:07 clojurebot: (* (+ c 3) 2)

8:09 danielszmulewicz: ,(clojure.walk/macroexpand-all '(-> routes

8:09 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

8:09 danielszmulewicz: (wrap-transit-params)

8:09 (wrap-datomic (env :db-url))

8:09 (wrap-defaults api-defaults)))

8:10 oops

8:16 noncom|2: i need to pass a form to a macro, and then return it as read but not evaled. however, whatever i try, the form gets evaled inside the macro. how could i acheive the desired result ?

8:17 like (defmacro m [form] `(.doSomethingJava java-object ~form))

8:17 the java method should receive the actual form, which is read, but not evaled

8:17 ?

8:17 ohpauleez: You don't want to escape the form, potentially

8:18 noncom|2: what do you mean? i should not use ` ?

8:18 ohpauleez: not use ~

8:19 wait, nvm. That would take the actually symbol form

8:19 noncom|2: nope.. it simply treats "form" as a symbol

8:19 yeah

8:19 so i am still wandering.. :)

8:19 so it gets inside the macro read, but not evaled..

8:19 theeeeen...

8:19 ?

8:20 i think that ~ implies evaluation..

8:20 am i right ?

8:20 i can make all work if i pass a manually quoted form

8:21 but these additional manual quotes will be annoying if i get to many calls like that..

8:21 ohpauleez: quote it

8:21 like this: (defmacro a [f] `(prn '~f))

8:21 noncom|2: wow, gotta try now..

8:22 umm, it still evals the form

8:23 but quotes the result

8:23 ohpauleez: On your repl (or in a comment block), use the code I pasted above

8:23 and call: (a (inc 1)), you'll see "(inc 1)"

8:24 that's not what you want?

8:24 noncom|2: oh wait, maybe i made a mistake, just a sec

8:25 ohpauleez: right, i made a mistake, i had "defn" instead of "defmacro" :) your last proposed solution works just fine!

8:25 thank you

8:25 ohpauleez: Excellt!

8:25 clojurebot: no, thank *you*: http://nedroid.com/2010/11/thanks-for-reading-my-comics/

8:25 ohpauleez: np, more than happy to help!

8:26 wow, I think I need to charge my keyboard, it's dropping letter

8:26 noncom|2: also i think you're on mac

8:26 am i right ?

8:26 ohpauleez: Correct

8:26 (currently)

8:27 noncom|2: heh.. sometimes the symbol  gets inserted by mac

8:27 instead of spaces

8:27 idk why

8:27 sometimes when my boss, who's on mac, writes me in skype, his messages are full of this symbol

8:27 so weird :)

8:28 the symbol is a dot in the middle of the line (not in the bottom, like the normal dot, more like the dot-the-multiplication-sign)

8:53 llasram: CookedGryphon: scrolling back, you could also use an eager version of `first-filter`: https://gist.github.com/llasram/995be648aa22e0630ce8

8:59 the-kenny: ClojureScript/Closure Question: I have (def ^:export enable-validation false) in a project. I'd like to be able to set this at runtime from the js-console (or some <script> tag) to enable/disable validation for production builds or on-demand. The problem: Closure inlines the `false' in the functions which are responsible validation. I need some kind of ^:volatile meta-data for this use-case, but couldn't

8:59 find anything yet. Any ideas?

9:00 (If there isn't anything like this, I'd just check for some property on the window object, but I find that quite ugly)

9:04 dnolen_: the-kenny: yeah ^:export doesn't work for configurable properties - that why we generally export functions to do this like set-print-fn!

9:05 the-kenny: dnolen_: That sounds reasonable, thanks

9:09 clgv: llasram: linter alert! please use `when` ;)

9:15 the-kenny: dnolen_: Btw. we're running our application built entirely in Om in production for some time now. We're super happy with it. As I already said in Krakow: Thanks for Om :)

9:15 TimMc: clgv: or add a nil alternative clause

9:16 I've been coming around to technomancy's view on if/when.

9:16 dnolen_: the-kenny: awesome! :)

9:17 daniel___: can anyone explain to me when and why transducers could be better than reducers?

9:17 they seem to accomplish more or less the same, but with arguments in a different order

9:18 and are built into code as a one-less arity

9:18 core*

9:18 dnolen_: daniel___: reducers aren't reusable in the same way

9:18 daniel___: transducers can be composed via function composition and then applies to lazy sequences, core.async buffers etc.

9:19 not possible w/ reducers - and transducers subsume reducer behavior

9:19 daniel___: reducers can't also be composed?

9:19 clgv: TimMc: that view consists of adding unnecessary nils?

9:20 dnolen_: daniel___: not in the same way no.

9:20 daniel___: reducers you have to nest like (r/filter even? (r/map inc [...])) rather than comp

9:20 bhauman: Morning all. Are people generally using Webjars and serving them through ring for static client side js libs?

9:20 daniel___: reducers can be composed with comp too

9:21 bhauman: Or are there downsides like libs not getting downloaded when deploying to prod?

9:21 dnolen_: daniel___: but you must supply something concrete, the interface just doesn't work for something like core.async buffers for example

9:22 daniel___: in the transducer case the channel can take the transducer stack since there are no assumptions about how it will actually be used.

9:22 s/the channel/the core.async channel

9:24 daniel___: fundamentally reducers must take a reducible thing (in the Clojure sense), not true for transducers.

9:27 TimMc: clgv: Depends on your definition of "unnecessary". Swearjure, for instance, eschews unnecessary alphanumerics...

9:28 daniel___: dnolen_: it's a little clearer, thanks

9:29 thesaskwatch: I have a question - I have an app which is supposed to read an external config file (which willl be clojure code). So I want to read it dynamically but also pass some values to it. How to do it the best way?

9:29 clgv: TimMc: the context was clojure :P

9:30 alandipert: bhauman, we have the https://github.com/tailrecursion/hoplon/tree/master/vendor system for boot-based cljs projects, with conventions that amene to gclosure etc

9:30 the-kenny: thesaskwatch: so you want to *eval* the code in the config file?

9:30 clgv: TimMc: I'd hesitate to add additional (unnecessary) noise

9:30 thesaskwatch: the-kenny: yes .. it's supposed to be a config which returns data (kind of dsl)

9:32 the-kenny: to be more specific - it's a program which provisions some heroku componens - I want to separate configuration from execution engine

9:33 TimMc: clgv: The idea is to have "when" signal "side-effects ahead!"

9:34 I'm the wrong person to defend this idea, though.

9:35 clgv: TimMc: well it also signals you did not forget the else-clause ;)

9:36 enn: Is HoneySQL is the best current option for generating SQL? In particular, is there anything out there that already supports window functions?

9:39 TimMc: clgv: I think that's the part that attracts me more.

9:39 thesaskwatch: the-kenny: however if I *eval* it - how can I pass some external values to it?

9:43 Ok, I guess this is the way: http://stackoverflow.com/a/8630122/343699

9:48 llasram: clgv: `when` is for side-effects :-p

9:49 clgv: ,(doc when)

9:49 clojurebot: "([test & body]); Evaluates test. If logical true, evaluates body in an implicit do."

9:49 clgv: llasram: not by contract :P

9:50 TimMc: meh

9:50 clgv: llasram: I have a lot of when-usage in absence of side-effects ;)

9:50 llasram: Sure, but by increasingly-common convention; which convention I happen to follow

9:51 hyPiRion: I tend to mutate vectors, as there's no contract saying I cannot do so

9:52 clgv: if you think about it there probably should have been (when pred expr) and a (dowhen pred expr1 ... exprN)

9:53 hyPiRion: ,(let [a [0 1 2]] (aset (.tail a) 0 10) (conj a 1))

9:53 clojurebot: [10 1 2 1]

9:56 llasram: (inc hyPiRion)

9:56 lazybot: ⇒ 42

9:59 TimMc: ,(let [a [0]] (aset (.tail a) 0 a) a)

9:59 clojurebot: [[[[[[[[[[#]]]]]]]]]]

9:59 TimMc: Suck it, haskell!

9:59 I can tie a knot too.

10:00 hyPiRion: hehe

10:01 clgv: ,(binding [*print-level* 100] (let [a [0]] (println (aset (.tail a) 0 a) a)))

10:01 clojurebot: [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[#]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]] [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[#]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]...

10:25 mikerod: hyPiRion: I still don't really get why these fields are public

10:26 hyPiRion: mikerod: rrb-tree compat afaik

10:26 want to share structure with it

10:26 mikerod: hyPiRion: share with what?

10:26 another core datastructure?

10:27 Bronsa: mikerod: a contrib datastructure

10:27 mikerod: Bronsa: oh..

10:27 Bronsa: mikerod: I mean, rrb-tree is a contrib ds, it needs to share structure with clojure vectors

10:29 mikerod: Bronsa: this sounds like a strange reason to make a public field on a core data structure of the main language :P

10:30 Bronsa: mikerod: that public field is an implementation detail and not part of the public API anyway

10:30 you're not supposed to use it

10:30 mikerod: I think that is fairly clear.

10:30 I just pretend it is not there

10:30 However, I'd hope others do to.

10:31 Bronsa: mikerod: nobody but TimMc and hyPiRion know about that field.

10:31 hyPiRion: mikerod: Well, I use it for the exact same reason as the rrb-tree impl.

10:31 haha

10:32 mikerod: Which is for - efficiency?

10:33 hyPiRion: mikerod: right. I'm implementing a data structure which can be efficiently converted from a persistent vector, and uses same structural sharing

10:34 mikerod: hyPiRion: hmm, I see

10:36 sdegutis: Hi.

10:36 "Caused by: java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.FutureTask@4fc5fa85 rejected from java.util.concurrent.ThreadPoolExecutor@51cf0670[Shutting down, pool size = 3, active threads = 3, queued tasks = 0, completed tasks = 94]"

10:37 oskarkv: I have a function that returns code, that I usually use inside a macro. But if I want to skip the macro, can I just eval the result of the function (the code)? I think I remember that someone said that using eval like that is not exactly the same thing, because the environment might be different, or something.

10:37 sdegutis: Please help. Thanks?

10:39 Bronsa: sdegutis: nobody can help you with just that exception line and no context

10:39 sdegutis: Thanks.

10:39 hyPiRion: sdegutis: we need some context

10:39 sdegutis: Yes.

10:39 llasram: sdegutis: BTW, have you considered providing some context?

10:40 sdegutis: Hi.

10:40 llasram: :-)

10:40 sdegutis: This is caused by a failed Datomic query on a background thread.

10:40 I'll give you the relevant line of code if you promise to give it back when you're done.

10:40 Because we need it for our website to run.

10:41 llasram: oskarkv: Well, compiling a macro-expansion vs explicit eval uses nearly the same mechanisms but with very different semantic implications. What exactly are you trying to achieve?

10:41 * llasram opens his notebook of corporate secrets, pen ready.

10:43 sdegutis: Here is a secret gist.

10:43 https://gist.github.com/sdegutis/00a9cdecc632abd12f3b

10:43 I will now change to the nick starlord.

10:43 starlord: Now I am using it.

10:44 llasram: starlord: But now you've changed color :-(

10:44 starlord: Yes. That is part of my special powers.

10:44 But don't worry it's just an optimal allusion.

10:44 I also own star-lord and star_lord.

10:47 oskarkv: llasram How about something like this https://www.refheap.com/a5c6a638ef7b0733f0ebefdf5

10:47 my internet connection is very bad, took forever to paste that :P

10:48 peeja: Hey, folks. I just went through the two Om tutorials on its wiki, and I'm looking for some good Om code to read, particularly code that persists data back to the server-side. Any suggestions?

10:48 starlord: Thanks in advance.

10:50 oskarkv: llasram it just seems unnecessary to do use the version with a macro. Wasn't sure if the version with eval is the same thing.

10:50 -do

10:54 maravillas: peeja: about halfway through the om readme is a list of applications written using om

10:55 llasram: Oh, top-level `eval`. Yeah, AFAIK that should be pretty much equivalent to defining a macro then immediately using it at top-level.

10:56 starlord: Hello.

10:56 llasram: ^ oskarkv on the last, obv

10:56 AlwaysBCoding: peeja: https://github.com/sgrove/omchaya ?

10:56 starlord: Is there some reason that might cause me to get an exception when in the background thread but not in the frontground thread?

10:57 llasram: starlord: Did someone call `shutdown-agents`?

10:57 starlord: Not beforehand, no.

10:57 Oh wait, yes.

10:57 llasram: Well there you go

10:57 starlord: Thanks in advance llasram.

10:57 You've solved it for me :)

10:58 oskarkv: llasram ok, thanks. Just out of curiosity, when is `eval` not equivalent to normal evaluation?

10:59 starlord: Well, this solves the latest mystery. But it doesn't solve the original one.

10:59 I think maybe it's just because Datomic is a giant hoarder.

11:00 llasram: oskarkv: Oh, when you call it at runtime (for whatever "runtime" means in your application)

11:00 alandipert: oskarkv, eval'd forms don't capture locals is one big difference

11:00 ,(let [x 1] (eval 'x))

11:00 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: x in this context, compiling:(NO_SOURCE_PATH:0:0)>

11:01 oskarkv: I see

11:01 Thanks

11:04 zot: heeeeello, within my .lein/profiles.clj, if i have multiple :jvm-opts, should it be of the form [["-Dfoo"] ["-Dbar"]], or something else?

11:08 oskarkv: zot I think ["op1" "op2"]

11:10 peeja: AlwaysBCoding: That looks perfect, thanks!

11:12 zot: oskarkv: tnx!

11:18 clgv: zot, oskarv: did that change? previously it was just a string with all options

11:19 ah no, you are right, a vector of strings per parameter

11:19 oskarkv: I dunno. I tried it yesterday and it worked.

11:30 eric_normand: anyone know of any Clojure consulting opportunities?

11:32 clgv: eric_normand: you want to consult companies how to use clojure? or you want someone to consult you?

11:33 eric_normand: clgv: I will consult them. Not necessarily training. Also contract work.

11:34 clgv: eric_normand: hmm the cognitect people will know some, but they are your competition ;)

11:34 *competitors

11:34 justin_smith: I have a retainer doing clojure work for my ex employer (after a couple of years of being a full time clojure dev, so it's a downgrade)

11:44 starlord: clgv: they aren't /quite/ competitors, as they can't take on /every/ client, and must turn some away; i.e. there is room for taking up their scraps :)

11:45 eric_normand: I've heard mixed things about Clojure consulting

11:45 some say there isn't much work

11:45 some say there's a ton

11:45 starlord: I personally would not use Clojure for web apps anymore, now that I've worked on a Clojure web app for the last 2 years.

11:45 clgv: starlord: maybe, maybe not...

11:45 starlord: I would just work on Rails.

11:46 clgv: starlord: why?

11:46 starlord: Because in Rails all the web-related functionality is done for you, all you have to do is bring the application logic; in Clojure you have to reinvent every wheel, hoping some are already invented for you.

11:47 And to be honest, I have not found Clojure's unique features (homoiconicity, macros, immutability, threads) to be significantly more helpful than using Ruby for solving most problems.

11:47 clgv: starlord: ah ok, so you need the ORM stuff and associated features?

11:48 mgaare: starlord: what libs were you using in your clojure web stack?

11:48 rboyd: starlord: did you do rails before your clojure web project? on a large scale?

11:49 starlord: clgv: no, but for example Rails has many security features built-in which in Clojure we do not have equivalent libraries for yet.

11:49 mgaare: ring, compojure, hiccup, garden, datomic, probably some others

11:50 rboyd: I've consulted on very large, ugly Rails projects.

11:50 rboyd: But the ugliness was not caused by the largeness; the apps would have been large either way. The ugliness was simply because they were implemented in a hurry.

11:51 rboyd: still waiting to see a large elegant rails codebase

11:51 starlord: Right now we have a mycompany.web namespace and a mycompany.features namespace; if I were to port it to Rails, the .web namespace would just be Rails controllers and models and such, and the .features namespace would be somewhere under lib/ or whatever it's called.

11:52 mgaare: starlord: I've found that compojure/ring tend to get ungainly above a certain size, but liberator makes things quite a bit nicer

11:58 justin_smith: so, one of the lead csound devs is writing a synthesis engine, inspired by supercollider with similar planned features to overtone, in clojure

11:59 the difference from overtone is that clojure will be used not just to define "instruments" staticaly and send events, but clojure will run inside the synthesis units themselves

11:59 TimMc: What's wrong with SC and overtone, one might ask.

11:59 justin_smith: see my last

11:59 TimMc: hmm

12:00 justin_smith: an actual programming language inside the synth

12:00 TimMc: Why not Lua? :-P

12:00 justin_smith: right now you have two languages - a weak one to run synths, and a powerful one on the client (controlling) side

12:00 csound has lua embedded, so that is an existing option

12:00 TimMc: (I don't actually know Lua, but it seems popular for fast and lean scripting.)

12:01 justin_smith: but this way we can use clojure, if we like it, and it's the full stack

12:01 starlord: mgaare: thanks, looking into it

12:02 justin_smith: TimMc: anyway, I find it interesting because Steven Yi knows his shit with audio synthesis (being one of the lead devs on csound for a while now). He has also been adding clojure inspired features to csound, maybe this is part of a master plan of some sort

12:04 TimMc: my experience, which I think is part of Yi's motivation, is that you have to juggle three layers of implementation to do serious work in most audio synthesis languages: the engine/plugins, written in C/C++, the synthesis language, made by chaining said plugins (not a full language by any means), and the control language, some kind of scripting language for building calls to and creation of said chains of plugins

12:05 TimMc: there is something very attractive about just using a reasonable language and flattening the three levels (if the language can handle all these roles)

12:06 TimMc: for example, in overtone you have macros that look like clojure code, but aren't, they are actually a DSL that emulates clojure but builds chains of plugins to run in the supercollider engine process

12:07 there's an overhead to remembering what's clojure and what's a DSL over scsynth

12:13 martinklepsch: anyone experience using nth-child selectors with garden? I can't require garden.selectors that contains some nth-child related things

12:13 TimMc: justin_smith: Interesting. I haven't played enough with Overtone to run into that.

12:25 starlord: Is there a channel-specific way to hide joins/quits/parts on the server-side?

12:27 amalloy: hide them on the server side? that doesn't make sense. the server has to tell you who's in the room; it's your client who decides what to print on your screen

12:27 starlord: Thanks.

12:28 I should edit my client then, becuase it only allows this toggle universally, not per-channel.

12:28 That resolves my question. Thanks.

12:30 TimMc: starlord: If you're using irssi it looks like /ignore -network freenode #clojure JOINS PARTS QUITS NICKS

12:30 eric_normand: does anyone know how to print out the profile names that are being pulled in with lein?

12:30 starlord: TimMc: Thank you in advance. I am not using irssi but thank you anyway.

12:30 I should use irssi, but I don't own a slicehost account anymore.

12:31 TimMc: The syntax may be similar for your client.

12:31 (particularly the level names)

12:31 starlord: I have tried it and saw no effect. I will perhaps ask in #limechat.

12:31 Thank you for your time in advance. Thanks.

12:33 What is a good alternative to slicehost for hosting your own persistent irssi between two computers these days? Thanks in advance, Regards.

12:33 Oh wait this is off topic now.

12:33 My apologies.

12:36 amalloy: starlord: you may be looking for what's called a bouncer. znc is a good one

12:37 starlord: Thank you amalloy in retrospect.

13:30 andonilsson: is it only possible to have one binding in an if-let?

13:31 ...and if I want more local bindings I should put them in a separate let, within the if-let

13:31 tanzoniteblack: andonilsson: correct

13:35 andonilsson: guess that makes sense

13:35 thx tanzoniteblack

13:35 justin_smith: ,(if-let [[a & bs] (range 5)] bs)

13:35 clojurebot: (1 2 3 4)

13:35 justin_smith: yes, destructuring works in if-let

13:36 wait, nobody mentioned destructuring

13:36 clearly I am out to lunch

13:36 starlord: Destructuring is probably the one feature I'd miss the most if I were to go back to Rails.

13:36 andonilsson: justin_smith: that might actually work in my case...I think

13:37 tanzoniteblack: destructuring inside an if-let and cause things to not quite work like you might expect:

13:37 ,(if-let [[a b c d e f] (concat (range 5) [nil])] f)

13:37 clojurebot: nil

13:38 tanzoniteblack: which makes sense, since if-let is only testing a, but if you're expecting it to be checking for all of the args to be truthy you're going to have some bugs

13:38 technomancy: ruby has destructuring, kinda

13:38 andonilsson: in my case I have a re-find in my if-let, so it'll work for me

13:38 amalloy: tanzoniteblack: it's not testnig a; it's testing the entire sequence

13:38 ie, testing that the sequence is neither nil nor false

13:39 tanzoniteblack: makes sense, thanks for the clarification amalloy

13:40 ,(if-let [[a b c d e f] (repeat 6 nil)] (boolean f))

13:40 clojurebot: false

13:45 splunk: anyone know how to get the name of anonymous fn? `(name (fn foo [] 42))`

13:46 starlord: Oh good question.

13:46 clgv: can I disable shrinking in test.check?

13:46 starlord: Another good one.

13:46 So far so good everyone, nice job.

13:47 Bronsa: splunk: you can, but that needs

13:47 splunk: but that needs to deal with how the compiler munges the generated classname

13:47 splunk: Bronsa: ah, so it won't be the symbol 'foo

13:47 Bronsa: splunk: why do you need it? the name of the anon fn is only usable from within the function

13:48 splunk: no, but ##(class (fn foo [])) you can get it back from this

13:48 lazybot: ⇒ sandbox5671$eval14042$foo__14043

13:48 splunk: Bronsa: trying to construct the following. given (fn foo ..) => {:f <fn> :name 'foo}

13:48 justin_smith: ,(if-let [[a & bs] (cons nil (range 5))] bs) ; tanzoniteblack it does not work like that

13:48 clojurebot: (0 1 2 3 4)

13:49 splunk: Bronsa: could do it with a custom macro, trying to avoid it

13:49 tanzoniteblack: justin_smith: yeah, amalloy pointed out that it's testing the entire sequence, not a

13:50 justin_smith: yeah, I'm still out to lunch, I see that now

13:50 splunk: Bronsa: or even just {'foo <fn>, 'bar <fn>}

13:50 amalloy: maybe you should have some actual lunch, justin_smith

13:51 Bronsa: splunk: (defn fn-name [f] (symbol (clojure.repl/demunge (first (clojure.string/split (last (clojure.string/split (.getName ^Class (class f)) #"\$")) #"__"))))) should work

13:51 amalloy: Bronsa: (class f) is already hinted to return Class; no need to hint it there

13:51 Bronsa: amalloy: oh, yeah

13:52 amalloy: but more importantly i'd lean towards "dude are you sure you really want to do this, it is a super-weird thing" and not "here is some gibberish you can paste into your program that will work most of the time"

13:52 llasram: (inc amalloy)

13:52 lazybot: ⇒ 156

13:52 splunk: Bronsa: you just blew my mind. Thanks! Will consider this carefully vs. the macro vs. none of the above.

13:53 arohner: if you're going to go the macro route, another option is to stick the 'real' name in metadata

13:53 llasram: splunk: OOC, why do you want these names?

13:54 technomancy: it's super annoying that the name isn't already in the metadata

13:54 splunk: arohner: thanks, I've been looking at metadata more and more, I don't have strong understanding of how it works (e.g. if it's associated with the symbol rather than the value, what if the values is bound to a different symbol??)

13:54 technomancy: though the arglists would be more useful than the name

13:54 llasram: Well, otherwise each instance would need to have a separate copy of the metadata map in case some one mut... Oh, wait

13:55 amalloy: Bronsa: clojure.repl/demunge is nice, though. i didn't know about that. but there are multiple munging schemes the compiler uses, right, for different scenarios? like the munging for a function name is different from the munging for the field of a deftype, i think

13:55 technomancy: <3 vary-meta

13:55 amalloy: i guess technically it should be spelled mungeing

13:56 arohner: splunk: I'm confused about your use of 'symbol' there. fns are just objects. There's no binding unless you use def or let

13:56 llasram: splunk: metadata is implemented via the `clojure.lang.{IMeta,IObj}` JVM interfaces. Any JVM type can carry metadata by implementing those interfaces

13:57 splunk: llasram: long story short: (defn make-ring-handler [db other-dep] (fn my-handler [request] <response-goes-here>)) ;; would like 'my-handler to be somehow associcated with the returned fn

13:58 the point of the gymnastics is so that `db` and `other-dep` are closed over in the handler

13:58 Bronsa: amalloy: TBH I don't think deftype fields get munged at all

13:58 arohner: splunk: I'd use metadata

13:58 technomancy: (inc metadata)

13:58 lazybot: ⇒ 1

13:58 technomancy: huh, just one?

13:59 llasram: splunk: Ok, but again why? Where are you intending to use the name?

13:59 amalloy: Bronsa: they do

13:59 ,(deftype Foo [-_$*x])

13:59 clojurebot: sandbox.Foo

13:59 amalloy: ,(seq (.getFields Foo))

13:59 clojurebot: (#<Field public final java.lang.Object sandbox.Foo.__$_STAR_x>)

13:59 amalloy: it's not even a reversible mungeing: you can't tell the _ apart from the -

14:00 Bronsa: amalloy: uh, ok

14:00 llasram: amalloy: Sure you can. '_' is culturally verboten in all identifiers

14:00 jonasen: Bronsa: That was a great read on the mailing list. You've done an amazing amount of work on these libraries!

14:00 amalloy: oh, llasram. treasure your youthful innocence

14:00 TimMc: snake_case_forever

14:01 * llasram wakes up and once more to his giant DB full of snake-cases key JSON-serialized data

14:01 llasram: wow, typing

14:01 ToxicFrog: snake-cases?

14:01 Bronsa: jonasen: thanks!

14:01 llasram: ToxicFrog: cf, typing

14:01 amalloy: ,(do (require 'clojure.repl) (clojure.repl/demunge "__$_STAR_x"))

14:01 clojurebot: "--/*x"

14:02 arohner: ToxicFrog: foo_bar, rather than foo-bar or FooBar

14:02 hiredman: metadata on functions is terrible, don't do it

14:02 TEttinger: gah, amalloy!

14:02 amalloy: demunge is *super* wrong for deftype fields. which is fine, since the docstring says it's for lambda names. just noting that there is another way to munge and it's not easy to reverse

14:03 Bronsa: amalloy: I was confused because (deftype x [-x]) (.--x (x. 1)) works, but it obviously works because field names in field access gets munged too

14:04 amalloy: ,(defrecord Bar [])

14:04 clojurebot: sandbox.Bar

14:04 splunk: arohner: thanks will check it out. disregard my comment about metadata on symbols, I was keying off http://clojure.org/metadata, which says it applies to symbols, or collections, but `(meta ^{:k "v"} (fn [] 42))` appears to totally work

14:04 Bronsa: also there are some places in the compiler where munging is just s/-/_/ but I can't remember where. probably just for namespaces

14:04 amalloy: ,(.---meta (Bar.))

14:04 clojurebot: nil

14:04 amalloy: ,(.-meta (Bar.))

14:04 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: No matching field found: meta for class sandbox.Bar>

14:04 arohner: splunk: probably old docs. meta got added to fns in 1.2? 1.3?

14:04 hiredman: splunk: don't do it

14:05 metadata on functions is terrible

14:05 arohner: hiredman: could you provide reasons rather than just asserting?

14:05 splunk: oh, one more question, is this just for debugging informative purposes, or are you running production code based on (meta f)?

14:07 splunk: llasram: arohner: long story short, I have a tree of functions, I am doing a tree traversal where I want to say "find fn in tree with id 'foo"

14:07 hiredman: arohner: metadata is implemented for functions as values, but functions as values for things like equality is very complex, the with-meta contract returns "new" value with the extra metadata, doing that for functions (bits of compiled byte code that close over state) is problematic

14:07 arohner: the way it is implemented in clojure also leaves a lot to be desired

14:07 dopamean: ive got sort of noob question if anyone is up for it.

14:08 amalloy: ~ask

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

14:08 hiredman: ,(let [f (fn [] 1) y (with-meta f {:a 1})] [(class f) (class y)])

14:08 clojurebot: [sandbox$eval187$f__188 clojure.lang.AFunction$1]

14:08 llasram: splunk: I'd recommend just associating a keyword name with the fn object when you build the tree.

14:08 arohner: splunk: that sounds.... strange

14:08 dopamean: thanks amalloy

14:08 arohner: hiredman: thanks

14:08 hiredman: metadata is almost always the wrong answer

14:08 dopamean: so ive got a vector of maps

14:08 llasram: splunk: No need to have the function object itself know its name, especially since that ties the name of the object implementation to the name w/in the context of your tree

14:08 ToxicFrog: hiredman: I like metadata :( it's been quite good to me in spellcast

14:09 Bronsa: also functions with metadata print horribly ##(with-meta (fn x []) {})

14:09 lazybot: ⇒ #< clojure.lang.AFunction$1@500d3200>

14:09 ToxicFrog: dopamean: a good start.

14:09 hiredman: given the contract of with-meta those instances should be equal, but given the equality semantics of functions, they are not

14:09 arohner: it's nice to have, but I don't use meta "in production"

14:09 hiredman: ,(let [f (fn [] 1) y (with-meta f {:a 1})] (= (class f) (class y)))

14:09 clojurebot: false

14:09 dopamean: all of them have the same keys in them and i want to return one of the maps where a given key returns a particular value

14:09 amalloy: i'm kinda bummed about that, bronsa, since i thought a ticked of mine improving the printing of that had been applied

14:09 technomancy: hiredman: that's an argument against calling vary-meta on functions and keeping the original function around

14:09 splunk: llasram: yeah that seems like the safe option, was hoping to not have to re-specify the name, but totally fine

14:09 technomancy: hiredman: adding metadata to a function and discarding the original doesn't run into those problems

14:10 amalloy: ,(with-meta (fn x []) {})

14:10 Bronsa: amalloy: it has, lazybot runs 1.4 though

14:10 clojurebot: #<clojure.lang.AFunction$1@597692>

14:10 hiredman: technomancy: it still does

14:10 amalloy: ah, yes. it prints slightly better in real life

14:10 Bronsa: amalloy: but I was talking about the lack of "x" in the class name, not about the extra space

14:10 dopamean: something like... [{"name" "nick"} {"name" "max"} {"name" "alan"}]. so if the name is alan i want to get back that entire map

14:10 hiredman: technomancy: you get an AFunction wrapper around the original function with all the problems of wrappers

14:10 technomancy: like say you have a macro that returns a function and you want to know the arities. doing that without metadata is terrible.

14:11 amalloy: dopamean: (first (filter #(= "alan" (get % "name")) maps))

14:11 TEttinger: damn that was fast amalloy

14:11 amalloy: although of course if you're doing lookups like this often, you should use a better data structure than a list of maps

14:11 TEttinger: (inc amalloy)

14:11 lazybot: ⇒ 157

14:11 splunk: arohner: yeah it's weird, but I'm playing with the concept that web routes are just a tree, which sort of makes a lot of sense to me. Similar to this: https://github.com/elliot42/siesta

14:11 dopamean: thank amalloy

14:11 ill play around with that

14:11 amalloy: TEttinger: i was bummed i couldn't use (comp #{"alan"} :name) because his maps have string keys

14:11 hiredman: technomancy: given that by definition metadata isn't considered when checking equality, should function arity information be part of the metadata?

14:12 technomancy: hiredman: that kind of question only makes sense if you have sensible equality semantics for functions to begin with

14:13 hiredman: technomancy: metadata on values only makes sense if you have sensible equality semantics for the values

14:13 which clojure doesn't for functions, so metadata on functions is a terrible idea

14:13 technomancy: that's an interesting assertion, but it appears groundless

14:13 ToxicFrog: amalloy: along similar lines, I keep getting tripped up by (some p xs) returning (p x) rather than x when it finds something.

14:13 hiredman: which one?

14:14 amalloy: ToxicFrog: yes, i hate the contract for 'some, but it's been water under the bridge for a long time

14:14 technomancy: the notion that metadata doesn't work with identity-based equality

14:14 you can put metadata on atoms, and they have identity-based equality

14:14 hiredman: technomancy: you skipped part of the assertion

14:14 technomancy: "metadata on values ..."

14:14 Bronsa: hiredman: we often use metadata as a way to work-around the lack of mutiple values returns, in that context metadata on functions makes sense

14:15 justin_smith: dopamean: amalloy: if doing frequent "name" lookups, there is always ##(group-by #(get % "name") [{"name" "bob"} {"name" "joe"} {"name" "al"}])

14:15 lazybot: ⇒ {"bob" [{"name" "bob"}], "joe" [{"name" "joe"}], "al" [{"name" "al"}]}

14:15 hiredman: technomancy: clojure effectively has two parallel metadata systems for values and identities

14:15 functions are plugged in to the value system

14:15 in a way that makes things terrible

14:15 technomancy: hiredman: this seems like a distinction you're inventing to defend your position

14:15 hiredman: technomancy: it isn't alter-meta vs. vary-meta

14:16 Bronsa: nah, that sounds pretty terrible too

14:17 Bronsa: hiredman: I partially agree, but I find it more useful than I find it "terrible"

14:17 technomancy: hiredman: oh, ok... interesting. there isn't any overlap.

14:17 I assumed vary-meta worked on identities, but it blows up

14:18 but I still agree with Bronsa

14:18 hiredman: Bronsa: using binding to setup a return stack seems better

14:18 technomancy: it's a much better way of expressing introspectable arity than the alternatives

14:19 Bronsa: hiredman: and use a map of fn -> value? I never thought about it

14:19 amalloy: Bronsa: not everything you want to return can support metadata anyway. what if i want to "multiple return" the values 1 and 2?

14:19 Bronsa: hiredman: I guess that could be an ok alternative, but that assumes you always have the thread-local binding set

14:19 hiredman: the problem is, functions are sort of values, have value metadata, but identity eqaulity due to Entscheidungsproblem

14:20 amalloy: Bronsa: well, you need something like multiple-value-bind to establish the thread-local binding that's set!-able by the function you're calling

14:20 mthvedt: hiredman: i don’t think it’s neccesary to solve the decision problem to have a meaningful definition of function equality

14:20 Bronsa: amalloy: yeah obviously, I was just making a case for fns

14:20 hiredman: Bronsa: no, I mean, logcally returns happen on a stack, a returning function pushes a value to return on to the stack, the caller pops it off the return stack to consume it

14:20 Bronsa: amalloy: hiredman with metadata the caller doesn't need to worry or even know about the fn having metadata attached if it doesn't care about it

14:21 hiredman: so you use binding to steup a thread local stack, and called functions push extra return values to it, and calling functions pop them off

14:21 amalloy: Bronsa: indeed, using metadata for multiple returns is a scheme that's easy to invent. i've done it myself. i just don't like it very much

14:22 technomancy: if only destructuring worked with metadata

14:22 * technomancy flees

14:23 hiredman: the problem with metadata is it is so easy to (mis)use that people grab it and use it for whatever terrible purpose

14:29 technomancy: anyway, I think it's pretty clear that just because functions have identity-based equality doesn't mean that they're intended to act as reference types

14:30 starlord: technomancy: you are correct.

14:30 technomancy: equality for functions is a very controversial topic and not widely agreed upon; in short, do not rely on testing functions for equality.

14:30 technomancy: I hope that helps. Thanks in advance. Regards.

14:31 bbloom: starlord: wait, what's controversial?

14:32 starlord: bbloom: Correct.

14:32 bbloom: function equality is proven undecidable

14:32 starlord: bbloom: You are correct.

14:32 bbloom: and clojure functions are compiled, so structural equality doesn't make sense...

14:32 and the default equality procedure is reference equality

14:33 soooo seems like a total no-brainer to me...

14:33 clojurebot: Excuse me?

14:33 technomancy: proven undecidable doesn't mean there's no way to know whether two functions are ever the same

14:33 I mean, for all pairs of functions

14:33 bbloom: technomancy: what good is an equality function that *sometimes* works?

14:34 llasram: true, false, FileNotFound

14:34 bbloom: yeah, seriously... equal, not-equal, and not-sure

14:34 starlord: bbloom: Now you see, it is controversial.

14:34 TimMc: true, false, and (System/exit 17)

14:34 bbloom: starlord: nope, still no controversy

14:34 technomancy: bbloom: I dunno, bloom filters are a thing? =)

14:34 sritchie: dnolen_: hey david, if you’re around, got a Q for you about component design

14:35 starlord: bbloom: Correct, there is disagreement.

14:35 bbloom: starlord: nope, there's a misunderstanding....

14:35 sritchie: dnolen_: working on the documentation site for this om-bootstrap project: https://github.com/racehub/om-bootstrap

14:35 starlord: Thanks in advance.

14:35 bbloom: technomancy: bloom filters implement a different contract

14:35 starlord: Regards.

14:35 bbloom: technomancy: the contract of equals (or clojure equiv) is that it provides a decision procedure

14:36 dnolen_: sritchie: actually gotta run, catching a plane

14:36 bbloom: technomancy: a heuristic procedure is, by definition, not Object.equals

14:36 dnolen_: sritchie: ping me later

14:36 technomancy: bbloom: I think could be room conceptually for another predicate, that's all

14:36 certainly not c.c/=

14:36 starlord: There are cases where two functions may be equal due to the same definition even though they are compiled as anonymous functions twice.

14:36 sritchie: dnolen_: has to do with prop mutation, I’ll write a mailing list note

14:36 Bronsa: starlord: can you please stop with thist "Thanks in advance. Regards" thing? it's honestly pretty annoying

14:36 starlord: I am not aware of whether Clojure optimizes this use-case.

14:36 sritchie: for sure, thanks!

14:36 starlord: Bronsa: Noted.

14:36 Bronsa: starlord: thanks

14:36 starlord: Bronsa: Pleasure.

14:37 bbloom: technomancy: now *that* is a controversy :-)

14:37 technomancy: whether or not having multiple defined equality predicates in your core language is a good idea, and if so which :-P

14:37 technomancy: bbloom: well, we have identical? and =

14:37 starlord: Imagine this line of code: (fn[] (fn[a b] (+ a b)))

14:37 It will return twice the same identical function, with no lexical captures. But are they equal? That is dependent on the compiler, even though we may infer that it clearly is.

14:38 It may not be, although that is up to the JVM compiler as well as the Clojure compiler.

14:38 technomancy: bbloom: and ==

14:38 starlord: Now this is clearly problematic: how can we rely on equality testing for functions if we don't know whether they will always return intuitive results?

14:38 hiredman: technomancy: I find this pretty funny given the arguments we've had were you insist egal solves everything and I say equality is difficult and the only reasonable thing is to have lots of predicates ala common lisp

14:38 starlord: Herein lies the initial problem.

14:38 bbloom: there are actually schema implementations that compare closures by comparing each closed over value

14:38 *cringe*

14:39 technomancy: hiredman: huh? I've never said egal should be the only predicate.

14:39 hiredman: just that egal is necessary but not sufficient

14:39 bbloom: one things certainly clear: egal is by far the best default

14:39 starlord: I hope this is now clear so that the confusion is resolved.

14:39 kirill: hi all, I'm new to clojure. someone recommended that I use this (https://github.com/abarbu/sanity). any thoughts on this from someone who knows more than I do (which should be anybody at this point)?

14:40 technomancy: hiredman: obviously you can't be self-hosting without having identical? so that seems like a bit of a straw man to begin with.

14:40 bbloom: i'd also argue that you can (in theory, but not as well in practice) encode any equality scheme in to egal by inventing new equality-class wrappers

14:41 amalloy: kirill: i would not touch this sanity thing

14:41 kirill: amalloy: how come?

14:42 amalloy: the readme indicates that it was written by a grumpy person with experience in some other lisp

14:42 technomancy: wow

14:42 kirill: yeah, this guy has no idea what he's doing

14:42 kirill: can you elaborate why he has no idea?

14:43 I mean, I'm happy to throw around accusations as much as the next guy, but you know what I mean :)

14:43 amalloy: the "improvements" he made don't fit with the rest of clojure, and if you use them you'll be writing this weird language that nobody but you or he can deal with

14:43 like, (seq ()) throwing an exception? that is the worst thing you could possibly do. it will break every function that exists

14:43 technomancy: kirill: he doesn't understand how syntax-quote's auto-qualification affects Clojure's macro system

14:44 amalloy: technomancy: well, i can sympathize with wanting something like #`. i've wanted it myself on occasion

14:44 sometimes i just want to build a list, not write a macro

14:44 bbloom: amalloy: there's backtick! :-)

14:44 TimMc: ,`(~@()) ;; wait, really?

14:44 clojurebot: nil

14:44 amalloy: ,`()

14:44 clojurebot: ()

14:44 bbloom: https://github.com/brandonbloom/backtick ; w00t

14:44 Bronsa: TimMc: I've already made a patch for that!

14:45 TimMc: This doesn't match the complaint-- oh, OK.

14:45 amalloy: Bronsa: just replacing the call to 'seq with a call to 'sequence?

14:45 technomancy: "The scoping of def and defn is broken yet for some reason they're still allowed outside the toplevel." doesn't really seem to understand what vars are either?

14:45 Bronsa: amalloy: correct

14:45 I can't find the ticket now because jira sucks

14:46 but trust me on that.

14:46 kirill: technomancy: eh... again I'm new here, but I don't find it productive to say "oh he doesn't understand what he's doing" without some more elaboration? I mean, I guess you seem like you know what you're doing, so can you elaborate what you mean?

14:46 bbloom: kirill: in short, he has invented a new language

14:46 kirill: his individual complaints/changes may or may not be a good idea

14:46 Bronsa: here http://dev.clojure.org/jira/browse/CLJ-1444

14:46 bbloom: but the result is "Not Clojure (tm)"

14:47 technomancy: kirill: he appears to be complaining about def's scoping, which indicates he doesn't understand that the point of it is to create a var, not to act like CL's setq

14:47 tanzoniteblack: kirill: at least for learning Clojure, it'd be a bad idea to use a library that attempts to completely re-write subsections of the language. The most obvious reason being it will be very difficult to get help on here or stackoverflow (or just google) with any issues you run into, because they very well might be caused solely due to those changes

14:47 llasram: Hmm, and he redefines some things in clojure.core. Like `let`

14:47 mthvedt: kirill: also, the docs suggest he doesn’t understand clojure’s decisions

14:47 always be suspicious of people who disagree with things they don’t understand

14:47 kirill: mthvedt: perhaps understands vs. agrees? :)

14:48 bbloom: some of the comments are kinda funny

14:48 alandipert: looks fun to me

14:48 all the best stuff seems to come from grumpy lisp people!

14:48 amalloy: i like bbloom's explanation

14:48 mthvedt: kirill: well, if a guy is creating a new way because he doesn’t trust a widely trusted existing way… the bayesian infrerence is his new way probably won’t make sense due to a lack of understanding

14:48 kirill: I dunno, I don't mean to antagonize anyone, but only about two people so far managed to provide some kind of productive explanations as to why they don't like it as opposed to "comments are kinda funny"

14:48 technomancy: my suspicion is he's a CL fan who was forced to write clojure and treats every divergence from CL as a mistake

14:48 mthvedt: like his comment about

14:48 lavokad: hi, how can fix "Fireplace: :Connect to a REPL or install classpoath.vim" message? I have classpath.vim install. Each time i want to use fireplace, i need to manually :Connect to running repl

14:48 mthvedt: This default behaviour (of quasiquote) leads to a lot of strange and broken code

14:49 kirill: mthvedt: I think he means that quasiquote has context-sensitive behaviour, which can produce surprises when you just need to construct a list?

14:49 llasram: kirill: He layers a different language on top of Clojure, by re-defining core constructs to support what he considers to be "more sane" interfaces/behaviors (usually CL/Scheme-derived).

14:49 bbloom: https://github.com/abarbu/sanity/blob/master/src/sanity/core.clj#L238-L244

14:49 weeee

14:49 what if i want tenth?


14:49 mthvedt: kirill: right, but the design goal of quasiquote is a way to write hygenic macros

14:50 llasram: kirill: The result will probably yield all sort of unexpected interactions, and will be a this little isolated tower of not-really-Clojure

14:50 kirill: mthvedt: do people write macros more often than lists in clojure?


14:50 bbloom: kirill: the tradeoff is different

14:50 hiredman: bbloom: ony can only hope he will fork the compiler and gnerate as needed

14:50 bbloom: kirill: most of the time when you create a list, you have the data you want in locals, or can get it via fn calls

14:51 amalloy: oh man. i was reading the description of https://github.com/abarbu/sanity/blob/master/src/sanity/improvements.clj#L115, and i misread it in a way that made me really interested

14:51 mthvedt: kirill: personally, i almost never use lists, unless you count calls to `cons`

14:51 bbloom: kirill: but when creating a list for a template, you want to stop evaluation

14:51 kirill: it's pretty rare you want to create a list that isn't code but also want to prevent evaluation

14:51 amalloy: i misread "bracketing" as "backtracking", because i'd also read the macro name as "conde"

14:51 technomancy: kirill: yes. since clojure has vectors, they're used more often than lists for literals.

14:51 mthvedt: the only time i can think of where i manipulate lists programatically is when i’m doing complicated macros

14:51 bbloom: kirill: yeah, and what technomancy said about vectors

14:51 technomancy: also symbols are used very rarely outside macros because of keywords

14:52 lemonodor: i am sympathetic to the cond (and let) bracketing complaint.

14:52 bbloom: i often want an `each` function, but he apparently hasn't seen doseq: https://github.com/abarbu/sanity/blob/12081bd2b61db5f58a8158827066a3e02a23eb20/src/sanity/core.clj#L249-L250

14:52 llasram: And evidence that he doesn't understand the language he's replacing: https://github.com/abarbu/sanity/blob/master/src/sanity/improvements.clj#L18

14:52 kirill: technomancy: what is the difference (practically) between using keywords and symbols?

14:52 jonasen: https://github.com/abarbu/sanity/blob/master/src/sanity/core.clj#L164 should obviously be renamed to tau

14:52 llasram: Which is a lot of work over (defn core-count @#'clojure.core/count) (if he really needed that)

14:52 technomancy: kirill: keywords evaluate to themself

14:53 kirill: llasram: sorry, but I can't take what you say seriously, because so far it seems like it's just direct accussations without backup :(

14:53 TimMc: kirill: I think it handles sequences better (nil != ()) but other than that it's not enough to justify a language replacement.

14:54 llasram: kirill: THat's why I explained. He says "it'd be nice if I could get a handle to these functions; oh well, now I'll copy-paste in a whole bunch of code instead". When really there's a simple way to get a handle to them

14:54 kirill: hmm so far this experience is somewhat strange. there are about 2-3 people here who are discussing things productively, and an array of people just posting insults and various troll-level messages that don't contribute anything. is this common for channels like this?

14:54 bbloom: kirill: the problem is the tone of the prose in the sanity project

14:54 ...even the name "sanity"

14:55 it reads like an attack, so people counter-attack

14:55 kristof: kirill: Yes.

14:55 technomancy: yeah, it's pretty clearly a troll to begin with

14:55 kristof: What's the context here?

14:55 hiredman: technomancy: and he didn't even bother to call it lava

14:55 amalloy: kristof: not really. #clojure is pretty friendly most of the time

14:55 kirill: but if we remember for a moment that we are not obligated to impress anyone, can we please discuss "sanity" in an objective manner such that we can hopefully do something productive here?

14:55 technomancy: "I'm forced to use clojure at work, but no one can force me to like it" afaict

14:55 TimMc: kirill: People also get tired of seeing these kinds of things over and over again, so people jump to ridicule pretty quickly.

14:55 technomancy: hiredman: missed opportunity!

14:55 kristof: technomancy: But, briefly, what's his/her problem?

14:56 amalloy: lemonodor: interestingly, you can define a let+ that supports both styles of bracketing

14:56 bbloom: kristof: decreased brain plasticity?

14:56 technomancy: kristof: CL superiority complex would be my guess

14:56 TimMc: bbloom: Not helpful.

14:56 kristof: Oh, well I've got one of those, so now I'm interested.

14:56 amalloy: (let+ [foo 1 (bar 2)] (+ foo bar)) ; the open paren doesn't make any sense in clojure's let, so this must be a lispy bracketing

14:57 kirill: bbloom: see? this is exactly what I'm talking about. you're probably a nice person, so why did you write that? we're not here to shit on anyone. the editorial choices of the dude on github don't have to turn all of us into insult machines =)

14:57 bbloom: sheesh, it was a joke...

14:57 kristof: I still don't know what this person even said.

14:57 kirill: a joke usually contains some element of cleverness or surprise at the end, which causes people to laugh. I didn't see that in that statement, which was just an insult

14:57 rweir: yowzer

14:57 kirill: so again, please...

14:58 TimMc: kristof: They linked to https://github.com/abarbu/sanity and people weren't impressed.

14:58 kirill: on the technical side, and if we ignore the editorial choices there, are there any *good* ideas in that repository?

14:58 amalloy: and you can do similarly with cond+, sorta: (cond+ (even? x) :even [(odd? x) :odd]); here it's a [ that doesn't make sense in clojure's cond, so you can use that to disambiguate

14:59 llasram: kirill: the `sanity.reader` namespace provides something which could be helpful, but bbloom's "backtick" does it better

14:59 technomancy: TimMc: oh, in some sense it's impressive; the level of dedication to his tribe. it's just not something that should be inflicted upon a Clojure beginner. =)

14:59 lavokad: hi, how can fix "Fireplace: :Connect to a REPL or install classpoath.vim" message? I have classpath.vim install. Each time i want to use fireplace, i need to manually :Connect to running repl

14:59 bbloom: kirill: defining infinity in core would be useful for clj/cljs compat

14:59 llasram: kirill: The `sanity.core` namespace has some reasonable-looking helpers, but there are many well-establish (flatland/useful, primsatic/plumbing)

14:59 tanzoniteblack: kirill: there seem to be some good ideas, like https://github.com/abarbu/sanity/blob/12081bd2b61db5f58a8158827066a3e02a23eb20/src/sanity/core.clj#L255 , but the problem is that that's already implemented in clojure core with mapv

14:59 amalloy: lemonodor: now, i wouldn't advocate actually using either of those macros, but it's neat that you can get the two styles of cond/let to coexist peacefully

14:59 bbloom: similarly, for the static functions on the java Math class

15:00 TimMc: kirill: The empty-seq-is-never-nil thing is good, but many of the other good things could just be used with Clojure as-is and do not demand a new language.

15:00 bbloom: tanzoniteblack: and mapv does it better too, with transients

15:01 amalloy: TimMc: i don't understand what you mean about the empty seq

15:01 mthvedt: timmc: i don’t agree with his complaints about seq equality, including that one. in clojure you are not supposed to generally compare seqs without putting them into the same data structure

15:01 because in both clojure and java, different data structures have different equality impls

15:02 kirill: mthvedt: is it appropriate to have a generic+deep+polymorphic equality tester for cases where the particular speed of the operation is of no consequence to the app in question?

15:02 bbloom: i genuinely don't understand how anybody can think it's a good idea to (def car first) (def cdr rest) ....

15:02 kirill: bbloom: why?

15:02 bbloom: i get it, you like car and cdr.... but really, clojure lists are always proper, so caddadadddr is never useful

15:03 kirill: bbloom: are some list selection procs (car, cdr, etc.) more frequently used than others?

15:03 hiredman: what I don't understand is why he doesn't just use a scheme or common lisp for the jvm, it seems like he would be so much happier

15:03 Bronsa: also frffrrffrest is so much better.

15:03 amalloy: bbloom: i don't think proper vs improper lists is terribly relevant to whether caddaaadadadr is useful

15:03 kristof: bbloom: There's a lot of anti-interface mentality in here.

15:03 lemonodor: bbloom: the issue of taking things typically used via java interop and moving them into clojure itself for consistency with clojurescript and other implementations seems like a thread that could be pulled on for quite a distance. do you have any general thoughts on that strategy?

15:03 bbloom: amalloy: it's somewhat relevant, but even more relevant is the fact that we have maps and destructuring :-P

15:04 TimMc: amalloy: I don't like punning nil with empty seqs. I agree with that author that it leads to too many problems.

15:04 kristof: bbloom: (def string-ref "Alias for clojure.core/nth" nth). What is the point of this?

15:04 bbloom: lemonodor: i think that if there is a function that is obviously available and consistent cross-platform, it should be surfaced in a non-interop way. however, i don't think we should try to patch up platform differences

15:04 TimMc: amalloy: That said, we're basically stuck with that.

15:05 amalloy: bbloom: did you ever see the with-cxrs macro i wrote, to bring the glory of caddaddddaaaadr to clojure?

15:05 bbloom: kristof: porting CL code?

15:05 amalloy: haha, yes, hilarious

15:05 kristof: bbloom: I don't know anyone who likes the fact that there are a million different "nth" implementations for every datatype in CL.

15:06 bbloom: kristof: no idea

15:06 mthvedt: kirill: i think if you’re comparing equality in a ‘generic’ way that ignores structure and behavior, that’s probably a code smell

15:06 bbloom: like i said, it's quite clear that this guy (knowningly or not) wants a different language

15:06 kristof: bbloom: Or the fact that there's a "copy-list" and a "copy-seq" which essentially do the same thing.

15:06 bbloom: and the beauty of lisp is that you can make any language you want

15:06 ... as long as it's another lisp

15:06 kirill: bbloom: I think anyone who introduces proposals for improving clojure wants a "different language". it's just that some of them make it and some don't..

15:06 bbloom: i take issue with his tone, however

15:07 kirill: there is no reason for you to feel personally offended by his tone. he probably doesn't know you and not writing it specifically to upset you :P

15:07 bbloom: kirill: there's a point when two cultures are separated for so long that their common language diverges in to two distinct languages, rather than two distinct dialects

15:08 amalloy: kirill: you seem offended by the things bbloom is saying, even though he's not saying them to offend you

15:08 bbloom: kirill: growing a language by adding definitions or idioms does not a new language make

15:08 amalloy: arguably this is because some of them are offensive, whether he intends it or not; the stuff in sanity is pretty offensive too

15:08 bbloom: kirill: replacing fundamental sentence structure? that's a new language...

15:08 kirill: amalloy: I'd like to avoid the one-uppery gymnastics just by pointing out that we're trying to discuss the technical aspects of that repository, nothing else..

15:09 bbloom: amalloy: other than the brain plasticity joke, have i said something offensive?

15:09 amalloy: bbloom: nothing that offends *me*

15:10 although for example "i genuinely don't understand how anybody can think it's a good idea to (def car first) (def cdr rest)" is a lot like "anyone who thinks this is bad at thinking"

15:10 bbloom: amalloy: well ok then :-P

15:10 Raynes: I want to know what happened but don't feel like all the ridiculousness in backlog.

15:10 AeroNotix: Same.

15:10 kristof: Raynes: Some guy posted a library that fixes things he doesn't like in clojure, and people find it silly.

15:10 bbloom: amalloy: no, i really think that it's a bad idea to define car and cdr on clojure list.... car and cdr are operations on pairs, not lists

15:11 Raynes: Oh, I see.

15:11 kristof: bbloom: Why does that change anything?

15:11 kirill: but lists are made of pairs, so the distinction appears academic at best

15:11 Raynes: So it immediately turned into a discussion not about his actual code, but about how offensive the response was.

15:11 kristof: A list is a pair whose cdr is another list or nil. *shrug*

15:12 Raynes: So, as per usual in these sorts of things, drama vs usefulness.

15:12 kirill: the fact that car "could" operate on an improper list doesn't change the fact that it can be used "safely" with proper lists?

15:12 bbloom: i think it's a perfectly reasonable idea to (def first car) and (def rest cdr) if you take the implicit restriction that first and rest are only defined for proper lists

15:12 ... made of pairs

15:12 kristof: Rest won't work on an improper list, right?

15:12 Then I agree with that sentiment.

15:12 xeqi: but I was going to use them on a vector

15:12 kirill: it will, but it will return a value such that (null? x) => #t

15:12 bbloom: xeqi: then you need polymorphism

15:13 :-)

15:13 kirill: I mean, that's in scheme, not clojure :)

15:13 amalloy: kristof: but lists actually *aren't* made of pairs in clojuer

15:13 kristof: amalloy: What? What the hell are they made of, then?

15:13 amalloy: or at any rate seqs aren't, and rest works on seqs, not on lists

15:14 kristof: No, I was talking about lists, not seqs.

15:14 AeroNotix: kristof: you can't do dotted pairs, either

15:14 bbloom: kristof: https://github.com/clojure/clojure/blob/43cc1854508d655e58e377f84836ba128971f90c/src/jvm/clojure/lang/PersistentList.java#L18-L20

15:14 they are counted and the "rest" must also be an IPersistentList

15:14 you can't put a non-list in the "cdr" cell

15:14 hiredman: what I don't understand is the persistent attachement to this library

15:15 AeroNotix: a link again to the library?

15:15 kristof: AeroNotix: yes, I'm aware.

15:15 TimMc: AeroNotix: *sigh* If I must... https://github.com/abarbu/sanity

15:15 kristof: Someone should just put it in the topic and declare Clojure dead.

15:16 hiredman: like "hey, I am new to clojure, is this any good" <a channel full of people, many of whom write clojure for a living> "no" <continued arguing>

15:16 kirill: hiredman: not sure what your point is :)

15:16 bbloom: hiredman: i've moved on to discussion pairs :-P

15:16 Raynes: In general, if you are one single person and you write a library called 'sanity' to fix an 'insane' language, you're probably kinda into yourself.

15:17 viperscape: lol

15:17 kirill: I suppose I ought to get information from a place where the level of discussion is more aimed towards the productive..

15:17 Raynes: "Hey guys, I've decided Clojure is insane and wrote this to fix it. Y'all best use it now."

15:17 kirill: I don't understand what's so hard in not making things personal

15:17 kristof: I wish I could inline assembly into clojure, and use go-tags, but *no*

15:17 bbloom: kirill: i take that personally.

15:17 kristof: This language is insane.

15:17 kirill: wow... okay, thanks to everyone who tried to help.


15:18 Raynes: kirill: People have addressed every single thing.

15:18 hiredman: kirill: my point is, you approached the channel as clojure novice asking if this is any good, and you got your answer from clojure experts, but you just seem to want to argue about it, which makes me wonder if you wrote this or something

15:18 Raynes: I don't know what more you're asking for.

15:18 Nobody is trying to be hateful, this guy was hateful first.

15:18 kristof: (def list->vector vec) (def vector->list seq)

15:18 kirill: hiredman: hah no, I didn't write sanity... this isn't my "shtick" where I write controversial (apparently) libraries and then pretend I didn't, hah

15:18 Raynes: From what I can tell reading backlog, people have picked this apart and proved that he lacks some fundamental understanding of the things he is trying to fix.

15:18 kristof: What exactly is the point of any of this library

15:19 Raynes: I'm not gonna give him a hug for that.

15:19 kirill: Raynes: they haven't "proved" it though

15:19 kristof: kirill: I've been posting examples this whole time

15:19 Like what I just wrote.

15:19 Raynes: kirill: You're the only person who turned this into a dramafest over whos being a big meanie.

15:19 kristof: (inc Raynes)

15:19 lazybot: ⇒ 48

15:19 AeroNotix: Instead of separating people into groups of "clojure experts" and "not clojure experts". It may behoove some of you to try to understand where some of these people are coming frm.

15:19 hiredman: kirill: sure, but you seem to have some emotional attachment to this library which makes you want to argue with #clojure when it is found wanting

15:19 starlord: "provides some functions which are more compatible with their better thought out Scheme counterparts."

15:19 AeroNotix: Some of the problems addressed here definitely are not without merit

15:19 starlord: zing!

15:20 kirill: Raynes: I called attention to the fact that people jumped on the bandwagon of insulting a person who's not even here, and making blanket statements like "this guy doesn't know what he's talking about" etc.

15:20 kristof: AeroNotix: since when did you start idling this channel?

15:20 AeroNotix: kristof: dunno, ~year ago?

15:20 Raynes: Because he bloody doesn't, and people have provided you with examples why.

15:20 kristof: AeroNotix: ...then when did you start idling #lisp?

15:20 AeroNotix: kristof: about ~2 years ago

15:20 kirill: hiredman: again, let's cut the ad hominem and stick to the facts. I'm just a person who's trying to find out information, and instead it sounds like people are just trying to bully anyone who smells like they might be "against the family"

15:20 kristof: Weird

15:20 AeroNotix: kristof: why?

15:20 ToxicFrog: kirill: you asked what people asked of the library, and their analysis is "this library was written by someone who doesn't know what they're doing".

15:21 hiredman: ad hominem?

15:21 ToxicFrog: And they have explained why.

15:21 kristof: Woah! Everyone stop! Do-over. Fresh plate. Someone ask a question, someone answer.

15:21 ToxicFrog: *what people thought.

15:21 arrdem: hiredman: argumentation technique based on personal insults

15:21 Raynes: This is ridiculous.

15:21 ToxicFrog: Raynes: I concur.

15:21 lemonodor: kirill: there’s always an aspect of that, because people are not abstract logic machines. but if you filter out the nonsense, it does seem like people have posted some concrete criticisms.

15:21 AeroNotix: ANYWAY


15:21 kristof: Don't you mean

15:21 arrdem: not I...

15:21 lemonodor: (and there’s always nonsense, so filtering it is a useful skill)

15:21 kristof: A hunk

15:21 nudge nudge

15:21 * TimMc swoons

15:23 llasram: A chunk?

15:23 No, wait. There's totally a better one with hunked-seqs in there somewhere

15:24 starlord: Please help me understand what `(~@(map (fn [x] (+ x 1)) '(1 2 3))) is supposed to do.

15:24 xeqi: does this fall under sexist behavior?

15:24 Raynes: I'm always entertained when this sort of thing happens and it's like one guy says this one thing that effectively everyone disagrees with, and the few supporters of the guy stop talking about the actual problem and turn it into some sort of minority hate crime crap. "against the family". This dude isn't rebel forces, he's just a guy with some opinions that most folks don't agree with. That's all.

15:25 Bronsa: starlord: return '(2 3 4)

15:25 llasram: xeqi: I think it might be inappropriate sexual comments, but which in this context are not sexist

15:25 kirill: Raynes: the fact that everyone disagrees with one person certainly has no impact on the validity of that person's statements or questions? just trying to figure out how this works

15:25 oskarkv: I wrote (defprotocol Something (some-fn [this] [this arg])) How should I write the code in defrecord to define the two versions? Also, what does "java.lang.AbstractMethodError: Method something.auto_size(Ljava/lang/Object;)Ljava/lang/Object; is abstract" mean?

15:26 Raynes: The fact that everyone disagrees with this person should be making you think "Wow, maybe this library is really bad.", but instead you've jumped straight into "THE MAN IS KEEPING US DOWN!"

15:26 Bronsa: oskarkv: (defrecord x [] Proto (f [_]) (f [_ _]) ..)

15:26 mthvedt: oskarkv: you probably forgot to implement a method in your deftype/defrecord

15:26 Raynes: Anyways, we've appeared to have moved on. I'd be happy to keep having a meta discussion in private if you like.

15:26 TimMc: (inc Raynes)

15:26 Raynes: we appear*

15:26 lazybot: ⇒ 49

15:27 kirill: Raynes: really? is this how it works? 7 people on the internet said a library is bad, so I'm supposed to just go "yeah I guess it's bad because these guys say they write clojure for a living..." ? are you serious?

15:27 Raynes: Are you serious?

15:27 Why did you even ask about this library/

15:27 llasram: Let's take a vote -- who here (a) writes Clojure for a living, and (b) is in favor of using `sanity`, especially for a newbie?

15:27 TimMc: Please take this to #sanity-shitfest-and-misunderstanding-gala

15:27 Raynes: You clearly didn't want truthful responses.

15:28 TimMc: llasram: Can we *not* feed this?

15:28 llasram: In the interest of reducing channel clutter, I'll assume any non-yays are nays

15:28 hiredman: clojurebot: the answer?

15:28 clojurebot: the answer is 42

15:28 llasram: TimMc: Ok, that's fair

15:29 Raynes: kirill: https://www.youtube.com/watch?v=lDlofPAOZy0 relevant to both of us

15:29 starlord: Did someone in here write sanity?

15:29 oskarkv: Bronsa mthvedt thanks

15:29 arrdem: (inc Raynes)

15:29 lazybot: ⇒ 50

15:29 starlord: Also why is `(~@(...)) around it?

15:30 AeroNotix: I think a lot of the butthurt in here might be caused by the wording of the README. Calling a lot of core.clj "broken" is not a way to entice Clojurians.

15:30 kirill: I think the issue might be that people take it personally when a tool they use is being insulted(?) by someone else

15:31 AeroNotix: Sure, ego and time invested into learning something are hard to separate. That's not unique to clojure

15:31 kirill: and then they just defer to the person who memorized the most docs to jump on the bandwagon of like "yeah this guy clearly has absolutely nothing to say... let's get back to the echo chamber now"

15:31 Raynes: http://www.thestate.ae/wp-content/uploads/2012/04/running-in-place-2.gif this is us right now.

15:31 starlord: kirill: who recommended you use sanity?

15:32 AeroNotix: kirill: if this has really affected you, I suggest a quick walk to clear your head or something. Programming shouldn't make you mad.

15:32 kirill: starlord: I was just cruising some clojure repositories on github and this one seemed curious because I have a Scheme background. I don't profess that Scheme is "superior" to any other language, but it looked interesting

15:32 llasram: kirill: But *no one* in this channel thinks this library is something you should use. It's not just the loudest people being heard

15:32 Raynes: kirill: Dude, can you please go to http://logs.lazybot.org/irc.freenode.net/%23clojure/2014-08-13.txt and re-read this whole conversation.

15:32 ToxicFrog: kirill: so, do you actually care about people's opinions on this library? If not, why did you ask in the first place? If so, why are you dismissing those opinions as "echo chamber" and similar?

15:32 Raynes: If you read what you've said and what everyone else said one more time and still feel the same way, I give up.

15:33 kirill: ToxicFrog: I care about their opinions, but not when they're not backed up by anything and/or consist entirely of blanket claims

15:33 Raynes: Dear God.

15:34 technomancy: Let's talk about Rust. How do you feel about Rust?

15:34 I enjoy algebraic data types with my morning coffee.

15:34 arrdem: Raynes: best thing since sliced bread if you absolutely have to write something C like...

15:35 ToxicFrog: kirill: except that people have repeatedly explained, in detail, why they hold those opinions, and you have casually dismissed and ignored those explanations out of hand.

15:35 Raynes: arrdem: And want to change your code every 45 minutes as releases are pushed.

15:35 ToxicFrog: no. stop. bad

15:35 No more talking to kirill. I'm banning it.

15:35 (about this topic)

15:35 kirill: hah :)

15:35 arrdem: Raynes: I look forwards to the day that Rust 1.0.0s at which point I will drop literally everything and hack rust for several months. Until then I just like the idea of rust.

15:35 Raynes: (please do keep talking to him about other topics)

15:36 ToxicFrog: I really should try Rust one of these days, but for now I'm having fun with Clojure and honestly not sure what I'd use Rust for.

15:36 Raynes: arrdem: Yeah, I really just want some stability before I start using it. Most of what I write is http stuff and I need a stable http client as well. There isn't a very good one, but there is a very good one in active development.

15:36 ToxicFrog: If it's ABI-compatible with C, maybe it would be a good choice for writing lua libraries in.

15:37 arrdem: ToxicFrog: My last non-GSoC job was writing sub-OS level software. Rust woulda been really nice for that.

15:37 rweir: ToxicFrog, it is!

15:38 lemonodor: aspiring bloggers might see the sanity library as fuel for an educational post, critiquing the good and bad from a position of experience…

15:38 ToxicFrog: arrdem: yeah, my industry work prior to this job was all kernel/driver stuff, and my thesis work was embedded systems -- but the former was in an established C++ codebase and the latter used a custom compiler that only understood a bastardized dialect of C.

15:38 It would have been useful back when I was doing a lot of Lua extension work, but that hasn't been for a few years except for vstruct, which has no C code at all.

15:39 starlord: I am liking Lua.

15:39 ToxicFrog: It's one of my favourite languages, although I've been increasingly moving to clojure for things more than a page or two long.

15:40 starlord: ToxicFrog: Why?

15:41 ToxicFrog: I've still got three major lua projects, emufun (HTPC frontend using the love2d engine), ss1edit (editing tools for System Shock), and vstruct (a binary data wrangling library used by ss1edit)

15:41 arrdem: how's it stood up? I've only ever used LUA for scripting my WM, and for that it didn't prove as modular as I would like.

15:41 ToxicFrog: starlord: library management in clojure with lein is way more convenient than it is for lua, deployment is generally easier with lein uberjar (it's a nightmare on windows, but so is lua)

15:42 starlord: ToxicFrog: Oh I see, so mostly just the tooling is nicer? Do you have any preference over the language itself?

15:42 ToxicFrog: I would still wholeheartedly recommend lua for scripting/configuration uses, but I've moved away from it for standalone programs.

15:42 (because in the former case, you can safely assume that the host program has solved all library/deployment issues for you)

15:42 (usually)

15:44 AWizzArd: I don’t know what version of Cider I’m using in Emacs, but it’s a few months old. Quick test: type this into your repl: (defn foo [& {:keys [a] :or {a 1/2}}] a). Now just type “(foo” and hit <space>. This crashes my emacs, and I see this error message:

15:44 ToxicFrog: Also, Lua's embedding API is excellent.

15:44 AWizzArd: ERROR: Unhandled REPL handler exception processing message {:id 28, :op info, :session 27d6fa9b-98a1-41ed-b818-1102fe9942eb, :ns user, :symbol foo}

15:44 arrdem: yeah LUA has done really well in all the embedded contexts I've seen it, I just can't imagine architecting a large (1k+LoC) program in it.

15:44 AWizzArd: java.lang.IllegalArgumentException: Cannot write value of type class clojure.lang.Ratio

15:45 Emacs wants to display the function signature and there are problems displaying ratios, for some reason.

15:45 ToxicFrog: As for the language itself -- it's minimal but in a good way. Readable, very easy to learn. Simple but powerful. I do miss macros, though; metalua is no replacement and it's awkward using pcall/error rather than (try+).

15:46 And yeah, there's not much for making large programs in it tractable the way you can get, say, bolt-on static type checking for clojure.

15:46 Its compiler is a lot better than clojure's, though :P

15:46 arrdem: they also have LuaJIT which is literally magic :D

15:47 ToxicFrog: Yeah, luajit is kind of awesome and I hope love2d moves to it at some point.

15:47 I actually have a medium-sized game idea kicking around that, if I ever write, I'll probably write in lua using love2d.

15:47 starlord: ToxicFrog: Wait, Lua's compiler is better than Clojure's?

15:48 ToxicFrog: starlord: mostly that was a jab at the clojure compiler's shit-awful error handling

15:48 starlord: ToxicFrog: I thought the advantage of Clojure's was that it just compiles to straightforward JVM bytecode, and thus has all the power of the JVM behind it.

15:48 ToxicFrog: I don't actually know enough about e.g. compiler internals to compare their code generation or the like

15:48 starlord: Oh.

15:48 ToxicFrog: So mostly you prefer Lua, but like Clojure macros for the sake of (try)?

15:48 ToxicFrog: As far as VM shootout goes, the Lua VM is actually very well designed and tiny, and the LuaJIT VM is larger but blazing fast.

15:49 Jaood: starlord: that's an advantage or disadvantage, depends on how you see it ;)

15:49 starlord: Jaood: what is?

15:50 ToxicFrog: starlord: no, I wouldn't say that. I like both for different reasons. Clojure, being a lisp, honestly doesn't have that much "language" in the sense of built-in syntax and stuff, it's mostly libraries (core and third-party) -- and clojure's libraries make it way more convenient to develop stand-alone stuff in than lua.

15:50 Jaood: starlord: compiling to JVM bytecode

15:50 ToxicFrog: It also, IME, tends to be more concise and easier to debug when it goes wrong, albeit harder to read at first glance.

15:52 starlord: Basically I would say, in a vacuum, I think clojure is a better language with better libraries. But lua is faster, smaller, easier to embed, has a lower barrier to entry, and is generally more newbie-friendly, which gives it an advantage in specific areas.

15:52 starlord: ToxicFrog: So far it sounds like most of what you like about Clojure is that it is batteries-included (i.e. like Python, Ruby), and that it has very easy and consistent dependency tooling.

15:53 arrdem: $google computercraft

15:53 lazybot: [ComputerCraft | Programmable Computers for Minecraft] http://www.computercraft.info/

15:53 arrdem: ^ lua embedded awesome

15:53 ToxicFrog: ...which is kind of just a long-winded way of saying that I think clojure is a better general-purpose language and I think lua is much better at the specific purpose it was designed for

15:54 For a while I used lua as my primary programming language, now I'm moving to clojure for general purpose stuff and lua for embedding stuff.

15:54 starlord: ToxicFrog: Have you used Lua with a batteries-included library?

15:54 I've seen a few on github but can't remember their names.

15:54 ToxicFrog: starlord: a few, yeah. The problem is that there's still nothing nearly as good as lein uberjar for actually distributing the result.

15:54 starlord: Right.

15:54 Okay I think I understand fully now.

15:55 ToxicFrog: Like, luaforwindows is batteries included. But I also want to distribute my program on linux. Do I build linux versions of all these libraries and ship with? Tell them to use the package manager? What if I depend on something that's in luaforwindows but not, say, the Fedora repositories?

15:55 xeqi: hmmm, I wonder how much lein contributes to clojure being useable

15:55 arrdem: xeqi: massively

15:55 xeqi: if I had to deal with bare jars I'd probably still be writing python

15:56 ToxicFrog: So, for personal work, those things are great. For distribution, you can manage it, but it takes a lot of effort, whereas with clojure I can just go 'lein uberjar' and get one file that works everywhere* and contains all the dependencies.

15:56 * offer not valid on windows machines on days ending in y

15:56 TimMc: AeroNotix: "Programming shouldn't make you mad." <-- I think that means you're not programming hard enough. :-P

15:56 xeqi: arrdem: theres maven

15:57 llasram: I will take this occasion to

15:57 (inc technomancy)

15:57 lazybot: ⇒ 130

15:57 arrdem: xeqi: true but it's not completely retard proof like lein, thus requires effort

15:57 AeroNotix: TimMc: I forgot to add "... at people"

15:58 starlord: ToxicFrog: This is the same conclusion I've come to, mostly.

15:58 xeqi: $google why you heff to be mad

15:58 lazybot: [Why you heff to be mad? (Original) - YouTube] http://www.youtube.com/watch?v=xzpndHtdl9A

15:58 starlord: ToxicFrog: I've used Ruby and Python for about 4 years, Clojure for 2, and Lua for 6 months. So far I'd agree that Lua is not great for distributing whole programs unless they're embedded in a host which takes care of all dependencies.

15:59 TimMc: AeroNotix: I dunno, ever worked with legacy code?

15:59 starlord: ToxicFrog: However, I would use Ruby for one-off programs since it feels considerably lighter-weight to me than Clojure (i.e. any JVM language).

15:59 TimMc: It also sometimes makes me mad at myself.

16:00 starlord: ToxicFrog: I admit that I don't like Ruby as a language, but relatively speaking, Clojure isn't better enough to make it worth waiting for the JVM.

16:00 ToxicFrog: starlord: for me -- python 2 years, clojure the same, lua 10 or so. Ruby not at all, I dabbled in it but didn't like the taste of either the language or community.

16:00 Jaood: we need a Clojure in C !

16:00 starlord: I like that I can write Ruby in most editors without needing special plugins.

16:00 ToxicFrog: For one-off programs I generally use lua or python, depending on what kind of library capabilities I need. Or bash for really small things.

16:01 starlord: ToxicFrog: fwiw, Ruby and Python are mostly equivalent

16:01 ToxicFrog: starlord: Ruby's syntax and feature set makes me think it was designed by someone who thought perl was a good idea but didn't go far enough~

16:02 Also, I looked at like three Ruby tutorials and all of them were incredibly condescending and pretentious

16:02 To date I have not ever had to work on someone else's Ruby code and thus have not regretted not pursuing it further

16:03 llasram: starlord: There are some pretty significant differences in the communities and available libraries, but yeah -- what the language semantics let you do easily are super-close

16:04 Jaood: there's also mruby now which can replace lua use cases

16:04 justin_smith: for a light weight, concise, high level language, with low startup time and runtim performance, ocaml is pretty hard to beat

16:05 that and was too ambiguous: low startup time, and great runtime performance

16:06 AeroNotix: justin_smith: terrible concurrency story though

16:06 in the same league as python

16:06 justin_smith: no worse than python or ruby really

16:06 but yeah, true that

16:06 lemonodor: i’d kinda love to use clojure on raspberry pi/beaglebone, but it’s sooo slooow on those platforms.

16:07 AeroNotix: lemonodor: which aspects of clojure interest you?

16:07 technomancy: racket is great on arm

16:07 AeroNotix: because there are many dialects of Lisp

16:07 ToxicFrog: Oh right, that's the other thing. If I were doing cluster computing I'd use Lua, at least for all the glue.

16:07 justin_smith: lemonodor: I wonder if the lower in-memory size with clojure-clr would help

16:07 ToxicFrog: Mostly because I have Lua bindings for a message-passing library (Pilot) on top of MPI and I like that a lot more than C.

16:07 lemonodor: i wonder if dalvik could run on beaglebone/raspberry

16:11 ToxicFrog: Back to Clojure for a moment -- my main objections are the slow startup time (which prevents me from using it for small scripts), the unpleasantness of developing in it without lein (ditto -- I can't just start something with #!/usr/bin/clojure and toss it in in ~/bin), and the compiler (which is the main reason I'm hesitant to recommend it)

16:11 Raynes: I can't think of a non-Go language that is easy to develop without some sort of tooling like lein.

16:12 justin_smith: lemonodor: I see references here and there to a thing called "alien dalvik", I dunno if it is available for raspberry pi though, seems people are using it on ios?

16:12 ToxicFrog: Raynes: lua and python come to mind :P

16:12 No compilation needed, I can just whip out a script, give a #! line and away it goes.

16:13 For python I can even split it into multiple files, then zip them and make the zip +x and it just works.

16:13 Although at that point there is an Actual Build Step.

16:14 Raynes: ToxicFrog: uh

16:14 ephemeron: ToxicFrog: For scripting, you might want to check out https://github.com/tailrecursion/boot. (I have not tried it yet.)

16:14 technomancy: Raynes: racket is like that

16:14 Raynes: ToxicFrog: Go try to write me a couple Python projects without virtualenv, pip, and setuptools.

16:14 ToxicFrog: If I look in ~/bin/ basically everything there is bash, lua or python. One is a symlink to a python-zip. Five or so are binaries compiled from C.

16:14 Raynes: Distribute some libraries, programs, write a website.

16:14 Do it all without any tooling.

16:14 ToxicFrog: Raynes: I've never used any of those soooooo

16:14 AeroNotix: ToxicFrog: *never* ?

16:14 ToxicFrog: Wait, no, I lie, I used pip once to install the dependencies for a FUSE module

16:14 Raynes: Can you show me some of your Python projects?

16:15 fading: I tried helloworld in ClojureCLR and was suprised how long it took to print

16:15 AeroNotix: Do you write Python professionally?

16:15 Raynes: I do.

16:15 AeroNotix: Raynes: who doesnt

16:15 fading: Whereas F# helloworld was instantaneous

16:15 Raynes: You literally cannot use Python without virtualenv. As soon as you need one single thing installed with pip, you're totally screwed.

16:15 ToxicFrog: AeroNotix: yes, but at my job we have our own custom tooling for everything; I'm just talking about one-off scripts here.

16:15 Raynes: Sure, you can write random scripts and execute them without dependencies and dependency management.

16:16 ToxicFrog: Raynes: bear in mind that the context is writing 1-2 page scripts for personal use, not production-quality release software

16:16 Raynes: Yeah, I still wouldn't do that without a virtual environment.

16:16 ToxicFrog: I can do that in python without tooling or any sort of build phase, I can't do the same in clojure.

16:16 Raynes: I'd rather not completely destroy my system package index.

16:16 Sure you can

16:16 AeroNotix: Raynes: what does "completely destroy"?

16:16 ToxicFrog: As for released software in python, I believe I only have one, https://github.com/toxicfrog/misc/tree/mo

16:16 Raynes: It's gonna startup slow, but you can do it with just clojure.jar.

16:17 AeroNotix: if all your serious projects use a venv, one-off scripts should be fine to fubar everything

16:17 llasram: AeroNotix: Python packages are not guaranteed to be uninstallable

16:17 AeroNotix: llasram: and?

16:17 ToxicFrog: Raynes: so, how much setup do I need to get to the point where I can write a script in clojure, chmod it a+x, and run it from the shell?

16:17 Raynes: AeroNotix: Develop two projects. Have dependency with transitive dependency on two different versions of the same library.

16:17 ToxicFrog: Because that's the bar to clear here.

16:17 Raynes: AeroNotix: boom without virtualenv.

16:17 AeroNotix: Raynes: one-off scripts vs projects

16:17 a script I'm writing to parse some turds out of a file does not need a venv

16:17 Raynes: If your one-off scripts never require dependencies, then you're good to go.

16:18 seangrove: Virtualenv burrito is pretty nice for python, from what I hear

16:18 Jaood: ToxicFrog: with java -cp clojure.jar clojure.main script.clj

16:18 Raynes: But I think it's silly to make that assumption and even more silly to champion one language over another for making this arguably not that useful use-case easy.

16:18 ToxicFrog: The only one that requires deps outside the python stdlib is the one I just linked, which requires mutagen

16:19 Raynes: But yeah, you can do exactly the same thing with a shebang like Jaood demonstrated. It'll just be slow, of course, so Python is clearly a better choice.

16:19 But I don't think tooling is the reason.

16:20 Jaood: Raynes: do you prefer Python over Ruby?

16:20 ToxicFrog: Jaood: and where do I find clojure.jar? Because locate sure doesn't know of it.

16:20 Raynes: Jaood: Yes.

16:20 I have Rails 2 PTSD.

16:20 Jaood: ;)

16:21 Raynes: ToxicFrog: clojure.org probably still offers clojure jar downloads. Otherwise, find it in your ~/.m2 folder where maven has stored it already.

16:21 xeqi: ToxicFrog: if you've already used lein, then ~/.m2/repository/org/clojure/clojure/1.6.0/clojure-1.6.0.jar for the right version

16:21 Jaood: ToxicFrog: well it should have a version in it clojure-1.6.0.jar

16:21 ToxicFrog: Raynes: well, I had three objections, of which tooling was only one of them; and I still maintain that '#!/usr/bin/python' is easier to remember than '#!/usr/bin/java -cp /path/to/wherever/the/hell/clojure.jar clojure.main'.

16:22 Aah, I was just looking for 'clojure.jar', without version number.

16:22 technomancy: #!/usr/bin/env lein run -m clojure.main

16:22 ^ is a thing that might work?

16:22 Raynes: Yes, clearly, but my point was more that "Oh look, I can just write this one off script. *writes 70% of one-off script*; oh shit, I need that library..."

16:22 ToxicFrog: technomancy: you can use lein run outside a lein project directory? I'll try that.

16:22 Raynes: I prefer to just start with an actual project from the beginning.

16:22 AeroNotix: Raynes: I just install that library globally. #yolo

16:23 mocker: heh

16:23 justin_smith: fading: I was mainly thinking the lower memory usage, but looking at a 1:1 comparison it's not a huge margin

16:23 technomancy: ToxicFrog: yeah, it starts in like half the time too

16:23 ToxicFrog: Raynes: yes, and then I go "zypper in that-library" and keep on trucking, at least in python/lua

16:23 Jaood: lein run will startup slower than just java -cp clojure.jar ...

16:23 Raynes: ToxicFrog: https://github.com/Raynes/basement makes it really easy to go from zero to executable properly structured Python program here.

16:23 Jaood: ToxicFrog: ^^

16:23 technomancy: err ^^

16:23 ToxicFrog: Well, 20% of the time I do that, the other 80% of the time it was already pulled in as a dependency by something else

16:23 technomancy: Jaood: only inside a project dir

16:23 justin_smith: fading: that is, comparing java -jar <path to>clojure-1.4.jar and mono clojure-1.4.exe

16:23 starlord: ToxicFrog: Sorry to delay, just had a meeting.

16:24 ToxicFrog: Raynes: you are completely missing my point, which is that my goal is to be able to dash off quick scripts with zero setup or deployment overhead.

16:24 lemonodor: yes, python needs a lein!

16:24 ToxicFrog: Python satisfies that handily.

16:24 Raynes: You're missing my point, which is that I think that's bad.

16:24 AeroNotix: Raynes: why do I need my shitty turd parser to have a setup.py?

16:24 starlord: ToxicFrog: I have seen good and bad code in both Ruby and Python, and good and bad documents and community activity in both also. I don't hold it against either of them.

16:24 Raynes: If you knew how much of that shit I've had to clean up over my very brief Python career, perhaps you'd be more sympathetic I suppose.

16:24 AeroNotix: Raynes: dude we all work with shit

16:24 Raynes: don't play that card

16:24 ToxicFrog: Raynes: yes, and at work, or for things that I'm actually releasing, I take more care

16:24 AeroNotix: that's not even an argument

16:25 Raynes: AeroNotix: ...?

16:25 Jaood: ToxicFrog: oh ok

16:25 technomancy: I just write elisp for quick one-off scripts

16:25 starlord: ToxicFrog, llasram: I personally have found that both communities tend to rely a little too much on inheritance, but the only time I found this to be excessively painful was when using Python's 'twisted' library.

16:25 AeroNotix: technomancy: but you obviously hate yourself

16:25 technomancy: ... why is everyone looking at me funny

16:25 Jaood: err technomancy I mean

16:25 Raynes: AeroNotix: I'm asking him to not *create* the shit we all work with. Not claiming I'm the only person who has ever worked with 'shit'.

16:25 ToxicFrog: Raynes: but not when I want to use /usr/share/dict/words to cheat at scrabble, or quickly scrape a website for some data, or download the complete Pterodactyl Squad discography

16:25 AeroNotix: Raynes: why would you be using his one-off scripts?

16:25 technomancy: AeroNotix: I've actually been switching to racket for that stuff

16:25 * Raynes rolls his eyes

16:25 starlord: justin_smith: I have not gotten into OCaml nor seen a good reason to use it over Ruby for the tasks I wan to accomplish.

16:25 Raynes: Okay kids.

16:26 I'm gonna go back to work now.

16:26 AeroNotix: Raynes: Just seems a funny thing to care about how untidy someone else leaves their site-packages when it doesn't affect you

16:26 Raynes: lol

16:26 AeroNotix: He said many times that in real projects he takes more care

16:26 Raynes: Okay.

16:27 technomancy: throw-away code is great if it actually gets thrown away

16:27 AeroNotix: I'm definitely not rolling out a requirements.txt or setup.py to run some quick numbers or make a few scripted HTTP call

16:27 s

16:27 Raynes: I sure am

16:27 starlord: I like Lua from a language standpoint - very lightweight, small, minimalist. But in practice, it's hard to write stand-alone programs in it.

16:27 AeroNotix: Raynes: learn to not waste time

16:27 Raynes: Because it's literally just 'ment athing'

16:27 technomancy: and that's why we need to develop a mechanism for programs that literally self-destruct after a given time

16:27 ToxicFrog: technomancy: mine actually lives in ~/bin/ forever and ever because sometimes I do actually need it again years later, to be honest.

16:27 starlord: I wrote this documentation scraper pretty quickly in Ruby: https://github.com/mjolnir-io/core.window/blob/master/gendocs.rb

16:27 fading: and virtualenv is pretty recent right? I mean I remember seeing how proud various IDEs where that they supported it now

16:27 Raynes: AeroNotix: You're getting a tad out of line.

16:28 starlord: I considered rewriting it in Lua, but it was too impractical. Ruby's standard libraries wouldn't have been available, so I would have had to write `map` myself, for example.

16:28 Raynes: Lets take this to PM.

16:28 AeroNotix: It's IRC, not a playgroup.

16:28 aperiodic: lemonodor: the most performant way to get clojure onto a raspberry pi or similar is to use clojurescript & node.js. the JVM can be run on it but it's a bit heavyweight for the platform

16:29 lemonodor: aperiodic: yeah, i was just thinking that.

16:29 ToxicFrog: starlord: yeah, the lua stdlib is extremely minimal. There's a few libraries that try to flesh it out. IME, most lua programmers gradually build up a personal utility library of such things.

16:29 AeroNotix: aperiodic: as much as I hate node.js, that's not a bad idea!

16:29 technomancy: aperiodic: https://github.com/greghendershott/rackjure!

16:29 at least it has runtime-eval =)

16:29 starlord: ToxicFrog: Now in my Objective-C application that embeds Lua, it's a lot easier: I can shell out to Foundation.framework for most things, i.e. HTTP, JSON, etc.

16:30 ToxicFrog: starlord: and yeah, I spent years using it for stand-alone stuff, but these days I've come to terms with the fact that it's not a good choice for that and is more comfortable in conjunction with a host language.

16:30 technomancy: it's "not clojure" but hey, neither is cljs

16:30 starlord: ToxicFrog: So I imagine in the future I'll be writing many more one-off programs as Lua extensions to this program that I'm writing. But that's a slightly different use-case than a documentation-scraper like I linked here.

16:30 aperiodic: you're probably better off with something like that and not having to weave your code in with node.js's crazy conventions

16:30 starlord: By the way, I wrote one of my first legit Makefiles: https://github.com/mjolnir-io/core.window/blob/master/Makefile

16:30 AeroNotix: SBCL should run fine on a raspberry pi

16:31 starlord: Very proud :)

16:32 ToxicFrog: That Makefile would have been less pleasant to write if I had used Clojure instead of Ruby for this task, fwiw.

16:32 AeroNotix: less pleasant to use as well

16:32 starlord: Yep.

16:32 ToxicFrog: So, out of curiosity I checked my ~/bin. bash: 33; binary: 7; python: 3; lua: 2.

16:32 arrdem: eh just build a "Clojure on SBCL" library and leave it for the rest of us :P

16:32 ToxicFrog: So apparently I do most of my one-offs in bash.

16:33 Although some of those bash scripts contain embedded blocks of lua code that it pipes stuff through~

16:33 starlord: ToxicFrog: mine only has `lein` in it.

16:33 lemonodor: yeah, actually clozure might be better for constrained platforms

16:33 starlord: I guess I don't have any one-off scripts.

16:33 technomancy: starlord: remind me to tell you about my referral marketing program

16:33 starlord: technomancy: Remember to tell me about your referral marketing program.

16:33 technomancy: "Leiningen: it's all you need. Thanks in advance. Regards." --starlord

16:34 * technomancy prints brochures

16:34 ToxicFrog: starlord: yeah, I tend to write things at the drop of a hat, I'd rather spend an hour writing a program to automate a tedious task for me than spend half an hour on that task

16:34 starlord: technomancy: nailed it

16:34 Bronsa: (inc technomancy)

16:34 lazybot: ⇒ 131

16:34 ToxicFrog: Some of these I can probably actually remove, they're interfaces to sites or services that no longer exist or helpers for completed projects.

16:34 iris_: Is it possible to use extend-protocol with a generic abstract Java class? For instance AbstractNode<T>?

16:34 starlord: ToxicFrog: I guess I don't have many tedious tasks; the few I do, I've been putting into my Objective-C program's custom configuration file for hotkeys.

16:35 ToxicFrog: But in general I write a lot of these, they live in ~/bin for a while, and then either graduate to ~/devel for cleanup and eventual release (that's what mo did -- it started as two python scripts, mtag and msort) or get removed some years later.

16:35 starlord: ToxicFrog: For example, I bound Mash-D to launch Dictionary.app for me or bring it to the front if it's not open.

16:35 *if it is

16:36 ToxicFrog: Bigger things -- where I expect up front that it'll need more than one file, or will be released someday more formally than "yo here's a bash script you might find interesting <pastebin>" on IRC, or that it needs actual testing -- start in ~/devel to begin with.

16:36 amalloy: my goodness #clojure has been vociferous today

16:37 ToxicFrog: starlord: right, for me, I'd probably write a small script to query a dictionary and display the results on stdout.

16:37 starlord: ToxicFrog: well Dictionary.app has find-as-you-type which I find helpful

16:37 Jaood: amalloy: chim in with your favorite scripting language!

16:37 starlord: ToxicFrog: I'd love it if there was an OS X command-line program that tapped into Dictionary.app's sources to do the same thing using ncurses or something.

16:38 arrdem: awk all day erry day

16:38 starlord: amalloy: I don't know what that word means. Thanks in advance, regards?

16:38 * arrdem has seen a 1kLoC awk script

16:38 aperiodic: starlord: don't you have dictionary.app bound to mash-d?

16:38 TimMc: arrdem: Was it Tetris?

16:38 ToxicFrog: I use awk and sed a lot but generally only in small snippets in support of bash.

16:38 starlord: aperiodic: Yes.

16:39 aperiodic: starlord: well then, why don't you know what vociferous means?

16:39 arrdem: TimMc: neg it's a genealogy graph generator

16:39 TimMc: mash?

16:39 starlord: aperiodic: I have not used it just now.

16:39 * seangrove used to do web scraping with awk/sed/curl, before he knew what he was doing

16:39 starlord: amalloy: I don't know what vehement or clamorous mean, thanks in advance regards.

16:39 ToxicFrog: seangrove: I still do :D

16:39 Not for anything I want to be robust, though.

16:40 amalloy: wait wait wait, has starlord been sdegutis all along, or was there a nick changeover?

16:40 seangrove: ToxicFrog: Fair enough, heh

16:40 sdegutis: What?

16:40 clojurebot: What is sampling a random integers betwen 2, 12 s..t. P(X = i) = (7-|i-7|)/36

16:40 sdegutis: No I'm here.

16:40 ToxicFrog: Then again, "robust" and "web scraping" don't generally go well together no matter what tech you're using.

16:40 sdegutis: amalloy: Why did you ping me?

16:40 * ToxicFrog rages at websites that do not expose proper stable APIs

16:40 amalloy: *eyeroll*

16:41 ToxicFrog: And now, home!

16:41 TimMc: amalloy: Just today, yeah.

16:41 And suddenly using "regard" a lot.

16:41 star-lord: Yeah.

16:41 AeroNotix: I'm sure it didn't have the hyphen before

16:41 star_lord: I own all three.

16:41 Just in case.

16:41 llasram: So many color changes

16:42 AeroNotix: yeah, it's confusing me

16:42 star_lord: Thanks in advance.

16:42 amalloy: i have to say i rather enjoyed the starlord personality he crafted. a solid troll

16:42 AeroNotix: I associate people's personalities with colours

16:42 starlord: amalloy: <3

16:42 AeroNotix: sigh

16:42 +b

16:43 sdegutis: Anyone got some advice on tuning a JVM for massive Datomic queries?

16:43 amalloy: AeroNotix: +b for nick changes? i wouldn't want to let you be king

16:44 AeroNotix: amalloy: I run a tight ship

16:44 lemonodor: my boss doesn’t know it yet, but the “Decrease [redacted] latency by 80%” item i put in my quarterly goals is going to be accomplished by writing and open sourcing clojure library.

16:44 AeroNotix: cool story

16:45 llasram: geez

16:45 TEttinger: lemonodor, decrease [java usage] by 80%

16:45 sdegutis: Ideally I don't think Datomic is the right overall choice, but the background thread that calculates statistics is really hurting performance.

16:46 We can't necessarily switch to Postgres just yet, so I have to performance-tune this beast in the meantime.

16:46 Fortunately I can reliably reproduce the 60+ second hang on staging. So now I just need to fine-tune it.

16:46 And no, I'm not going to rewrite the site in Lua. It's not batteries-included enough.

16:46 (Ruby, maybe.)

16:48 dsrx: how can I get clojars to know about the github repo for my project + list it on the project page?

16:48 technomancy: dsrx: put a :url in project.clj

16:48 dsrx: already done so

16:49 https://github.com/tomjakubowski/weasel/blob/master/project.clj

16:49 to be clear, I mean the section on this page with the github icon, just below the project description in the main area of the page: https://clojars.org/weasel

16:50 sdegutis: I bet it's happening because Datomic is producing tons of intermediate small immutable garbage objects that the GC can't keep up with.

16:50 technomancy: dsrx: hm... I think it reads the .git directory during pom generation?

16:50 not sure

16:50 amalloy: sdegutis: probably not. tons of small immutable garbage objects is what the GC is pretty good at doing

16:51 TimMc: Heap too big?

16:51 amalloy: probably

16:51 dsrx: oh, does leiningen insert SCM information into the generated pom.xml?

16:51 technomancy: dsrx: yeah, but you can override it; see lein help sample

16:51 TimMc: I don't know why this is a problem we have.

16:52 Does the JVM come with a collector that can do smaller pauses, or is it always stop-the-world?

16:52 arohner: sdegutis: are you holding onto the resultset somehow?

16:52 amalloy: TimMc: there are better collectors bundled with the popular jvms

16:52 arohner: TimMc: depends. there are multiple, configurable, GC engines

16:52 puredanger: sdegutis: you should probably ask your datomic question on the datomic mailing list https://groups.google.com/forum/#!forum/datomic

16:52 sdegutis: Possible. Or maybe Datomic is internally. They're pretty big Datomic queries that touch almost the whole database.

16:52 arohner: sdegutis: gathering data is a good place to start. VisualVM is good for this kind of thing

16:52 sdegutis: puredanger: It's not quite a fully formed question yet. I'm mostly just trying to figure out what /could/ be the cause.

16:53 arohner: Yeah I checked that but my results seemed meaningless (mostly longs and char[]s)

16:53 TimMc: amalloy: Any that allow you to use giant heaps without big pauses?

16:53 arohner: TimMc: that's kind of the holy grail of GC

16:53 rweir: TimMc, azul is 'pauseless'

16:54 BorisKourt: What is an efficient way for me to get a val for :name in the same map as an :id of n. Here is a sample of data: https://gist.github.com/BorisKourt/f52826c40ee766d72954 I have been searching and can't come up with a clean solution myself.

16:54 rweir: in exchange for $$$$ and hassle

16:54 puredanger: sdegutis: if you suspect gc, then turn on gc logging -verbose:gc and other such options

16:54 sdegutis: puredanger: Ahh, thanks. Will check it out.

16:54 islon: so guys, i have this function that needs to generate a cartesian product of tuples like [[1 2] [3 4]...] The best I could came up with was that: https://gist.github.com/stackoverflow/89104188d940616dbb62 which is even worse than the Java equivalent

16:55 amalloy: TimMc: -XX:+UseConcMarkSweepGC can't *guarantee* no pauses, but if you give it good tuning options it does enough work proactively that on the rare occasions you do get STW pauses they're reasonable

16:55 islon: there's probably a much easier way to do that

16:55 amalloy: &(partition 2 (range 10))

16:55 lazybot: ⇒ ((0 1) (2 3) (4 5) (6 7) (8 9))

16:55 sdegutis: islon: not knowing much about the pattern you mentioned, it looks like you can just use partition with range to get this.

16:55 puredanger: TimMc: agreed with rweir - Azul (and Zing) are really the best at huge heaps, but G1 is a good option in newer vms

16:55 sdegutis: amalloy beat me to it.

16:55 (inc amalloy)

16:55 lazybot: ⇒ 158

16:55 sdegutis: Whoa.

16:55 amalloy: you've been busy

16:56 islon: i have 2 ranges not only one

16:56 amalloy: puredanger: i actually had some trouble with big pauses in G1 and found ConcMarkSweep solved them

16:56 dsrx: technomancy: bingo, adding the scm to the project.clj did the trick, thanks

16:56 amalloy: obviously that's not conclusive: i surely missed some useful settings

16:56 islon: it's like a cartesian product of (range x) and (range y)

16:56 amalloy: &(for [x (range 5) y (range 6 10)] (list x y))

16:56 lazybot: ⇒ ((0 6) (0 7) (0 8) (0 9) (1 6) (1 7) (1 8) (1 9) (2 6) (2 7) (2 8) (2 9) (3 6) (3 7) (3 8) (3 9) (4 6) (4 7) (4 8) (4 9))

16:56 TimMc: The context here is on-heap caching; we'll probably just end up using off-heap caching anyhow.

16:57 but it sounds like there are some options!

16:57 puredanger: amalloy: CMS is great when it can keep up but has generally failed disastrously for me when it can't

16:57 islon: amalloy: perfect! I knew there was a better way =D

17:13 sdegutis: Why is everyone quitting IRC suddenly?

17:13 Perhaps it is a strike?

17:13 I had not heard of one though.

17:14 aperiodic: sdegutis: mission accomplished?

17:14 sdegutis: Seems like it was a short lived strike.

17:14 aperiodic: I do not understand you.

17:15 aperiodic: don't be coy

17:16 sdegutis: aperiodic: I don't know what coy means.

17:16 aperiodic: Now I know what coy means, but I don't see how I'm being coy.

17:17 aperiodic: whatever you say, starlord

17:18 sdegutis: aperiodic: I don't know what you're implying by referring to me as my other nick.

17:19 aperiodic: Are you implying that I secretly do not like Clojure and thus plotted the downfall of #clojure via some kind of secret spy-bot attack? Because if so, the fragments of what story you think you may have are not very believable and will not be accepted widely.

17:19 aperiodic: Besides, rest assured that nobody you discuss it with will take it very seriously, for various suspicious reasons.

17:21 aperiodic: I'm implying that your masterful troll of this channel as starlord made everyone delayed rage-quit IRC

17:21 but more likely it's just a netsplit

17:21 perhaps the BGP tables are filling up again

17:21 sdegutis: Oh.

17:22 aperiodic: Yes, let's go with that.

17:22 aperiodic: That's a very benign cause and doesn't put much blame on me.

17:22 technomancy: the #emacs channel has a bot feature that will emit technobabble when you ask it for an ,excuse

17:22 sdegutis: I see someone else has a similar mindset to me but is more prepared.

17:22 rweir: Let's use #emacs as a role model

17:23 technomancy: hehe

17:23 arrdem: lets not get hasty now... we're way more on topic than #emacs ever is..

17:23 TimMc: technomancy: Hell, I do that and I'm not even a bot.

17:24 technomancy: I don't know if that was intentional, but one of the other #emacs traditions is to make outlandish suggestions starting with "Let's ..."

17:24 Jaood: #emacs is 99% off-topic

17:24 rweir: (it was, i've been in there on and off for like 13 years)

17:24 arrdem: technomancy: is this where the "lets rebuild emacs atop guile" thing came from? it's just a huge misinterpreted joke?

17:25 technomancy: arrdem: we can only speculate =)

17:25 iris_: Is it possible to use extend-protocol with a generic abstract Java class? For instance AbstractNode<T>?

17:25 technomancy: iris_: the JVM doesn't have generics

17:25 hyPiRion: arrdem: let's rebuild emacs atop clojure

17:26 sdegutis: In the theme of #lua vs #lua-support (see lua-l) someone ought to fork #clojure with #clojure-support due to "constant off-topic noise" in here.

17:26 arrdem: hyPiRion: I thought someone tried that already..

17:26 iris_: parameterized types?

17:26 technomancy: iris_: they're part of the java language only.

17:26 rweir: hyPiRion, don't joke about things you don't want to risk happening

17:26 hyPiRion: arrdem: I thought that was vi

17:26 iris_: makes sense

17:26 sdegutis: On a related note, lower-case L in anything is almost always a bad decision, especially by itself.

17:26 arrdem: hyPiRion: I'd totally help with this but I'm busy forking clojure

17:26 sdegutis: arrdem: how is your Clojure compiler going?

17:27 hyPiRion: rweir: Well, I don't think it would case significant harm

17:27 iris_: Unlike the CLR... ah I remember now... thanks

17:28 rweir: hyPiRion, famous last words

17:28 TimMc: technomancy: I think you can ask for type params via reflection (on a class, not an instance, natch)

17:28 hyPiRion: sdegutis: I wasted 30 minutes because of that today actually

17:30 sdegutis: hyPiRion: l ?

17:31 hyPiRion: sdegutis: not alone, but somehow managed to replace a capital I with l.

17:31 sdegutis: Yeah, it's very confusing to see it in the Programming in Lua book and in their documentation, and on their mailing list. None of these managed to have a decent font that renders it differently enough from 1. I've wasted many minutes in the past few weeks confused over simple things due to it.

17:32 Fortunately in clj it's not too hard to spot due to the pattern.

17:32 AeroNotix: cIj

17:32 sdegutis: sdegutis -> starlord

17:32 starlord: done.

17:33 1 I l

17:33 metellus: |1Il

17:33 starlord: the 1 and l are harder for me to differentiate than I and l.

17:34 dav: Can anyone give me good pointers on how to use authenticate on Google in order to use GAPI on Picasa in Clojure? (i.e. generate an URL that can be open in a browser to get a token, etc.)

17:35 starlord: ToxicFrog: Also have you tried Penlight? It doesn't solve the platform problem but it solves the stdlib problem.

17:54 dav: nobody?

17:54 clojurebot: nobody wants to refer clojure.edn/read fully-qualified over and over

18:13 SagiCZ1: .

18:22 whats the equvivalent function definition using the hash mark notation to this?

18:22 (fn [x] [x i])

18:22 #([% i]) does not work

18:23 Slackwise: The anonymous function literal only uses implicit parameters. They're positionally numbered.

18:23 Oh wait, I read that wrong.

18:23 tanzoniteblack: SagiCZ1: #(vector % i)

18:24 technomancy: ,`#([% i])

18:24 clojurebot: (fn* [p1__25__26__auto__] ([p1__25__26__auto__ sandbox/i]))

18:24 technomancy: ^ for a hint as to why it doesn't work

18:24 SagiCZ1: technomancy: thank you, that explains it

18:24 tanzoniteblack: thanks, that works

18:29 SegFaultAX: Is there an easy way to split a string from the right?

18:32 SagiCZ1: SegFaultAX: reverse it first?

18:39 ToxicFrog: technomancy: so, regarding the #! discussion earlier --

18:39 'lein run -m clojure.main foo.clj' works just fine.

18:41 '#!/usr/bin/lein run -m clojure.main' does not; it tries to pass 'run -m clojure.main' as a single argument.

18:41 technomancy: ah sure; that's too bad. needs an alias.

18:41 ToxicFrog: Yeah, easy enough to set up.

18:42 technomancy: maybe we can add one built-in

18:42 ToxicFrog: Also, wow, that does start up way faster.

18:43 Still needs 100MB of memory though~

18:47 SegFaultAX: SagiCZ1: :(

19:05 justin_smith: ToxicFrog: what about #!/usr/bin/env ...

19:07 never mind, I just tried that, to no avail

19:10 danielcompton: Does anyone use evil with Cider in emacs?

19:13 verma: ToxicFrog, tried with env?

19:13 oh

19:13 sorry justin_smith already suggested that

19:14 danielcompton, try #clojure-emacs too

19:15 ToxicFrog: Yeah, it looks like #! passes everything after the command proper as a single arg

19:15 technomancy: that's ... pretty dumb

19:15 actually wait

19:15 that's really dumb

19:17 danielglauser: technomancy: How do you really feel?

19:23 bbloom: heh, the lesson of unix is "parsing is hard"

19:27 Guest19631: exit

19:27 exit

19:27 exit

19:33 bbloom: maybe i'm crazy, but has anybody ever seen such a thing as an "immutable weak map" ? or i guess a "persistent weak map" ...?

19:34 technomancy: only as a proposed april fool's post?

19:35 bbloom: weak map in the sense that entries disappear if the key is no longer reachable, but persistent in the sense that i can make many small variants of a particular weak map that all share structure

19:35 it would be observably immutable, but not seqable

19:35 and uncounted

19:36 technomancy: c'mon, this can't be that crazy

19:36 arrdem: bbloom: it looks... possible with some hackery.

19:36 I consider this a rather strange datastructure... but the tools exist to forge it.

19:37 technomancy: you have to admit it sounds humorous

19:37 danielglauser: What would you use it for?

19:37 bbloom: so as some of you know, i've experimented with first class environments

19:37 in interpreters

19:38 the issue is related to locals clearing, where you have things you can, but don't reference going forward

19:38 each new let binding or fn or whatever introduces a small variation on previous environments and the environments don't change

19:38 but some portions of the environments may be "semantic garbage" in that they are never accessed again

19:39 assuming your keys are uniquely generated ids instead of symbols

19:39 i guess now that i say it, that could just be one global mutable weak map, if the ids are truly unique

19:39 danielglauser: bbloom: you mention the entries disappear if they are no longer reachable, but then you say you can reach them

19:40 bbloom: danielglauser: i mean the internal structure can reach them

19:40 danielglauser: Ah...got it

19:40 bbloom: like subvec

19:40 (doc subvec)

19:40 clojurebot: "([v start] [v start end]); Returns a persistent vector of the items in vector from start (inclusive) to end (exclusive). If end is not supplied, defaults to (count vector). This operation is O(1) and very fast, as the resulting vector shares structure with the original and no trimming is done."

19:40 Jaood: technomancy: I tested 'time lein run -m clojure.main foo.clj' vs 'time java -cp clojure-1.6.0.jar clojure.main foo.clj' and got 4 vs 1 secs

19:40 bbloom: ,(def v (subvec (vec (range 1000)) 0 10))

19:40 clojurebot: #'sandbox/v

19:40 bbloom: ,v

19:40 clojurebot: [0 1 2 3 4 ...]

19:40 Jaood: outside of a lein project

19:40 technomancy: Jaood: do you have a lot of user plugins?

19:41 bbloom: ^^ 9990 wasted values

19:41 or i guess 990

19:41 technomancy: Jaood: I've gotten lein to launch in ~800 ms outside a project

19:41 and I have a computer from 2009

19:42 Jaood: technomancy: only {:user {:plugins [[cider/cider-nrepl "0.8.0-SNAPSHOT"]]}} - could that be it?

19:42 technomancy: I don't think so, but try without?

19:42 * Jaood tries

19:44 Jaood: technomancy: yeah, without that plugin the results are most equal

19:45 technomancy: wow

19:45 probably worth filing a bug report

19:46 Jaood: technomancy: to cider-nrepl or lein?

19:46 technomancy: Jaood: cider-nrepl

19:46 bobwilliams: is there a way to run lein such that you do not have to restart it on code changes?

19:47 technomancy: bobwilliams: lein repl?

19:48 Jaood: bobwilliams: yeah, that's what the repl is for

19:48 bobwilliams: technomancy: thx! I'm writing a HipChat bot in clojure

19:48 technomancy: and so need to run the code and test the plugins and what not

19:49 technomancy, Jaood: was looking for away to have it restart or whatnot as I'm making changes...guess I could do repl

19:49 technomancy: doesn't really matter what you're writing; reloading the code as you go is just how you write clojure

19:49 bobwilliams: technomancy, Jaood: thx!

19:49 technomancy: (or any non-painful language, now that you mention it)

19:49 bobwilliams: haha!

19:50 yea, was wondering if anything existed that would detect a file change and auto-restart lein basically..might have just found my next project :D

19:51 technomancy: there's a few of them out there, but you should use a repl

19:52 if you want to get fancy, configure your editor to send a reload command on save

19:55 amalloy_: yeah, auto-restarting on file change is not as fun as it sounds. you save files a lot more often than you think, and you have state in your repl that you don't want to accidentally blow away

19:55 arrdem: technomancy: got a minute?

19:56 technomancy: arrdem: sorta

19:56 arrdem: technomancy: would later/tomorrow be better

19:56 technomancy: yeah, cleaning up after an outage ATM

19:56 arrdem: kk

19:57 Jaood: technomancy: did you remove the line where it said that leiningen is like ri, bundler, gems, irb all together?

19:58 technomancy: Jaood: I never said that, and if someone once said that, I'm glad it's been removed =)

20:00 Jaood: technomancy: oh its in the tutorial, I knew I saw it somewhere, I exaggerated a little though ;)

20:00 it was RubyGems/Bundler/Rake

20:07 its still true though, from an outsider leiningen really is RubyGems/Bundler/Rake/ri/irb :)

20:16 bobwilliams: technomancy: thanks again!

21:08 TimMc: Gotta say, I'm not really seeing the usefulness of this Transit thing.

21:14 xeqi: anyone know of an instaparse grammar for clojure?

21:20 gfredericks: TimMc: compared to?

21:20 TimMc: JSON?

21:22 gfredericks: TimMc: I think not having so much contextual types everywhere seems like a good thing; same selling point for edn

21:22 TimMc: The Cognitect post didn't do a very good job of defending the creation of a new format.

21:22 Could've used a real-world example of where it would be superior.

21:23 gfredericks: The self-describing nature sounds better than data-readers, sure...

21:23 gfredericks: it's the same as data-readers

21:24 a little less global I guess

21:26 maybe more tied to system types

21:29 arrdem: xeqi: there isn't an official one, but I've been working on one as part of http://github.com/oxlang/oxlang

21:30 xeqi: expect to test/debug/improve that one tho, it's got three or four of my 3am exhausted daze hours in it and nothing more.

21:34 TimMc: gfredericks: There's also some very important stuff missing from the spec. I just raised this issue: https://github.com/cognitect/transit-format/issues/18

21:34 That could make or break it.

21:35 gfredericks: TimMc: is string encoding not handled by the underlying transport?

21:35 e.g., json

21:35 TimMc: Sort of.

21:37 For instance, JSON can contain "any Unicode character" except for some syntactic ones and the control characters.

21:37 xeqi: arrdem: neat

21:37 thanks

21:37 gfredericks: TimMc: so...therefore transit can as well?

21:37 TimMc: Does this mean that 𐀀 is transmitted in UTF-8, or UTF-16?

21:37 Balveda: Question; how could I eagerly concatenate a string?

21:37 arrdem: xeqi: hope it helps... note that there are several known issues with that grammar especially around the #"" literal.

21:37 gfredericks: TimMc: the JSON parser will worry about that won't it?

21:38 TimMc: Or will it be encoded in \uXXXX format? And if so, in which format?

21:38 arrdem: Balveda: (apply str string1 string2)

21:38 TimMc: gfredericks: It's more a question of the encoder.

21:38 xeqi: arrdem: I might just wait, considering doing some stuff for yet another side project

21:38 llasram: TimMc: I'm not a big fan of transit so far, but I don't think that's really an issue

21:38 TimMc: JSON is a character-oriented format; Transit is byte-oriented. I think.

21:38 gfredericks: TimMc: I fail to see how this could cause a problem

21:38 Balveda: thanks

21:38 gfredericks: TimMc: transit runs on top of json

21:39 arrdem: xeqi: heh we'll see I may make fixing that grammar tonight's project.

21:39 xeqi: what's this for?

21:39 llasram: I'm pretty sure Transit strings are in fact character-oriented, just like strings on the JVM

21:39 TimMc: llasram: The example on transit-clj has it writing to a ByteArrayOutputStream, so that's not obvious to me.

21:39 gfredericks: TimMc: it converts to json first

21:39 TimMc: Bottom line: I do not want to have to *assume* it does the right thing.

21:40 Balveda: also, how do I nuke an entire sexp in paredit?

21:40 gfredericks: C-k

21:41 TimMc: gfredericks: And then? After it converts to JSON?

21:41 xeqi: arrdem: considering modifying marginalia to output differently for a site similar to gobyexample.com, and I'm not sure aobut its current parsing internals

21:41 llasram: TimMc: That seems like just Java laziness, assuming that the character-oriented JSON round-trips through bytes as UTF-8

21:41 gfredericks: TimMc: well you can write it to a byte array output stream just like you can with json

21:42 TimMc: gfredericks: That requires the use of a transformation format.

21:42 Which one are they using? It's not specified.

21:42 xeqi: arrdem: and theres already an issue for changing it (parsley mentioned explicitly, but instaparse also could work)

21:42 arrdem: did your oxcart talk get recorded?

21:43 gfredericks: TimMc: is this a problem with JSON as well?

21:44 TimMc: JSON ignores this -- a JSON document is a sequence of Unicode code points.

21:45 gfredericks: okay so the complaint is that they don't specify how the json characters are encoded by their byte writers

21:45 TimMc: You are permitted to encode any code point, but not required except with C0 (and DEL?), ", and \.

21:46 Sure, although I'm not familiar with MessagePack.

21:50 gfredericks: how do people get away with not thinking about this when they sling json all over the internet?

21:50 TimMc: fuck if I know

21:50 I mean... really, they don't.

21:51 At my last job I discovered that ExtJS was just using eval to "parse" JSON.

21:51 llasram: Because they trust their underlying Unicode-data transport to correctly encode their Unicode characters

21:51 Which is exactly what is happening in the transit-clj example, using the default UTF-8 encoding

21:51 TimMc: llasram: Default, eh?

21:51 Whose default?

21:51 llasram: The JVM's, right?

21:52 TimMc: hahahahaha

21:52 gfredericks: llasram: well you have to coordinate that with others, no?

21:52 TimMc: I can tell you use a Mac or Linux.

21:52 gfredericks: or just hope it's everybody's default?

21:52 bbloom: Balveda: arrdem: you don't need that apply

21:52 ,(str "abc" "xyz") ; Balveda

21:52 clojurebot: "abcxyz"

21:52 bbloom: ,(apply str "abc" "xyz") ; same thing but slower

21:52 clojurebot: "abcxyz"

21:53 TimMc: llasram: On Windows, the default character encoding -- conveyed from system, to JVM, to your Clojure apps -- is Windows-1252.

21:53 llasram: TimMc: Ok, could be UTF-16 on Windows? Either way

21:53 * llasram is honestly skeptical

21:53 TimMc: I've been there, dude.

21:54 llasram: Hmm

21:54 clojurebot: Cool story bro.

21:54 llasram: Well, I'll believe you, but will hold out some hope that your experience was with Java 1.5 or such :-

21:54 :-) even

21:54 bbloom: isn't the default encoding on the jvm even locale dependent?

21:55 TimMc: You *must always* specify the character encoding when opening a stream in Java, unless you're using a library (like ztellman/byte-streams) that Does The Right Thing.

21:55 llasram: But it's bed time EDT. I'll see in the morning what revelations are revealed!

21:55 TimMc: bbloom: I'm pretty sure, yeah.

21:55 * bbloom has turkish i flashbacks

21:55 bbloom: http://www.i18nguy.com/unicode/turkish-i18n.html *cringe*

21:56 TimMc: fucking Turkısh

21:57 or English. I mean, the Turkish way kind of makes more sense.

21:58 gfredericks: the transit-java repo does not contain the string "UTF"

22:00 TimMc: transit-clj has it... in the XML preamble and in the string "outputFile". :-P

22:04 gfredericks: so if they'd kept their APIs at the character level this would be a non-issue?

22:04 messagepack is supposedly binary; I have no idea what that means wrt strings

22:06 TimMc: gfredericks: Yeah, but it's almost certianly better to simply define the character encoding as UTF-8 and be done with it.

22:08 ivan: In 2010 I tested a bunch of browser APIs and decided to transmit everything as ASCII to avoid problems with XHR and XDomainRequest and Flash

22:08 gfredericks: TimMc: so the users don't have to bother

22:08 ivan: XDomainRequest was the weirdest, U+FFFD'ing non-characters

22:09 TimMc: ivan: Did you b64 everything?

22:09 ivan: TimMc: I JSON'ed everything with escapes

22:09 of course this is not a great solution because you are using 6 bytes and you can't human-read non-English

22:10 TimMc: Oh, I didn't finish telling about ExtJS -- because it uses eval to parse JSON, it breaks when U+2028 or U+2029 comes down the pike, since those aren't valid whitespace in JS.

22:10 And come down the pike they did, eventually. So yeah, shit just breaks.

22:11 (So kids, remember to escape U+2028/2029 even though the spec doesn't require it...)

22:12 ivan: Python 2.7.6:

22:12 >>> print json.dumps(u"\u2027\u2028", ensure_ascii=False)

22:12 >>> print simplejson.dumps(u"\u2027\u2028", ensure_ascii=False)

22:12 "‧\u2028"

22:12 gfredericks: TimMc: so back to your original point, if they DO specify a UTF-8 default, that would make transit immediately superior to json in that respect?

22:13 I remember rich saying "all existing json is automatically valid transit" so that might be problematic

22:13 but I guess they also said they haven't nailed down the format yet either

22:14 TimMc: I feel it is important for them to specify a default encoding, yes.

22:15 I suppose they could punt and say "naw, it's just a code-point-level format" -- but if they provide byte-oriented utilities anyhow, they'd *better* use UTF-8.

22:17 gfredericks: I always thought the "regular json supported too" feature was a little weird

22:19 TimMc: They don't really give an example of what that would look like, probably because it's ugly and verbose and they don't want people to latch onto that.

22:20 gfredericks: no I think the idea was the readers could take a typical plain ole json thing and parse it the way you'd want

22:20 which sounds like a guaranteed ambiguity

22:21 TimMc: Hmm, it doesn't quite round-trip NaN.

22:22 Double/NaN -> "NaN"

22:23 gfredericks: it comes back as a string you mean?

22:23 TimMc: yeah

22:25 gfredericks: OK, that's fucked. The JSON {"foo":"bar"} reads as {"foo" "bar"}; the JSON {"~foo":"bar"} gives NumberFormatException

22:26 gfredericks: TimMc: that's the ambiguity I referred to :)

22:26 TimMc: {"~~foo":"bar"} reads as {"~foo" "bar"}, though...

22:26 gfredericks: yeah ~~ is an escape for ~ I think

22:27 TimMc: gfredericks: Yeah, just verifying 'cause I hadn't notice that "feature".

22:27 gfredericks: it might be that the feature is sort of a side effect of supporting the pretty-json format

22:28 TimMc: "This is useful for configuration files" <-- that's just asking for someone to request comments

22:31 Hmm! From RFC 7159: "JSON text SHALL be encoded in UTF-8, UTF-16, or UTF-32."

22:32 gfredericks: lol

22:33 TimMc: and then it says the default is UTF-8

22:41 gfredericks: messagepack's corresponding documentation would be relevant

22:41 I guess that would be what it thinks a string is, rather than how to encode it

22:49 TimMc: gfredericks: Where did you see that it could take plain JSON?

22:51 amalloy: gfredericks: i know at my last job there were numerous instances of "oh shit, we didn't think about character encoding for our json, and now stuff is broken"

22:51 Balveda: If I have a variadic function with an apply str, which would be the best way to deal with the n parameters, seeing as how they come in as a list?

22:54 TimMc: Balveda: Like, you have (fn foo [& args] (apply str args)) ?

22:54 amalloy: i liked to say that i spent 25% of my time there reminding people that character encodings are hard, and another 25% reminding people that times/dates are impossible

22:54 TimMc: amalloy: *nod*

22:54 Balveda: never mind

22:54 just use another apply str

22:56 * TimMc sees "uri(String uri)" in the Transit Javadocs and gets uncomfortable

22:58 gfredericks: TimMc: rich said it in his talk

22:58 TimMc: Oh phew, it's not java.net.URI

23:02 kristof: Next clojureconj should be in anchorage

23:04 amalloy: or in Ångström so they learn to be more careful about character encodings

23:04 is that a place? i think it's a place

23:04 maybe it's just a name. point stands though

23:05 * TimMc takes over Sealand and renames it 𐀀 in honor of his favorite testing character

23:07 kristof: Java is... UCS-2 internally, yeah?

23:08 amalloy: utf-16, i think, which is slightly different

23:08 but maybe not

23:08 kristof: slighter than slightly

23:10 TEttinger: ,(int \𐀀)

23:10 clojurebot: #<RuntimeException java.lang.RuntimeException: Unsupported character: \𐀀>

23:10 TEttinger: woah

23:10 ,(map int "𐀀")

23:10 clojurebot: (55296 56320)

23:11 TEttinger: ah, multibyte

23:11 good test char

23:11 TimMc: amalloy: UCS-2 doesn't have surrogate pairs, IIRC.

23:11 amalloy: TimMc: right, i went and looked it p

23:12 TEttinger: looks like a telephone pole

23:12 ,(long \𐀀)

23:12 clojurebot: #<RuntimeException java.lang.RuntimeException: Unsupported character: \𐀀>

23:12 TimMc: gfredericks: At this point I'm thinking that some verbose-json outputs might coincidentally be readable as JSON, but that it's not expected that all JSON can be readable as verbose-json transit.

23:13 TEttinger: what even... is transit

23:13 I've seen that it has an IRC channel

23:13 TimMc: TEttinger: And ##(char 0x10000)

23:13 lazybot: java.lang.IllegalArgumentException: Value out of range for char: 65536

23:13 TEttinger: I saw a clj lib for it

23:13 TimMc: TEttinger: http://blog.cognitect.com/blog/2014/7/22/transit

23:15 TEttinger: some big names on that contributor list

23:17 I've found libgdx's dialect of json to be particularly human-readable. The only difference from regular json is that it isn't valid js because unquoted words are automatically turned into strings

23:19 johnwalker: is there a standard place for lein plugins to use for configuration ?

23:20 TimMc: johnwalker: Like, system-wide conf, or project conf?

23:20 TEttinger: johnwalker, good question. what does yours do?

23:21 TimMc: Midje allows the use of a config file at the project root, but most plugins just have you attach things to the project.clj.

23:21 johnwalker: well, plugin configuration

23:21 this one should be system-wide

23:21 the plugin adds new dependencies to project.clj's

23:22 TimMc: Probably in the user's profiles file.

23:23 johnwalker: Is this dynamic injection into projects, or actually modifying the on-disk files? And what kind of dependencies?

23:24 johnwalker: it's actually modifying disk files

23:24 so you can do lein plz add cljs and get the latest clojurescript dependency appended to :dependencies

23:24 TimMc: Yeah, ~/.lein/profiles.clj sounds like a good place.

23:24 johnwalker: the thing that needs to be in configuration is the map of abbreviations

23:25 well, thats what i think too

23:25 xeqi: johnwalker: you want to let the user change the abbrevation map?

23:25 johnwalker: xeqi: thats right

23:26 so theres an edn map that goes {:org.clojure/clojurescript #{"cljs" "clojurescript" etc}}

23:27 TimMc: but the thing thats weird is that the project map passed by leiningen doesn't contain all of whats in profiles.clj

23:27 xeqi: and I really wanted to use https://clojars.org/clojurescript

23:28 johnwalker: xeqi: lol, well thats one reason i'm letting the user specify. the other is so you can have reasonable defaults and then go crazy with one character to a project

23:29 it's really cute. i like it and it works.

23:31 xeqi: johnwalker: lein will only add based on the profiles its using at the time. Do you have the map under {:user {:abbrevations ...}} or such

23:32 johnwalker: thats right

23:32 bbloom: ,(declare foo)

23:32 clojurebot: #'sandbox/foo

23:32 bbloom: ,(def foo foo)

23:32 clojurebot: #'sandbox/foo

23:32 bbloom: ,foo

23:32 clojurebot: #<Unbound Unbound: #'sandbox/foo>

23:32 bbloom: ,@foo

23:32 clojurebot: #<ClassCastException java.lang.ClassCastException: clojure.lang.Var$Unbound cannot be cast to java.util.concurrent.Future>

23:33 bbloom: fun

23:33 xeqi: ,(def bar foo)

23:33 clojurebot: #'sandbox/bar

23:33 xeqi: ,@bar

23:33 clojurebot: #<ClassCastException java.lang.ClassCastException: clojure.lang.Var$Unbound cannot be cast to java.util.concurrent.Future>

23:35 xeqi: ,bar

23:35 clojurebot: #<Unbound Unbound: #'sandbox/foo>

23:35 johnwalker: ahh

23:35 are you saying i need to add the profile to the plugin ?

23:36 i only had some data in the system profiles.clj, but didn't do anything in the project's

23:36 xeqi: no, I just wanted to make sure :abbrevations or whatever wasn't in the top most map

23:36 johnwalker: oh

23:40 bbloom: whoa:

23:41 ,(def cool #'cool)

23:41 clojurebot: #'sandbox/cool

23:41 bbloom: ,cool

23:41 clojurebot: #'sandbox/cool

23:41 brehaut: tying the knot with vars?

23:42 xeqi: ,@cool

23:42 clojurebot: #'sandbox/cool

23:42 bbloom: brehaut: i'm always up to something no-good

23:42 xeqi: ahh, I thought that was going to blow up

23:42 brehaut: bbloom: careful, that way lies haskell ;)

23:44 bbloom: it seems like the DefExpr$Parser creates the var and gives it to the def, so when def is evalutated (or compiled, i guess) the var already exists, even though it's not in the current env of the init yet

23:50 Balveda: How could I remove a key value pair from a map and keep the rest?

23:54 xeqi: Balveda: ##(doc dissoc)

23:54 lazybot: ⇒ "([map] [map key] [map key & ks]); dissoc[iate]. Returns a new map of the same (hashed/sorted) type, that does not contain a mapping for key(s)."

23:54 technomancy: johnwalker: are you using the change task for this?

23:54 johnwalker: technomancy: no, but it sounds like i should

23:54 i was using rewrite-clj

23:55 technomancy: eh; that works too if you're not concerned about dependencies

23:55 Balveda: Thanks xeqi

23:55 ,(inc xeqi)

23:55 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: xeqi in this context, compiling:(NO_SOURCE_PATH:0:0)>

23:56 johnwalker: lein change probably takes care of this nasty indentation business

23:56 Balveda: (inc xeqi)

23:56 lazybot: ⇒ 12

23:58 johnwalker: actually it looks like it's basically the same thing

23:58 i'll switch and cut off a dependency

Logging service provided by n01se.net