#clojure log - Jun 15 2013

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

0:00 ddellacosta: hmm, I wonder if there is a Google Closure IRC group with any activity...

0:04 bbloom: dnolen: scalajs has source maps!

0:04 http://lampwww.epfl.ch/~doeraene/presentations/scala-js-scaladays2013/

0:08 "Scala standard library = 16 MB of JavaScript code after compression by Google Closure's simple optimizations."

0:08 wow. heh

0:09 ddellacosta: how much was Clojurescript at first?

0:11 bbloom: ddellacosta: cljs has supported goog advanced optimizations since v1

0:11 ddellacosta: but there are some things that prevent dead code elimination that weren't fixed until quite recently (and i think there might be a few left)

0:11 even still, compiled code is under 400k with no optimizations

0:11 clojure core is TINY compared to scala's core

0:12 there isn't really a scala core to speak of

0:12 it's a very large std lib

0:12 and the type system is a dense cyclic graph, so it's gonna be really hard for them to untangle it and get that size down

0:13 but since they are a research group, i'm excited to see what they come up with :-)

0:14 ddellacosta: gotcha, thanks bbloom for the explanation

0:14 very interesting, I look forward to hearing more too.

0:15 bbloom: i suspect they will be able to leverage the type system to perform some smart, static code elimination

0:15 they don't really bother w/ dead code elimination on the jvm, since there isn't really a point

0:16 also, i should mention that unoptimized cljs core has grown from 400k to about 600k

0:17 futile: woot: https://github.com/evanescence/test2/blob/master/SPEC.md

0:18 tomjack: 1.3-beta???

0:18 lazybot: tomjack: How could that be wrong?

0:19 futile: tomjack: meaning, the spec kept changing and i didnt want people building from it yet

0:20 SegFaultAX: You should semvar that.

0:20 tomjack: usually 1.0 is like a big deal

0:20 SegFaultAX: And it shouldn't have a whole digit version if it's still in complete flux

0:20 bbloom: i need to write an anti semver blog rant so i can link to it in anger :-)

0:21 futile: tomjack: ok then its really 0.1

0:21 SegFaultAX: bbloom: What's your issue with semvar?

0:21 (I have no particular allegiance other than it's relatively common and easy to implement)

0:21 bbloom: SegFaultAX: you'll just have to mention semver again sometime in the future after i've written that rant to link to :-)

0:21 futile: fixed version number

0:22 SegFaultAX: bbloom: Well that's the tl;dr?

0:22 bbloom: my biggest issue isn't w/ semver, it's with things like node's npm which ASSUME semver

0:22 SegFaultAX: What's*

0:22 Semver* I don't know why I keep hitting a

0:23 bbloom: managing breaking changes is a subtle and complex process which 99% of maintainers can't be trusted with, so it is totally the wrong default for a package repository

0:23 tomjack: I have made a bunch of commits removing the goddamn tildes in package.json that my coworkers forget

0:24 every time I make the message "remove TILDES OF DOOM" but they don't learn :(

0:34 futile: Okay so, nesting things actually breaks this idea I had of *assertion-result*

0:34 kinda

0:57 Oh man.

0:58 I'm not sure how the Run-fn is supposed to recursively run descendent groups *while* still executing once-fixtures around each group.

0:59 These 4 lines need to be wrapped in a once-fixture: https://github.com/evanescence/test2/blob/master/src/test2/api/run.clj#L32-L35

0:59 Once I can figure that out, it's done.

1:38 Raynes: $mail futile (if-let [pending (:pending (meta test-fn))] ..)

1:38 lazybot: Message saved.

1:48 callen: Raynes: brave.

1:48 Raynes: callen: Valiant.

1:53 n_b: So, when releasing stuff on Clojars, is the preference for the tld.yourdomain.some.id nonsense from Java-land, or straight up library names?

1:54 I checked a few common libraries and there was a mix, and core does the clojure.data.* stuff, clj-http is just that, fogus has his namespaced

1:57 callen: n_b: I think it's up to preference.

1:57 n_b: but the pattern you saw is more or less indicative.

1:57 Raynes: The domain stuff is not at all nonsense.

1:57 If you don't do it, then it's impossible for two people to name their projects "beep".

1:57 Namespacing helps with that.

1:58 callen: n_b: I would base it on how likely there is to be somebody else with the same name and preference.

1:58 tomjack: I've wanted to name projects ridiculous things like 'io'

1:58 in protest :)

1:59 n_b: Raynes: It does, my gripe is more the ridiculous namespacing that is so prevalent in Java (and somewhat forced upon you by the language) that it results in import statements with more periods in them than a James Joyce novel

2:00 callen: Yea, that makes sense. There are literally no projects on GitHub with the same name, and it's a word from a small language, so I'll just go straight up

2:00 Just need to fix a few remaining bugs and write the test suite before I push up the 0.0.01 release

2:01 callen: n_b: what's the name?

2:01 n_b: "eventyr"

2:01 callen: n_b: I'd namespace it.

2:02 Raynes: The better question is why does n_b *not* want to namespace.

2:02 Like, what do you lose?

2:03 n_b: like, five whole characters!

2:03 Raynes: I used to hate namespacing as well for the same reason.

2:03 n_b: I was more concerned about what convention was

2:03 Raynes: But then I became a man.

2:03 Oooh, burn.

2:03 * Raynes pats himself on the back for that one.

2:04 Raynes: n_b: The convention is to either: a) not give a shit and so no namespacing b) namespace based on domain names or something c) namespace based on the name of the project.

2:04 Like, less-awful-ssl by aphyr is namespaced as less.awful.ssl

2:14 * Apage43 namespaces if the 'thing name' is something that is at all likely to be not unique

2:14 Apage43: dictionary word? namespace that puppy

2:21 amalloy: tomjack: you'll find "io" is already taken, from back before ninjudd heard the holy word of namespacing

2:23 tomjack: hah

2:24 well, even better

2:24 I'll just publish a library with the same name to another repo

2:59 lain1: Hello. Hopefully it's ok if I ask about clojurescript here since #clojurescript is quiet right now

3:00 I'm new to clojurescript and clojure. When would I use an atom over a var in clojurescript. As far I can tell javascript is basically a single threaded environment so I don't see the point in atoms

3:04 wei_: anyone have an example of combining the maybe monad with the writer monad?

3:07 lain1: as far as i know there are no vars in clojurescript

3:09 lain1: Ah, that's right there in the documentation

3:09 So I guess atoms for all mutable state then

3:10 wei_: yep

3:11 tomjack: wei_: in clojure?

3:11 like algo.monads or something?

3:11 clojurebot: Something weird that I noticed: & (use '[clojure.contrib.json :as json]) & &| (json/pprint-json nil) |&

3:11 wei_: tomjack: yes, preferably with algo.monads

3:16 tomjack: do algo.monads even compose?

3:16 there are no transformers, are there?

3:20 nonuby: is there anything like lein-search but recently so I can find the semver of say clj-http without switching it browser and hitting github or clojars

3:20 tomjack: then I'm guessing with protocol monads you just get crazy unpredictable behavior if you try to mix?

3:22 oh looks like protocol-monads has transformers

3:24 wei_: tomjack: there do seem to be transformers

3:25 i was trying (def writer-maybe-m (maybe-t (writer-m []))) but the final value is always nil

3:27 lain1: nonuby: Never tried it but is this what you're looking for: https://github.com/cldwalker/lein-grep

3:28 nonuby: found there actually just "lein search" i was trying to use the 2 year old lein-search plugin. so most of issue solved!

3:31 wei_: btw, my goal for this is to have chain a series of actions that may fail at any step, and return the value along with a success/failure message. maybe+writer seemed like a good fit

3:31 lain1: Oh cool

3:32 nonuby: lein-grep is better though, just install it, much easier to navigate results (.e.g on lein search latest clj-http appears on page 2 and need to reissue query not very user friendly)

3:33 thanks

3:33 just install => just installed

4:17 can3p: Hello everyone. I'm making my first steps with clojure and clojurescript. I have a question and did not find the answer in the docs. If I have multiple declarations in the let form, are there any cases when it's valid to reference between them?

4:22 terom: ,(let [a 1, b a] b)

4:22 clojurebot: 1

4:26 terom: can3p: What do you mean by referencing between? You can reference a previously declared symbol later in the let form, as you can see above.

4:37 can3p: So, I cannot make a mutual recursion between them, right?

4:39 mthvedt: can3p: not without using some tricks. clojure is not lazy by default, even though many of its data structures are

4:48 wei_: is there a long-polling client library for clojurescript?

4:52 can3p: mthvedt: thanks for the clarification

4:54 ddellacosta: wei_: not sure if this suits your needs but maybe take a look at http://docs.closure-library.googlecode.com/git/class_goog_net_xpc_IframePollingTransport.html, since it's baked in?

4:56 augustl: wei_: I would have used Faye and interop for that

4:57 wei_: thanks guys, will look into it

4:57 if there was a clojure port of socket.io would have loved to use that

5:09 augustl: wei_: I'm a big fan of interop.. You should consider it :)

5:09 wei_: augusti: i did find this netty-socketio implementation, maybe i'll give it a shot

6:25 danbell: Question: are there multiple macro steps? As in, is it possible to use a macro, and have it expand into code that ALSO uses a macro, which macro then expands into...you get the idea?

6:25 hyPiRion: danbell: yes, that's exactly how -> and ->> works today

6:25 ,(source ->)

6:25 clojurebot: Source not found\n

6:26 noahlz: I have a lot of experience packaging Java apps with Maven Assembly Plugin, but it seems there's no equivalent for Leiningen? Should I just whip up a small plugin of my own for packaging - or has the world moved on to Pallet / Chef / etc for distribution of complex JVM apps that include scripts, directory structure etc.

6:26 hyPiRion: $source ->

6:26 lazybot: -> is http://is.gd/8ScCRY

6:26 hyPiRion: danbell: ^

6:26 danbell: just checked source in my own repl

6:26 ty

6:27 hyPiRion: np

6:27 danbell: ok, less fundamental question: how do you namespace-qualify that "returned" macro

6:27 "?

6:27 -> is obv. in the same namespace as ->

6:27 noahlz: hmm perhaps will post that question on lein mailing list

6:28 danbell: I'm trying to use dommy's node macro (from...dommy.macros) in a separate macro ns

6:29 hyPiRion: danbell: all macroexpansions will be namespace-qualified. So for instance, if you use clojure.string/blank?, then even this works fine:

6:29 ,(require '[clojure.string :refer [blank?]])

6:29 clojurebot: nil

6:29 hyPiRion: ,`(blank? "")

6:29 clojurebot: (clojure.string/blank? "")

6:30 hyPiRion: if there's no symbol with that name, it will just use the current namespace

6:30 ,`(foo a b c)

6:30 clojurebot: (sandbox/foo sandbox/a sandbox/b sandbox/c)

6:31 danbell: hm....k, I must have gotten my ns declarations wrong

6:31 ty very much

6:31 hyPiRion: np

6:32 callen: noahlz: generally speaking, leiningen knows enough about your application that it's best to use leiningen itself or a specialized plugin to package your application for your into a jar.

6:32 noahlz: I am lazy as all hell so I uberjar pretty much everything and so have a deployment story approxiating `rsync muh_app.jar`

6:33 hyPiRion: wow, rsyncing the jar is new

6:33 augustl: is there a clojure XML zipping cheat sheet out there?

6:34 noahlz: ok

6:34 hyPiRion: oh, read that wrong. Well, it's almost like I rsync it as well

6:34 sans environment variables and those other nitty gritty details

6:35 callen: augustl: http://clojure.github.io/data.zip/ http://nakkaya.com/2009/12/07/zipping-xml-with-clojure/ ?

7:02 danbell: hypirion: reason i was having trouble was b/c that was all enclosed in a macro-helping helper fn, so backtick resolved to macro ns

7:03 hyPiRion: oh, I see.

7:03 I've (luckily) not worked much with macros in practise.

9:27 fikusz: is there something like mapAccumL (haskell) in the clojure libs? http://hackage.haskell.org/packages/archive/base/latest/doc/html/Data-List.html#v:mapAccumL

9:43 bpr: does anyone have experience using with friend with pedestal?

9:49 abp: bpr: https://github.com/cemerick/friend/pull/54

9:51 bpr: thanks

9:52 ivanpierre: @fikusz look reducers http://www.infoq.com/presentations/Clojure-Reducers?goback=.gmr_1058217.gde_1058217_member_249925963

9:57 noncom: how to know if a vector of keywords contains a keyword?

9:57 can't find a simple way

9:59 afaik `contains?` only verifies index containtment

9:59 hyPiRion: noncom: .indexOf

9:59 ,(.indexOf :b [:a :b :c])

9:59 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: No matching method found: indexOf for class clojure.lang.Keyword>

9:59 hyPiRion: whops, wrong order

9:59 ,(.indexOf [:a :b :c] :b)

9:59 clojurebot: 1

9:59 hyPiRion: ,(.indexOf [:a :b :c] :f)

9:59 clojurebot: -1

9:59 noncom: heh, nice :)

10:00 thank you!

10:00 hyPiRion: although (some #{:b} [:a :b :c]) is perhaps more idiomatic

10:00 np

10:00 noncom: ,(some #{:b} [:a :b :c])

10:00 clojurebot: :b

10:00 noncom: ,(some #{:f} [:a :b :c])

10:00 clojurebot: nil

10:01 noncom: ,(time (some #{:b} [:a :b :c]))

10:01 clojurebot: "Elapsed time: 0.042404 msecs"\n:b

10:01 noncom: ,(time (.indexOf [:a :b :c] :b))

10:01 clojurebot: "Elapsed time: 0.048897 msecs"\n1

10:01 noncom: ,(time (some #{:c} [:a :b :c]))

10:01 clojurebot: "Elapsed time: 0.034186 msecs"\n:c

10:01 noncom: ,(time (.indexOf [:a :b :c] :c))

10:01 clojurebot: "Elapsed time: 0.041578 msecs"\n2

10:02 hyPiRion: noncom: .indexOf is certainly faster, although the speed shouldn't matter that much

10:02 noncom: looks like the sets solution is a time win

10:02 supersym: lein deps :tree gives [ring-mock "0.1.5"]

10:02 hyPiRion: thing is, .indexOf issues a reflection call here

10:02 for larger vectors you may see it

10:02 supersym: overrides [ring-mock "0.1.5"]

10:02 hyPiRion: ,(time (.indexOf (vec (range 4000)) 3999))

10:02 clojurebot: "Elapsed time: 22.294616 msecs"\n3999

10:03 hyPiRion: ,(time (some #{3999} (vec (range 4000))))

10:03 clojurebot: "Elapsed time: 7.985011 msecs"\n3999

10:03 hyPiRion: wha

10:03 supersym: they are the same, or not? few other deps too... same version numbers appear to conflict

10:03 noncom: hmmm

10:03 hyPiRion: Not that time is the best way to measure, but .indexOf should in theory be faster

10:03 oh well

10:03 noncom: yeah, maybe a type hint would do

10:04 ,(time (.indexOf ^java.util.Collection<Float> (vec (range 4000)) 3999))

10:04 clojurebot: #<CompilerException java.lang.ClassNotFoundException: java.util.Collection<Float>, compiling:(NO_SOURCE_PATH:0:0)>

10:04 noncom: umm

10:05 ,(import java.util.Collection)

10:05 clojurebot: java.util.Collection

10:05 noncom: ,(do (import java.util.Collection) (time (.indexOf ^java.util.Collection<Float> (vec (range 4000)) 3999)))

10:05 clojurebot: #<CompilerException java.lang.ClassNotFoundException: java.util.Collection<Float>, compiling:(NO_SOURCE_PATH:0:0)>

10:06 noncom: pff

10:06 hyPiRion: yeah, generics are a bit messy

10:06 ,(time (.indexOf ^Collection (vec (range 4000)) 3999))

10:06 clojurebot: "Elapsed time: 1.3185 msecs"\n3999

10:06 hyPiRion: bwahah

10:07 supersym: yup

10:15 noncom: that timing which is faster is strange since vectors are known to implement Collection by default. so why casting matters?

10:19 supersym: say guys, what's to be expected if I have a piece of what seems clj abandonware, and updated it to current references/deps

10:19 hyPiRion: no, it's not strange, because the JVM/Clojure has no way of knowing what vec returns

10:20 so it'll have to figure out what kind of object this is, look up the hierarchy tree etc

10:20 supersym: should I put it in clojars or...how does that work/what are the social conventions? :P

10:21 hyPiRion: supersym: with the proper group id and a reference to the abandoned project in a readme or something, that shouldn't be an issue

10:21 e.g. if Leiningen somehow died tomorrow and I wanted to continue it, it would be com.hypirion/leiningen

10:22 (and yeah, clojars)

10:29 supersym: nah none of that proportions, but same may prove to be useful to a niche at least. Not that I personally care too much but I wanted to know what one would expect. Maybe like 1 out of a handful explicitly asked for maintainer anyway, so not too much concern. And I can do with a github fork and lein checkouts/local mvn

10:29 same*some

11:10 gfredericks: has anybody written anything that analyzes which vars in a namespace use which others?

11:10 I remember technomancy wanting such a thing, and at a glance it seems like it might be easy to do on top of jvm.tools.analyze

11:19 futile: ,(test +)

11:19 clojurebot: :no-test

11:22 futile: Only one file left, and then test2 is feature-complete.

11:27 gfredericks: ,(doc test)

11:27 clojurebot: "([v]); test [v] finds fn at key :test in var metadata and calls it, presuming failure will throw exception"

11:28 gfredericks: what a weird thing to have in core

11:32 wink: wat

11:33 supersym: yea sorta.. not like its bash test equivalent important, or so it seems to me

11:35 loliveira: is there some way to access the project's version?

11:35 the verion

11:36 the version witch is defined by lien's defproject.

11:36 supersym: i think you need lein-environ for that

11:36 https://github.com/weavejester/environ

11:37 loliveira: thank you.

11:52 gfredericks: I think there's also a file compiled into jars that you can look for

11:53 it at least has the git sha but I expect the version as well

12:05 fsmunoz: I need to specify a -cp, so apparently I can't use -jar. THis is likely obvious but what is the name of the main function? My ns is oradcn-demo.core .

12:07 I.e. whatever I must use as foo.bar.baz in "java -jar -cp proprietary.jar:lein_uberjar.jar foo.bar.baz"

12:07 (unless this doesn't make any sense at all, of course :) )

12:08 gfredericks: fsmunoz: if you have a vanilla :gen-class in your ns then oradcn_demo.core should be the class name

12:08 i.e., the main gotcha is the underscore substituted for the dash

12:09 fsmunoz: gfredericks: splendid, that was it

12:09 Now I remember reading about that in the tutorial, but without a real need I forgot about it.

12:12 gfredericks: ,(chunked-seq? (range))

12:12 clojurebot: false

12:12 gfredericks: am I crazy? isn't (range) the canonical example of chunked-seq gotchas?

12:16 Bronsa: ,(chunked-seq? (rest (range)))

12:16 clojurebot: true

12:17 Bronsa: gfredericks: the ChunkedCons is wrapped in a LazySeq

12:17 ,(map class ((juxt identity rest) range))

12:17 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.core$range>

12:18 Bronsa: ,(map class ((juxt identity rest) (range)))

12:18 clojurebot: (clojure.lang.LazySeq clojure.lang.ChunkedCons)

12:18 gfredericks: ah ha

12:18 I should have examined the source closer :)

12:19 Bronsa: it's easy to miss the lazy-seq at the top

13:00 piranha: alandipert: hi

13:09 dnolen: jasonjckn: yeah it was never clear to me what the source of the AOT issue was, doesn't matter much now, the problematic code was badly written and has since been replace with something much simpler.

13:10 jasonjckn: double win then

13:11 dnolen: bbloom: I find it very surprising that they didn't address the code size thing up front - something to definitely give rhickey credit for.

13:11 jasonjckn: yes, core.match is much simpler now - I hope to write up some detailed explanations about how it works.

13:12 bbloom: also the emitted JS is written in a way that it defeats advanced optimization. I'm sure they'll sort it out in the end

13:12 bbloom: dnolen: i skimmed a little more info about it. seems like generating advanced-mode js is almost done, but their std lib is too large for gclosure to compile w/o freaking out

13:13 dnolen: bbloom: hmm interesting

13:13 bbloom: dnolen: i expect them to do a lot of scala-level dead code elimination

13:13 dnolen: bbloom: yeah

13:13 still cool to see another language join the fray

13:13 bbloom: dnolen: which we should do too, but it's just not as pressing as it is for them

13:14 their approach os having js types defined w/ implicit conversions to scala types is interesting

13:15 dnolen: bbloom: what are they doing exactly?

13:15 bbloom: http://lampwww.epfl.ch/~doeraene/presentations/scala-js-scaladays2013/#/16

13:17 they basically encoded a js type system in their own type system

13:17 turns out scala's type system is sufficiently expressive to cover the same sorts of things as typescript

13:17 dnolen: bbloom: I'm not gleaning anything from that slide

13:17 bbloom: oh interesting

13:18 bbloom: so they do stuff like this: https://github.com/lampepfl/scala-js/blob/master/library/src/main/scala/scala/js/JSAny.scala

13:18 and, if i'm understanding correctly, the compiler replaces those stub impls with the equivilent of js*

13:23 dnolen: they did a nice job on it though overall. they compiler is only ~3200 lines of code & includes a proper JS AST & printer

13:28 dnolen: ooo very interesting. they actually don't compile directly to javascript

13:28 dnolen: they compile to "Extended-JS"

13:28 * Extended-JS is a non-existent language that is a superset of JavaScript

13:28 * with Scala-esque constructs. Most notably, most constructs can be used in

13:28 * expression position. Extended-JS also features ES6-like classes.

13:28 then they desugar that

13:28 clever.

13:28 dnolen: well I can't even play with it SBT just OOMed

13:29 bbloom: heh.

13:31 dnolen: how did you install sbt?

13:32 dnolen: brew

13:32 bbloom: you on the latest?

13:32 0.12.3

13:34 dnolen: oh looks like I'm not

13:34 bbloom: after you do that, run `brew info sbt`

13:34 and edit your .sbtconfig file

13:38 shesh, the compiler is sloooow

13:39 dnolen: heh I'm not convinced about this JS AST business

13:39 bbloom: thoughts?

13:41 dnolen: hard to say without playing around with it a lot more

13:43 seems less usable than initial ClojureScript release after 2 months of development

13:43 bbloom: to be fair, this was done by a student in 4 months :-P

13:43 dnolen: so something to watch, but in it's current state - a curiosity

13:43 bbloom: rich & team are a weee bit more experienced :-)

13:44 dnolen: and Clojure is simpler

13:44 but true enough

13:44 bbloom: much.

13:44 just in sheer number of syntactic forms to process, clojure is just a smaller volume of work

13:45 dnolen: definitely looking forward to seeing where it goes

13:45 bbloom: likewise

13:45 dnolen: overall it's cool see more people taking JS target seriously

13:45 in 5 years no one will bat an eye about compile to JS langs

13:46 bbloom: my real hope is that in 5 years, it will be a no brainer to finally push to standardize some sort of more sane browser compilation target :-)

13:46 but maybe that's 5 years after your no-eye-batting scenario

14:09 i have a really freaking hard time writing ruby now. clojure has ruined my brain

14:09 i have to resist the urge to call freeze on everything

14:10 gfredericks: module SelfMethods

14:10 dnolen: bbloom: unlikely

14:10 bbloom: gfredericks: ?

14:12 gfredericks: bbloom: I have a hard time resisting mocking the weird OOP patterns that the ruby community has developed

14:12 so I was just mentioning one :)

14:12 bbloom: gfredericks: i'm not familiar with that one

14:13 gfredericks: it's instead of class Foo; def self.bar; ...; end; end

14:13 class Foo; module SelfMethods; def bar; ...; end; end; extend SelfMethods; end

14:13 or maybe s/extend/include/; I can never keep those two straight

14:13 bbloom: oh that thing where they put the instance and class methods in two different files b/c their file got too damn large?

14:13 gfredericks: not quite that

14:14 SelfMethods keeps you from specifying `self.` in the method name

14:14 futile: Whoa.

14:14 Ruby?

14:14 clojurebot: Chunky bacon!

14:14 gfredericks: and probably some other subtle "benefit"

14:14 futile: I have to admit, once I learned Ruby I hated all other languages I knew in comparison.

14:14 It was really really fun and enjoyable, and I felt like I *got it*.

14:15 Ruby seemed so simple and consistent!

14:17 gfredericks: futile: did you know `-42` and `- 42` parse differently?

14:17 futile: Nope.

14:17 bbloom: gfredericks: that hardly seems surprising

14:17 gfredericks: that's my favorite ruby syntactic trivium

14:17 bbloom: also not surprising that they're semantically different?

14:18 futile: I know that Ruby fakes consistency with all sorts of ugly hacks.

14:18 bbloom: gfredericks: even haskell has some weirdness around negative vs minus

14:18 futile: Like, the top-level self.

14:18 gfredericks: oh haskell I have no syntactic respect for :D

14:19 but maybe slightly more than for ruby

14:19 futile: Clojure has spoiled me with its consistency.

14:19 bbloom: gfredericks: http://www.haskell.org/haskellwiki/Unary_minus

14:19 gfredericks: lisp has ruined my appreciation of any other syntax

14:19 futile: I'm sure there are inconsistencies in Clojure. I just don't know about them off-hand, which is a good sign.

14:20 And compared to every other language, lisp-family or not, Clojure seems pretty pure in its semantic and syntactic consistency.

14:20 gfredericks: I assume though that in haskell `-42` and `- 42` cannot be made to evaluate to different things

14:20 futile: Seriously, what are some inconsistencies in Clojure?

14:20 gfredericks: futile: this sounds like a fun list to curate

14:20 hyPiRion: syntax-wise or semantic-wise?

14:20 gfredericks: the first one off the top of my head is conj

14:21 hyPiRion is probably a treasure-trove of syntactic curiosities :)

14:21 futile: lets say syntax for now

14:21 murtaza52: I am creating a leiningen plugin which watches over a folder an executes an action if any file has changed. Is there some code which I can use to watch over a folder?

14:22 futile: $mail Raynes ok

14:22 lazybot: Message saved.

14:22 * gfredericks imagines hyPiRion removing a large 3-ring binder from his "clojure" filing cabinet drawer

14:22 hyPiRion: Heh, what would you expect ((-> [%] #(list %)) 10) to do?

14:22 futile: gonna finish test2 today. Just two functions left to write, and I think I know how to make it work.

14:22 hyPiRion: hmm

14:22 hyPiRion: I'm not sure if it's inconsistent, but it's surprising.

14:23 gfredericks: hyPiRion: my guess is a symbol not found error

14:23 futile: ,(list [10] 10)

14:23 clojurebot: ([10] 10)

14:23 futile: That.

14:23 hyPiRion: gfredericks: yep

14:23 ,((-> [%] #(list %)) 10)

14:23 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: p1__57# in this context, compiling:(NO_SOURCE_PATH:0:0)>

14:24 * gfredericks high fives himself

14:24 futile: Oh no wait, because #() isn't a form that -> can handle, it's a reader form, so it probably gets converted into (fn...)

14:24 * futile gives up

14:24 futile: man Clojure sucks.

14:24 gfredericks: futile: that's it

14:24 the [%] becomes the arg list

14:24 futile: gfredericks: oh so I did get it right?

14:24 gfredericks: ,'#(list %)

14:24 clojurebot: (fn* [p1__86#] (list p1__86#))

14:24 gfredericks: so you end up with (fn* [%] [p1__86#] (list p1__86#))

14:24 futile: yay!

14:24 bbloom: ,(macroexpand '(((-> [%] #(list %)) 10))

14:24 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

14:24 bbloom: ,(macroexpand '(((-> [%] #(list %)) 10)))

14:24 clojurebot: (((-> [%] (fn* [p1__142#] (list p1__142#))) 10))

14:24 bbloom: ,(macroexpand '((-> [%] #(list %)) 10))

14:24 clojurebot: ((-> [%] (fn* [p1__171#] (list p1__171#))) 10)

14:25 bbloom: ,(macroexpand '(-> [%] #(list %)) 10)

14:25 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (2) passed to: core$macroexpand>

14:25 futile: ok, moving on

14:25 bbloom: blah i can't even parse that

14:25 too much line noise

14:25 haha

14:25 futile: Now BESIDES macros, what are some inconsistencies in Clojure?

14:25 hyPiRion: ,(macroexpand-1 '(-> [%] #(list %)))

14:25 clojurebot: (fn* [%] [p1__229#] (list p1__229#))

14:25 hyPiRion: oh, conj man

14:26 gfredericks: the arg signature of distinct vs distinct? is annoying and was discussed the other day

14:26 hyPiRion: ,(conj {1 2} [3 4])

14:26 clojurebot: {3 4, 1 2}

14:26 hyPiRion: futile: see that? ^

14:26 bbloom: my biggest issue w/ any language that isn't clojure: nothing has a fucking sane default printed representation

14:26 futile: I never ever use conj directly. Only usually via into.

14:26 bbloom: blargh. i do no want to see fucking pointers when i call to_s

14:26 hyPiRion: Guess what (conj {1 2} {3 4, 1 6}) would do.

14:27 futile: Cuz I always want to know where something is gonna go, like which end.

14:27 bbloom: blargh. i do no want to see fucking pointers when i call to_s

14:27 gfredericks: futile: I'm not sure why into is any different in that regard

14:27 bbloom: sorry didn't meant o send that twice

14:27 hyPiRion: gfredericks: oh yeah, there is one issue with the reader actually

14:27 bbloom: but i guess the emphasis is important

14:27 gfredericks: bbloom: having rouble wih your t's?

14:27 futile: gfredericks: and I only use into like ##(into {} [[1 2] [3 4]])

14:27 lazybot: ⇒ {1 2, 3 4}

14:27 bbloom: gfredericks: i have issues with everything all the time

14:27 futile: That's the only time I ever use conj that I'm aware of.

14:28 hyPiRion: ,`{~@[1 2] ~@[3 4]}

14:28 clojurebot: {1 2, 3 4}

14:28 hyPiRion: ,`{~@[1 2]}

14:28 clojurebot: #<RuntimeException java.lang.RuntimeException: Map literal must contain an even number of forms>

14:28 Bronsa: ew hyPiRion

14:28 hyPiRion: ,`{~@[1 2] ~[3 4]}

14:28 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: No value supplied for key: [3 4]>

14:28 bbloom: hyPiRion: oh yeah, that's annoying

14:28 hyPiRion: It's a big issue when you're swearjuring.

14:29 futile: see here: ##[(conj {1 2} [3 4]) (conj {1 2} {3 4, 5 6})]

14:29 lazybot: ⇒ [{3 4, 1 2} {5 6, 3 4, 1 2}]

14:29 futile: hyPiRion: no comprendo

14:30 but to be fair, my attention has moved back to test2 right now

14:30 hyPiRion: the last result is weird.

14:30 ah, ok

14:30 futile: to make it official: bbl

14:30 ,(prn "bbl")

14:30 clojurebot: "bbl"\n

14:30 hyPiRion: gfredericks: btw, seen this little gem?

14:30 ,(let [s (set (apply hash-map (range 10)))] [s (keys s)])

14:30 clojurebot: [#{[2 3] [4 5] [6 7] [8 9] [0 1]} (2 4 6 8 0)]

14:31 gfredericks: hyPiRion: I've been watching the clojure-dev list, so this seems totally reasonable now :)

14:31 hyPiRion: oh darn you

14:32 gfredericks: would replacing `set` with any of seq, vec, list* do the same thing?

14:32 hyPiRion: yeah

14:32 futile: Btw does anyone wanna go through the Spec and tell me in what places it doesnt make any sense and is stupid? https://github.com/evanescence/test2/blob/master/SPEC.md

14:33 I'm pretty sure the spec is feature-complete now, aside from lacking a few keys for timing tests in the assertion-result and test-result types

14:33 hyPiRion: well, the same thing as in you'd get the keys back. The order depends on the data structure

14:33 futile: I spent tedious amounts of time making this spec as easy as possible to navigate for extension-authors.

14:33 navigate/read

14:33 and /understand

14:43 berdario: Hi, I think I might have stumbled on a lein-cljsbuild bug

14:45 It should be line 100 of cljsbuild.compiler

14:46 the (load ) fails

14:46 probably, it's a classpath issue

14:57 I don't know if it's related... but it seems that lein it's not creating a target/ directory when compiling

14:58 futile: Raynes: what was that if-let-pending thing supposed to be?

15:00 berdario: no, if I delete the target/ directory, it can still build just fine

15:02 futile: ,e

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

15:02 futile: then why does it highlight weird in clojure-mode.el!

15:05 Bronsa: https://github.com/technomancy/clojure-mode/blob/master/clojure-mode.el#L251-L252

15:05 futile: Oh.

15:07 Crap. `carton update` broke something in my emacs initfile

15:08 Someone broke my delete-selection-mode :/

15:10 nm

15:16 Raynes: futile: An improvement to the run.clj or whatever code you linked to last night.

15:16 futile: ok thx

15:18 mthvedt: futile: why are group maps required to be in vars?

15:19 futile: mthvedt: so it can uniquely identify groups that multiple tests point to

15:19 mthvedt: I can imagine a sub-group of one group having the same :description as a sub-group of another group, yet they should be considered different groups.

15:19 mthvedt: ok bad example. better one: two top-level groups with the :description should be considered different

15:20 mthvedt: thus (defn ^:test ^{:group #'some-group} test-name [] ...)

15:20 mthvedt: although usually you wont have to type that, some macros will generate that for you since its kind ugly.

15:21 mthvedt: futile: that doesn't explain why a var, instead of a symbol or a string name

15:21 * futile is binary searching my ~/.emacs.d/init.el to see what the crap broke this delete behavior

15:21 futile: mthvedt: because vars are automatically super-duper-unique

15:22 mthvedt: symbol or string name has the same non-uniqueness problem that a map does.

15:22 mthvedt: vars are tied to a namespace and file and line, etc. ie, what people usually mean.

15:23 mthvedt: futile: it seems like you're stating an opinion, that test groups should only exist by def-ing a var in a .clj file

15:24 the uniqueness problem with, say, symbols is easily solved if you're generating them, and if you're using them in code symbol collisions work the same as var collisions.

15:24 futile: mthvedt: no, just that the alternative creates too many identity problems

15:24 mthvedt: are there any downsides to making it a var?

15:28 Aha! Paredit broke deleting stuff!

15:28 awwwww

15:29 mthvedt: futile: you're making a var _key_ part of a data definition, which seems odd. the value doesn't know about the uniqueness you're imposing on it. someone reusing a var is as likely as someone reusing a symbol, except now your var has been redefed and your code doesn't know.

15:29 futile: it's very easy to make an auto generated unique :id, or something.

15:30 futile: mthvedt: hmm yeah. so you propose just leaving it up to the user to make sure their groups are unique?

15:30 mthvedt: (i.e. maybe with some macros like defgroup or something)

15:30 mthvedt: futile: yeah, as long as you're already assuming the use of macros in the common case, i don't see why not

15:30 futile: Also, everybody using emacs: don't update paredit, the latest breaks deleting stuff.

15:30 mthvedt: vars as keys make me uneasy because they aren't values.

15:30 in the clojure sense

15:31 futile: mthvedt: ah

15:31 mthvedt: how do you feel about test-fns being vars like the spec says?

15:32 mthvedt: futile: fns aren't (usually) values either so that doesn't bother me as much

15:33 futile: though again you're not using the var for its var-ness, you're using it because it has metadata on it.

15:34 futile: ok

15:35 mthvedt: so now the spec should mention that they should be made unique to all other groups with something like :id

15:35 mthvedt: so the var seems like an extra assumption. fns are almost always unique, and when they're not unique, that's on purpose

15:35 futile: mthvedt: i suppose that makes sense

15:40 amalloy: i can't imagine a good reason for a generalized testing tool to only work on vars. why can't i build up a map of functions at runtime and run tests on them?

15:40 bbloom: amalloy: i've said that a few times, but apparently nobody cares

15:41 amalloy: in fairness i don't care either, because i don't see myself using test2

15:42 bbloom: amalloy: now we agree on two things :-)

15:42 not to disparage the effort, i think it's worthwhile

15:42 i just don't really care until/unless it takes off

15:42 gfredericks: A function which, given a filename, returns a map from vars to sets of referenced vars: https://gist.github.com/fredericksgary/5789305

15:43 futile: amalloy: well, the metadata thing was just so it can find any tests written like (defn ^:test my-test [] ...)

15:44 amalloy: if that were all, then it would just need test functions, and that would be all.

15:44 amalloy: gfredericks: plz to call this on a file with the following contents: "(map inc [1 2]) ;; for testing"

15:44 futile: amalloy: but i needed a way for you to mark a test as pending without throwing exceptions, and this seemed reasonable: (defn ^:test ^:pending my-test [] ...)

15:45 I'm open to another way to mark tests as pending statically without depending on its metadata.

15:45 gfredericks: amalloy: empty map, as I would expect

15:45 oh hwait

15:45 amalloy: gfredericks: you sure you didn't, say, put a newline at the end of the file? cuz my string doesn't have one

15:45 gfredericks: this is about my parens isn't it

15:45 and the newline

15:46 amalloy: gfredericks: right. wrapping with () and using read-string is a gross hack, when you can just use (read) the way it was meant to be used

15:46 gfredericks: with loop?

15:46 mthvedt: futile: it sounds like you're assigning something to 'test' what really is a way to help things find tests.

15:46 once you've gathered all your test vars, you have no need for the var anymore

15:46 futile: mthvedt: yes, thats why i want to get rid of the use of vars for test fns

15:46 mthvedt: but there's still the problem with pending.

15:46 amalloy: gfredericks: well, with take-while and repeatedly

15:46 futile: i Really dont want to have it throw exception from within the test to tell that its pending.

15:46 amalloy: or loop, whatever

15:47 futile: mthvedt: right now ^:pending is part of the metadata. is there a way to define it as part of the function's metadata while ditching the var?

15:47 ,(meta +)

15:47 clojurebot: nil

15:47 futile: ,(meta #'+)

15:47 clojurebot: {:arglists ([] [x] [x y] [x y & more]), :ns #<Namespace clojure.core>, :name +, :column 1, :added "1.2", ...}

15:47 gfredericks: amalloy: in any case that's beside the point; do you know if this function existing elsewhere?

15:47 if not I'm surprised, given how easy it was

15:48 amalloy: *shrug* slamhound probably has something similar

15:48 gfredericks: technomancy has said that he wishes this function existed

15:48 if I understood him correctly

15:49 futile: ,(defn foo [])

15:49 clojurebot: #<Exception java.lang.Exception: SANBOX DENIED>

15:49 futile: aw

15:49 ##(defn foo [])

15:49 lazybot: java.lang.SecurityException: You tripped the alarm! def is bad!

15:49 futile: aww

15:49 amalloy: anyway, any particular reason you said you wouldnt use test2?

15:50 mthvedt: futile: with-meta, or #(vary-meta % merge …)

15:50 any IObj can have metadata

15:51 futile: mthvedt: right but I don't see any easy way, when using defn, to attach it to the fn itself

15:51 gfredericks: ,(instance? clojure.lang.IObj #())

15:51 clojurebot: true

15:51 gfredericks: ,(instance? clojure.lang.IObj #'first)

15:51 clojurebot: false

15:51 futile: if it was using (def a-test ^:pending (fn)) that's doable, but ugly since it's not using defn

15:51 mthvedt: futile: does it need to be attached to the fn itself at defn time?

15:51 amalloy: futile: to paraphrase http://blogs.msdn.com/b/ericgu/archive/2004/01/12/57985.aspx, every new project starts out at -100 points

15:52 metaprojects doubly so, imo

15:52 futile: amalloy: oh, gotcha. chronology-bias

15:53 mthvedt: my hope is that anyone who has a test-fn (direct fn, not var) can statically determine whether it's pending and should be not run.

15:53 mthvedt: (and if so, why)

15:53 amalloy: i also regard test2 as a windmill you're tilting at while you learn clojure. a good thing for your development, but i don't expect a project written by someone who's still asking pretty basic questions in #clojure to change the testing landscape

15:53 futile: amalloy: hmm

15:53 amalloy: thats all very fair. thanks for your input :)

15:54 amalloy: you're welcome. glad to hear you weren't too offended by my rude bluntness

15:57 gfredericks: another win for nerds communicating via plain text

15:57 mthvedt: futile: dunno if that's possible at all, if you define tests using defn.

15:58 futile: amalloy: well you're right, no reason to be offended at the truth.

15:58 gfredericks: amalloy: are you aware of the undocumented `recursive?` arg to read?

15:58 amalloy: (inc gfredericks)

15:58 lazybot: ⇒ 24

15:58 mthvedt: probably, if something's handing off tests to test2, you can trust it to assign the correct metadata

15:58 futile: mthvedt: i think it has to be done via exceptions. arg. i didnt want the spec to talk about exceptions.

15:58 amalloy: gfredericks: i just know that it's an arg i never want to pass, and that if you want the doc for it you can probably find it in CLTL

15:59 gfredericks: that's a weird single thing to know

16:00 amalloy: gfredericks: i mean, the signature for clojure.core/read was stolen from another lisp, and i'm reasonably certain CL has the same signature. so CLTL is probably the place to look, but maybe it's the hyperspec

16:00 gfredericks: gotcha

16:00 thx

16:02 futile: amalloy: i dont mean to say you're right about it not gonna take off, just that it seems unlikely :)

16:02 hyPiRion: gfredericks: yeah, it's from CL

16:02 from the hyperspec: "If recursive-p is true, the call to read is expected to be made from within some function that itself has been called from read or from a similar input function, rather than from the top level."

16:03 mthvedt: futile: i don't think pending-ness is an intrinsic property of the test, it's something you attach to a test to say "hey don't run this"

16:03 the mechanism that gathers tests should get to decide which tests are pending

16:03 amalloy: hyPiRion: where is that? i couldn't find it in CLTL

16:03 hyPiRion: amalloy: http://www.lispworks.com/documentation/HyperSpec/Body/f_rd_rd.htm

16:03 futile: mthvedt: but some libs let you stop half-way through the test and say "oh no wait nm im actually pending"

16:04 hyPiRion: oh, it's not in the spec?

16:04 that's a bit strange I suppose.

16:04 mthvedt: futile: well, if that's the case, metadata won't help anyway :P

16:04 amalloy: hyPiRion: http://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node195.html#SECTION002621000000000000000

16:04 futile: mthvedt: yeah i suppose. i was trying to just ignore those libs and say "lalala i cant hear you" to them

16:05 amalloy: but it's in the hyperspec; cltl isn't a spec

16:05 futile: mthvedt: because i REAALLY dont want to add an exception to the spec

16:05 finishingmove: anyone into skinning LightTable?

16:05 futile: Does LightTable have paredit-like functionality?

16:06 hyPiRion: amalloy: "Many input functions also take an argument called recursive-p. If specified and not nil, this argument specifies that this call is not a ``top-level'' call to read but an imbedded call, typically from the function for a macro character. It is important to distinguish such recursive calls for three reasons."

16:06 amalloy: hyPiRion: yeah, i just got to that bit myself. i didn't read that far at first, because the signature looked like it was just at the top

16:07 rather than scattered throughout the text like a gibbon

16:26 gfredericks: ,(namespace-munge "foo.bar-baz$*&")

16:27 clojurebot: "foo.bar_baz$*&"

16:39 antares_: wrote a blog post about ClojureWerkz docslate and how you can use it to document your Clojure project well: http://blog.clojurewerkz.org/blog/2013/06/15/how-we-document-our-projects-with-clojurewerkz-docslate/

16:51 gfredericks: lein has started putting jars under target/provided ?

16:51 rodnaph: when eval'ing code, is there a way to pull in other namespaces? (like... "(require 'foo) (foo/bar 1)")

16:57 ianeslick: Is there a way to ensure that a particular namespace is evaluated when a jar is on the classpath at load time, or do you have to manually require it from somewhere?

17:01 bpr: ianeslick: i'm fairly sure you have to require it. there are tools to scan the classpath to find all the available namespaces though.

17:01 ianeslick: I'm writing a little library that extends a method; so you have to add it to dependencies and explicltely require it to get the new methods.

17:02 (I take it)

17:02 bpr: yes

17:04 gfredericks: your library has side-effects when you load it?

17:05 ianeslick: I'm extending a multi-method defined in another namespace. Would be nice if you could just add it to dependencies and get the new methods.

17:05 But requiring is fine

17:05 bbloom: gfredericks: any library that does defmethod has side effects when you load it :-/

17:07 Raynes: http://i1.kym-cdn.com/photos/images/newsfeed/000/322/446/dde.gif

17:07 Technically any library with a def has side effects when you load it, guys.

17:08 ianeslick: Right, but having the jar on the classpath doesn't mean it is loaded!

17:08 bbloom: Raynes: yes, but that side effect has no impact on a consumer who isn't using :use

17:08 ianeslick: So it is only loaded when required (when the usual def side effects happen)

17:08 Raynes: bbloom: I didn't say it did.

17:09 I was merely pointing out that using the word 'side effects' when you mean 'bad things' is probably not a good idea.

17:09 noprompt: ughh, i need halp.

17:09 Raynes: There is no doubt.

17:09 Call the poison control center at ...

17:10 noprompt: Wazzup?

17:10 noprompt: well garden is starting to grow (no pun) intendended, and i'm having to think a bit harder about the organization of the library and what stuff goes where.

17:11 Raynes: noprompt: (no pun) intendeded

17:11 bbloom: well if it's growing as intendeded, what's the problem? (grin)

17:12 noprompt: Raynes: yeah, my typing skills are bad.

17:12 Raynes: That was the most confusing sentence I've read since I read the logs from the last time I got wasted.

17:12 noprompt: or rather, my re-reading skills.

17:14 Raynes: basically, i'm not sure in some cases what the right choices are when it comes to working with record types and protocols.

17:14 Raynes: Nice. I just realized that having an external mouse plugged in causes OS X to display scrollbars.

17:14 noprompt: Raynes: it could just be that i'm not used to building a large library in clojure.

17:15 or large libraries in general.

17:15 Raynes: yep.

17:16 i mean i'm not gonna commit suicide or anything over it but it'd be nice to have a little feedback from time to time. even if it's heavy on the criticism

17:17 Raynes: noprompt: But what if it's so heavy on the criticism that you commit suicide?

17:19 noprompt: Raynes: the that would imply something i can't even fathom.

17:19 Raynes: noprompt: What part are you having trouble organizing>

17:19 ?

17:19 The library is split up pretty well.

17:20 tjb1982: I'm having a problem connecting to postgres. "No suitable driver found" I have `[org.clojure/java.jdbc "0.3.0-alpha4"]` and `[postgresql "9.1-901.jdbc4"]` in my project.clj file, so I would've thought that would be enough. The `:classpath` arg is "org.postgresql.Driver" and the :subname is `"//postgres:postgres@localhost/myDatabase`

17:21 noprompt: Raynes: you think? maybe i'm just hard on myself when things aren't dry.

17:25 Raynes: tjb1982: What are you passing a :classpath arg for?

17:26 tjb1982: I had been using the `with-connection` api previously, and I happened upon some documentation that made mention of that

17:26 Raynes: when I don't supply it, I get a different error

17:26 noprompt: Raynes: btw, clojure is hard to teach.

17:28 tjb1982: Raynes: without the :classname I get a NullPointerException

17:28 Raynes: sorry, I meant to say :classname not :classpath

17:30 Raynes: so to be clearer, I had the old with-connection style working before with this "postgres://postgres:postgres@localhost/myDatabase"

17:30 noprompt: it could just be state colleges, but i get the feeling that universities aren't spending enough time on functional programming.

17:30 by that i meant spending enough time teaching functional programming.

17:34 laliluna: Is there a convention to use 'test_foo.clj' instead of foo_test.clj in clojure contrib libs? I stumbled over it as clojure test mode is not enabled by the first one.

17:36 SegFaultAX: Holy crap, have you guys seen prismatic.com?

17:37 akhudek: their domain is getprismatic.com

17:38 SegFaultAX: akhudek: Prismatic's is, sure.

17:38 akhudek: SegFaultAX: then I guess I don't get what the big deal is with prismatic.com

17:38 SegFaultAX: Prismatic Sign's website is like a walk down year 1999 memory lane.

18:07 NeedMoreDesu: Hi. Is there a way to write this with tail-recursion optimizations? http://www.everfall.com/paste/id.php?p7ol3exb0dw1

18:09 noprompt: NeedMoreDesu: the first thing i would suggest you do is pull that (defn two ..) part out. defn's shouldn't be nested. instead you should probably use something like letfn.

18:10 ,(doc letfn)

18:10 clojurebot: "([fnspecs & body]); fnspec ==> (fname [params*] exprs) or (fname ([params*] exprs)+) Takes a vector of function specs and a body, and generates a set of bindings of functions to their names. All of the names are available in all of the definitions of the functions, as well as the body."

18:10 NeedMoreDesu: Well, yeah, with letfn. Anyways.

18:11 Could it be optimized?

18:11 noprompt: have you learned about loop/recur?

18:12 NeedMoreDesu: You can recur to function "two", but you can't recur to "one".

18:12 noprompt: so you need mutual recursion?

18:12 bbloom: NeedMoreDesu: i just want to clarify noprompt's feedback. letfn isn't simply more idiomatic here, defn is *wrong* to be nested

18:12 NeedMoreDesu: I know.

18:13 Hm, maybe it's the name.

18:14 bbloom: NeedMoreDesu: anyway. in *theory* any mutually recursive function can be eliminated by inlining one into the other

18:14 NeedMoreDesu: and any non tail recursive function can be made tail recursive by consuming heap space with an explicit stack in your loop args

18:14 NeedMoreDesu: however, it's generally easier to utilize a trampoline

18:14 (doc trampoline)

18:14 clojurebot: "([f] [f & args]); trampoline can be used to convert algorithms requiring mutual recursion without stack consumption. Calls f with supplied args, if any. If f returns a fn, calls that fn with no arguments, and continues to repeat, until the return value is not a fn, then returns that non-fn value. Note that if you want to return a fn as a final value, you must wrap it in some data structure and unpack it after trampol

18:15 noprompt: bbloom: beat me to it. :)

18:15 NeedMoreDesu: How do I write my example with trampoline?

18:15 Apage43: https://www.refheap.com/15814

18:15 bbloom: wrap your recursive calls in #()

18:15 then wrap your whole function in trampoline

18:16 but i'm not looking at your example at all, just speaking from first principals

18:18 NeedMoreDesu: bbloom: this works, thanks :3

18:18 Apage43: Well, yes, but it's not the same.

18:20 berdario: Does someone here knows if it's possible to use the repl from lein-cljsbuild, without a ring (or another kind of) server?

18:21 I'm trying to connect it through a pure cljs application... and in the web inspector console, I see that there's an error when trying to access the robots.txt

18:21 so, I fear that it might not really be fit for this purpose

18:26 Uhm, according to this https://github.com/clojure/clojurescript/wiki/The-REPL-and-Evaluation-Environments

18:26 there shouldn't be any server requirements, aside from the repl listener

19:49 futile: mthvedt: this means at compile time every group *contains* all of its parents: (defn ^:test ^{:group {:description "a group" :parent {:description "another group" ...}} my-test [] ...)

19:49 mthvedt: that's weird

19:55 mthvedt: but maybe its not that bad to have every group contain its parent group directly (if it has one), instead of just referencing it..

19:55 Thoughts anyone?

19:58 cc bbloom gfredericks et al

20:00 mthvedt, amalloy: ooh yeah I remember another reason I made tests be vars instead of fns: so you can get useful metadata about it for reporting, like the function's name and docstring, etc.

20:07 mthvedt: futile: what do you think of having the test finder pick up the metadata

20:08 i'm of the opinion that the piece that does running and reporting shouldn't have any assumptions about where test comes from

20:09 futile: mthvedt: I was thinking that too. If the finder is responsible for knowing about ^:test, perhaps it can translate :name and :doc etc too. Only problem is, where does it store this information, if a test is supposed to be just a function, plain-and-simple?

20:10 mthvedt: Can functions reliably house metadata? http://clojure.org/metadata says only symbols and collection, even though I think it might technically *work* for a function.

20:14 mthvedt: ,(meta (with-meta (fn [] 'foo) {:a :b :c :d}))

20:14 clojurebot: {:a :b, :c :d}

20:15 futile: So it seems to work, but is it reliable? Who knows.

20:16 ,(let [f (with-meta + (meta +)] [f (meta f))

20:16 clojurebot: #<RuntimeException java.lang.RuntimeException: Unmatched delimiter: ]>

20:16 futile: ,(let [f (with-meta + (meta +))] [f (meta f)]

20:16 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

20:16 futile: ugh

20:16 ,(let [f (with-meta + (meta +))] [f (meta f)])

20:16 clojurebot: [#< clojure.lang.AFunction$1@c943ba> nil]

20:17 hyPiRion: I think you meant this

20:17 futile: probably

20:17 amalloy: metadata on functions is reliable, but i don't know why you want to use metadata at all. what is "better" about '[^{:test blah :doc whatever :name foo} f ^{:test more} g] than '[{:test blah :doc whatever :name foo :fn f} {:test more :fn g}]?

20:17 hyPiRion: ,(let [f (with-meta + (meta #'+))] [f (meta f)])

20:17 clojurebot: [#< clojure.lang.AFunction$1@139110c> {:arglists ([] [x] [x y] [x y & more]), :ns #<Namespace clojure.core>, :name +, :column 1, :added "1.2", ...}]

20:18 hyPiRion: (with-meta foo (meta foo)) is like saying just foo.

20:18 futile: amalloy: i.e. where "test" would be a map of info about a test, including the test fn itself?

20:19 amalloy: indeed

20:19 mthvedt: futile: i use a 'punning' approach in this parser lib i wrote, https://github.com/eightnotrump/clearley

20:19 where a parse rule can be one of several things, and there are exposed fns to turn them into "full fledged" rules

20:19 futile: amalloy: I dunno. I think part of the initial attraction was how simple it would be to find and run tests. This adds a little complexity to the intermediate functions, although I think it's probably worth it and usually hidden enough inside "required" functions to be unnoticable.

20:19 mthvedt: it's a little messy but was much less messier than other approaches i tried--protocols, multi methods, putting conds in everything…

20:22 futile: ie, its really not that bad if you have to do (run-test (test-from-fn my-widget-test))

20:22 mthvedt: so you could say that a test is a var, or a fn, or a test record, and expose a punning multi method

20:22 that might be too heavyweight

20:23 futile: mthvedt: yeah I try my best to always avoid "you could give it this, or this, or this, or this, or even this if you want, and itll Just Work™"

20:23 thats nothing but HeadacheVille and BugLand

20:24 mthvedt: futile: clojure has a lot of that kind of punning. i don't think there's a problem as long as you try to stay well defined

20:24 Duffman: Hello, I'm experiencing some problems in Clojure and I'd like to get a second opinion on it as I have no ide at all what's going wrong. Should I paste my code in pastebin or so to get help here?

20:24 gfredericks: Duffman: sure

20:24 futile: Duffman: we like refheap.com

20:25 mthvedt: but if you're not careful with your mishmash of types, you end up with javascript

20:25 Duffman: also I should admit that I'm doing this in the context of a school assignment

20:25 I hope that's no problem.

20:25 futile: mthvedt: [] + {}

20:26 mthvedt: oh sorry I meant {} + []

20:26 amalloy: Duffman: go for it

20:27 Duffman: Okay thanks. I'll just be a minute. I'm writing some context

20:33 Okay, here goes: https://www.refheap.com/b36e93390aed8c1b132639cab

20:33 I tried to add some context at the top of the file. The first time i get an element from the cache, it all works fine. But if I type "c" then in my REPL (look at the end of the file) or do another cache-get, it fails utterly.

20:35 It looks as if "c" is broken once I invoke (cache-get c :a) because if I type "c" in the repl after this first invocation (which works fine); I get this error;

20:35 StackOverflowError java.util.HashMap.get (:-1)

20:36 if the description of the purpose is not clear, I can supply you with some more information

20:38 amalloy: is the stuff in the context a required way to implement the algorithm, or a description of how you've chosen to go about it? because it seems crazily complex

20:40 Duffman: it's sort of required

20:41 it's a suggested way to do it

20:42 amalloy: like, if i were implementing an lru cache around a function, i would just have two maps: hashmap from key->value and sorted-map of access-time->key

20:42 Duffman: because the cache needs to be so efficient.

20:42 yeah, that would be simpler but it should be more efficient than that

20:43 I'm not sure whether this is more efficient but I think they just want to add a degree of difficulty

20:43 amalloy: the description doesn't sound efficient at all. doubly-linked lists in a functional language are basically impossible, and reimplementing a hashmap by hand is a sure way to get slow code

20:44 anyway, if you have to do it that way then you have to, i guess. but i can't make heads or tails of the code, so hopefully someone else can help

20:45 Duffman: https://www.dropbox.com/s/d68b586csffu2gb/Project-Clojure.pdf

20:45 description of the exercise

20:46 I know I'm starting late but I had to hand in a thesis yesterday and that really got my priority

20:57 Thanks for looking at it anyway amalloy!

21:01 hyPiRion: Duffman: So the properties that you want for that second data structure is fast removal of an element you know exists in the structure, along with fast insertion at the front

21:02 Along with order

21:02 Duffman: yes

21:02 I found one of my errors btw, on line 86 I should deref first, instead of ref

21:02 so I'm working on a new problem now

21:03 I'll try to fix it on my own first

21:04 I know see a lot of other errors like not adding keys to the cache and stuff like that, so I'm going to look into that first

21:04 hyPiRion: ok

21:08 wei_: cljsbuild just started throwing this: Exception in thread "main" java.lang.RuntimeException: No such var: json/pprint, compiling:(cljs/source_map.clj:142:7)

21:08 anyone seen that before?

21:12 Duffman: hyPiRion: one small question though if you don't mind

21:12 amalloy: i wonder if you just want a ring-buffer instead of a doubly-linked list

21:12 Duffman: (repeat 5 (ref '()))

21:12 hyPiRion: sure

21:12 Duffman: that spawns a list of 5 refs

21:12 amalloy: Duffman: that's the same ref five times, not five different refs

21:12 Duffman: yes indeed

21:12 how can I make them different?

21:12 amalloy: &(doc repeatedly)

21:12 lazybot: ⇒ "([f] [n f]); Takes a function of no args, presumably with side effects, and returns an infinite (or length n if supplied) lazy sequence of calls to it"

21:12 Duffman: I thought that ref made a new pointer everytime

21:13 hyPiRion: ,(vec (repeatedly #(ref '())))

21:13 amalloy: Duffman: it does. but you only called it once

21:13 clojurebot: #<OutOfMemoryError java.lang.OutOfMemoryError: Java heap space>

21:13 hyPiRion: oh ops, I forgot the amount

21:13 Duffman: hm that documentation makes sense

21:13 I had no idea repeat worked like that

21:13 but it has to work like that

21:13 otherwise repeat until infinity couldn't be possible

21:14 amalloy: Duffman: repeat just takes a value, and gives you N copies of it

21:15 Duffman: thanks amalloy, got it

21:17 hyPiRion: amalloy: persistent of mutable ring buffer? I haven't heard of a persistent ring buffer before, but how would you provide fast random-time removal?

21:17 s/of/or/

21:17 papachan: &(doc slurp)

21:17 lazybot: ⇒ "([f & opts]); Opens a reader on f and reads all its contents, returning a string. See clojure.java.io/reader for a complete list of supported arguments."

21:17 amalloy: hyPiRion: i already have!

21:17 $google amalloy ring buffer

21:17 lazybot: [amalloy/ring-buffer · GitHub] https://github.com/amalloy/ring-buffer

21:18 amalloy: anyway, he doesn't need fast removal from anywhere, only from the end, right?

21:18 i think you're right that ring buffers aren't right, but it's close

21:18 hyPiRion: amalloy: he need to update elements if they're in the cache

21:18 Duffman: it's not really removal amalloy

21:18 amalloy: i'd still use a sorted-map, personally, since it's O(log(n)) on an n that's known to be small, but if he needs O(1)

21:19 Duffman: I have to add an element at the front of the list, and the one-but-last element it's next should then refer to 'nil'

21:19 hyPiRion: Right, it's "push-to-front"

21:19 Duffman: its next*

21:21 hyPiRion: Duffman: I think it's smart to just implement a version using a sorted-map and a counter first

21:22 Just so you have something to deliver

21:22 Duffman: yeah maybe you're right

21:22 this does make things complicated

21:24 hyPiRion: "It is not necessary to make use of Java

21:26 Duffman: indeed

21:26 hyPiRion: that's what confuses me, heh.

21:35 gfredericks: for programs whose main output goes to STDOUT, is printing progress messages to STDERR considered normal behavior?

21:35 by "main output goes to stdout" I really meant that progress messages would corrupt the output

21:36 hyPiRion: gfredericks: depends. For e.g. lein classpath, we would like "fetching repository..." messages to be stderr so that you can pipe the results of lein directly into another command

21:39 zRecursive: &(doc ->)

21:39 lazybot: ⇒ "Macro ([x] [x form] [x form & more]); Threads the expr through the forms. Inserts x as the second item in the first form, making a list of it if it is not a list already. If there are more forms, inserts the first form as the second item in second form, etc."

22:28 tomjack: gfredericks: wget is an example which does that

22:29 although, hmm, what's STDOUT? empty?

22:51 noahlz: http://stackoverflow.com/q/17129117/7507

22:51 noticed this question, wondering about the answer

22:51 "something like find-doc but that gives you a prompt of matching names"

22:52 remember seeing it too

22:54 xeqi: &(doc clojure.repl/apropos)

22:54 lazybot: ⇒ "([str-or-pattern]); Given a regular expression or stringable thing, return a seq of all definitions in all currently-loaded namespaces that match the str-or-pattern."

22:58 noahlz: hmm

22:58 yeah, the person asking this seems to think it is clojure.contrib.repl-utils/show

23:08 wei_: for anyone else who runs into this exception: Exception in thread "main" java.lang.RuntimeException: No such var: json/pprint, compiling:(cljs/source_map.clj:142:7).. my fix was to add [org.clojure/data.json "0.2.2"] to my project

23:09 bbloom: wei_: dnolen added that as a dependency to cljs. i guess maybe you've found a lein-cljsbuild bug? or are on an older version?

23:10 wei_: I'm on 0.3.2

23:11 tomjack: I experienced that as well. my guess is `lein cljsbuild clean` would fix it

23:11 futile: Gents.

23:12 And ladies, but I can't tell the difference in here.

23:12 Does it make sense to just use exceptions to tell that a test is pending?

23:12 dnolen: wei_: that should just work - but I'm not 100% sure

23:13 wei_: in anycase, bbloom is correct, if it doesn't work cljsbuild and clojurescript are out of sync

23:14 wei_: thanks, I've fixed my project by adding the data.json dependency, but it fails if I take it out. investigating more to see if I isolate the problem.

23:15 futile: I think no other lib uses "pending" except speclj.

23:15 wei_: dnolen: btw, does the existence of cljs/source_map.clj mean we'll see cljs source in the inspector soon? :)

23:15 muhoo: interesting, if i use a library whose license is EPL or MPL, and there's no documentation, just code in test/core.clj, i can't use that code unless i keep the whole app EPL/MPL?

23:16 dnolen: wei_: there's basic support there, but we need more accurate information from the reader, this work is supposed to be part of GSoC 2013

23:16 wei_: sounds good. that's a killer feature

23:19 muhoo: hmm, nevermind, i'm so used to GPL i forgot that EPL and MPL aren't quite that strict.

23:38 wei_: it appears that adding a library that includes a previous version of data.json, like [clj-pusher "0.3.1"], breaks cljsbuild unless you include the newest data.json in your own project.clj. demonstration app here: https://github.com/yayitswei/cljsbuildtest

23:43 akhudek: https://github.com/akhudek/zip-visit

23:44 just finished some docs for the above library, hope it's useful to someone

23:45 dobry-den1: if you define a function within a (let […]), that will get defined every time the fn is called. is that reason enough to extract those functions and use (defn- …) instead?

23:45 wait a second...

23:45 nevermind

23:46 Duffman: I built a small use-case

23:46 https://www.refheap.com/15821

23:47 anybody any idea why 'y' doesn't work anymore?

23:47 nor does x

23:47 I'm guessing its because they refer to each other and you shouldn't do that in clojure?

23:48 amalloy: Duffman: the exception is when the repl tries to print them

23:48 Duffman: oh

23:48 amalloy: mutually recursive refs aren't really a good idea, but they're perfectly possible

23:48 Duffman: but the repl can't print them because he keeps on jumping back and forth between both?

23:49 amalloy: right

23:49 Duffman: I see

23:49 makes it hard for debugging

23:49 I've literally been looking into this for the past 2 hours

23:49 looks like it's a limitation of the REPL

23:49 amalloy: not half as hard as having mutally-recursive mutable state does :P

23:50 tomjack: if you set *print-level* you can print them

23:50 amalloy: can you? i thought print-level was for nested lists, not nested print invocations

23:50 but even as i say it now, it sounds crazy

23:50 tomjack: I dunno how it works, but just tested to see if it works on refs

23:51 Duffman: how do you set the print-level Tom? http://clojuredocs.org/clojure_core/clojure.core/*print-level* doesn't give an example

23:51 tomjack: (set! *print-level* 4)

23:51 Duffman: I see

23:51 thx

23:51 tomjack: not that I think you should be doing what you're doing :)

23:52 Duffman: I know

23:52 I was just experimenting

23:52 tomjack: hmm, I'm confused

23:53 the only use of *print-level* seems to be in print-sequential

23:53 oh, but the print-method for IDeref uses print-sequential

Logging service provided by n01se.net