#clojure log - Aug 21 2013

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

0:01 amalloy: callen: (doall #(future ...)) throws an exception for any ... :P

0:05 fbernier: validating and converting a string into a number is harder than I thought...

0:05 sinistersnare: fbernier: no regex?

0:11 fbernier: ... makes sense I guess :)

0:11 sinistersnare: fbernier: what?

0:11 fbernier: thanks for the idea

0:12 sinistersnare: great!

0:25 TEttinger: fbernier, ##(map #(when-let [num (re-find #"\d+" %)] (read-string num)) ["argh" "11" "a1 steak sauce"]) not sure what validate means here

0:25 lazybot: ⇒ (nil 11 1)

0:26 TEttinger: fbernier, if you only want pure numbers, no letter allowed, ##(map #(when-let [num (re-find #"^\d+$" %)] (read-string num)) ["argh" "11" "a1 steak sauce"])

0:26 lazybot: ⇒ (nil 11 nil)

0:28 callen: amalloy: I wasn't typing to type it accurately.

0:28 anyway, I'm experimenting with a medium weight based implementation and one using core.async now.

0:41 * dsagsda Welcom to Allinone.nix.vn Sexy Free!

0:44 amacdougall: TEttinger: I'll give it a shot! Wonder if it'll pause execution?

1:12 ozzloy: what about 1e5

1:12 that's a number

1:13 an integer even

1:51 ddellacosta: is there a way to use limit for a query using the SQL dsl in clojure.java.jdbc? That is, if I'm using sql/select, how do I add a limit clause?

1:56 callen: ddellacosta: looking at the query syntax, I see two plausible places for a :limit 10 type dilly to go. Did you try both?

1:58 ddellacosta: callen: well, from what I can tell, all of the clause-type options are provided as functions within the sql namespace. I did try passing in a hashmap like (java.clojure.jdbc.sql/select [:some_col] :some_table {:limit 1}) which is not supported (obviously, when you look it up), and I searched for a limit function, and there is none. So I'm falling back on just using the normal way of specifying the query, as a

1:58 string, although it's not ideal.

1:59 callen: but, did I miss something? Not sure if what I tried falls within the two options you were thinking of.

2:00 callen: drop the { and } around :limit 1

2:00 see what it does.

2:00 ddellacosta: lemme give that a shot

2:01 Nope, just ignores it. Bummer: => (s/select [:some_col] :some_table :limit 1) ; ("SELECT some_col FROM some_table")

2:01 * callen squints then scuttles off to read the code

2:01 ddellacosta: heh

2:03 callen: honestly, I think it's just not supported by the SQL dsl--the select function is pretty straightforward, and ends at "order-by" more or less. No alternative options seem to get parsed. I suppose I could stuff it into a string and pretend it is the where-clause, perhaps, but I should probably just submit a patch. But it's low priority, and very easy to get around with clojure.java.jdbc (why I'm using it).

2:04 ryanf: it looks like it just doesn't support limit clauses

2:04 callen: there's no way it's that limited.

2:04 ryanf: yeah

2:04 callen: no. that would be insane.

2:04 ryanf: the code is pretty clear

2:04 callen: I refuse to believe cjj is that misconceived.

2:04 ddellacosta: while I'm poking around the code, try moving the :limit 1 outside of the select to the query section.

2:04 ddellacosta: callen: I mean, let's be clear--I'm just talking about the dsl

2:04 callen: I get that just fine.

2:04 ddellacosta: callen: ah, okay--I wasn't trying that, let me give it a shot

2:04 ryanf: https://github.com/clojure/java.jdbc/blob/master/src/main/clojure/clojure/java/jdbc/sql.clj#L229-265 really doesn't leave any room for extra clauses

2:05 you can see exactly where each part is coming from, and the interface of the function doesn't have any way to add more to the string part of the query

2:05 oh I guess you could put it in the order-clause position actually, since it lets you pass a string for order

2:06 callen: that's...jfc.

2:06 I really thought they'd fixed all this. ;|

2:06 ryanf: that actually wouldn't be that bad if they just documented the order-by param as representing the whole end of the query instead of specifically ordering

2:07 ddellacosta: yah

2:08 ryanf: yeah, that works. callen, I wasn't able to pass in limit within query (but outside dsl) as a map or in a named arg kinda form either. But ryanf's suggestion is better than what I was doing before. I think this is just not baked in yet.

2:08 callen: Korma has had limit since forever :|

2:09 ddellacosta: callen: yeah, but I mean to be fair, this dsl is not trying to solve the same problems as korma--it's much smaller in scope. Part of the point (as I understood it) is that it allows you to get more low-level more easily, but doesn't give you as much magic as korma

2:10 callen: I'm not sure a DSL that doesn't enable non-hacky limit clauses is really accomplishing being low-level.

2:11 I understand the objective, but that is...a frightening oversight.

2:12 ddellacosta: callen: well, I mean, I suspect a lot of people are using the java.clojure.jdbc.sql stuff in a limited fashion. The real power in the lib is in the clojure.java.jdbc namespace. I don't need the dsl to use anything in there.

2:13 …which is to say, I suspect if you need a "serious" dsl for SQL, you'll use…Korma. haha

2:14 * callen mutters inaudible imprecations

2:15 ddellacosta: haha

2:15 imprecation is not a word I encounter with any frequency. Lovely.

2:15 callen: ddellacosta: what did the Japanese in your recent tweet say?

4:08 sontek: Are there any good examples of a getting started with web development in clojure?

4:08 Want to play with it in my spare time and see if I could make the switch from python

4:18 shdwprince: sontek: see webnoir.com

4:19 sontek: after django I was impressed

4:20 oh, not webnoir

4:20 search for noir framework

4:20 fredyr: .org is it

4:21 sontek: I use Pyramid, so hoping for something a little like that inside of Django like

4:21 I'll checkout noir

4:22 fredyr: there's also pedestal

4:22 http://pedestal.io/

4:23 dark_element: sontek, noir is deprecated now. Take a look at compojure or pedestal

5:13 mpenet: sontek: there is also luminus

5:38 noncom: how do i in clojurescript treat javascript'b object "method" as a function?

5:39 like i want to pass it around and then call on a particular instance and with args

6:05 augustl: noncom: methods in javascript is pretty easy to do by hand. The only thing that really changes in a method is what "this" is.

7:10 dissipate: anyone have a recommendation for a good book to learn clojure?

7:10 vijaykiran: dissipate: http://www.clojurebook.com/

7:11 NiKo`: dissipate: I much enjoyed Clojure Programming from O'Reilly

7:11 what vijaykiran said

7:11 Saturnation: how do you get pprint loaded in emacs nrep-jack-in?

7:12 dissipate: NiKo`, surely that book is out of date though? doesn't cover clojure 1.5?

7:12 Saturnation: I know it's something easy, I just keep forgetting it :/

7:13 NiKo`: dissipate: dunno if it's been updated, though the core concepts aren't changing that much

7:14 btw do you guys know who's in charge of maintaining clojuredocs.org? seriously needs to cover 1.5

7:15 shdwprince: dissipate: 1.5 is not much from 1.4. I forgotted to change dep in lein project and programmed for 1.4 for week, but thought it was 1.5.

7:16 dissipate: NiKo`, that book says it was tested on version 1.4

7:17 shdwprince, i see

7:18 shdwprince: dissipate: nvm, 1.5 generally brings a bunch of functions, which you can read about on documentation

7:19 dissipate: shdwprince, how important are those functions for learning clojure?

7:21 shdwprince: dissipate: it was not important for me

7:22 and I can recomment http://java.ociweb.com/mark/clojure/article.html - short and hard introduction to clojure's aspects if you dont wanna read tons of text explaining simple things

7:53 calvin91: good morning clojure!

8:39 ker2x: meep

8:39 ordnungswidrig: pong

8:43 ker2x: i'm reading shdwprince's link :)

8:51 instilled: hi! I'm wondering if it is possible to extend an existing protocol method with additional dispatch methods implementations. I would be grateful if someone could point me into the right direction. Thanks!

8:59 dnolen: instilled: extending an implementation of protocol? Not supported though you could probably come up with something that will work for you.

9:03 instilled: dnolen: i use deftype to extend a protocol and would like to define additional dispatch on some of the functions of that type (protocol or implementation thereof).

9:03 freiksenet: is that expected behaviour? https://gist.github.com/freiksenet/057398a16478a6c8856d

9:04 dnolen: instilled: like i said not directly supported. a deftype can provide one implementation of a protocol fn that's all. You can make this flexible yourself if you like.

9:05 instilled: dnolen: ok. wasn't sure if I put it clear enough. thanks. could you briefly describe what to do? …I'm quite new to clojure.

9:05 noncom: what is the current recommended AJAX approach for clojurescript?

9:06 i assume core.async would do if it were net-capable, but looks like it is not yet, so whats the usual alternatives?

9:06 stuartsierra: freiksenet: I believe so, yes. Sequences over mutable collections are not guaranteed to be stable.

9:06 noncom: calvin91: good morning, man!

9:07 freiksenet: clojure docs say "When seq is used on native Java arrays and objects that implement Iterable, the resulting sequence is still immutable and persistent, and will represent a single pass across the data. B"

9:07 dnolen: instilled: a component entity design is one possibility I've played around with, but I don't have any more guidance than that.

9:07 freiksenet: stuartsierra: so in a way it is supposed to be guaranteed

9:08 I would say array copy is missing in ArraySeq.java if it is to follow the idea of seqs

9:08 instilled: dnolen: cheers! I'll ponder about it more deeply and see what I can come up with...

9:09 stuartsierra: freiksenet: Interesting.

9:10 dnolen: freiksenet: it's intentionally missing for performance reasons as far as I can tell, you can clone the array yourself.

9:10 freiksenet: obviously that would be a major performance hit

9:10 dnolen: then this should be explicetely mentioned in docs

9:10 explicitly*

9:11 cause currently they are misleading in a sence that they claim persistence of the seq over native arrays

9:11 also IMO that is a bad behaviour design-wise as it breaks the contract of the seq interface. You have to worry about implementation if you are to be sure that your seq is immutable

9:12 dnolen: freiksenet: performance matters, if you're dealing with primitive arrays you obviously know what you are doing.

9:12 freiksenet: it's not like you are always in control of your code or that you can easily say that this seq is an arrayseq

9:12 of all your code*

9:13 dnolen: freiksenet: anyways the other choice is equally undesirable without complicating the seq api - aka, seq-mutable, or seq w/ a flag

9:13 freiksenet: documentation should be fixed anyway

9:13 stuartsierra: It's definitely an inconsistency with the documented behavior on clojure.org/sequences

9:13 dnolen: freiksenet: anyways it's a design choice that balances the desire to work with mutable arrays w/o incurring copy on write.

9:14 tbaldridge: couldn't ArraySeq cache array[idx] at each next? Thats what LazySeq on top of an array would do.

9:14 dnolen: freiksenet: stuartsierra: I don't disagree the docs are off.

9:14 freiksenet: I understand)

9:14 tbaldridge: that would mean it will take double the space

9:14 tbaldridge: only if you realized the entire seq

9:14 freiksenet: at worst case

9:15 is there a bugtracker for clojure docs?

9:15 tbaldridge: although, if you're doing seq on array do you really care about extreme performance? As long as it isn't O(n)

9:15 dnolen: tbaldridge: you do

9:16 tbaldridge: on CLJS at variable arity call sites, we wrap the array in seq

9:16 tbaldridge: no copy on write and no traversal overhead critical

9:16 stuartsierra: freiksenet: There's no JIRA for clojure.org, but I'll push the issue to those who can fix it.

9:16 tbaldridge: dnolen: I just wonder if I'm already allocating a ArraySeq item for every single array element, what's one more pointer?

9:16 freiksenet: thanks!

9:17 tbaldridge: dnolen: you have the transversal overhead of allocating ArraySeq

9:17 dnolen: tbaldridge: every variable arity in the core library slows down. When I read through ArraySeq I breathed a sigh of releaf.

9:18 tbaldridge: overhead of allocating ArraySeq is very low, it's just a wrapper, traversal is just incrementing an integer

9:18 and another wrapper

9:19 tbaldridge: I wonder what the perf impact would be if it was cached on the first get. That way at least doing (first s) several times in a row wouldn't return different values.

9:20 that way there is not transversal cost, only a cost on a get.

9:20 freiksenet: you would have a cost of either allocating an full array for that at double space cost

9:21 or having to allocate buffers or smth like that on time cost every time you have to allocate new/expand

9:21 IMO in such case it's better to copy

9:30 dnolen: tbaldridge: so with ring buffer drop in - pushing 1 million events in core.async takes about 2.5 seconds under Chrome/Safari. I think this good enough for a good number of applications :)

9:30 stuartsierra: freiksenet: I chatted with Rich & Alex Miller: We're going to fix the docs on clojure.org.

9:30 tbaldridge: dnolen: is that with the new dispatch code?

9:31 dnolen: tbaldridge: I left everything else alone, I think my tick idea was misguided. just w/ ring-buffer change that made Chrome 3-3.5X faster

9:31 freiksenet: stuartsierra: great

9:33 cmajor7: are there any built in ways to monitor/restart if down threads (i.e. futures)?

9:37 dnolen: tbaldridge: most of my problem was that I didn't really understand how core.async works - that writes will proceed if you use buffers and only dispatch if it can't proceed

9:37 tbaldridge: dnolen: yeah, and I learned something about semantics yesterday as well.

9:37 dnolen: tbaldridge: I finally understand why Rich kept saying we don't need a scheduler, you can express task granularity at the level of buffers

9:38 stuartsierra1: cmajor7: If you want notification that a thread died because of an exception, you can use Thread/setDefaultUncaughtExceptionHandler.

9:38 dnolen: tbaldridge: the reason I was thrown off was because I was benchmarking and seeing weird behavior w/ large buffer sizes, which is no longer the case

9:39 tbaldridge: dnolen: I'm still not convinced that we need everything in channels.cljs. I'm thinking about using ring buffers inside channels themselves, and then rewriting channels from scratch. We could add "resize" to the ring buffers, and then they'd work just fine for put/take queues

9:39 dnolen: yes, also "cleanup" is super slow on large buffers, not sure what to do about that

9:39 dnolen: tbaldridge: what is cleanup?

9:40 tbaldridge: dnolen: it pulls out (= (active? val) false) values in the put/take queues.

9:40 cmajor7: stuartsierra1: thx, let me check it out

9:40 tbaldridge: dnolen: but because we're single threaded, I think we could move that code somewhere else.

9:42 stuartsierra1: cmajor7: But there's nothing like `monit` for Java threads that I know of.

9:42 dnolen: tbaldridge: ah I hadn't even looked at the other queues in channel beyond buf

9:43 tbaldridge: I will say in my benchmarks so far at this point hardly any time seems spent in core.async now - it's all in dispatch

9:43 tbaldridge: post ring buffer change

9:43 cmajor7: stuartsierra1: right, I though maybe there is an elegant way to wrap a "supervisor" around one or two threads..

9:44 stuartsierra1: cmajor7: Sounds like Erlang ;)

9:45 tbaldridge: dnolen: yeah, that dispatch code still needs some improvement. After testing some of it yesterday, I'm fine with the tick version you had. We may improve it later, but I haven't seen any major issues with it.

9:45 dnolen: tbaldridge: oh cool! yeah it didn't seem to change the semantics in any interesting way - and sliding buffer performance shot way way up

9:46 cmajor7: stuartsierra1: it does, but I want it to sound like clojure :)

9:57 mikerod: Does the map function guarantee the resulting seq is the same order as the colls given?

9:59 hyPiRion: yes

10:00 mikerod: hyPiRion: thought that was the case

10:44 boblarrick: Is there an idiomatic way to tell what iteration of a doseq on a lazy seq you are on?

10:47 nDuff: boblarrick: there's something in the standard library that emits a lazy sequence of [idx value] pairs, given a sequence.

10:48 boblarrick: ...I don't remember just what it is offhand, though.

10:48 boblarrick: :)

10:48 fredyr: map-indexed

10:48 is perhaps what your thinking of

10:48 babilen: that still maps a function though

10:49 hyPiRion: well, (map vector (range) seq) is probably what you want if you want no manipulation

10:50 boblarrick: I'm processing lines of a (large) file and want to print out what line i'm on periodically

10:51 atom seems a bit heavy

10:52 ToBeReplaced: picking up some academic books off amazon, looking for some timeless recommendations, and need one recommendation for category theory -- quick picks?

10:52 hyPiRion: ,(doseq [[idx value] (map vector (range) [:a :b :c :d :e :f :g])] (when (even? idx) (prn value)))

10:52 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: doseq requires an even number of forms in binding vector in sandbox:>

10:55 hyPiRion: ,(doseq [[idx value] (map vector (range) [:a :b :c :d :e :f :g])] (when (even? idx) (prn value)))

10:55 clojurebot: :a\n:c\n:e\n:g\n

10:55 hyPiRion: meh, sneaky whitespace

10:56 dnolen: tbaldridge: pushing 1 millions message down a channel is now takes <1.7 seconds on Chrome

10:57 tbaldridge: after staring at the profiles for a long time - dispatch is not the bottleneck, there's a lot of places to optimize the code

10:57 boblarrick: hyPiRion: thanks!

10:58 tbaldridge: dnolen: that's what I was seeing last night. I was actually seeing high usage of nth in some of my tests. I think we can simplify the channel code and that should help

11:02 kral: namaste

11:05 dnolen: tbaldridge: I pushed some type hinting changes and switched = to ==, big difference

11:05 tbaldridge: nice

11:06 dnolen: tbaldridge: the ioc macros need to type hint terminator argument

11:06 tbaldridge: otherwise you're going to needlessly pay for protocol dispatch overhead

11:06 tbaldridge: dnolen: the == ::recur part?

11:06 dnolen: tbaldridge: no any place where the macro inserts calls to impl.protocols/put! take! etc

11:07 you need to type hint the argument to those

11:07 tbaldridge: at that point I think it's just optimizing the body of put! and take! of ManyToManyChannel

11:07 "after that point"

11:08 tbaldridge: I suspect we can get pretty close to 1 million messages a second :)

11:09 tbaldridge: dnolen: do we need more besides ^not-native here? https://github.com/clojure/core.async/blob/master/src/main/clojure/cljs/core/async/impl/ioc_helpers.cljs#L41

11:09 or do calls to these functions need type hints?

11:20 TimMc: I have a namespace in an uberjar that is somehow getting loaded even though nothing :requires it. Might AOT be responsible?

11:24 llasram: TimMc: What's the namespace? And is it actually getting fully loaded, or just created and having vars interned in it?

11:24 TimMc: gen-class classes do load their backing namespace as part of static class initialization

11:25 That's the only obvious thing I can think of for the fully-loaded case

11:26 TimMc: llasram: There's a namespace "auth" with a defmulti, and a namespace "auth-ldap" with an implementing defmethod.

11:27 dnolen: tbaldridge: oh ok you generate calls to ioc-helpers, ok we don't need more type hints thens

11:27 TimMc: Nothing :requires auth-ldap, but the multimethod dispatch nevertheless contains that entry.

11:27 llasram: TimMc: Interesting...

11:28 TimMc: Needless to say, everything blows up at the REPL.

11:28 I've since fixed the code to put the defmethod in the same ns as the defmulti, but I don't know how it ever worked.

11:28 llasram: Clojure gnomes sneak into your JARs at night, fixing up multimethod dispatch entries while you sleep

11:29 TimMc: *nod* That makes as much sense as anything else.

11:31 https://github.com/search?q=%22how+did+this+ever+work%22&type=Code&ref=searchresults

11:32 llasram: I like that C is the most common language for this lament

11:34 hyPiRion: or, if you search for "fuck", VimL is the largest one

11:34 TimMc: It's a little misleading; there are a ton of duplicates in some languages.

11:36 sevvie: 51 pages of "How did this ever work?"

11:37 ... sorted by "Best Match."

11:46 TimMc: llasram: ...and I can't reproduce it as a SSCCE.

11:48 llasram: TimMc: Those drive me batty

11:49 TimMc: Hmm. Are there any gen-class'd classes at all in uberjar? Maybe there's an expected reference to one of them, which is causing an unexpected chain of transient namespace loads

11:50 s,transient,transitive,

11:50 TimMc: The main ns is gen-class'd, and there are others.

11:54 yedi: is there a blogpost that depicts the stages of a clojure programmer's journey?

12:00 llasram: The journey to Clojure/conj kind of depends on where you live and where the Conj is hosted in a given year. You'll probably need to fly, but other options might be available

12:05 amacdougall: I hereby mark this answer as "accepted"

12:20 noncom: kral: namaste

12:24 yedi: there were some, but i'm missing links

12:26 yedi: noncom: sucks, would have loved to read some

12:27 noncom: yedi: i think that if you google, you gonna find something...

12:27 btw, what do you expect for these stages to be?

12:36 amacdougall: Stage 1: http://0.tqn.com/d/animals/1/0/X/7/shutterstock_714240.jpg Stage 2: http://oxun.ge/uploads/posts/2011-02/1297948507_green_lantern.jpg

12:39 arrdem: lol

12:45 upwardindex: I'm getting a Compilation error: TypeError: cljs.core.coercive_boolean is undefined on himera when trying to run a doseq, is the problem on my side?

12:45 ,(doseq [x [1 2 3]] 3)

12:45 clojurebot: nil

12:46 dnolen: upwardindex: more likely something out of sync in himera

12:47 upwardindex: dnolen: the reason I'm trying it there is that doses with 4 bindings or more hang my cljs at home

12:48 3 bindings or less run just fine

12:48 doseqs*

12:48 dnolen: upwardindex: paste please

12:48 upwardindex: and what do you mean hang? hang Rhino? Hang browser? Hang Node.js?

12:49 upwardindex: browser

12:49 justin_smith: this was really fun to write: http://sprunge.us/HePW?clojure (generates and prints spiral paths through 2d vectors)

12:49 upwardindex: I'll make a paste, one sec

12:55 dnolen: this will hang brepl when trying to compile http://pastebin.ca/2435411

12:56 as a workaround i split it into 2 doseq and it works

12:59 dnolen: upwardindex: yeah that generates a lot of code, the compiler seems to handle it find, but Rhino does like it too many locals

12:59 upwardindex: feel free to file a ticket in JIRA

12:59 s/does/doesn't

13:00 upwardindex: it's not obvious to me what we can do about that, also would prefer to have a lot more information about it in the ticket

13:01 upwardindex: i.e. does it work under compilation and under which compilation modes

13:05 upwardindex: It's very weird, if I paste the doseq in the repl it can evaluate it fine. If I paste the defn containing the doseq, repl hangs

13:08 boblarrick: I'm trying to use nrepl, but C-<up> isn't doing anything, I have to do M-x nrepl-backward-input. How can I track down why and fix it so C-<up> works?

13:11 technomancy: boblarrick: why not M-p instead?

13:11 llasram: boblarrick: Do `M-x describe-key RET`, then hit C-<up> (or M-p) and see what it says it's currently bound to instead

13:11 technomancy: control sequences with non-letters don't translate well over SSH, so it's best to avoid them

13:12 llasram: Oh yeah -- that might be it. I had to tweak Emac's under standing of control characters to make it work for me

13:12 Emacs's even

13:15 boblarrick: technomancy: M-p works great, thanks

13:25 shdwprince: Anyone can offer me a handy vim plugin for dealing with lisp syntax? I know about surround.vim, but it can't, for example, delete contents of braces, or braces with content

13:29 Foxboron: shdwprince: paredit.vim

13:33 rasmusto: shdwprince: I would recommend checking out vim-sexp too, its less popular, but is a good middle-ground between paredit and normal vim editing

13:36 shdwprince: Foxboron: thanks, its a plugin what I was searching for; rasmusto thanks too, I'll check it out after paredit

13:36 gvickers: is there anyway to retrieve the namespace loaded after (load-file) is called?

13:39 nevermind, looks like load-file returns the first function in the namespace

13:48 dnolen: hrm it looks like Closure Compiler changes are going to force us to write a real rewriting pass in ClojureScript

13:49 bbloom: dnolen: what changes are coming?

13:49 dnolen: also, fuck yes more clojure-level compiler optimizations :-)

13:49 dnolen: bbloom: Closure used to optimize if expressions where the test would emitted as a function we just invoke

13:50 in Clojure|Script `and` and `or` are macros around `let`

13:50 in expression context `let` is wrapped in `(function() { ... })()`

13:50 we've been getting a free ride for a long time

13:50 but it's never been as good as I would have liked

13:50 bbloom: yeah, they used to hoist that to a top level function?

13:50 dnolen: you often have have to move these things around

13:51 bbloom: no they wouldn't hoist to a function

13:51 just rewrite semantically the same things, a series of ifs

13:51 bbloom: and they no longer do that, why?

13:51 dnolen: bbloom: I don't know I sent along an email to list

13:52 bbloom: still it's finicky

13:52 bbloom: i think we should do this: http://matt.might.net/articles/a-normalization/

13:52 dnolen: bbloom: you often have to manually lift

13:52 bbloom: it's a really easy transform, i already did a proof of concept

13:52 & makes analysis much easier

13:52 lazybot: java.lang.RuntimeException: Unable to resolve symbol: makes in this context

13:52 bbloom: er code generation, i mean

13:52 dnolen: bbloom: I'm ok with anything that is a surgical change around if

13:53 bbloom: dnolen: tty in a bit

14:06 shdwprince: damn, after reading vim koans I smile every time entering the Tim Pope's plugin page

14:12 silasdavis: what is my best option for getting my project root directory when running a clojure project with leiningen

14:19 `cbp: silasdavis: you mean like (System/getProperty "user.dir") ?

14:21 silasdavis: actually I just want to read a file that is below the root of project

14:23 justin_smith: silasdavis: current directory will be the directory where you started lein

14:23 silasdavis: since lein should be started in the root dir, just give a path under the root dir

14:24 silasdavis: but if your code may end up in a library, use io/resource so that you could potentially load the file from a jar without changing your code

14:24 (or if your code may be packed in a standalone jar or war)

14:25 silasdavis: can I use io/resources?

14:36 justin_smith: you can use io/resource to load a file from the file system (if it is in your class path), or inside the same jar

14:36 (slurp (clojure.java.io/resource "project.clj"))

14:37 bbloom: dnolen: sorry, had a phone call. here's a surgical if transform: https://github.com/brandonbloom/cljs-cps/blob/master/src/cps.clj#L128-L135

14:37 `cbp: is there any framework for RESTful web services or should I just use any web framework?

14:37 justin_smith: just for the heck of it ,(slurp (clojure.java.io/resource "project.clj"))

14:38 amacdougall1: `cbp, I've just recently got started with Liberator, and I dig it so far.

14:39 `cbp: amacdougall1: thanks I will try it out

14:39 bbloom: dnolen: the problem is that it can't be that surgical b/c you can use if inside an expression, like (foo (if x y z)), so you also need to ANF the foo invoke

14:39 dnolen: this applies globally, sadly

14:39 amacdougall1: I considered using just Compojure and doing the plumbing myself, but Liberator really makes it easy to use only the HTTP features you need, while handling the rest transparently.

14:40 `cbp: amacdougall1: does it have a lein template?

14:40 amacdougall1: I just used lein new app and it was fine. Just follow the guide on the site.

14:40 bbloom: dnolen: but, adding a complete ANF pass will be < 200 lines of code & can probably remove 30-50 lines from the emitter where it has to worry about wrapping things in (function() { })() scope things

14:40 dnolen: makes many optimizations much simpler too

14:41 amacdougall1: http://clojure-liberator.github.io/liberator/tutorial/getting-started.html — this guide covered 90% of what I needed to get started.

14:42 dnolen: bbloom: I'm really only concerned about a very small change at this point, unless somebody's offered up to do the ANF stuff, do all the testing, and benchmark compile times :)

14:42 bbloom: I only care about optimizing (if (and ...) ...) and (if (or ...) ...)

14:43 bbloom: dnolen: any individual transform pass is gonna be cheaper than either the current analyze or codegen

14:43 dnolen: MIGHT speed up the gclosure process a tiny bit too by having fewer functions to analyze, but unlikely to make a large impact

14:43 amacdougall1: `cbp: the only pitfall I ran into with Liberator was that if you're defining a route with a parameterized resource, such as (GET "/user/:id" [id] (user id)), the argument must have the same name as the path segment. "id", in this case. When you get to the part of the guide, you'll get it.

14:44 dnolen: bbloom: you missed what I was saying. It's not work I'm interested in doing.

14:44 bbloom: happy for someone else to do all the work.

14:44 clojurebot: It's greek to me.

14:44 dnolen: bbloom: otherwise I'll do the small amount of work that I care about.

14:45 bbloom: dnolen: ok, well what i'm saying is that the solution to this problem is to do an ANF transform. you can do ONLY :if, which will solve the immediate problem, but doing that mixed in to the analyze or code gen pass is likely to be a bad plan

14:45 just gonna get complicated fast

14:46 dnolen: bbloom: not going to touch the analyzer

14:46 bbloom: just the compiler, and I don't care about handling all cases

14:46 bbloom: the only place where Closure Compiler doesn't seem to life is if((function() {})()) { ... }

14:47 and that only important case where I'm annoyed by that is (if (and ...) ...) and (if (or ...) ...)

14:47 everything else c'est la vie

14:47 bbloom: dnolen: sure, so you traverse the tree and transform only :if nodes in to ANF, the problem goes away

14:47 dnolen: but these two cases are needed by all the persistent data structures and critical code like in core.async.

14:48 bbloom: sure, and I'm happy to take your patch if you got one :)

14:48 bbloom: dnolen: would you be OK with me adding an AST pass?

14:50 dnolen: bbloom: I would be OK that, would need to talk over the details - but this Google Closure change has me annoyed enough that I want to put this logic into ClojureScript and not rely on Google Closure for it anymore.

14:50 bbloom: dnolen: btw, the following ops generate instant-call closures when in expression contexts: throw, do, try, let, loop, letfn

14:51 dnolen: bbloom: yes, but these are not problematic in my experience. if get it for free OK.

14:52 muhoo: this feels.... ugly and possibly reinvention of a wheel? https://github.com/kenrestivo/utilza/blob/cea210cdc874ff084e6497c0fe28af0c5e47cf6b/src/utilza/misc.clj#L127

14:52 bbloom: dnolen: at minimum, the pass would need to walk & no-op all forms except for :let and :if

14:52 tbaldridge: bbloom: I'd love all of those for core.async (except letfn, who uses that?)

14:52 hiredman: !

14:52 letfn is sweet

14:53 bbloom: tbaldridge: do you manually inline all of your mutually recursive functions? :-)

14:53 tbaldridge: bbloom: I never write non-polymorphic mutually recursive functions ;-)

14:53 bbloom: i use letfn occasionally when i have a bunch of auxillary functions that i don't want to heavily parameterize, so i define them in the lexical closure

14:54 makes for very tidy code

14:54 tbaldridge: bbloom: yeah, I think I've used it for something like that....once :-)

14:54 bbloom: https://github.com/brandonbloom/cleff/blob/master/src/cleff/core.clj#L13-L20

14:54 that code was HORRIBLE before i made those two little functions

14:54 tbaldridge: back on the subject though, gos in core.async use loop, if, etc. optimizing those would be nice

14:54 bbloom: it's still mildly horrible :-)

14:55 tbaldridge: yup, i think a full ANF makes sense for lots of reasons

14:56 dnolen: bbloom: tbaldridge: there was one place in core.async CLJS I had to manually lift, the giant case - would be nice to not have to do that naymore.

14:56 "giant case of the state machine"

14:57 tbaldridge: dnolen: yeah, I'm not sure how to fix that with the current compiler. I did a test using letfn once (lol) but it was slower on the JVM, may not be the case in JS

14:57 bbloom: dnolen: the real issue is that comp/emit is a public API right now & people depend on it

14:58 dnolen: bbloom: eh, I think people relying too deeply on the internals of ClojureScript know they're hooking into a moving ship.

14:59 bbloom: dnolen: ok, well i think we should create a public "compile" api call w/ an options map

14:59 dnolen: bbloom: so something separate from emit which can stay stable?

14:59 bbloom: yes

14:59 dnolen: bbloom: good idea

14:59 bbloom: similarly, i think the analyzer needs a proper public API too, but that requires standardizing the AST first

14:59 that's more important than the analyze call signature

15:00 but a source -> target compile function doesn't need to expose it's internal representations

15:00 dnolen: my proposal is to break the API first, w/o changing anything else, then we can start to add passes & otherwise improve the structuring of the compiler

15:01 dnolen: bbloom: ok, but let's do this by writing it up, easier to go over the details this way before writing code.

15:02 bbloom: dnolen: you're the gatekeeper, so let me know how you wanna do this

15:03 dnolen: bbloom: just start a page on Confluence or use an existing one. I'd like to go piecemeal, so first lets talk about the step 1 - breaking API and how this will enable passes and improvements

15:04 bbloom: dnolen: you know that i feel that design pages are where progress goes to die :-)

15:06 dnolen: i spend some of my time to write up design notes & in the rare case that somebody actually comments on or improves them, i still then have to go write the code b/c nobody else will…. meanwhile, i'm gonna have to write the code to understand the problem well enough to document it

15:06 dnolen: bbloom: in this case don't worry it won't die. I'll read and comment, this something I want to see fixed in a relatively short amount of time.

15:08 bbloom: I was less interested in the past because I thought we could rely on Google Closure, now that this turning out not to be the case, it's a lot more interesting to push it along.

15:08 bbloom: dnolen: fine, but you'll note that i've got like 5 design pages that have garnered zero attention or made any progress

15:09 dnolen: bbloom: and this probably one of those, and now there's interest :)

15:09 bbloom: dnolen: http://dev.clojure.org/display/design/Compiler+Re-structuring

15:09 i'll add a few notes

15:10 dnolen: bbloom: part of the problem is pages like this, it's too broad

15:10 bbloom: dnolen: i'm adding some notes, hold your horses

15:10 you can reorg it however you want

15:11 dnolen: bbloom: k

15:15 bbloom: dnolen: http://dev.clojure.org/display/design/Compiler+Re-structuring what else? i got 2 more minutes to write some more notes b4 i gotta run

15:16 dnolen: bbloom: that's ok start I'll work in it some more later today.

15:16 bbloom: k

15:17 i'm happy to implement the ANF transform if you're willing to do the work to get a nice compile function & implement a no-op pass to prove we have passes :-)

15:17 my existing ANF transform was like 80% of the way there. i'll fix & finish it, then do all the testing on that

15:18 hiredman: bbloom: which representation is that transform working on? clojure, analyzer tree, javascript ast?

15:19 bbloom: analyzer ast

15:19 hiredman: cool

15:19 bbloom: an old version of it

15:19 btw, this will bring up the :children debate again, lol

15:19 anyway, i gotta run

15:21 hiredman: sure, that is why I was interested, the tree is so rich it seems actually difficult to do transforms

15:23 invariants seem like they would be hard to maintain

15:54 upwardindex: I'm playing a bit with goog.ui and not exactly loving it so far

15:54 What are the popular ui libraries in cljs?

15:56 dnolen: upwardindex: probably goog.ui or jquery.ui, honestly I wouldn't use either.

15:56 upwardindex: dnolen: what do you use?

15:57 dnolen: upwardindex: I don't use anything (I work on the compiler mostly), if I used something I would probably write it from scratch.

15:59 shaungilchrist: dnolen: do you plan on naming/releasing your core.async/ui utils? That is what I keep looking for.

16:00 dnolen: shaungilchrist: when its less half baked probably

16:03 shaungilchrist: you say half baked I say al dente

16:03 cgag: let the community help you bake the other half

16:04 dnolen: shaungilchrist: there are a couple of missing bits that I'm trying to understand first

16:04 cgag: well hopefully what I've already written about coded up is sensible enough for other people to run with

16:05 cgag: but I'm not up for maintaining another project at the moment

16:05 wkelly: k

16:12 gvickers`: (load-file "../file.clj") returns #'file.core/foo after it loads file.clj's namespace. Now say I have N different .clj files all with their own implementations of foo. Is there any way to 1. Veriy that foo exists and 2. construct a seq of namespaces I have loaded via (load-file)

16:14 also what does the pound sign mean in my repl output?

16:15 shdwprince: gvickers`: (loaded-libs) can affort you a set of loaded ns's

16:16 nDuff: gvickers`: 'file.core/foo is a symbol; #'file.core/foo is a Var

16:17 gvickers`: oh cool thanks

16:18 if I am getting #'file.core/foo back as a Var, is there a way to change the var to a symbol?

16:21 stuartsierra: gvickers`: Indirectly, by looking at the Var's metadata

16:25 gvickers`: stuartsierra: thanks, thats exactly what I was looking for.

16:45 vmarcinko: hi. noob question - is there some other REPL-oriented workflow description out beside stuart sierra one? Im just starting with clojure projects, and somehow I dunn oexactly how to define the workflow best...

16:49 max2: vmarcinko: how about the REPL flow described in Clojure Programming?

16:50 vmarcinko: ok, i got it, just checking if there are some additional ones out there, or someone here can describe his...

17:15 amacdougall: I'm not terribly sophisticated, but I have vim set up to push code straight to the terminal via tmux; then, while working on my file in vim, I can just execute definitions to set them in the running REPL. Works nicely so far.

17:16 cgag: have you checked out fireplace? I use it and it's fairly solid

17:16 amacdougall: I wrote this blog post about the vim->terminal thing: http://www.alanmacdougall.com/blog/2012/03/27/using-vim-slime-with-pry-for-repl-perfection/ — it's about Ruby with the Pry REPL, but applies 100% to any other terminal REPL.

17:16 glosoli: Any recommendations for a plugin for VIM that would keep my Parens safe, some sort of decent alternative to Par Edit ?

17:16 Raynes: How about paredit? :P

17:16 $google paredit.vim

17:16 lazybot: [emezeske/paredit.vim · GitHub] https://github.com/emezeske/paredit.vim

17:16 glosoli: :O

17:17 cgag: $google vim-clojure-static

17:17 lazybot: [guns/vim-clojure-static · GitHub] https://github.com/guns/vim-clojure-static

17:17 Raynes: https://bitbucket.org/kovisoft/paredit

17:17 glosoli: ^

17:17 glosoli: hmm bitbucket seems to be the only one up to date

17:18 Raynes: Yes.

17:18 glosoli: damn, not sure how vundle will handle this

17:18 Raynes: Despite writing pretty good vim plugins, the author hates us.

17:18 :p

17:18 Ew vundle.

17:18 Pathogen noob.

17:18 seangrove: dnolen: I'm pretty confused about the constant lookup table for keywords in cljs. I've gone through the Java implementation, and it looks like the table there is a lookup of symbol => references, which doesn't seem to aply in js

17:18 Raynes: >:3

17:18 glosoli: Raynes: :DD or Emacs package manager

17:19 cgag: vundle is where it's at

17:19 glosoli: hmm

17:19 lolgician: i followed this guide for a happy vim->repl experience http://michaelalynmiller.com/blog/2013/02/27/vim-tmux-clojure/

17:19 i haven't tried vundle

17:19 cgag: https://github.com/tpope/vim-fireplace

17:20 tbaldridge: seangrove: CLJS uses "magic strings" for keywords. They are nothing more than strings prefixed with a magic unicode character that no one uses.

17:20 cgag: i use this and basically the cpp, :%Eval, and cqc commands

17:20 and sometimes drop stuff into my files like

17:20 (comment (run-server))

17:20 (comment (run-tests))

17:20 and just eval those inner expressions occasionally instead of running them from the repl

17:20 dnolen: tbaldridge: yeah we want to get rid of that

17:21 glosoli: cgag: you was not kidding about Vundle having that paredit.vim plugin ?

17:22 cgag: i have Bundle 'vim-scripts/paredit.vim'

17:22 in my vimrc and it works for me

17:27 seangrove: tbaldridge: Yeah, so I'm taking a stab at implementing "real" keywords, as dnolen calls them

17:28 But could use some help with the details. Been looking at the implementation of other types, and the Java implementation of Keyword for reference, understanding the idea better, but not well enough to implement it independently

17:31 amalloy: seangrove: i understand the java implementation pretty well, and i agree that it's not at all obvious how to port it to a language without weak references

17:32 seangrove: amalloy: Took your advice to get more familiar with the clj-jvm implementation, hasn't bee too bad yet. Thanks for the suggestion

17:32 amalloy: i think there was once a version of clojure that interned keywords permanently; probably you could port that instead, and warn developers not to keywordize arbitrary strings

17:32 dnolen: amalloy: seangrove: the whole idea on anything requires weak references - it's just a constant lookup table

17:33 amalloy: seangrove: the only gotcha is that keywords are supposed to be identical? I already went over this a bit with Rich, he's OK w/ documenting it's not possible in JS because no weak references, thus keyword-identical?

17:33 "the whole idea on anything" -> "the idea punts on anything requiring weak refs"

17:33 seangrove: dnolen: I'm confused on the constant-lookup part. I think the keyword symbols are the keys - what are the constants they're looking up?

17:33 dnolen: seangrove: a unique identifier for that constant

17:34 seangrove: they are entries in a table that we preallocate

17:34 seangrove: Ok, so the equivalent of (.hasheq :keyword)

17:36 dnolen: seangrove: for example :else, everywhere :else appears in CLJS should be replaced with

17:36 constant-table.keywords.else

17:37 where that entry has been set to (Keyword. "else" ...)

17:41 seangrove: Alright, so the analyze finds a keyword :else for the first time, creates an entry in constant-table.keywords.else = (Keyword. "else")

17:42 dnolen: seangrove: well it records it during analysis, so the compiler can emit it later

17:42 seangrove: I'll start with just the analyzer part.

17:44 I'm also unclear about the compiler/runtime separation - the (deftype Keyword ...) isn't available at analysis/compile time, so how can we instantiate (Keyword. "else") in the analyzer?

17:46 dnolen: seangrove: we're going to have to get clever, but very little in the standard library actually "runs" now

17:47 seangrove: so we just emit the lookup table after the core library and before all user code

17:48 seangrove: JS is late bound so this be fine, we just need to make sure however we emit it Closure can still optimize it.

18:18 oneness: any one knows if lein uberjar also calls lein clean?

18:20 hyPiRion: oneness: no, not by default at least

18:20 oneness: hyPiRion: thanks.

18:24 nacon: Hmm. Learning Clojure and having to look at this: http://imgur.com/a/WfKD4 (font alignment). I don't know why it bothers me that much..

18:24 callen: nacon: that's a little strange.

18:25 nacon: I suppose those are font issues..

18:30 hyPiRion: my OCD would've died if that was the case for me. Is this a monospace font?

18:30 oh wait, that's a gist.

18:30 callen: that's what weird, gists are supposed to be monospaced.

18:31 it looks like either there's an actual space there, or the font rendering is boned.

18:31 nacon: probably a system font issue on my side

18:31 no, there's no extra space. the raw gists is properly aligned and looks good.

18:32 callen: nacon: leaning towards your system font being fucked. What are you using?

18:35 amacdougall: If you're on Chrome/Firefox, try using the Stylish extension to set <pre> to a different monospaced font. See if that helps.

18:35 (Or set a spot font-family style using the devtools actually)

18:36 nacon: I'm using Chromium's default (Bitstream Vera) -- but it's the same in Firefox so I suppose it maps to the same system font

18:36 amacdougall: Any time you think, "man, this site I go to all the time has this one really annoying formatting issue!", just add a rule in Stylish. :+1:

18:36 callen: nacon: OS?

18:36 nacon: Gentoo

19:06 Peetski: good evening, morning, afternoon

19:09 brehaut: ~ugt

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

19:10 `cbp`: that feeling when I can finally close IDEA and go back to emacs :-)

19:12 Peetski: ok then, good ugt everyone.

19:13 arrdem: brehaut: I'm so glad we have a convention for this

19:13 it formalizes beer-30!

19:13 brehaut: lol

19:14 arrdem: alright, well it's 6:00 (UGT) and I'm punching out. 'night people!

19:14 brehaut: later arrdem

19:15 Peetski: what happened to ugt?

19:16 cgag: it's night ugt for him

19:17 Peetski: Ah I see. Doh!

19:29 callen: `cbp: what were you doing in IDEA?

19:30 TakeV: Suppose I have a helper function in a namespace for a few other functions, but I don't want people using the namespace to use the function. Is it more idiomatic to define it with defn-, or to wrap all defns functions in a single letfn?

19:30 dnolen: hrm, should this work?

19:30 ,(flatten (object-array [1 (object-array 2) 3]))

19:30 clojurebot: ()

19:38 holo1: hi

19:38 `cbp: callen: php

19:38 hiredman: dnolen: flatten has a history of behaving very oddly when passed non-seqs

19:38 ,(flatten {:a 1})

19:38 clojurebot: ()

19:39 * `cbp queues some really tragic music

19:39 callen: `cbp: sweet jesus. I'm so sorry.

19:40 akurilin: Quick question. I want to write some logic to generate a large set of data for multiple "model types" and populate my DB with it. I'm debating between just writing a ruby script for this, or whether I should add this as Clojure code in my ring app that I can run as a one-off from the REPL. Anything wrong with the latter?

19:40 Do people writing ring apps eventually end up with a "scripts" namespace anyway, for one-offs?

19:41 cgag: I did, I called it tasks a la rake tasks

19:41 callen: akurilin: I do. I usually use lein exec or something comparable for my scripts.

19:41 akurilin: I script stuff with lein exec that doesn't even have anything to do with a clojure project.

19:41 threaded scripts is nice, yo.

19:41 I have one such script running right now...scraping an API...

19:42 akurilin: callen, you still have to setup a whole new project with lein new every time, right?

19:42 callen: akurilin: please read the documentation to lein exec.

19:42 akurilin: okie dokie

19:44 callen, have you been able to wean yourself off of python/ruby/perl/whatever with lein exec?

19:45 callen: akurilin: yes, there are odds and ends suited to Python, but it's becoming less the case over time.

19:45 akurilin: Right tool for the right job and all that, but I'd be quite happy to move most of the heavy scripting off of ruby.

19:45 I'd be happy with just bash + clojure :)

19:45 callen: yeah, I was in a similar position WRT Python.

19:46 It'll never be 100% because I work in a company that uses a lot of Python, but my relatively "internal" scripts have all been Clojure lately.

19:46 API, database, text munging.

19:48 holo: akurilin, i use fish shell + pyp. it keeps me away from python, yet. not that i don't like python, but i don't find it worth it for the size of my scripts

19:49 callen: the scripts I write vary from trivial (bash) to small-large (clojure)

19:50 the one thing I don't have a good solution for is quick remote automation like what Fabric is useful for.

19:52 akurilin: callen, what's a use case for quick remote automation? I'm only familiar with non-quick remote configuration management with puppet/ansible.

19:53 holo, I'll have to check out that combo, not familiar with either.

19:53 callen: akurilin: long tail of random shit that isn't necessarily about instantiating a machine via puppet.

19:54 if it can be done in puppet/ansible, by all means

19:54 but I have to do random-ass stuff that would make the former annoying, and nobody uses ansible here.

19:54 ansible has a good mechanism for being used like Fabric though.

19:57 akurilin: yeah I do enjoy my --tags on occasion

19:58 callen, so regarding lein exec, if I'm understanding correctly, there's nothing stopping me from creating a bunch of scripts under my ring app and then use the already existing data access layer from them, when calling from lein exec?

19:58 holo: akurilin, i'm not aware if people usually use it as a combo. i decided to use it as a combo myself. fish shell because i don't need to read the manual every time i read/write a form (like i had to do in bash). pyp cause it brings to the shell all the convenience of split/join of python lists/strings combined with pipes for text transformation

20:00 akurilin: holo, that's fair, I never thought of exposing the interpreter straight onto the shell

20:00 that's a pretty neat idea

20:03 holo: akurilin hehe.. the guys at sony pictures needed to do it.. it's basically a python script

20:04 i'm developing a library for format conversion exposing this interface (convert "mystring" from :source-format to :target-format) . when :source-format is unknown (convert "mystring" to :target-format)

20:04 is this too many word for such simple task?

20:05 callen: akurilin: that's a good question @ existing data access layer.

20:05 Anything that uses my "models" is usually more formalized than the sort of scripts I'm talking about. That sort of thing gets dispatched "in project".

20:06 you don't need lein exec if that's what you're doing.

20:07 cgag: can also use lein run -m <namespace> if you've got a main function in there

20:08 callen: yep ^^

20:09 holo: guys/girls, i would appreciate some honest opinion about it. i don't want to expose an api that too many people hate

20:11 callen: holo: is that a literal representation of the function interface?

20:12 holo: wtf is from and to?

20:12 holo: callen, it's a symbol

20:13 yes, it's a literal representation, except that :source-format/:target-format can be any other key that represents some supported format

20:13 callen: holo: drop the from/to bullshit

20:13 holo: hehehe.. that's what i needed

20:13 callen: it's weird and doesn't serve an actual function.

20:14 holo: two arities of: (convert "blah" :target-format) and (convert "blah" :target-format :origin-format) would suffice I think.

20:15 holo: callen, thanks

20:15 callen: holo: if you wanted to be really nice, you could return a closure from convert

20:15 and do something like: (convert :target-format) and (convert :target-format :origin-format) which both return a "converter" fn that accepts a single argument of "data"

20:15 hyPiRion: I would use (convert mystring :from format :to format) in that case, mayybe

20:16 callen: I really don't think the :from/:to is a good idea unless there's more to spec he's not telling us.

20:16 hyPiRion: then destructure by doing [in-string & {:keys [from to]}].

20:16 callen: well yeah, :target-format :origin-format works just as well I suppose

20:16 holo: callen, there's nothing more about the spec. btw, your idea about returning a closure using the first argument sounds like a great idea

20:17 callen: holo: well it spares people needing to use partial or something in order to pass around a "converter fn"

20:17 but having an arity for "immediately execute this dude" is a good idea.

20:17 holo: callen, sure

20:17 callen: you could split out the closed over, and non-closed over into separate APIs.

20:17 this is getting into frippery though.

20:18 just exploring options.

20:18 I've had really good luck with closure based library APIs lately though.

20:18 holo: hyPiRion, doesn't it look ugly (convert "mystring" :to :target-format) ? there's too consecutive keywords.. it seems like they are at the same level

20:20 callen: I don't like extraneous noun/verb keywords in function arguments unless a complicated DSL is involved

20:20 even then, I'm really hoping there's a simpler fn underlying it.

20:20 holo: "you could split out the closed over, and non-closed over into separate APIs" - looks even better

20:21 callen: converter vs. convert

20:21 former is the closure API, latter is the "fire this off plz"

20:21 hyPiRion: holo: I'm not sure, you're saying "that :source-format/:target-format can be any other key that represents some supported format"

20:22 holo: callen hehehe.. when you said that pair converter/convert, i immediately reasoned the same thing. i think it's intuitive

20:22 hyPiRion: (convert mystring :target-format :my-format :source-format :some-other-format) ?

20:22 I don't know, I'd probably pass in a map instead

20:24 holo: hyPiRion, the clojure library guidelines give preference to (form :to format) comparing to (form :to some-map)

20:24 i mean (form some-map), sorry

20:25 callen: I really don't think explicitly decorating target/source args with prefix keywords is necessary or a good API.

20:26 again, unless there's a more complicated DSL the function is participating in, and has overloaded meaning.

20:26 clojurebot: Roger.

20:26 callen: and in that case, you're fucked anyway.

20:26 KISS.

20:28 holo: callen, converter/convert just feels great

20:28 akurilin: callen, back. Sounds good, I'll give that a shot. Will probably go tasks/ route as cgag suggested

20:28 holo: hyPiRion, thanks for ideas too

20:29 callen: akurilin: if you're calling into code that lives in the project, that's a better idea.

20:29 holo: supports using the global state or a closure: https://github.com/bitemyapp/bulwark/blob/master/src/bulwark/core.clj#L83-L85

20:31 aaelony: a couple days ago I asked if there existed a "melt" function for incanter datasets the same way it exists in R to make wide data long. Didn't get a response so cobbled the following hacky version together. I'm sure there is room for improvement. Please critique away … https://www.refheap.com/17922

20:31 should work for *any* Incanter dataset

20:32 holo: callen, thanks, looking up that example

20:33 callen: holo: your library shouldn't need global state like that, just showing how you can adapt a function to multiple purposes.

20:33 convert/converter is probably better in your case.

20:38 holo: callen, yes, i think this one doesn't apply for global state. yes, i'll stick to convert/converter

20:42 seangrove: dnolen: To get a bit more concrete, does this look like the right approach? https://gist.github.com/sgrove/6301866

20:42 dnolen: seangrove: why are you storing the .hashCode ?

20:43 cgag: akurilin: this is what i had https://github.com/cgag/bookmarking/blob/master/src/tasks/db.clj, and then i could run like `lein run -m tasks.db rebuild seed`

20:43 seangrove: dnolen: updated the gist

20:43 cgag: only the last like 10 lines there are of interest probably

20:43 seangrove: What should I be storing instead? (Keyword. k) ?

20:44 dnolen: seangrove: and you maybe shouldn't update the table there, instead do it around analyze, if analyze itself returns a constant you know you have something - keywords are an important case but we should handle everything.

20:44 seangrove: it could probably just be a set, just the value

20:45 seangrove: dnolen: Struggling with that - What is the value?

20:45 dnolen: :foo

20:45 seangrove: Ah, ok

20:45 dnolen: seangrove: put the thing in the set of known constants

20:46 seangrove: Ok, got it, I was overcomplicating it

20:49 dnolen: seangrove: I'm going to write up some notes about this

20:53 seangrove: dnolen: I'd really appreciate it, thanks.

20:56 akurilin: Quick sanity check, I can't seem to get this leiningen injection to work: :injections [(require 'spyscope.core '[taoensso.timbre :as timbre])]. Spyscope works fine, timbre not so much.

21:13 dnolen: bbloom: I erased what you wrote earlier, I think this is a better start http://dev.clojure.org/display/design/Optimizing+Expression+Semantics

21:13 anybody else interested in ClojureScript AST stuff feel free to chime in

21:13 seangrove: working on Constant Optimization page next

21:17 cgag: dnolen: this stuff with the clojurescript compiler sounds interested, but i don't know much about it, is there anything i should read besides the compiler source itself?

21:18 dnolen: cgag: hmm not really, fortunately the analyzer and the compiler are two relatively short programs - together ~1900 LOC i think

21:22 cgag: cool. i'll just dig in sometime then, i only just started using clojurescript, but it's awesome, actually has me excited to write frontend stuff

21:32 fbernier: Is it possible to reference an import from another namespace if this namespace is required ?

21:32 holo: is it that bad to return truthy/falsey instead of strict boolean in "predicate?" fns?

21:33 amacdougall: Same here… I saw dnolen give a talk on it at nyc.js, but only recently got around to embarking on a real-life clojure/clojurescript project. We'll see how it goes!

21:33 mlb-: Has anyone here had much luck with manipulating WSDL files in clojure?

21:34 holo: fbernier, if you mean cyclic requires, no, it's not possible

21:35 fbernier, it's usually an indication of smell too when you need such a dependency

21:36 fbernier, design smell

21:37 fbernier: holo: I've got (:import [java.awt.image BufferedImage]) in a file where I do image processing

21:37 then in another file where I do my compojure routing, I use extend-protocol to define a response for BufferedImage

21:37 I was just wondering if I need to also import BufferedImage in this file

21:38 or if I could just reference it since its imported in the other file I am requiring

21:39 holo: fbernier, from what i've experienced, you don't even need import at all, if you are willing to just use java.awt.image.BufferedImage

21:39 dissipate: wtf, the tutorial on http://tryclj.com/ is waaaay too short

21:39 TimMc: fbernier: Yes, because :import is just for name resolution, not classloading.

21:39 fbernier: holo: aaah right

21:39 still mixing those things up

21:39 thanks

21:39 dissipate: does anyone have a link to a longer interactive tutorial?

21:39 holo: np

21:39 dnolen: seangrove: http://dev.clojure.org/display/design/Optimizing+Keywords

21:40 seangrove: let me know if you need me to flesh out some more

21:43 holo: dissipate, there's 4clojure.com it's not a tutorial, but you can from there. there was also some kind of step by step learning lab built under joodoo/judoo/something.. let me try to find it out

21:43 *can learn

21:46 dissipate: holo, cool, thanks

21:47 holo: dissipate, found it! http://clojurekoans.com never tried it though looks kind of mistical

22:04 here http://faustus.webatu.com/clj-quick-ref.html I read "The function boolean converts from Clojure logical truth to boolean true and false, primarily for Java interop.". is it maybe that pred? should return boolean true,false instead of logical truth values for java interop?

22:15 saolsen: Is anybody familiar with nrepl. I'm embedding it in an app where I care about which thread the code executes on so I need to write some middleware (or a handler?) that, instead of executing the code, wraps it as a function, places it on a queue, waits for another thread to pick it up, execute it and put the result somewhere and then pull the result and send it back to the nrepl client. Has anybody done something like this with nrepl middlewar

22:22 akurilin: Is it idiomatic to use get on vectors if I'd rather get a nil than an exception in case of out of bounds? I could also go with nth, but that requires an extra param.

22:27 dnolen: akurilin: intention of nth + extra param is probably going to be clearer

22:37 akurilin: dnolen, that's a fair point, thank you.

23:14 ToxicFrog: So I have here a library that tries to read input using slurp, and a string containing the input.

23:14 Just passing the string to the library causes it to explode (it tries to use it as a filename).

23:14 How do I make the string slurpable?

23:20 xeqi: &(slurp (java.io.StringReader. "some string"))

23:20 lazybot: ⇒ "some string"

23:20 xeqi: ToxicFrog: ^

23:37 amacdougall: It would be nice for the library to provide read and read-file though.

23:37 a la json, etc

Logging service provided by n01se.net