#clojure log - Mar 23 2010

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

0:02 danlarkin: technomancy: it does not

0:02 technomancy: danlarkin: even with clean+deps?

0:06 danlarkin: any particular task after which it's supposed to hang?

0:07 technomancy: hrm... try deps in the sample project

0:07 or test in lein itself

0:08 danlarkin: works just fine

0:08 technomancy: intelesting.

0:08 thanks for checking.

0:09 danlarkin: heh I was just about to say I must have pulled wrong, github says the last commit was 11 minutes ago but git log says the last one was yesterday... but then I realized it's 8 after midnight :-o

0:10 technomancy: ...

0:10 just set your clock to PST and be done with it man... =)

0:10 or PDT I guess... /me grumbles

0:10 TheBusby: or set everything to GMT and leave time zones for the farmers

0:12 technomancy: yes

0:12 danlarkin: *ahem* I think you mean UTC :-D

0:12 technomancy: I want to set my time zone to Pitcairn island time since it's like PST but it stays year round without any shenanigants

0:13 http://en.wikipedia.org/wiki/Pitcairn_Islands

0:13 TheBusby: couldn't you just set it to PST (disabled auto DS if required)?

0:14 technomancy: TheBusby: I don't know if you can disable DST in most systems

0:15 TheBusby: I've done it a a fair amount in *NIX

0:15 don't know about Oracle or Windows though

0:17 technomancy: phones might be an issue too

0:17 rads: getting a weird error when trying to use some of my project's files in a local leiningen task: Exception in thread "main" java.lang.VerifyError: class clojure.contrib.string$loading__4789__auto____3 overrides final method meta.()Lclojure/lang/IPersistentMap;

0:17 there is a (:require [clojure.contrib.string :as s]) in there, but I'm not sure why it's causing an error

0:18 TheBusby: er, phones, cellphones in particular use your carriers time usually. Yeah that would likely be a problem

0:19 if you're going to go off of whatever your local time is though, might as well go whole hog and use UTC ;)

0:19 hiredman: rads: your contrib and clojure jars are out of sync

0:21 rads: oh

0:22 leiningen is probably using clojure 1.1.0 when I have 1.2.0 in my project.clj

0:23 hiredman: should be using what is in your project.clj

0:23 for 1.2.0 you should be using a snapshot contrib too

0:24 rads: yeah

0:24 it works fine for lein swank, but for my user-defined task I get this: {:major 1, :minor 1, :incremental 0, :qualifier }

0:25 same thing for lein repl

0:25 hiredman: what version of lein?

0:25 I know the repl task used the wrong version in .5, it might still

0:25 rads: latest version

0:26 from github

0:29 when I use DEBUG=1, it seems that the clojure jar from my leiningen checkout is in front of my project's clojure.jar in the classpath

0:37 rads_: any idea how to get lein to use the correct version?

1:30 headius: hey, someone confirm that I understand the example here: http://clojure.org/runtime_polymorphism

1:30 defmulti defines an aggregate method given a selector function

1:31 in this case, that function takes the two incoming arguments and pulls the species from each, returning that tuple

1:31 the tuple is then used to do a search of some table in the multimethod build up by subsequent defmethods

1:33 looking at defmulti impl now

1:34 looks like clojure.lang.MultiFn does the actual aggregation

1:37 quiet in here at night

1:40 psykotic: headius: yeah, you got it right

1:40 headius: good

1:40 MultiFn looks similar to various dyncall caching structures in JRuby (and other dynlangs

1:41 is it also fair to say that normal function dispatch isn't really dynamic?

1:41 if I understand it right, clojure can statically see the set of functions available at any point

1:41 psykotic: there's a level of indirection

1:41 when you call a function defined at the top level of a namespace, it actually dereferences a variable at each call site

1:42 but yes, it has to see at least the symbol entry in the relevant namespace, if not its value

1:43 that's why you need to use a dummy def (or the shorthand declare macro) if you want to have mutually recursive function definitions

1:43 headius: so the complexity of locating a function is always constant

1:44 in the normal non-multi case

1:44 psykotic: right, it does the "hash" lookup at compile time, but the deref at run time

1:44 headius: I'm doing a talk tomorrow on invokedynamic, wanted to talk about where in various languages dynamic comes into play

1:44 psykotic: so it doesn't statically resolve the actual call

1:44 headius: so the deref could initially be slow but then it never changes?

1:45 it's like a "once" dynamic lookup?

1:45 psykotic: well, you should think of the phase distinction like this:

1:45 at compile time, symbols are resolved to vars (which are first-class objects that have a root binding and can be further rebound on a per-thread local basis)

1:46 when a variable is evaluated at run time, it is dereferenced. so it's like a cheap thread local storage deref kind of operation, although there is a branch-taken-expected fast path when there is only a root binding and no thread-local rebindings

1:47 the net effect of this is that you can reload function and variable definitions at runtime and existing referrers will pick up the difference

1:47 so it's still perfectly dynamic in that sense

1:48 headius: so a function within a function is stuffed into that outer function's binding

1:49 psykotic: not quite

1:49 inner functions just generate new subclasses of AFn that are then newed (passing the closed-over values from the scope) by the outer function referencing it

1:50 that doesn't really figure out into the namespace binding at all

1:50 *figure into

1:50 headius: how do calls to the inner function get resolved compared to calls to top-level functions?

1:51 psykotic: well, the inner function is statically known, right? you don't need any indirection like for top-level functions.

1:52 headius: so only top-level functions have to be dynamically resolved because new files can be loaded in that aren't available at initial compile time?

1:52 psykotic: well, more to the point, old files can be reloaded

1:52 headius: whereas a function is bound to a single file and can be statically mapped out for calls within that context

1:52 ok

1:53 psykotic: Compiler.java is actually really readable (even if it isn't very orthodox Java style)

1:53 headius: none of clojure's java is orthodox java style :)

1:53 psykotic: right :)

1:53 headius: it's almost like it was written by someone who likes lisp

1:53 psykotic: yeah, crazy that

1:53 headius: thanks, I think I get it all now

1:53 psykotic: the whole symbol/var distinction is something that's quite different about clojure from scheme or common lisp

1:54 so it's a little confusing at first

1:54 joshua-choi: I for one am very glad for it

1:54 headius: I'm more interested in the plumbing than the language anyway

1:54 psykotic: right

1:54 but if you try to map it to what you know, you might be confused, that was my point

1:55 headius: a part of me is jealous of the simplicity compared to what we have to do in jruby, where everythign is dynamic all the time

1:55 but that's part of the fun

1:55 psykotic: i don't know much ruby, but i know python and i guess resolution of variables is quite similar?

1:55 i.e. hash tables, all the time :)

1:56 with that kind of approach, when you redefine a variable, you actually update the hash table

1:56 in clojure, you don't touch the hash table, you only update the var which the hash table points to

1:56 the first time you try to something something, it creates the var, etc

1:57 err, you try to def something

1:57 headius: local variables are statically determined

1:57 instance variables are hash-like, but jruby call-site caches both methods and ivar locations

1:57 psykotic: right but what about modules?

1:57 headius: our ivar logic is probably similar to how clojure handles vars

1:58 what about modules?

1:58 psykotic: one thing i dislike about python, re: dynamic development, is that when you import things directly (i.e. from foo import x, y, z), you actually get the values directly at the time of import

1:58 which means that if you reload foo and update x, y, z, you need to reload this client module as well

1:58 if you only import foo and reference x, y, z as foo.x, foo.y, foo.z, then you don't have to reload

1:59 it's an annoying difference

1:59 headius: ahh

1:59 well python is pseudo-OO to me

1:59 psykotic: well, i thought ruby worked the same

1:59 headius: compare to ruby where importing will define classes, but those classes are still mutable

1:59 psykotic: if i import all symbols directly from another module, do i get the values imported into my namespace?

1:59 headius: no

2:00 they go into constant tables, but "constant" lookup is dynamic

2:00 class Foo; end is equivalent to Foo = Class.new { }

2:00 Foo becomes an entry in some lexical/hierarchical constant table

2:01 so if you're talking about including a module into a class, to get its set of functions...

2:01 psykotic: right

2:02 headius: the functions aren't copied in; a stub is inserted into the class hierarchy with a reference to the module

2:02 so the module can continue to be mutated

2:02 psykotic: python's problem here isn't really about OOness. it's that it "flattens" imports. if i do from foo import x, my module gets a 'x' : foo.x (where foo.x is resolved to a value at import time). after this, it doesn't know that x came from x, it's been resolved away.

2:02 headius: mm sure

2:02 psykotic: so, really, even if i'm just trying to get a shorthand for foo.x as x, it subtly changes the semantics

2:03 headius: yeah, there's nothing like that, really

2:03 a bare x would either be a variable or a call, depending on context

2:03 psykotic: okay, that's good

2:03 headius: if it's a variable, it's statically determined to be a variable always

2:03 if it's a call, it's dynamically looked up, always

2:03 psykotic: well, what if the variable says x = 42 originally, but it's later redefined?

2:03 that's what i'm talking about

2:03 headius: can't be

2:04 once there's an x = whatever in a given context, x is treated as a variable for the rest of that context

2:06 psykotic: btw, you mentioned call-site caching, i guess you can't do it inline due to the direct and indirect cost of regenerating bytecode? in machine code, you can update the direct target address of a call by just mutating that part of the call instruction the same way you mutate any var.

2:07 headius: it's pretty close to inline

2:07 LeNsTR: hi all

2:07 headius: there's a trampoline

2:07 a dynamic call is normally a call to CachingCallSite.call, with an instance of CachingCallSite constructed per call site in code

2:07 each site gets its own monomorphic cache

2:08 we also have in-hierarchy caching for fail cases, so it should eventually be 1 hash hit at worst and one object comparison at best

2:08 comparison as in identity

2:08 there's flags to remove the trampoline and pull the method object all the way back to the actual Java call site, so it can be inlined

2:08 psykotic: btw there's a fairly recent concept in clojure called protocols, which is an interesting compromise between multimethods and more traditional java style OO

2:08 headius: but they slow down JVM without tweaking inlining thresholds

2:09 I heard something about protocols a few months back

2:09 have not looked into it

2:09 psykotic: they have the post-hoc open extensability of multimethods, and they also interop with interfaces nicely where possible

2:09 headius: for all the pain it causes, ruby's all-dynamic-all-the-time is the least of our problems...jruby's dynamic dispatch is comparable to interface dispatch in java, overhead-wise (assuming a successful cache)

2:10 psykotic: but they're dispatched only on the type (in an extended sense--not just jvm types but also clojure's own dynamic "type tag hierarchy",) of the first argument

2:10 headius: even ruby to java dispatch is generally no worse than a single hash hit

2:10 psykotic: that's nice

2:10 so if that's the least of your problems, what's the biggest?

2:10 headius: I want to add clojure's cheat of specifying a signature

2:11 psykotic: type hints?

2:11 headius: ahh, the biggest problems are fixnums (value types, etc...clojure has the same problem), and what I call "out of band data" from call to call, which forces us to stand up heap structures

2:11 in the grand scheme of things, value types would probably be the biggest boost

2:11 psykotic: yes, type hints

2:11 psykotic: or the 'cheap-ass escape detection' that cliff mentioned in the 2008 jvm talk

2:12 headius: yeah, that never has worked well enough

2:12 psykotic: which should have much the same net effect as value types, if it works

2:12 headius: and it depends so heavily on inlining

2:12 no inlining, and it's worthless

2:12 psykotic: well, i think he was proposing a special case of escape analysis, not the current thing which never works :)

2:12 headius: sure

2:12 psykotic: and yeah, you need inlining in general to get visibility

2:12 headius: I can get dyncalls to inline all over the place, but escape analysis doesn't eliminate anything in its current incarnation

2:12 psykotic: are value types on the table potentially?

2:13 headius: they're probably the next highest item not being worked on

2:13 psykotic: for the jvm i mean

2:13 headius: everyone needs them, really

2:13 even java

2:13 dynlangs need them worse though

2:14 psykotic: so, the typical kind of case where there is a lot of "short range" heap allocing is when you run a list in lieu of multiple return values

2:14 err, return a list

2:14 i assume that's what you mean by out of band data?

2:14 headius: somewhat...ruby has some implicit "out" values for certain calls, and the current design of JRuby's call protocol doesn't provide a channel through which to pass them

2:15 so we have to allocate a heap structure, stuff it into a thread-local stack

2:15 the unfortunate part is that we don't always know when that data is really needed, since we only have the names of methods to go on

2:15 psykotic: have you thought of doing your own object pooling?

2:15 headius: so we use those known method names as a trigger that says "I might need OOB data"

2:16 psykotic: right

2:16 headius: yes, and we do reuse some fixed-size structures

2:16 on the worst end, there's eval and friends, which we full deopt for

2:18 psykotic: you might know a good answer to this--

2:18 i've been talking to some people about profiling clojure code, and i keep hearing (i'm new to the jvm) that profilers and hotspot interfere so much that you can't really trust the profile data

2:18 headius: I don't think that's generally true

2:19 psykotic: okay, that's a relief

2:19 headius: the problem with clojure is that profiling method performance is not going to produce great results, since as I understand it clojure usually suffers more from allocation costs

2:19 which don't really show up in normal method timing profiles

2:19 psykotic: otherwise i'm not really sure how useful profiling would be, assuming you aren't bound by io or whatever

2:19 right

2:19 headius: for example, if I profile numric algorithms in JRuby, the results are not really helpful

2:19 psykotic: and the cost of GC churn is usually very indirect

2:19 e.g. cache streaming

2:19 headius: because the cost is the fixnum allocation

2:19 right

2:20 and actually, it's probably not even GC

2:20 it's just the allocations

2:20 psykotic: shouldn't that just be a pointer increment for gen 0?

2:20 headius: we had someone run numbers on how much allocation we were doing, and even though GC took almost no time at all we were requesting chunks of heap at a rate that saturated the memory pipeline

2:20 it was all young data, so nearly free to collect

2:20 but there's a cost to getting it in the first place

2:21 psykotic: right, that's what i meant about cache streaming

2:21 headius: yeah

2:21 GC times were less than 1% of execution

2:21 it was all spent waiting to get the objects

2:21 psykotic: value types would definitely be a huge win here

2:21 headius: right

2:22 psykotic: since they're on the stack, so you just keep hitting the same lines

2:22 headius: we can almost compete with implementations that have true fixnums, which is mind-boggling

2:22 if we had value types, we'd smoke them

2:23 psykotic: how many people are using jruby for fixnum heavy apps though?

2:24 headius: none...and anyone using any ruby impl for numerics is probably kidding themselves

2:24 psykotic: i was working with lau the last few days on some stuff that's super float heavy, and we would definitely benefit there

2:24 headius: we provide easy ways to call out to java or duby and that should be enough for anyone

2:24 psykotic: heh

2:24 headius: no amount of value type or fixnum magic is going to compare to actual primitive math

2:24 psykotic: i actually have this DSL-like thing i wrote around objectweb.asm that's basically sexpression java, but with macros

2:25 headius: heh, have you seen bitescript?

2:25 psykotic: no?

2:25 headius: http://github.com/headius/bitescript/tree/master/examples/

2:25 it's my ruby DSL for ASM bytecode

2:26 psykotic: nice

2:26 headius: er I mean org.objectweb.asm

2:26 but yeah

2:26 psykotic: i call mine demiurge but it still isn't ready for public viewing :)

2:26 headius: it's the backend for duby as well

2:27 there's a primitive macro system, but I haven't used it for much

2:27 psykotic: the nice thing is that i just hook into clojure's macros

2:27 ah, mine is slightly higher level

2:28 headius: I just use ruby's blocks, mostly

2:28 psykotic: for example, you don't need aload/lload if you've specified types, you can just use plain load

2:28 headius: macro :blah do |args| ... do some bytecode whatever here; end

2:28 then blah foo, bar just calls it

2:29 psykotic: it started out as a pretty straight sexpression transcription of objectweb asm but as i started to add convenience features like that, i realized i eventually had sexpression java

2:29 headius: mmm

2:29 psykotic: (i still don't handle generics at all though)

2:29 headius: interesting

2:29 duby's a similar sort of thing

2:29 ruby syntax for java

2:29 http://github.com/headius/duby/tree/master/examples/

2:30 it's a full type-inferred language though

2:30 psykotic: yeah, mine is still intended for embedding, rather than standalone use

2:30 like you might have a tight inner loop

2:30 you can define it right there inline with demiurge

2:31 it will even capture lexical scope and pass it in to the generated java class

2:31 headius: mmm sure

2:31 I want to do something similar with duby

2:31 you can define duby methods in a ruby class, but that's not exactly inline

2:31 psykotic: (clojure has a neat &env magic argument for anonymous functions that gives you access to the lexical bindings in the context, which i use for this)

2:32 or i should say, it reifies the context

2:33 but yeah, my main goal is to minimize the discontinuity between clojure and demiurge for this kind of 'inline' use

2:33 with the jvm it's obviously a lot better than the typical ffi thing in the c world

2:33 but it could still be improved with this kind of thing, imo

2:34 duby looks neat, btw

2:35 is it a proper subset of ruby?

2:35 headius: no

2:35 it's not ruby at all

2:35 just ruby syntax

2:35 I'm trying to map as much of ruby's syntax as I can to "java" without introducing any runtime library

2:35 .duby file goes in, .class or .java file comes out, and that's it

2:36 as a result, you can use duby for anything you can use java for

2:36 psykotic: btw i'm curious what the binding time is for jruby for jvm interop

2:36 headius: gwt, android, java ME

2:36 for java calls, binding time is the same as ruby calls

2:36 psykotic: so every time you reference a jvm method it does full from scratch reflection?

2:37 headius: no

2:37 the method object cached aggregates all signatures for a given name

2:37 grouped by arity

2:37 psykotic: hmm

2:37 i wonder if clojure would benefit from call-site caching from statically unresolvable jvm calls

2:38 headius: a second level of caching uses an aggregate of the incoming object's classes' hashcodes

2:38 so once you've called a given named method on a java object with all the types you're going to use, it should be a single hash hit

2:38 psykotic: in most cases where performance matters, people tend to add type hints until the compiler stops complaining when *warn-on-reflection* is set

2:38 gotcha

2:38 headius: yeah

2:39 we still use reflection, but ruby-to-java calls are nearly as fast as java.lang.Method invocation can be

2:39 I also have some code to generate non-reflected stubs

2:39 psykotic: right, so you can say "generate stubs for this class"?

2:39 and then call through them?

2:39 headius: yes

2:40 I'll be using them for jruby on android, where reflection costs a lot more

2:40 psykotic: btw one thing i've been wanting to play with is something like that combined with a 'type mapping' facility

2:40 headius: elaborate?

2:40 psykotic: for example, right now clojure has a "be generous in what you accept, strict in what you hand out" with respect to the jvm

2:41 for example, there's a special case code for adapting jvm strings, etc, to clojure sequences

2:41 but of course you can't pass a lazy character sequence (for example) to some jvm method expecting a java string

2:41 so i've been thinking of writing code that generates stubs for classes while passing certain arguments through some kind of user-specifiable type mapping

2:42 as long as you adhere to this policy i mentioned, you only need to do it for arguments, not return values

2:42 it would be a nice way of making some java apis more "clojure-friendly" without manual work

2:43 i'm not sure what you do in jruby

2:44 headius: ahhh

2:44 jruby is moving toward user-definable object marshalling for java dispatch

2:45 currently it calls toJava on each object, and some objects know how to convert (like Strings, Arrays, Fixnums, etc)

2:45 a future version will also dispatch to ruby-land "to_java" on the object if it's present

2:45 psykotic: my thinking was that you sometimes want this to be done per api rather than globally

2:45 headius: so you can add your own java coercion protocols

2:45 hmmm

2:46 yes, I suppose I could see that

2:46 call_with_coercer

2:46 or be able to decorate a given call with a specific coercion protocol

2:46 psykotic: for example, if you're clojurifying some c-like api like opengl where there are int parameters that are bit flags of things, you might have a special adapter that takes a list of keywords (corresponding to the different flags), maps the keywords to the right powers of two and ORs them together

2:46 headius: given method, rather

2:46 sure

2:46 in jruby you can just add those things to the class though

2:47 reopen the java class, alias methods, add methods, whatever

2:47 the protocols could be added that way

2:47 psykotic: ah, clojure is pretty strict about separating the jvm and clojure worlds

2:47 you would have to create stubs to do something like this

2:47 headius: class java::lang::System; def self.[](name); getProperty(name); end; end

2:47 pretty straightforward

2:48 psykotic: nice

2:48 headius: yeah, I'm sure clojure doesn't maintain its own method tables for java classes like we do

2:48 psykotic: this makes me think that there might be a way of extending the current protocol design to accommodate something like that

2:48 headius: once you maintain your own metaclass/method tables, you can add things

2:48 psykotic: although it would require a redesign of the interop system for sure

2:49 headius: a little bit goes a long way

2:49 psykotic: heh

2:49 headius: you don't need to go crazy like groovy

2:49 hmm, 4 minutes on my battery

2:50 I hope my 1-hr flight tomorrow is enough to finish a completely new hour presentation on invokedynamic

2:50 sigh

2:50 psykotic: anyway, nice talking to you, i hope some of the info about clojure's vars and namespaces was helpful

2:50 headius: why do I put these things off

2:50 psykotic: yes, it was very helpful, thank you

2:51 btw

2:51 it might be possible to repurpose duby's backend with different syntaxes

2:51 I've been toying with the idea

2:51 anything that could produce a duby AST would just work

2:51 leverage the same type inference, .java and .class backend

2:51 (and there's a C# backend out there somewhere)

2:52 anyway, I have to go

2:52 nite

2:52 psykotic: bye

3:24 LauJensen: Morning team

3:25 hoeck: good morning Lau

3:33 psykotic: it seems like #=/EvalReader isn't really EvalReader as much as ApplyReader :)

3:34 ,#=(symbol "foo")

3:34 clojurebot: EvalReader not allowed when *read-eval* is false.

3:35 psykotic: anyway, it will allow things like (symbol "foo") where you have a single function application with already evaluated arguments, but you can't do something like (symbol (str "foo "bar")) because the (str "foo" bar") is just passed to symbol unevaluated as a persistentlist

3:38 aha, you can just use #= recursively: #=(symbol #=(str "foo" "bar")) will work

3:41 LauJensen: psykotic: What docs were you reading RE #= ?

3:41 psykotic: source code

3:41 EvalReader in LispReader.java

3:42 it's intended for read time evaluation, so you can do things like #'#=(symbol "myvar")

3:42 (yes, i know about resolve)

3:43 LauJensen: ok - Just wanted to make sure there wasn't an unclear doc floating

3:44 psykotic: did anyone see this? http://ketain.blogspot.com/2010/03/clojure.html

3:44 it's... interesting code. heh.

3:45 LauJensen: Fun experiment

3:46 psykotic: it's a not a bad idea for a project but the code is awful

3:47 just the parser is an insane mix of regular expressions, ad hoc "let's count the parentheses separately to see if they are balanced" like things, exception-wrapped Integer/parseInt calls, etc

3:52 btw what's the convention in clojure when you have a cond where you want to put the test and result parts of a clause on separate lines? do you indent the result so it stands out from the test?

3:54 LauJensen: cgrand: does, if possible I keep each condition and body on the same line

3:54 psykotic: me too

3:54 i'm asking about cases where that would be harder to read than splitting

3:55 LauJensen: And also, if its the same predicate being used over and over, condp is preferred

3:55 psykotic: yes

3:56 incidentally, i really wish condp took an actual predicate as argument rather than a binary relation. the binary relation case would be subsumable as (condp #(= foo %) x ... y ... z ...)

3:56 LauJensen: That would be more intuitive

3:57 cgrand: LauJensen: what are you talking about?

3:57 psykotic: cgrand: he meant to tell me

3:58 LauJensen: cgrand: yea sorry about that - I was just commenting on your style of identation in cond-statements

3:58 cgrand: ha ok, I can go back to my accounting then :-/

3:58 psykotic: cgrand: sounds like fun!

4:00 LauJensen: psykotic: I think there's still an entire cond module in contrib though

4:00 psykotic: yeah, there's a predicate (rather than binary relation) version called something i can't remember

4:00 LauJensen: condb ?

4:03 psykotic: clojure.contrib.cond only has cond-let

4:03 i can't remember the name but i believe i saw it

4:03 LauJensen: oh

4:03 psykotic: contrib is a really strange mix :)

4:03 LauJensen: Maybe I'll write (switch ...)

4:04 psykotic: the closest thing to c's switch is case, so that might be confusing

4:04 LauJensen: Naah

4:06 psykotic: maybe call this thing pcase :)

4:06 there's already (deprecated) fcase is like condp (takes a binary relation, etc)

4:07 zmila: i use the same identation pattern for cond as in the given blog. if not fit in one line, then the second part - on new line and indented

4:07 psykotic: zmila: yeah, that's what i'm doing too

4:08 most other lisps group each clause with ( and ), so you don't need it in those for readability

4:10 zmila: but i think this very long cond is the subject to use some way to defmethod

4:11 psykotic: oh, i don't mean his code

4:11 i have a simple three-clause cond but one of the tests is long enough that it looks better with the result broken into its own line

4:14 screw it, two nested ifs look better here

4:56 licoresse: In emacs clojure-mode, I absolutely loathe the way indentation works. How can this be set to, say 3 spaces, and always stick to this?

4:57 Just reading http://ketain.blogspot.com/2010/03/clojure.html, and I want to have indentation like it...

4:58 well, I see it is not really what I want after all... :(

5:00 Chousuke: licoresse: 2 spaces is the lisp standard. everyone's going to think you're weird if you deviate from that :P

5:00 licoresse: yeah, 2 spaces is fine, just as long as M-C-q works

5:01 working with proxy defintions, the indentation gets all messed up

5:02 Chousuke: parameters are usually aligned, but special forms and macros get special indentation.

5:03 licoresse: Am I weird if I don't like special forms having special treatment?

5:03 Chousuke: they would indent way too much if they didn't

5:03 would you like defn to indent so that the code aligns with the parameter list? :/

5:04 licoresse: no

5:04 I would like each indent to be 2 (or whatever) spaces, thats it!

5:04 Chousuke: the indentation on that page doesn't look very special to me

5:05 licoresse: Chousuke: my fault, I was skimming to fast

5:06 Chousuke: I think clojure-mode has a setting for context-sensitive indentation

5:06 but I don't even know what effect it has, if any

5:07 licoresse: looking at clojure-indent-function

5:07 psykotic: Licenser: what about function calls with multiple parameters broken across lines?

5:07 you want those be indented by only 2 spaces

5:07 ?

5:08 Chousuke: 'clojure-mode-use-backtracking-indent it seems

5:08 psykotic: s/Licenser/licoresse/, damn autocomplete

5:08 licoresse: :)

5:08 Chousuke: I have it disabled it seems

5:08 licoresse: psykotic: Everything should be 2 spaces, no special rules

5:08 psykotic: a foolish consistency is the hobgoblin of small minds :)

5:09 licoresse: Then I have a small mind, thats ok

5:09 backtracking indent, hmm

5:10 Chousuke: function calls would be difficult to read with nonaligned parameters :/

5:10 psykotic: backtracking indent, is that like haskell-mode's tab cycling?

5:10 ineed

5:10 licoresse: I'll have a try

5:11 Chousuke: I have no idea what that is :P

5:11 licoresse: Soon we will

5:21 Licenser: greetings my lispy friends

5:21 licoresse: good morning

5:21 spariev: morning

5:23 LauJensen: Morning Licenser

5:29 _invis: guys Why this is always () ???

5:29 (def Alpha1

5:29 (map #((if (not (= 100 %1)) (atan (/ %2 (- L4 %1))))

5:29 (if (> %2 0) (/ Math/PI 2))

5:29 (if (< %2 0) (/ (* 3 Math/PI) 2))

5:29 (if (= %2 0) 0)) (range 0 61 20) (range 61 0 20)))

5:29 ,(def Alpha1

5:29 (map #((if (not (= 100 %1)) (atan (/ %2 (- L4 %1))))

5:29 (if (> %2 0) (/ Math/PI 2))

5:29 (if (< %2 0) (/ (* 3 Math/PI) 2))

5:29 (if (= %2 0) 0)) (range 0 61 20) (range 61 0 20)))

5:29 clojurebot: EOF while reading

5:30 _invis: ,(println (def Alpha1

5:30 (map #((if (not (= 100 %1)) (atan (/ %2 (- L4 %1))))

5:30 clojurebot: EOF while reading

5:30 _invis: (if (> %2 0) (/ Math/PI 2))

5:30 (if (< %2 0) (/ (* 3 Math/PI) 2))

5:30 (if (= %2 0) 0)) (range 0 61 20) (range 61 0 20))))

5:30 licoresse: everything on one line, and no def

5:30 _invis: no def ?

5:30 licoresse: ,(def jalla 123)

5:30 clojurebot: DENIED

5:30 _invis: def Alpha1 :)

5:30 my clojure compile it

5:30 licoresse: clojurebot does not accept def

5:30 _invis: but println zero

5:31 *nil

5:31 ()

5:31 why this function doesnt work :(

5:32 tomoj: _invis: please don't do that

5:32 hircus: which function?

5:32 Chousuke: _invis: use a pastebin

5:32 no lisppaste here though

5:32 hm

5:32 ~paster

5:32 ~paste

5:32 clojurebot: Pardon?

5:32 lisppaste8, url

5:32 Chousuke: duh

5:33 _invis: emm

5:33 tomoj: I think bots should be more self-documenting

5:33 Chousuke: http://gist.github.com ... remember to pick Clojure as the language

5:33 also, really, you should use a proper function instead of the shortcut form

5:33 hoeck: _invis: a few things, your second range returns (), and map only maps over the smallest sequence when given multiple sequences

5:34 _invis: I guess you wanted (range 61 0 -20)

5:35 _invis: actually I wanted Xa - coll, but here for example I paste (range ...)

5:35 Chousuke: also keep in mind that identifiers containing uppercase characters are not particularly idiomatic

5:36 _invis: ok

5:37 hoeck: _invis: http://gist.github.com/340990

5:37 _invis: now here is exception :)

5:38 hoeck: _invis: right, cause your first "if" returns nil and calling nil throws an NullPointerException

5:38 _invis: no

5:39 it was Double to IFN exception

5:39 java.lang.ClassCastException: java.lang.Double cannot be cast to clojure.lang.IFn

5:39 hoeck: o right, it returns a number

5:39 _invis: hoeck: its work. ty

5:39 Chousuke: yes, that was because you had #((if ...))

5:40 the if expression returned a double and it tried to run that as a function

5:40 but I would still avoid using the anonymous function in that case

5:40 make it a proper one and give it a name

5:41 _invis: but I use it just here, for one time

5:42 licoresse: _invis: it's hard to read and understand, especially when you're tired

5:42 Chousuke: you can use let or letfn

5:42 or at least make the #() into (fn ...) with named parameters

5:43 In my opinion a #() expression that has to be split on multiple lines is usually too long.

5:43 _invis: why this isnt work too http://gist.github.com/340994

5:44 Chousuke: you have an extra pair of parens around the second if

5:44 _invis: this if for ELSE for first if

5:44 Chousuke: but honestly, I can't figure out what that even does :/

5:44 _invis: :)

5:45 Chousuke: the extra pair of parens is still redundant

5:45 you don't wrap the else expression of an if in parentheses. you just write it as you want it

5:45 (if a x (if b y :nothing))

5:46 but that's bad style by itself. (cond a x b y :else nothing) is better

5:47 _invis: what it should do http://slil.ru/28839037

5:49 Chousuke: also, it looks like you're doing the ifs like (if foo (something)) (if bar (something else))

5:49 that won't work, because even if the first if returns something, the second if still gets executed and the first one's return value is simply ignored

5:50 spariev: is it right syntax for typehinting typed array - (aget #^"[Lcom.browseengine.bobo.api.BrowseHit;" hits %) ? compiles still reports Reflection warning - call to aget can't be resolved

5:51 *compiler

5:51 Chousuke: spariev: remember to hint the index as well

5:51 spariev: and I think hinting arrays as #^objects works just as well.

5:51 _invis: Chousuke: thank you

5:52 So I cant write like this: (if (expr ) (do something if true) (another if if else)) ?

5:53 hircus: no, unless your expr is actually a thunk (a function that takes 0 argument)

5:53 Chousuke: _invis: you can, but you seemed to be writing (if expr do-something) <- note closing paren (if expr2 ...)

5:54 spariev: Chousuke: thanks, hint on index did the trick

5:55 Chousuke: _invis: whereas the syntax for if is (if condition then-expr else-expr) ... and in the case of nested ifs, the else-expr is just another if. that's all there is to it

5:56 _invis: hmm :)

5:56 Chousuke: _invis: but again, using cond is better. it leads to less nesting

5:56 _invis: ok I will use cond, but just wanted to understand what was wrong

5:57 Chousuke: _invis: keep in mind that ifs in Clojure are not statements like in other languages. they're just expressions

5:57 _invis: you can do things like (+ 1 (if *some-global* 2 4))

5:58 _invis: I understand that

5:58 hoeck: _invis: with nested ifs: http://gist.github.com/341008

5:58 _invis: ohh

5:59 Thank you man :)

5:59 that was I try so much to understand

5:59 licoresse: a little reformatting can work wonders

6:00 _invis: will it work with X and Y ?

6:00 why not %1 ? just for view nice ?

6:00 Chousuke: heh, it won't actually.

6:01 licoresse: _invis: it is a hint for you to not use anon func

6:01 Chousuke: I suppose he intended to transform the #(....) to (fn [x y] (...))

6:02 Licenser: I often find it nicer to use not #() but actual (fn [] ) since you can name the parameters

6:03 Chousuke: I tend to use #() only for very short and obvious things nowadays

6:03 * Licenser nods

6:03 Chousuke: like #(= 100 %) or whatever

6:03 Licenser: Chousuke: I like (partial = 100) there :P

6:03 don

6:03 't know why but it makes me feel so lispy

6:03 Chousuke: that's longer :P

6:04 Licenser: so what?

6:04 _invis: thanks a lot

6:04 Licenser: it looks cooler and people who read that can say 'woooh Licenser understood how partial functions work!!!'

6:04 licoresse: :)

6:04 Licenser: ;)

6:07 spariev: Licenser: I use ->> for the same reason :) looks way cooler

6:08 Licenser: spariev: see, I don't know exactly what ->> does :P

6:08 spariev: ,(doc ->>)

6:08 clojurebot: "([x form] [x form & more]); Threads the expr through the forms. Inserts x as the last 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 last item in second form, etc."

6:09 hoeck: Licenser: do you know -> ?

6:09 Licenser: hoeck: no, never got the whole arrows, after the knee OP I am scared of them o.o

6:09 licoresse: finally!! an interview with Rich on seradio

6:09 hoeck: cool!

6:10 Licenser: (doc ->)

6:10 clojurebot: "([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."

6:10 * hoeck downloads

6:11 Licenser: ,(->> 1 (+ 2) (+ 3))

6:11 clojurebot: 6

6:11 Licenser: ,(macroexpand '(->> 1 (+ 2) (+ 3)))

6:11 clojurebot: (+ 3 (clojure.core/->> 1 (+ 2)))

6:12 Licenser: ,(macroexpand1 '(->> 1 (+ 2) (+ 3)))

6:12 clojurebot: java.lang.Exception: Unable to resolve symbol: macroexpand1 in this context

6:12 Licenser: ,(macroexpand- '(->> 1 (+ 2) (+ 3)))

6:12 clojurebot: java.lang.Exception: Unable to resolve symbol: macroexpand- in this context

6:12 Licenser: ,(macroexpand-1 '(->> 1 (+ 2) (+ 3)))

6:12 clojurebot: (clojure.core/->> (clojure.core/->> 1 (+ 2)) (+ 3))

6:12 Chousuke: :P

6:12 Licenser: why is macro expand stopping at the middle?

6:12 Chousuke: it doesn't macroexpand inner expressions

6:12 Licenser: ,(macroexpand '(-> 1 (+ 2) (+ 3)))

6:12 clojurebot: (+ (clojure.core/-> 1 (+ 2)) 3)

6:13 Licenser: ah okay -> puts it in the first ->> puts it in the end :)

6:13 hoeck: congratulations!

6:14 spariev: Licenser: also check out this screencast by Sean Devlin on -> & ->> http://vimeo.com/8474188

6:14 hoeck: the doc for -> and ->> is nearly uncomprehensable

6:14 Licenser: hoeck: I agree it is horrible to read

6:14 hoeck: or uncomprehensible

6:14 Licenser: then again, risking that I get stoned, most of the clojure docs are horrible

6:15 hoeck: well, except for the function docs

6:15 licoresse: Would love if someone initiated a project to insert examples in all the doc-strings

6:17 * esj stands back from this reckless display of volunteerism.

6:18 licoresse: something like this: http://wiki.squeak.org/squeak/5699

6:50 jwr7: Any hints as to why "lein swank" doesn't set up the classpath? I only get clojure, clojure-contrib and swank...

6:52 leafw: kotarak ?

6:53 esj: jwr7: this used to be a problem, but I think its sorted now. It is for me.

6:53 leafw: anybody iusing vimclojure, I'd appreciate help. I can never get it to install i na new machine.

6:53 jwr7: esj: Hmm. I just installed leiningen 1.1.0 and no cigar. Googling around, but can't find anything...

6:54 Leiningen 1.1.0 on Java 1.6.0_17 Java HotSpot(TM) 64-Bit Server VM -- on Mac OS X.

6:54 esj: you're not using emacs by any chance ?

6:55 jwr7: I am — using slime-connect to connect to the swank started by lein swank

6:55 Mec: If i have a string representation of a data structure do i just use eval to realize it?

6:56 zmila: ,(doc read-line)

6:56 clojurebot: "([]); Reads the next line from stream that is the current value of *in* ."

6:57 esj: jwr7: one work around which I used to use was M-x swank-clojure-project, which got around this

6:57 zmila: ,(type (read-line "123"))

6:57 clojurebot: java.lang.IllegalArgumentException: Wrong number of args passed to: core$read-line

6:57 zmila: ,(type (read-string "123"))

6:57 clojurebot: java.lang.Integer

6:57 esj: jwr7: but I just checked, both my stable and -dev version of leiningen, on a setup pretty much like yours do work

6:58 zmila: Mec - you can use (read-str "aoeu")

6:58 Mec: thanks, i didnt know about read-string

6:58 jwr7: esj: that's strange... perhaps I'm doing something wrong, then. Do I need anything else apart from adding lein-swank to :dev-dependencies?

6:59 esj: nope

6:59 jwr7: esj: or could it be that swank-clojure is lying about namespaces? Hmm.

6:59 esj: try (use ) something

7:00 jwr7: esj: nope. And ,change-package completions show user, clojure, clojure.contrib and swank. That's it.

7:01 jwr7: btw, my slime and swank-clojure.el are from ELPA.

7:01 esj: mine too

7:02 dunno man, sorry. If you're developing and running on the same machine I'd suggest M-x swank-clojure-project as a good workaround.

7:02 leafw: vimclojure cannot even be built using the README.txt instructions.

7:02 "no build.xml file!", compains ant

7:02 s/compains/complains/

7:02 jwr7: esj: yes, I guess I'll revert to that, or my old ways of hacking with a lib directory full of symlinks... But leiningen was supposed to change that...

7:02 esj: thanks anyway.

7:03 esj: sorry dude.

7:03 jwr7: hold on

7:04 your :dependencies in project.clj is setup right ?

7:04 jwr7: esj: Yes. And lein deps downloaded a ton of stuff into lib/

7:04 esj: does lein repl work ?

7:04 jwr7: also, would anybody happen to know why C-c C-c in SLIME gives me NullPointerExceptions ( 0: clojure.lang.Compiler$FnMethod.parse(Compiler.java:3739)), while C-x C-e works just fine?

7:06 esj: jwr7: again, I dunno, mine compiles.

7:07 jwr7: People should pay me for testing software — I *always* hit all the quirks that nobody has ever hit before. In every piece of software I touch :-)

7:12 licoresse: in emacs: swank-clojure-project

7:59 in a vector [:a :b :c :d] is there a contains?-like function that allows me to do (contains? [:a :b :c :d] :b) ?

8:00 noidi: ,(some #{:b} [:a :b :c])

8:00 clojurebot: :b

8:00 noidi: ,(some #{:d} [:a :b :c])

8:00 clojurebot: nil

8:00 rhickey: licoresse: why not use a set?

8:01 licoresse: yeah, why not... :)

8:01 gotta think a little

8:03 yes, (#{:a :b :c :d} :d) is much better!

8:03 psykotic: then you can just do...

8:03 licoresse: right

8:03 psykotic: ,(#{:a :b :c :d} :b)

8:03 clojurebot: :b

8:03 licoresse: :c

8:04 psykotic: ,(#{:a :b :c :d} :e)

8:04 clojurebot: nil

8:04 licoresse: cool

8:09 noidi: one case in which the "some" trick is handy is when you have a function that takes a variable number of optional arguments

8:09 (if (some #{:fire-the-missiles} options) ...)

8:09 licoresse: I see

8:10 ,(doc some)

8:10 clojurebot: "([pred coll]); Returns the first logical true value of (pred x) for any x in coll, else nil. One common idiom is to use a set as pred, for example this will return :fred if :fred is in the sequence, otherwise nil: (some #{:fred} coll)"

8:10 spariev: ,(clojure.contib.seq-utils/includes? [1 2 3 4] 4)

8:10 clojurebot: java.lang.ClassNotFoundException: clojure.contib.seq-utils

8:10 spariev: ,(clojure.contrib.seq-utils/includes? [1 2 3 4] 4)

8:10 clojurebot: true

8:11 licoresse: sets serves my purpose well

8:11 but thanks

8:11 noidi: the reason I prefer "some" over "includes?" in those cases is that sometimes options may imply other options

8:11 spariev: includes? will do if you need to deal with vectors

8:11 noidi: a dumb example: (if (some #{:-f :--overwrite-files) options) overwrite-files)

8:51 Licenser: ping

8:51 zmila: ,ping

8:51 clojurebot: java.lang.Exception: Unable to resolve symbol: ping in this context

8:51 zmila: ,(ping)

8:51 clojurebot: java.lang.Exception: Unable to resolve symbol: ping in this context

8:52 djpowell: http://blogs.tedneward.com/2010/03/23/How+To+And+Not+To+Give+A+Talk+On+F.aspx is some good advice for Clojure evangelists

8:52 Licenser: (let [ping "pong"] ping)

8:52 ,(let [ping "pong"] ping)

8:52 clojurebot: "pong"

8:53 djpowell: it always seems that the 'classic' example program for any given technology, is always the most stupid and inappropriate

8:54 eg every SOAP example is a 'stock ticker', which would be better done with http. i'm sure AOP can do more than add log statements. and computing fibonacci numbers, badly, using explicit recursion isn't a great example for functional programming

8:55 zmila: djpowell - tĥx, good article to be read on the way home :)

8:56 esj: djpowell: I'm not sure if I agree with the article

8:57 djpowell: we can't pretend that these languages are like the C#s etc

8:57 and shouldn't want to

8:57 fogus: Some applies to Clojure talks, but others very not

8:57 spariev: not sure about REPL, I think it's a fantastic tool esp for people stuck with Java

8:58 chouser: That's a good article.

8:58 fogus: I agree with the math stuff

8:58 cemerick: More generally, "know thy audience", but yeah.

8:58 esj: i agree that it should not be made to seem other-worldly, but the big win from a pragmatic functional language lies with it being functional

8:58 chouser: I think the underlying theme may be: tell them things that can be meaningful to them where they are, not things that we all have come to realize are amazing after some amount of time.

8:59 cemerick: right

8:59 djpowell: yeah - tho I never really use the repl directly - I use inferior lisp mode together with a real edited file. I think if I had to use a repl directly, I wouldn't so often. Eg, I've never done very much python, but I can't imagine I'd spend much time in the repl. The same probably applies to F# - don't know...

8:59 chouser: like the REPL -- if a 3-minute example of how to use it doesn't grab a person, another 25 minutes of repeating the fact isn't going to convince them.

8:59 Licenser: I use the repl a lot

9:00 I am not sure, didn't read the entire article but some things do not fit me

9:00 fogus: I doubt something like the REPl would even need to be addressed directly

9:00 Chousuke: it's good to mention though

9:00 cemerick: My general rule is, don't show (much) code, don't show (much) programming. Broadly writ, people care about apps and end-user functionality (i.e. "why the hell should I care about XXX"), not the gritty bits (which don't present well in a talk anyway).

9:00 esj: absolutely, its a big, big win

9:00 chouser: I'm afraid macros are in roughly the same category.

9:01 djpowell: I think using a resultset-seq as your example data is going to grab people more than using a vector of ints or something when you are showing off map/filter/reduce

9:01 chouser: djpowell: I was just thinking that.

9:01 Chousuke: cemerick: I think Rich does an excellent job explaining why people should care about Clojure's state model, at least :)

9:01 chouser: most developers are keenly aware of the clumsiness of dealing with resultset-seqs

9:01 well, result sets

9:01 esj: hehe

9:02 * fogus raises hand

9:02 cemerick: Chousuke: For sure, but we aren't Rich, and our audiences are rarely Rich's audiences :-)

9:02 chouser: shhh, he's here.

9:02 Licenser: DO stress that F# can do everything C# or Visual Basic can do. // <- I'm not sure 'can do what Visual Baisc can' is something to be proud of

9:02 rhickey: anyone want:

9:02 Chousuke: heh

9:02 rhickey: (letfn [(foo [& {a :a b :b}] [a b])] (foo :a 1 :b 2)) => [1 2]

9:02 djpowell: resultset-seqs are ace. i'm wondering whether I might be able to have something like a resultset-seq that makes datatypes so that i can implement protocols over the data in 2.2

9:02 not sure how well that will work

9:03 chouser: rhickey: mmm!

9:03 esj: thats slick

9:03 Licenser: it looks nice but it isn't really intitive is it?

9:04 after & I exect that I can pass as many arguments as i like and then get a list

9:04 cemerick: I can't say I've ever used letfn. :-/

9:04 fogus: It took me a second to realize what I was looking at, but I like it

9:04 djpowell: no me neither yet. i guess lispers are more familiar with it

9:04 rhickey: all associative destructuring options in play, not a special case

9:04 Chousuke: Licenser: it's not much different from (fn [& [foo bar]] though

9:04 chouser: the point is destructuring a seq of alternating key/values into map keywords

9:04 rhickey: cemerick: letfn is not important here

9:04 Licenser: Chousuke: you can do that?

9:05 cemerick: rhickey: yeah, that's just me adding noise

9:05 rhickey: so :keys and :or are also available?

9:05 Licenser: ,(letfn [(foo [& [a b]] [a b]) (foo 1 2))

9:05 rhickey: chouser: right, and implemented exactly like that - if a seq? arg to associative destructuring, hash-map it first

9:05 clojurebot: Unmatched delimiter: )

9:05 Licenser: ,(letfn [(foo [& [a b]] [a b])] (foo 1 2))

9:05 clojurebot: [1 2]

9:05 Licenser: ,(letfn [(foo [& [a b]] [a b])] (foo 1 2 3))

9:05 clojurebot: [1 2]

9:05 Licenser: hmm I see how it works

9:05 djpowell: ah, that does look pretty cool

9:06 rhickey: cemerick: yes, everything is available

9:06 Licenser: could you use :as there too?

9:06 rhickey: Licenser: really, everything

9:06 cemerick: rhickey: Good. There goes the "fns should not require users to pass map literals" preference :-)

9:06 Licenser: cool then you have my vote in favour

9:06 not that it matters

9:07 chouser: sometimes when I do keyword arg parsing manually, I transition to keyword args when I find the first keyword in the input, not a fixed arg count.

9:07 rhickey: so, the one icky bit is that (let [{a :a b :b} [:a 1 :b 2]] [a b]) and (let [{a :a b :b} (seq [:a 1 :b 2])] [a b]) are different

9:07 cemerick: chouser: asking for trouble, no?

9:07 Licenser: something like: massing areguments in order or as a key would be incredible

9:08 chouser: cemerick: depends on the arg type I suppose. I don't remember being worried.

9:08 rhickey: does anyone use associative destructuring on vectors?

9:08 * Licenser has to play kicker with his boss now, see you all later

9:09 chouser: rhickey: the first is [nil nil]?

9:09 rhickey: chouser: yes

9:10 I think the problem is less that there will be a desire to get associative destructuring of vector than that this will be one of very few cases where a vector can't be used where a seq can

9:10 chouser: ,(let [{a 0 b 3} [4 5 6 7]] [x y])

9:10 clojurebot: java.lang.Exception: Unable to resolve symbol: y in this context

9:10 chouser: ,(let [{a 0 b 3} [4 5 6 7]] [a b])

9:10 clojurebot: [4 7]

9:10 rhickey: or at least, the behavior will be different

9:10 chouser: no, I don't think I've ever done that.

9:11 fogus: Hmmm, I didn't even realize that you could do that :(

9:11 cemerick: It's surely more of a curiosity than actual practice.

9:12 rhickey: so, if no one has become curious, it could be changed to map destructuring and vecs/seqs get same treatment

9:12 cemerick: rhickey: what would the key interface be?

9:13 Chousuke: I don't think I've ever seen associative destructuring on vectors

9:13 rhickey: cemerick: j.u.Map

9:13 but much less nice than associative

9:14 chouser: it's not obvious to me which behavior would be better for vectors

9:14 rhickey: because associative also works for sets: (let [{:keys [a b c]} #{:a :c}] [a b c]) => [:a nil :c]

9:15 not that that anyone knows that either

9:15 :)

9:15 chouser: :-)

9:15 * cemerick raises his hand

9:15 cemerick: I actually use that :-/

9:15 rhickey: cemerick: congrats!

9:16 cemerick: eh, it's in one hacky spot where I can get a set or map, and that ended up working out.

9:16 rhickey: I'm ok with the seq? test, as the overwhelming case is for & args

9:16 chouser: yeah

9:17 Chousuke: I think most people would expect map destructuring not to work on vectors.

9:17 in the associative way, that is. so I'm in agreement

9:17 cemerick: The current consistency is too perfect tho.

9:17 rhickey: "Map binding-forms allow you to bind names to parts of associative things (not just maps), like maps, vectors, string and arrays (the latter three have integer keys)."

9:18 chouser: Chousuke: but if that's the case, they might expect vectors to destructure like seqs

9:18 rhickey: first sentence of map binding docs ^^

9:18 cemerick: I think a seq test is perfectly reasonable.

9:18 ...and puts the burden on the new feature, at least for now.

9:19 chouser: This class name is probably a hint that I'm going about things the wrong way: java.lang.ClassNotFoundException: clojure.core$eval__56$mmap_factory$reify$reify__64$eval__66$mmap_factory__67

9:20 Chousuke: uh

9:20 cemerick: heh

9:21 Chousuke: is that a closure of mmap-factory that reifies something and evals a call to itself recursively? :/

9:21 fogus: rhickey: I remember that example from the docs, but I suppose the implications were lost on me

9:21 chouser: yes

9:21 rhickey: heh, so keyword args was just a one-liner away all this time

9:21 have fun! http://github.com/richhickey/clojure/commit/29389970bcd41998359681d9a4a20ee391a1e07c

9:22 cemerick: rhickey: wait for the griping about the braces :-P

9:22 rhickey: cemerick: there's no possible argument against them

9:22 given [a & [b c]] already

9:23 cemerick: rhickey: I know. That won't be a deterrent, tho. :-)

9:23 * cemerick is feeling punchy. Shocker.

9:23 chouser: griping will more likely be around the extra word and nesting of {:keys [b c]}, I'd think

9:23 rhickey: cemerick: you just can't please some people

9:23 cemerick: tell me about it.

9:24 Chousuke: chouser: that would be like complaining "we want the language to be inconsistent!

9:24 dnolen: rhickey: huh, so [a & [b c & rest]] is allowed as well?

9:24 rhickey: well, it's a completely clean extension and now works everywhere

9:24 dnolen: sure

9:24 fogus: Chousuke: You've seen programming languages right?

9:24 dnolen: I sense a hidden feature of Clojure.

9:24 chouser: people often think they inconsistency is at times convenient.

9:25 rhickey: dnolen: it's not hidden, it just falls out of the nestability of binding forms

9:26 dnolen: rhickey: no I know :) reference to Stack Overflow question. but I guess defining mutiple arity fns is preferred over this right?

9:27 cemerick: dnolen: depends on what you're doing

9:27 * fogus destructuring as internal mini-language

9:28 Chousuke: the destructure function in clojure.core is pretty scary

9:28 dnolen: cemerick: a simple example where [a & [b c]] would be preferred over multiple arity?

9:28 chouser: ooh, let's count the mini-languages!

9:28 fogus: 1. destructuring

9:28 Chousuke: chouser: count the number of macros!

9:28 chouser: 2. list comprehension

9:28 3. regex

9:29 noidi: exception handling? :)

9:29 fogus: 4. #()

9:29 chouser: Chousuke: hm, I guess -- somehow what 'for' provides seems more like a language than 'defn'

9:29 rhickey: regex is not mini

9:29 chouser: 5. syntax-quote

9:29 Chousuke: chouser: defn provides a mini-language for defining functions :)

9:30 chouser: Chousuke: ultra-mini

9:30 Chousuke: or I suppose that's fn

9:31 chouser: well, it has pre/post, metadata, arglists (with "special" destructuring) and doc strings

9:31 ordnungswidrig: ns macro

9:31 fogus: 6. pre- post-

9:31 chouser: but those mostly just feel like keyword args

9:31 but defn's mini language mostly just feels like keyword args

9:32 fogus: 7. (some #{...} ...) ???

9:33 chouser: nah

9:33 Chousuke: There's nothing wrong with having mini languages though. if anything, it makes things consistent. If the language provides access to the mechanisms used to create those mini languages, you can design your own APIs to be more consistent with the core language :)

9:33 fogus: I suppose that's just an idiom

9:33 7. -> ->>

9:35 * fogus running out of ideas

9:35 chouser: ns

9:36 fogus: I missed numbering that earlier

9:36 cemerick: dnolen: if it's a simple matter of optional positional args, then [a b & [opta optb optc]] is *always* easier than having mulitple arities. I just saved three overloads right there.

9:36 chouser: oh, right, I missed it entirely

9:37 rhickey: heh, (let [[& {:keys [a b]}] [:a 1 :b 2]] [a b]) => [1 2]

9:37 consistency rocks

9:37 lpetit: gen-class

9:38 fogus: rhickey: So would you say that it's safe for me to change the section on named args in the book?

9:38 rhickey: fogus: I haven't gotten to that yet, but probably

9:38 fogus: lpetit: ooooo, a sub-mini-language

9:38 cemerick: 8. literal numerics i.e. 1e7, 11r02

9:39 9. #^ints, #^bytes, etc

9:40 fogus: rhickey: great thanks

9:42 chouser: hm... so a macro that expands something like `(~(fn ...) ~arg) usually works (as long as fn is not a closure), but apparently sometimes gives me ClassNotFoundException

9:43 rhickey: I actually quite prefer this to defnk or whatever, in spite of being more verbose, as it just reuses existing knowledge of {} binding, and gives the same caller experience, which is what matters

9:45 spariev: solussd, are keywords via destructuring (defn foo [a b & [:kw kw :kw2 kw] are preferred over ruby-like options hash, as in first example here - http://stuartsierra.com/2010/01/15/keyword-arguments-in-clojure

9:45 so*

9:46 Chousuke: chouser: you could work around that with `((fn ~@[...]) ~args)

9:47 chouser: well, that was simplification. the fn is actually cached in a map, and I was trying to get away with a single lookup at compile time instead of a lookup once per call at runtime.

9:47 and it mostly works -- not sure why it sometimes doesn't.

9:48 raek: could there be another &, say &&, that turns the seq into a hashmap?

9:48 * raek is thinking about python's * and **

9:49 solussd: hehe. autocomplete spariev?

9:49 spariev: solussd: yep, sorry :)

9:49 raek: (let [[x y && {:keys [a b]}] [1 2 :a 3 :b 4]] [a b]) => [3 4]

9:51 I have no idea how descructuring actually is implemented in clojure, so take this with a metric ton of salt

10:11 dnolen: raek: with rhickey's latest changes your example just works. no need for &&

10:13 rhickey: well, you do need one &

10:17 dnolen: raek: also ** could defined as (defn ** [x] (flatten (seq x)), then (apply somefn 1 2 (** options)) just works.

10:20 Licenser: hmm IU've a function that is suposed to extact code from free text: http://gist.github.com/341213 any thoughts to that?

10:41 rhickey: does lein have a self update?

10:43 ohpauleez: rhickey: I believe 1.1 and onward does

10:43 rhickey: and to get to 1.1 from 1.0.1?

10:44 ohpauleez: you just install over top I believe

10:49 technomancy: rhickey: yeah, self-update is new; to upgrade to 1.1 you just replace the bin script manually and then self-install

10:50 rhickey: technomancy: ok, thanks

10:51 any way to get compojure to use something other than current working directory as the root?

10:57 licoresse: how can I represent the string of :a => "a"

10:57 dnolen: ,(str :a)

10:57 clojurebot: ":a"

10:57 chouser: ,(name :a)

10:57 clojurebot: "a"

10:58 dnolen: oops :)

10:58 licoresse: name, yess

10:58 thanks

10:58 cemerick: rhickey: you mean for hosting static stuff?

11:00 Licenser: another interesting application for this: http://gist.github.com/341257

11:00 a very simple template engine

11:05 rhickey: cemerick: yeah

11:05 cemerick: rhickey: see serve-file. You can root things whereever you like.

11:06 G0SUB: rhickey: (letfn [(foo [& {a :a b :b}] [a b])] (foo :a 1 :b 2)) is returning [nil nil] for me. (I tried the latest master with 29389970bcd41)

11:07 rhickey: cemerick: right, I have existing code I don't want to change that already calls serve file

11:07 cemerick: rhickey: Unless you're just playing around, I'd take the 10 minutes to get set up with proper war packaging, which would give you a lot of options. Then you can just let jetty serve the static stuff on its own.

11:07 rhickey: ah. In that case, I think rebinding serve-file is your only option.

11:08 rhickey: cemerick: not my project

11:09 hircus: we should try plugging Clojure to this guy -- he has quite a large readership and is contemplating a Lisp to learn: http://reprog.wordpress.com/2010/03/23/the-long-overdue-serious-attempt-at-lisp-part-1-which-lisp/

11:10 cemerick: hircus: he says explicitly no Clojure *shrug*

11:10 hircus: he perhaps does not realize how Lispy it is

11:11 drewr: does he *really* want to use LISP as it was in 1958?

11:11 I don't even think that's possible on modern hardware

11:11 hircus: but well. funny, considering he just claimed he looks forward more than back. sounds like a tailor made match for Clojure if his claim is true

11:11 fogus: "I want to start with foundations, and that means the language from 1958" That rules out Scheme

11:11 hircus: drewr: I'm sure you can emulate a 1958 machine :p

11:11 yeah. not very consistent

11:12 fogus: Lisp as it was in 1958. Have fun. http://github.com/fogus/lithp

11:12 drewr: hircus: which would be much more cumbersome than learning haskell or clojure ;-)

11:12 rsynnott: fogus: that also rules out Emacs Lisp and Common Lisp

11:12 cemerick: Eh, he calls out a couple of langs explicitly as not interesting to him right now.

11:12 rsynnott: though Emacs Lisp is probably closest

11:12 Licenser: fogus: byte code asm :P

11:12 hircus: I sympathize with anyone who has to work on ELisp for a living

11:13 rsynnott: hircus: there's a Google employee with a blog whose job used to involve maintaining Amazon's customer support system, which was an elisp app

11:13 cemerick: Clojure and any good scheme are (almost, sorta) equivalent anyway (excepting the concurrency stuff). External considerations drive a choice between the two, so any advocacy will likely fall on deaf ears.

11:14 rsynnott: (can't find the article now, but it sounded pretty terrible, all right)

11:14 rhickey: cemerick: um, what?

11:14 cemerick: rhickey: for someone new to lisps in general?

11:14 cypher23: rsynnott, that employee wouldn't happen to be Steve Yegge?

11:14 * rhickey can't remember a good Scheme with pdstructures as the default

11:14 rsynnott: cypher23: ah, yep, that's him

11:15 hircus: rsynnott: worst abuse of ELisp I could think of. I know some sites use Common Lisp but that actually makes sense

11:15 drewr: hircus: elisp is a great choice if emacs is your env

11:15 * rsynnott has used Common Lisp for a few production-ish things; it's fine. Would not even CONSIDER emacs lisp

11:15 hircus: if that's Yegge that experience did not seem to cause lasting harm :)

11:15 drewr: yes, it makes sense, but Amazon ran their customer support system from within Emacs ?!

11:15 rsynnott: hircus: well, he's implementing javascript as an elisp competitor

11:16 that surely indicates it left some scars? :)

11:16 hircus: allegedly

11:16 cemerick: rhickey: but PDSs surely aren't necessary in a first lisp.

11:16 G0SUB: rsynnott: not any more. last time I checked, he has abandoned the project.

11:16 hircus: very true. odd choice. granted, Javascript was *meant* to be a Lisp...

11:17 esj: Hey at least we're 'fashionable arrivestes'. I can't recall having been one of them before.

11:17 drewr: hircus: maybe that's all they needed to take info from a customer and persist it to disk

11:17 emacs is a lisp machine that runs everywhere, even over a terminal

11:17 rhickey: cemerick: so you meant "Clojure and any good scheme are (almost, sorta) equivalent anyway" only in that context?

11:17 hircus: I guess this must be in the early days when a single thread can do the job in real time

11:17 cemerick: rhickey: right, related to this fellow who wants to learn some lisp, linked somewhere above

11:21 rhickey: hmph

11:21 cemerick: rhickey: You should post exactly that as a comment there. :-)

11:22 or, I should say, ;-)

11:22 powr-toc: Is it possible to use enlive as a DSL for generating HTML,

11:22 without using any HTML?

11:24 Raynes: Licenser__: ping

11:26 powr-toc: I realise Enlive uses selectors to insert HTML into the HTML

11:26 template... but can it be used standalone to generate HTML, without a HTML file?

11:27 cemerick: powr-toc: yeah, that's doable. Not pleasant, perhaps, but doable.

11:27 powr-toc: cemerick: not pleasant in what sense?

11:27 cemerick: Sorta defeats the point, at least a little.

11:27 powr-toc: cemerick: sure... It's just right now, I don't have a

11:27 designer... I just want to knock up a small amount of HTML inside clojure

11:28 cemerick: powr-toc: Insofar as one chooses enlive to populate pages with data, maintaining a clean separation between design and "templating".

11:28 powr-toc: later on, when maybe there is a designer it'd be good to use the

11:28 separation aproach

11:28 cemerick: powr-toc: I don't have a designer, either :-) You'll still be better off having your pages on disk, and populating them later.

11:29 Keep separate concerns separate, even if you're wearing both hats.

11:30 powr-toc: cemerick: I agree, but that doesn't mean I need the complexity of

11:30 having extra files when I'm probably talking about a handful of

11:30 forms... I can seperate the logic from the template in a single file

11:30 of pure clojure

11:31 cemerick: powr-toc: yikes. "extra files" isn't complex compared to balling up all your presentation into one ball of mud IMO.

11:33 powr-toc: cemerick: it is while you're talking about just two or three

11:33 simple HTML forms. I'd break it out when it got any bigger.

11:34 hircus: powr-toc: if you really want to do all your work from a single language, you might want to check this out -- http://twitter.com/Tordf/status/10794263684

11:34 cemerick: HTML is really, really good at representing HTML. :-P But anyway, *peace man*. :-)

11:35 hircus: powr-toc: I guess you can always write a simple Clojure map/vector => HTML converter. My previous university generated its pages from Scheme

11:36 hiredman: or just use one that already exists

11:36 hircus: powr-toc: but you'd end up only with a slightly more concise representation (no duplicate close tags) and if/when you get a designer that person will get confused

11:36 hiredman: http://github.com/mmcgrana/clj-html for example

11:36 powr-toc: hiredman: yeah, I know there's hiccup too... but I quite like

11:36 enlive's approach

11:37 hircus: they wouldn't because I'd have converted them back to

11:37 HTML for them

11:37 chouser: I think that enlive consumes the structures produced by clojure.xml/parse

11:37 powr-toc: (that is I like enlives approach for when you have a designer)

11:37 chouser: so you'd only need to convert from [:a {:href "foo"} "text"] to {:tag :a :attrs {:href "foo"} :content ["text"]} ...

11:39 powr-toc: chouser: hmm interesting

11:40 hiredman: ,(let [[tag attrs & content] [:a {:href "foo"} "text"]] {:tag tag :attrs attrs :content (vec content)})

11:40 clojurebot: {:tag :a, :attrs {:href "foo"}, :content ["text"]}

11:40 chouser: right, but the vec needs to be recursive, you probably want to allow for missing attr maps, etc.

11:41 hiredman: chouser: :(

11:41 chouser: I feel like I've written such code before...

11:43 lpetit: cemerick: Assembler is really, really good at representing Assembler. :p :p . Hopefully we have compilers to write assemblers from higher-order languages nowadays. Same for abstracting html away (if there is a viable option) IMHO.

11:43 cemerick: all for want of an html file or three :-/

11:44 powr-toc: cemerick: It looks like hiccup or a clj-html are all I need

11:44 now... I was just wondering if enlive supported a similar usecase

11:44 cemerick: lpetit: Cute, but there's essentially no connection between HTML and assembler. HTML is *the* delivery mechanism that generally doesn't have any incidental complexity, so abstracting away from it is a little silly.

11:45 s/that/and

11:45 Fossi: those rock

11:45 the right thing to do is abstracting you data retrieval layer from the frontend

11:45 powr-toc: cemerick: except that clojure's syntax is easier, less verbose & paredit ensures

11:45 tags are closed...

11:46 fogus: lpetit: I think Erran Gat mentions using Lisp as an assembly "DSL" in this article: http://www.flownet.com/gat/jpl-lisp.html

11:46 Fossi: then add some compojure, clj-html etc into the mix and it's (much) greater than php

11:46 lpetit: cemerick: in your dreams :-). More seriously, I mean HTML is *theoretically* abstract, but I guess at least browers differences in implementation make this dream not become true.

11:47 That's certainly why GWT has a lot of traction those days

11:47 cemerick: lpetit: assuming you're using HTML and CSS for what they're respectively designed for, then I'm not sure what could be gained by driving presentation bits into code.

11:47 GWT and the apps it produces have zero connection with a simple set of forms (which is what powr-toc was aiming for).

11:48 lpetit: cemerick: Wait ! I'm talking about some real abstraction layer over html. Not one of those who just allows you to write [:p] instead of <p> of course.

11:48 cemerick: my bad for jumping into a conversation without having read it from the beginning. Sorry guys.

11:49 cemerick: lpetit: well, that's fine enough then. :-) But the latter is exactly what's going on at the moment, sadly enough.

11:49 hiredman: a real abstraction layer is what? swing -> html?

11:49 powr-toc: cemerick: I'm not even needing CSS though... I really just

11:49 require plain old HTML just now. There isn't any real presentation... just a very small structured document.

11:50 cemerick: hiredman: apparently, [:p :content "hello"] or whatever is better than <p>hello</p> 9.9

11:50 lpetit: hiredman: alas, I guess this one has still to be invented. But at least an additional layer that fills the gap between theoretical html+css code (which should work 'as is' on any browser on any OS), and the reality :-)

11:50 cemerick: powr-toc: But, of course, you will. Why pay now, and then pay later?

11:50 * lpetit needs to take a serious look at seaside one of those days

11:51 zaphar_ps: I'll take enlive over any abstraction layer any day

11:52 * fogus looks sideways at the GWt code on his screen

11:53 lpetit: fogus: doing GWT right now ? I will start my first GWT app in a few hours/days. Any advice for a beginner ? :-)

11:53 fogus: lpetit: Don't use anything lower than version 2.0

11:53 powr-toc: cemerick: yagni might be one reason

11:54 lpetit: fogus: I like this quotation from the article you cited : "Apparently they got this idea that because I worked at Google for a year that I was now a search engine expert" :)

11:54 fogus: yeah, the "Programmation GWT 2" by Sami Jaber is on my desktop :-)

11:54 zaphar_ps: lpetit: I run into that sometimes google does a lot more than just search

11:54 fogus: lpetit: Who hasn't had that experience? Being the default-expert that is.

11:55 cemerick: powr-toc: Insofar as HTML is viewed by humans, it requires CSS for reasonable presentation. *shrug*

11:55 lpetit: fogus: yes, so true :)

11:57 powr-toc: cemerick: I don't require reasonable presentation... the form

11:57 will just be used by me

12:03 * zmila is using GWT for two years, but the project is semi-in-production and we can not upgrade to newest version of GWT. we stuck at 1.5

12:06 lpetit: zmila: so bad

12:07 zmila: i'd like to learn gwt 2.0, it has more interesting traits

12:13 cemerick: Is there any hope of being able to use non-Java languages for GWT sometime in the future? I presume not, but hope abounds.

12:14 chouser: maybe if there was a clojure compiler backend that emitted java source? :-/

12:14 cemerick: ha

12:14 I'm sure there is still, in the murky depths of rhickey's hard drive.

12:29 lpetit: *that emitted java source restricted to only the part of the JDK which is ported to JS :-/

12:49 fogus: cemerick: I heard a rumor about a Scala GWT being planned

12:49 cemerick: be still my heart :-P

12:49 fogus: I knew you'd like that. ;-)

12:49 chouser: you did say "non-Java languages" :-)

12:50 cemerick: chouser: I'm an impossible bastard. :-D

12:50 still, if scala is in the works, then adding support for a third option will be that much easier.

12:51 fogus: Scala is only like Java for the first 6-months

12:51 cemerick: that long? ;-)

12:51 fogus: I'm slow

12:52 cemerick: rubbish

12:52 chouser: Make sure you put fogus' last comment on the front of the book.

12:53 fogus: It can be the subtitle

12:53 chouser: heh

12:53 shales: Is there a way to cast a number to a number that uses less bits and simply truncate the value? For example, something like if (byte 255) returned the byte -1

12:53 chouser: ,(.byteValue 255)

12:53 clojurebot: -1

12:53 lpetit: shales: sure, use clj-native

12:54 :)

12:54 shales: ah of course, thanks chouser

12:54 cemerick: shales: of course, keep in mind that...

12:54 ,(-> 255 .byteValue class)

12:54 clojurebot: java.lang.Byte

12:54 peregrine81: ,(+ 2 2)

12:54 clojurebot: 4

12:54 peregrine81: sweet

12:54 cemerick: ^^ that's no primitive (reacting here to the "uses less bits" part)

12:55 chouser: well, it's trute that's not a primitive, but that test didn't prove it.

12:55 ,(-> 5 byte class)

12:55 clojurebot: java.lang.Byte

12:56 chouser: there was a primitive byte in there for a moment, before it got boxed to send to 'class'

12:58 fogus: ,(-> 5 .byteValue Byte/toString)

12:58 clojurebot: "5"

13:00 * fogus realizes that proves nothing

13:01 peregrine81: How lispy is clojure if it doesn't contain TCO? Therefore removing opportunity for recursion..

13:02 chouser: lispy enough

13:02 peregrine81: lol good answer

13:02 I was pondering it while reading little schemer

13:03 cemerick: peregrine81: see the recur form, which provides a better option (IMO) for 98% of the use cases for TCO.

13:04 peregrine81: cemerick: I've barely used recur yet so I don't know all of the possibilities, thinking about sort of porting scheme to clojure

13:05 chouser: peregrine81: I'm not sure that will go very well. The Java runtime (and therefore the Clojure runtime) are not best at doing the kinds of things scheme wants to do. They have other strengths.

13:05 peregrine81: chouser: okay

13:06 chouser: In Clojure, however, it's a rare algorithm that needs TCO, and trampoline handles 95% of those.

13:06 cemerick: peregrine81: you'd have to figure out what you actually want to port.

13:06 Different macro systems might be interesting, though I've always taken more naturally to clojure-style (née CL-style) macros.

13:07 peregrine81: good point

13:08 I'm no pro at clojure or lisps in general but I want to learn

13:08 cemerick: chouser: 'course, if what you thought you needed TCO for just gets "unrolled" into a loop with recur, why not call that TCO?

13:08 or, über-TCO, or mutual-TCO, etc.

13:09 Meaning, call the other 5% those latter names.

13:14 Licenser_: hmm the compujure readly is quite wrong :(

13:23 arohner: rhickey: how do you feel about a patch that replaces several calls to SOURCE with SOURCE_PATH, in exception messages in the compiler?

13:27 Licenser_: *sigh*

14:32 * fogus listening to http://www.se-radio.net/podcast/2010-03/episode-158-rich-hickey-clojure

14:56 chouser: unreadably printed objects are a pain

15:02 arohner: Man, I really want an emacs mode that allows me to visit old git trees using find-file

15:02 like find-file ~/my-project/.git/sha-1/old-file

15:06 LauJensen: fogus: Thanks for that link :)

15:18 technomancy: arohner: C-x v ~ maybe?

15:18 (for a single file)

15:22 rrc7cz-hm: I've switched from Clojure Box to Emacs+Slime+Lein-Swank, and I'm having one bit of trouble: C-c C-k is undefined. The REPL is working fine (with classpath configured, etc), but I can't seem to compile

15:26 fogus: rhickey: Thanks for the shout out!

15:27 arohner: is (symbol (name :foo)) really the best way to convert a keyword to a symbol?

15:27 oh, there's (.sym :foo)

15:28 kotarak: ,(symbol :foo)

15:28 clojurebot: java.lang.ClassCastException: clojure.lang.Keyword cannot be cast to java.lang.String

15:28 kotarak: a pity

15:33 arohner: (symbol :foo) should work IMO

15:44 ipostelnik: rrc7cz-hm, I usually run M-x swank-clojure-project to init my projects in emacs

15:48 jwr7: fogus: thanks, didn'tknow about that one yet. Will serve as listening material for the dog walk tonight :-)

15:49 rrc7cz-hm: ipostelnik: Is that only for creating a new project? In this case I have an existing project, and I run "lein swank" to start up a local server. Then I do a slime-connect to that server

15:49 ipostelnik: rrc7cz-hm, for existing project

15:50 rrc7cz-hm, you need to provide location of project.clj (emacs will prompt) and then clojure-swank will run "lein swank" for you

15:52 rrc7cz-hm: ipostelnik: that's working beautifully

15:53 ipostelnik: perhaps I spoke too soon. it does run lein swank and connect automatically, with a working reply, but compilation doesn't look right

15:56 ipostelnik: rrc7cz-hm, you can see what it's doing in *slime-events* buffer

15:57 rrc7cz-hm: ipostelnik: it is compiling okay, but it's a bit different than I'm used to with clojure-box. When I compile a script that depends on other scripts, it just failed out with ClassDefNotFound instead of recursively compiling the dep script

15:58 for example, I have a top-level, gen-class -main script which uses some other script. I'd expect if I compile this top-level script, instead of failing with ClassDefNotFound, it would simply compile the dep script.

16:00 * rhickey races chouser to moderate ggroup

16:01 chouser: oh, is that what we're doing?

16:01 * chouser stops

16:01 rhickey: chouser: should be harmless

16:01 chouser: but ... you can't be, you're busy giving an interview.

16:02 ipostelnik: rrc7cz-hm, that's odd, it resolves dependencies in the project just fine

16:03 rhickey: actually I was making the labrepl work with Enclojure - works quite well now

16:05 * rhickey wonders what interview he missed

16:06 naeu: is there a recognised way of creating a command line clojure script that accepts params etc.?

16:06 chouser: I'm just listening to the software engineering radio interview fogus linked to earlier.

16:07 naeu: there's a weak, poorly-documented think in contrib you can at least start with. command-line

16:07 naeu: chouser: thanks

16:07 programble: naeu: i also think *command-line-args* gets populated

16:08 ,(doc *command-line-args*)

16:08 clojurebot: "; A sequence of the supplied command line arguments, or nil if none were supplied"

16:08 naeu: my problem is that I'm new to using the JVM for real programming (dabbled with it at uni etc.) and I'm very used to writing simple scripts in Ruby to do useful things

16:08 I was wondering to what extent I could start using clojure for those kinds of tasks

16:08 kotarak: ,(let [[hd & tl] (map #(doto % prn) (iterate inc 1))] hd)

16:08 clojurebot: 1

16:08 1 2

16:09 chouser: naeu: yes, and you can do this with *command-line-args* and clojure.contrib.command-line, but unfortunately the JVM startup time reduces the set of problems for which this kind of thing is a good solution.

16:09 * Drakeson has a [incomplete] way of creating clojure scripts using ng + with bash completion

16:09 naeu: chouser: sure, but these are things for which I don't mind waiting for 10 seconds or so :-)

16:10 chouser: naeu: ah, good. you'll be set.

16:12 naeu: cool, thanks

16:14 slyphon: so, if i want to in effect alias a method from namespace X to another namespace Y, such that it would be public in Y, uh, how do you do that?

16:15 chouser: you just want to use the function in Y, or make it available to users of Y?

16:15 slyphon: make it available to users of Y

16:16 chouser: yeah, that's not recommend. :-)

16:16 slyphon: oh, ok :)

16:16 i'll do something different then

16:17 Drakeson: look at clojure.contrib.ns-utils/immigrate :D

16:17 slyphon: ah, that's the one i was thinking of, but i think i can just do something more straightforward

16:18 chouser: immigrate has been generally disavowed, I think even by its creator

16:18 slyphon: you can have foo/bar/baz.clj and foo/bar/baz/spam.clj right?

16:19 chouser: yes

16:19 slyphon: ok, just making sure

16:19 Drakeson: IMHO, it only makes sense when the library was poorly designed, e.g. with too many unnecessary sub-namespaces

16:20 (using immigrate, I mean)

16:32 kotarak: ,#"\\" "/"

16:32 clojurebot: #"\\"

16:36 Drakeson: is leiningen (git) after 2010-03-15 is also [partially] broken for you, too? lein deps copies the library to lib/ and then stays there forever. It does not terminate.

16:38 technomancy: Drakeson: I've noticed that, but it doesn't seem to be consistent on all systems. just use ctrl+c for now; I'll be looking into it later.

16:39 Drakeson: technomancy: so it is harmless?

16:39 technomancy: yeah

16:39 just a weird artifact of the ant APIs we're using, I'm guessing

16:39 Drakeson: thanks

16:43 naeu: I must say, I find the whole JVM classpath thing a real royal pain

16:45 I've just pulled and built the latest edge clojure and clojure contrib jars, placed them into their own special directory, written a zsh script that sets the class path (to point to those jars) and to start up a repl, and I can't seem to reference clojure.contrib.command-line

16:45 programble: ew, zsh

16:45 naeu: java.io.FileNotFoundException: Could not locate clojure/contrib/command_line__init.class or clojure/contrib/command_line.clj on classpath

16:45 ew that rather than ew zsh

16:45 zsh isn't that bad

16:45 :-)

16:45 chouser: ok, so I've got an IPersistentMap implementation via reify, but I need it to work as a key in another map, matching an array-map.

16:46 slyphon: wow, i have macro bug that's causing the clojure compiler to throw a StackOverflowError

16:46 what do i win?

16:46 :D

16:46 Chousuke: hmm

16:46 chouser: I've got = working properly now, so (= my-reify-map my-array-map) and vice-versa

16:46 slyphon: oh, nothing, i'm just a retard

16:46 hoeck: slyphon: thats easy, just write a recursive macro which never terminates

16:46 naeu: slyphon: are you sure your macro isn't referencing itself or something like that?

16:46 slyphon: naeu: yeah, it is

16:47 naeu: slyphon: at least you got your classpath set up

16:47 slyphon: i had a defn blah*/defmacro blah combo

16:47 chouser: ...but ({my-array-map :val} my-reify-map) is still nil because the hash codes are different

16:47 scottj: http://paste.lisp.org/display/96803 I can't figure out why this macro works fine when called directly but doesn't work when called inside a function. I think it has to do with the function having the same variable names but I'm not how to use gensyms to fix it. Ideas?

16:47 hoeck: naeu: maybe post your script?

16:47 slyphon: naeu: leiningen takes care of that for me

16:47 chouser: what's the Right Way to get the correct hash code. The implementation appears to be locked up inside APersistentMap where reify can't get to it?

16:47 hoeck: naeu: should be as short as java -cp clojure.jar:clojure-contrib.jar clojure.main

16:48 naeu: hoeck: I don't even have a script yet, I'm just trying to reference command_line without it dying

16:48 miltondsilva: How do I add a doc to a def? I've seen this done but I keep forgeting how to do it :S

16:48 Chousuke: (def #^{:doc "blah"} foo ..)

16:48 miltondsilva: thanks :)

16:49 kotarak: scottj: the macro sees name the symbol not name the local.

16:49 naeu: hoeck: can i use relative paths in the classpath?

16:50 kotarak: naeu: sure

16:50 scottj: kotarak: how come that's different when called directly vs called in the function?

16:51 kotarak: scottj: because direct call sees "op" the string

16:51 chouser: put another way, is there a good way to call an instance method of an abstract class on an object that doesn't extend it?

16:51 heh, I suppose not. Any way at all?

16:51 * chouser starts poking around with reflection. bleh.

16:51 naeu: hmm, I still can't seem to reference command_line

16:51 Chousuke: just look at the APersistentMap implementation and translate it :P

16:52 naeu: what's the most basic test to see whether I have built and classpathed contrib correctly?

16:52 Chousuke: start a repl and try to use it :)

16:53 I think mvn clojure:repl should set up everything for you thoug

16:53 h

16:53 naeu: Chousuke: that's what i'm doing

16:53 Chousuke: but then you can only run that in the contrib dir :(

16:58 chouser: Chousuke: yeah, that was much better

16:58 (apply + (map (fn [[k v]] (bit-xor (hash k) (hash v))) my-map))

16:59 scottj: kotarak: how would I fix it?

16:59 chouser: APersistentMap/hashCode changes, anyway

16:59 kotarak: scottj: you can't. This is an intrinsic limitation of macros. Rewrite your macro as function.

17:02 Chousuke: scottj: the string that eventually becomes bound to 'name does not even exist when the macro is executed

17:02 scottj: do you see the problem? :)

17:04 scottj: Chousuke: nope, when is the macro executed, when the function that calls it is defined or called?

17:04 Chousuke: scottj: just before the function is compiled

17:05 and never again! ;P

17:06 lpetit: hello

17:07 does enclojure integrate with lein ?

17:07 slyphon: lein is *for* clojure

17:07 no?

17:07 naeu: here's my failed attempt to reference contrib.command-line: http://gist.github.com/341655

17:07 dnolen: lpetit: stuart halloway has submitted a patch to lein to make it possible for enclojure to open lein projects.

17:07 naeu: if anyone can see what I'm not quite doing correctly, I'd love to hear!

17:08 slyphon: oh, i'm sorry

17:08 lpetit: dnolen: do you know the details ? I don't understand (yet) what has been done ? And why it is on the lein side ??

17:08 kotarak: naeu: no ~ in classpath

17:08 naeu: tilde is shell, use qualified names

17:08 naeu: kotarak: so how is it pulling in clojure.jar?

17:09 lpetit: dnolen: I'm interesting in the part where enclojure can (automagically ?) download all the needed dependencies from the lein project description ! ? !

17:09 kotarak: naeu: the first ~ works because of the shell

17:09 naeu: ahhh...

17:09 kotarak: naeu: subsequent tildes are hidden from the shell => no expansion

17:09 dnolen: lpetit: not sure on all the details, but it sounds really promising.

17:09 naeu: yep, that makes sense

17:09 kotarak: thanks so much :-)

17:09 lpetit: dnolen: sure. I would like to provide this kind of interop for ccw too

17:09 technomancy: lpetit: "lein pom", then "create project from maven pom" or some such, I believe

17:10 need the latest lein from git

17:10 dnolen: lpetit: http://github.com/technomancy/leiningen/commit/1bbcf902f040d5b823647961cb8d35181b65716d is the commit I think

17:10 lpetit: technomancy: oh, so if this is it, then I could also achieve the same by adding additional eclipse maven plugin installation

17:10 dnolen: oh, sorry the man himself speaks :)

17:11 lpetit: technomancy, dnolen: so it is a little bit vaporware (yet) to say "no lein, no pom" in the installation instructions for netbeans in the labprepl README ...

17:11 technomancy: well I haven't used it; just repeating what Stuart told me.

17:11 lpetit: ok

17:13 KirinDave: Damn

17:13 being grilled

17:14 kotarak: oh my... labrepl sucks in the world...

17:14 lpetit: kotarak: he ?

17:15 kotarak: lpetit: well, I said: lein deps. Now I get the world downloaded it seems.

17:16 lpetit: Yes, I had the same experience an hour a go. But it's taking some time, so go ahead by another disk ;-)

17:16 s/by/buy

17:16 kotarak: -.- geez

17:17 Raynes: The fact that Ioke ints !- Java ints and Ioke strings != Java strings are annoying.

17:17 s/are/is/

17:22 lpetit: I'm *really* impressed by the quality of the material in labrepl. Really a great work. Both from the technical side and the pedagogic side.

17:23 KirinDave: Holy crap these folks are picking me dry

17:23 This is crazy detail they want

17:23 I'm naming line numbers.

17:24 Doh

17:24 Man wrong room over and over.

17:27 lpetit: ok, maven 2 plugin for eclipse seems to work like a charm, labrepl will get detailed instructions on how to work from scratch with eclipse+ccw within minutes

17:28 With the advent of the Egit (Eclipse Git) plugin, there will be no need at all to touch the command line, even for the "clone labrepl" part ;-)

17:32 slyphon: once you've defonce-d something, is it possible to undef it? (for REPL experimentation purposes)

17:33 drewr: lpetit: you say that like it's a good thing ;-)

17:34 kotarak: (doc ns-unmap)

17:34 clojurebot: "([ns sym]); Removes the mappings for the symbol from the namespace."

17:34 noss: are there any problems with running clojure code in webstart?

17:34 slyphon: kotarak: ok, cool

17:35 kotarak: noss: http://groups.google.com/group/clojure/browse_frm/thread/2d79e297431e2d29#

17:35 technomancy: slyphon: actually just "def" will do it

17:37 noss: kotarak, thanks, *reading*

17:37 slyphon: technomancy: oh, mm'kay

17:37 technomancy: wait, so (def *my-defonced* nil)?

17:39 technomancy: slyphon: sure. defonce is the only piece enforcing the "oncedness"

17:39 kotarak: slyphon: with def the Var will survive (*my-defonced* is still available), with ns-unmap it will be completely gone.

17:39 slyphon: technomancy: ah! of course

17:40 kotarak: ok, i understand

17:40 thanks

17:41 lpetit: drewr: one should never listen to what I'm saying :-)

18:00 naeu: ok, so now i'm running with a classpath, I'm trying to work through this: http://stackoverflow.com/questions/1341154/building-a-clojure-app-with-a-command-line-interface

18:00 although i'm failing at the compilation stage

18:11 hoeck: naeu: you don't have to compile just to run your script

18:12 run your script with: java -cp <your classpath> clojure.main <your-script.clj>

18:13 naeu: hoeck: oh, interesting, so clojure.main takes a src file to interpret as a param?

18:13 does that src file need to be on the classpath too?

18:13 Raynes: Yes.

18:14 naeu: I'm totally going to write some scripts to get around this mess

18:14 hoeck: no, I don't think so

18:14 the clj, can be anywhere

18:14 Raynes: Most people don't bother compiling unless they need compilation specific features, or some of the other benefits of compilation.

18:14 hoeck: Really?

18:14 hoeck: but all scripts you refer to (via use or require) must be on the classpath

18:15 Raynes: well, just tried it with a simple example and it works

18:15 naeu: Raynes: does compiling improve execution performance? Or just startup time?

18:15 hoeck: naeu: no, only writes the already compiled stuff to disk

18:15 every clojure function is always compiled, there is no intepretation

18:15 lpetit: hoeck: startup time

18:16 naeu: startup time

18:16 Raynes: naeu: startup time.

18:16 naeu: :-)

18:16 lpetit: :)

18:16 hoeck: lpetit: right, and java-interop

18:16 lpetit: sure

18:16 using it everyday on ccw hacking ! :)

18:26 kylesmith: I would like to suggest an improvement to the docstring of dorun.

18:27 When you have a lazy-seq whose elements are themselves lazy-seqs, it seems dorun will not actually force them.

18:28 Has anyone else encountered this pitfall before?

18:30 hoeck: no, but I never had to force a lazy seq of lazy seqs via dorun :)

18:31 kylesmith: well, the outer lazy-seq of from iterate, so I can't use doall

18:32 kotarak: kylesmith: oeh, you can't use dorun also, no?

18:32 dorun won't return

18:32 kylesmith: I can now (I had to add a doall to the inner lazy-seqs, which obviously don't need to be lazy for my purposes)

18:33 kotarak: kylesmith: I don't get, how this solves the infinite outer iterate....

18:34 arnihermann: I vaguely remember there being a problem with macros and symbols being resolved -- can anyone recall something about that?

18:34 when in fact, they were not supposed to be

18:34 kylesmith: well the outermost iterate is still lazy. The problem is dorun wasn't forcing each element of the iterate call, so it just returned immediately.

18:35 kotarak: arnihermann: that is a feature => hygienic macros. If you don't want to resolve symbols use ~'unresolved-symbol

18:36 arnihermann: ah

18:36 kylesmith: ,(time (dorun 4 (iterate #(do (Thread/sleep 1000) (map inc %)) [0 0 0])))

18:36 clojurebot: "Elapsed time: 4004.01 msecs"

18:37 licoresse: How can I reset a ref that is defined like this: (def selection (ref (sorted-map))) ? I tried (dosync (alter selection {})) but obviously this is not correct

18:37 kylesmith: ack, bad demo.

18:37 kotarak: Oha. dorun takes a also an optional count.

18:38 licoresse: ref-set

18:38 licoresse: ,(doc ref-set)

18:38 clojurebot: "([ref val]); Must be called in a transaction. Sets the value of ref. Returns val."

18:38 licoresse: :) thanks

18:39 arnihermann: kotarak: what if I'm doing some work outside the syntax quote? and preparing that symbol there?

18:39 kotarak: kylesmith: (dorun 4 (map dorun (iterate stuff here)))

18:40 kylesmith: ,(time (dorun 4 (iterate #(map (fn [x] (Thread/sleep 1000)) %) [0 0 0])))

18:40 clojurebot: "Elapsed time: 0.679 msecs"

18:40 kylesmith: kotarak: yes, that will work, but my point is that how is anyone ever supposed to know to do that?

18:41 kotarak: arnihermann: (let [good (gensym) bad (symbol (str "abc" "xyz"))] `(vector ~good ~bad))

18:41 kylesmith: I never expected dorun to do what you want. It is nowhere stated. And how do you get a non-recursive dorun?

18:42 kylesmith: I'm not expecting dorun to recursively force seqs either, but I think it would be nice to mention this 'problem' in the docstring.

18:43 kotarak: ,(time (dorun 4 (map dorun (iterate #(map (fn [x] (Thread/sleep 1000) x) %) [0 0 0]))))

18:43 clojurebot: Execution Timed Out

18:43 noss: is there any form of dependency injection implemented in clojure?

18:43 arnihermann: kotarak: I'm doing (symbol (str "'" param))) where param is a parameter passed to the macro (sort of) and I need to be that exact value

18:43 kotarak: noss: dependency injection is handled via functions/closure.

18:44 arnihermann: kotarak: but otherwise, that would work just fine

18:44 kotarak: arnihermann: the ' is not part of the symbol.

18:44 arnihermann: ah

18:44 noss: kotarak, no reflection on type annotation and automatic resolving of what actual implementation to pass in?

18:44 arnihermann: right

18:44 kotarak: ,(let [x (symbol "abc")] `(~x))

18:44 clojurebot: (abc)

18:45 noss: i got the book by stuart and started reading it the last days, so i dont know how used this #^notation is used.

18:46 kotarak: ,(macroexpand-1 ''foo)

18:46 clojurebot: (quote foo)

18:47 kotarak: arnihermann: 'foo is equivalent to (quote foo)

18:47 arnihermann: kotarak: thanks

18:47 kotarak: noss: #^{:foo :bar} x is similar (but not equivalent) to (with-meta x {:foo :bar})

18:48 noss: #^String x ~~> (with-meta x {:tag String})

18:49 noss: kotarak, can i reflect on those meta after code has been compiled?

18:49 kotarak: noss: sure

18:49 ,(meta #'map)

18:49 clojurebot: {:ns #<Namespace clojure.core>, :name map, :file "clojure/core.clj", :line 1764, :arglists ([f coll] [f c1 c2] [f c1 c2 c3] [f c1 c2 c3 & colls]), :doc "Returns a lazy sequence consisting of the result of applying f to the\n set of first items of each coll, followed by applying f to the set\n of second items in each coll, until any one of the colls is\n exhausted. Any remaining items in other colls are ignored. Function\n

18:49 noss: kotarak, cool, then at least there is a good chance someone will get something like google guice implemented if it has not already been done for clojure.

18:49 kotarak: ,(meta (with-meta [] {:foo :bar}))

18:49 clojurebot: {:foo :bar}

18:50 Chousuke: #^Foo attaches the metadata to the symbol, at read-time; with-meta attaches it to the value, at runtime

18:51 arnihermann: kotarak: thanks, i was confusing quote with ' being a part of the name of the symbol

18:51 kotarak: thanks alot!

18:51 kotarak: Chousuke: that's why I said "is similar (but not equivalent) to" (shame-less self promotion: http://kotka.de/blog/2009/12/with-meta_and_the_reader.html)

18:52 arnihermann: kotarak: btw, awesome blog, love it

18:52 kotarak: arnihermann: thanks :)

18:53 lpetit: any enclojure developer here ?

18:56 I'm writing a "mini-dsl" :-) where a text editor state is (minimally) currently represented as a map : {:text "the text" :offset 3 :length 0}, and in the "human friendly" form, it is just represented as "the| text". The pipe denotes the cursor position.

18:58 Now I want to extend it to really represent selections in the text editor, e.g. {:text "the text" :offset 3 :length 2}. I don't know if the "human friendly" from can just be as "the| t|ext" with two pipes, or as "the< t>ext" with a start and a stop delimiter.

18:58 Raynes: Licenser_: You around?

18:58 Licenser_: Me?

18:58 Noooo!

18:58 Raynes: ;P

18:58 Licenser_: Adding doc to the whitelist doesn't seem to do anything.

18:58 Licenser_: hmm

18:58 lpetit: Does anybody know whether some editors *really* have different behaviors if the selection has been made left to right or right to left ?

18:59 Licenser_: ,(macroexpand '(doc doc))

18:59 lpetit: That is, if :selection can be a negative integer ?

18:59 Licenser_: (clojure.core/print-doc (var doc))

18:59 you've to allow this

19:01 lpetit: rofl: I already implemented it with the two pipes version when I first wrote it, will stay with this for now on

19:03 Raynes: Licenser_: "(doseq [x \"Hello, World!\"] x)" -> SecurityException.

19:03 Licenser_: did you allow doseq?

19:03 Raynes: It's already allowed in the default sandbox.

19:03 Licenser_: yap it is

19:03 Raynes: But even if I allow it manually, it does that.

19:04 Licenser_: okay let me investigate :)

19:04 Raynes: Heinz - Private Sandbox Investigator. :P

19:04 Licenser_: yuck good greif

19:04 did you ever macroexand that

19:05 and haha, nice title

19:05 Raynes: Nosir. Never macroexpanded that.

19:05 Licenser_: it is 4 lines long on my screen

19:06 (loop* #'clojure.core/seq #'clojure.core/int #'clojure.core/int #'clojure.core/< let* . #'clojure.core/nth recur #'clojure.core/unchecked-inc let* #'clojure.core/seq let* #'clojure.core/chunked-seq? let* #'clojure.core/chunk-first recur #'clojure.core/chunk-rest #'clojure.core/int #'clojure.core/count #'clojure.core/int let* #'clojure.core/first recur #'clojure.core/next #'clojure.core/int #'clojure.core/int) <- functions included

19:06 Raynes: :o!

19:06 Licenser_: so I guess the problem is that I don't have half of that in the lists :P

19:07 Raynes: Hehe. There is a lot you don't have in the list.

19:07 Licenser_: yap

19:07 Raynes: Would you mind if I added some obviously safe functions to the list myself? I have some in mind.

19:10 Licenser_: Raynes: please you're as good as me when it comes to it :P

19:10 Raynes: Hehe.

19:12 Licenser_: When you get that fixed, could you push 0.2.5 for me? I have to take off (once again :|) for a while.

19:12 Licenser_: of cause

19:12 have fun Raynes

19:12 Raynes: Thanks buddy. <3

19:16 Crowb4r: Anyone here use Scala all that much?

19:18 defn: I haven't touched scala yet. Clojure has been my only foray into FP beyond Haskell thus far

19:19 * Licenser_ didn't neither

19:19 Licenser_: greetings defn by the way :)

19:20 miltondsilva: scala is to java as java is to c++ ... it's an improvement but one limited by what the mainstream accepts

19:22 (at least that's how I felt when I wrote some small programs in it... but I may be totally wrong)

19:30 defn: Hiya Licenser_

19:30 Licenser_: I toyed a bit with your walton, I hlope you don't mind

19:30 defn: By all means!

19:30 polypus: ~ping

19:30 clojurebot: PONG!

19:30 defn: It's WTFPL for a reason. ;)

19:31 Licenser_: ^^

19:31 but you'll like the stuff I think, results are now really good

19:32 underdev: miltondsilva: i'm totally stealing that line

19:36 defn: Licenser_: I'm really excited to see the progress

19:36 have you submitted a pull req.?

19:36 miltondsilva: underdev: ;)

19:36 Licenser_: not sure if I did for the latest changes, let me see

19:37 defn: Licenser_: Perhaps it would be interesting to create a site now which contains core fn examples. That was always my hope with an earlier project, but no one submitted any examples.

19:38 Licenser_: http://playground.licenser.net:3000/walton.html

19:38 ;)

19:38 defn: you little!

19:38 haha

19:38 oh cool! you actually show it's output now!

19:38 Licenser_: yap

19:38 defn: we need to do syntax hilighting, and maybe make some ajaxy drop downs or something to see output

19:39 Licenser_: defn: I was coding remotely, putting the webside online was the simplest thing

19:39 defn: *nod*

19:39 very cool Licenser_ -- This is fantastic.

19:39 Licenser_: defn, it's your work, I just tossed in a bit sandbox

19:40 defn: Licenser_: it's a collaborative effort :)

19:40 Licenser_: :)

19:41 defn: whoa. I didn't know github let you apply merges automagically from their web interface

19:42 Licenser_: :)

19:42 they do?

19:43 defn: I clicked something that said "Fork Queue" -- which sounds funny if you say it out loud

19:43 Licenser_: heh

19:43 defn: but i digress, I selected your commits and hit "apply"

19:43 looks like it's applying them right now without the fetch/merge/push

19:44 It is "processing" them right now -- no telling how long this will take...

19:44 Licenser_: heh

19:45 bad news is, it got slower :P

19:46 defn: the functionality is what is important

19:46 as long as the utility isn't sacrified i dont see speed as a big factor

19:46 it's really just about getting a nice example in your REPL for how to use a function

19:53 Licenser_: *nods*

19:53 when things are 'longer running' you can save stuff and speed things up

19:55 hrm lein is hating me :(

20:07 it really does grrr

20:10 lein just tells me: All :namespaces already compiled.

20:10 but there isn't anything compled :(

20:15 defn: Licenser_: what does your :namespaces line look like in project.clj?

20:16 Licenser_: nothing, I don't have that

20:16 worked fine untill now

20:16 defn: mine looks like :namespaces [walton.core, walton.blah]

20:16 you need to explicitly say which namespaces to compile nowadays

20:16 you may also need a (:gen-class)

20:16 depending on if it has a main

20:17 zaphar_laptop: does clojure occasionally have problems when calling a java constructor when the arguments are a super class of the constructors expected argument types?

20:18 I'm getting a class cast exception that seems to be doing that

20:18 Licenser_: :(

20:18 narf

20:18 defn: nARF!

20:18 Licenser_: exactly

20:18 I want to run clicky on my server!

20:21 _mst: you can also do ':namespaces :all' to have it sniff them all out for you

20:21 technomancy: don't do that though.

20:21 unless you have a good reason

20:22 _mst: is laziness a good reason? :)

20:22 technomancy: it just breaks compatibility across clj versions

20:24 defn: Licenser_: I pulled your changes in

20:24 we should be up to date now

20:24 Licenser_: defn: cool!

20:24 ^^

20:30 kylesmith: I'm experiencing an index out of bounds exception, but A. it doesn't give me the index, and B. the stack trace is all in clojure code, not my code. How can I debug this?

20:30 defn: Licenser_: one thing I've been thinking about is... It might be neat to weight users who are contributors to Clojure

20:30 And also order them by most to least recent

20:31 zaphar_laptop: stupid ClassCastException!!!

20:32 defn: It would introduce another layer of parsing, but this could be done on a daily basis. In other words, the logfile's name would tell us how recent something was

20:32 * zaphar_laptop is frustrated

20:33 kylesmith: Other than nth, what clojure functions can throw index out of bounds exceptions (if any)?

20:34 technomancy: Licenser_: the next version will tell you *why* no namespaces were compiled instead of that unhelpful message

20:34 defn: technomancy: that will be very nice

20:34 technomancy: i saw you mentioned something in a tweet about upcoming swank-clojure goodness -- what were you referring to if you dont mind me asking...

20:35 Licenser: defn: hmm not sure, examples can come from everyone and especially code few new users give easy examples

20:35 technomancy: that'd be great :)

20:35 defn: Licenser: yeah I don't know if it makes sense to weight on users, but for new things like cell, it could be handy

20:35 Licenser: true

20:36 defn: there has been a lot of pseudocode bandied about for cells

20:36 however, if it runs in the sandbox, who is to say it is incorrect

20:36 Licenser: heh

20:38 defn: Licenser: now we need to get some fancy syntax hilighting here

20:38 Licenser: heh

20:41 defn: Licenser: how long does it take for you to run (walton "zipmap") at a REPL?

20:41 Licenser: oh you ask questions

20:42 I run it on a slow system for testing, the combine stuff took 1.2 minutes or so

20:42 I got a new toy for you all http://82.210.31.97:8080/

20:43 defn: any what is this? :)

20:43 and*

20:44 Licenser: This is clicki! A clojure code wiki

20:44 you can just add a 'path' and write code, result of this code will be shown

20:44 you can define functions and call functions from other pages

20:44 dnolen: Licenser: I don't see anything at that url

20:44 Raynes: Nor do I.

20:44 Licenser: dnolen: a Hello World text right?

20:45 dnolen: no, nothing

20:45 Licenser: oh I should have restarted the server after stopping it :P

20:45 zaphar_laptop: hrmmm how does clojure handle interfaces in a constructor signature?

20:45 anyone know?

20:46 Raynes: Licenser: If you get the clj-sandbox stuff figured out tonight, query me, or email me if I'm not online.

20:46 Licenser: http://82.210.31.97:8080/info

20:47 Raynes: I'll work on this tomorrow, I looked into it and it is something more seriouse/complicated :(

20:47 Raynes: Licenser: Okay. I'll be around for testing tomorrow anyways, so it works better for us both. :p

20:47 Licenser: cool

20:48 Raynes: Licenser: java.lang.SecurityException: Code did not pass sandbox guidelines: clojure.lang.LazySeq@0 <-- You aren't kidding about complicated! I just executed (println "HAI") on the page you linked. :p

20:49 Licenser: println is forbidden :P

20:49 Raynes: Oh yeah. I forgot that I had whitelisted it for my bot.

20:49 It seems harmless enough.

20:49 ,(println "Hai thar, I'm clojurebawt!")

20:49 clojurebot: Hai thar, I'm clojurebawt!

20:50 Licenser: :)

20:50 Raynes: :)

20:51 Licenser: hrm there seems to be a seriouse issue in the sandbox

20:52 defn: Licenser: how do you edit text on clicki

20:52 oh i see, page/edit

20:52 zaphar_laptop: so apparently clojure doesn't handle method signatures that specify interfaces very well that is somewhat prohibitive

20:52 Licenser: no just /page

20:53 or /page?edit=

20:53 defn: if the page already exists it is /page/edit, though right?

20:53 oh okay

20:53 * zaphar_laptop is now sad

20:53 defn: /page/edit works

20:53 Licenser: but you can do /page/subpage/sub/sub/page ...

20:53 hrm

20:55 technomancy: defn: it's locals-inspecting at breakpoints and debug-repl integration (in swank)

20:55 hugod is the man behind that

20:55 defn: ooo!

20:55 debug-repl!

20:55 * defn is absolutely giddy

20:55 technomancy: the one, the only, the legendary debug-repl

20:56 you can use it in the swank-break branch already, but it's still got a couple issues

20:56 defn: often imitated, but never duplicated

20:56 etc. etc.

21:01 zaphar_ps: hello can you guys hear me in here?

21:01 dnolen: zaphar_ps: yeah. no luck on searching for that issue on the ML? what are you trying to do exactly?

21:02 zaphar_ps: sorry I thought I was having trouble with chat client there

21:02 for a while it looked like I had been banned or something was getting weird messages

21:03 dnolen: I have a class whose constructor takes arguments of a certain interface but I get classCastExceptions when I try to code it

21:04 Plain java it works fine

21:04 dnolen: have you posted your code somehwere?

21:04 zaphar_ps: in clojure it doesn't

21:04 getting ready to

21:04 trying to find links to related javadocs as well

21:11 http://gist.github.com/341873

21:12 there code that dies and an accompanying link to example java code

21:12 it seems like this should work but it doesn't

21:12 which leaves me somewhat stranded for setting up an appengine test datastore environment

21:12 well I can probably dig in a little and use lower level api's but it's annoying still

21:14 dnolen: what happens when you try to print helper-conf#

21:14 ?

21:14 zaphar_ps: ^

21:15 zaphar_ps: dnolen: #<LocalDatastoreServiceTestConfig com.google.appengine.tools.development.testing.LocalDatastoreServiceTestConfig@78361e>

21:16 in the repl instance? shows that it is an instance of the correct interface LocalServiceTestConfig

21:17 I did manage to boil the crash down to two lines of code in the repl that crash the same way as clojure.lang.Reflector.boxArg is doing

21:18 (.cast (class LocalServiceTestConfig) helper_conf#) crashes with the same exception

21:18 I'm guessing because java interfaces can't cast their implementors?

21:19 which is how clojure boxes it's args

21:21 dnolen: any thoughts?

21:22 dnolen: zaphar_ps: sadly I know too little about Java interop. Though I'm assuming what you want can be done. This pattern is similar to event listeners right?

21:22 zaphar_ps: I'm not sure if it is or not

21:23 defn: i wonder how hard is it to call elisp from clojure

21:23 it is*

21:24 dnolen: zapahr_ps: have you looked at proxy?

21:24 zaphar_ps: ^

21:24 slyphon: argh

21:24 zaphar_ps: dnolen: I don't think it will help since both the class and the argument are java

21:25 slyphon: clojure.contrib.sql is gonna make it hard to use two db connections simultaneously

21:25 zaphar_ps: slyphon: bummer, but maybe you have some idea what I'm missing?

21:25 http://gist.github.com/341873

21:26 the crash actually occurs on line 364 of this file in the clojure source code: http://github.com/richhickey/clojure/blob/master/src/jvm/clojure/lang/Reflector.java

21:26 slyphon: hrm

21:27 zaphar_ps: classCastExceptions are ruining my project

21:27 * zaphar_ps cries softly

21:27 slyphon: uh, maybe it'd be easier to do that stuff in a function which your macro calls?

21:27 dnolen: zaphar_ps: why wouldn't proxy work? you can create an instance of class and define interfaces it implements? I'm guess here tho.

21:27 guess -> guessing

21:28 slyphon: i find that pattern sometimes helps to clarify things

21:28 though, i'm really not sure

21:29 zaphar_ps: slyphon: I could try but it's not a syntax error and I can reproduce the crash in a repl without functions or macros

21:29 slyphon: oh, then i have no idea

21:29 zaphar_ps: dnolen: I don't want to reimplement my own datastore config I want to use the one Google already thoughtfully provided

21:30 dnolen: zaphar you don't have reimpliment.

21:30 zaphar_ps: ^

21:30 zaphar_ps: dnolen: I'm not following

21:31 dnolen: I have a hunch. try using proxy that is all :) if it doesn't work it doesn't work. But I'm sure someone has butted up against this very problem before, take it to the Mailing List.

21:32 alexyk: ,(letfn [(endpoints [n m] (let [chunk (int (/ n m))] (loop [r [] prev 0 curr chunk] (if (> curr n) (conj r n) (recur (conj r prev) curr (+ curr chunk))))))] (endpoints 100 3))

21:32 clojurebot: [0 33 66 100]

21:32 alexyk: is there an FP-ier way?

21:32 defn: is there something similar to osascript for linux?

21:33 alexyk: endpoints breaks 0..n into m chunks and shows the starting points of each chunk, trailed by n

21:33 zaphar_ps: dnolen: I'll trye but I'm not sure how to use proxy without implementing the required methods

21:33 dnolen: but you're extending a class which already implemented that Interface right? why do you need to implement them?

21:34 zaphar_ps: or there something going on in the Java code which I don't grok. Is it creating an Interface object or something?

21:37 zaphar_ps: no it creates an instance of a class that implements an interface

21:38 dnolen: I'll humor you and try to recreate :) which jar do I need in my path. I have the latest appengine.

21:38 zaphar_ps: ^

21:39 zaphar_ps: appengine-testing-1.3.1.jar

21:39 dnolen: ^

21:39 dnolen: where is that in the appengine folder?

21:40 i see appengine/lib/testing/appengine-testing.jar

21:42 defn: Is there a java property which states the current OS the JVM is running on

21:42 somnium: ,(let [f (fn [n m] (conj (->> n range (partition (int (/ n m))) (map first) vec) n))] (f 100 3))

21:42 clojurebot: [0 33 66 100]

21:43 defn: nvm, found it

21:43 (System/getProperty "os.name")

21:43 ,(System/getProperty "os.name")

21:43 clojurebot: java.security.AccessControlException: access denied (java.util.PropertyPermission os.name read)

21:44 alexyk: so I have a BDB with a database of N keys. I can split 0..N into ranges and have one read cursor open for each range, thread-safe. Which concurrency primitive is suitable for scanning all cursors in parallel, where each returns a vector of pairs, to conj them all together or suck into a map?

21:44 zaphar_ps: dnolen: hrmmm the interface isn't that complicated so creating a proxy that wraps the actual object might be doable is that what you meant?

21:44 somnium: ,(let [f (fn [n m] (conj (->> n range (take-nth (int (/ n m))) vec) n))] (f 100 3))

21:44 clojurebot: [0 33 66 99 100]

21:44 dnolen: zaphar_ps: yes

21:44 alexyk: somnium: interesting

21:44 zaphar_ps: dnolen: trying now (thanks for the suggestion I only just now understood)

21:45 defn: Anyone on OS X? What is the output of (System/getProperty "os.name") on OSX?

21:46 alexyk: defn: "Mac OS X"

21:46 defn: ty

21:46 alexyk: np

21:54 zaphar_ps: dnolen: proxy exhibits same issue :-(

21:55 looks like it's mailing list time

21:55 dnolen: zaphar_ps: what happened?

21:55 zaphar_ps: same classCastException

21:56 dnolen: can you gist your proxy code?

21:56 zaphar_ps: dnolen: sure

21:56 one sec

21:57 http://gist.github.com/341873

21:57 same gist

21:58 dnolen: I think the proxy should specify [class-to-instantiate interface]

21:58 zaphar_ps: dnolen: how so?

21:58 dnolen: (proxy [LocalDatastoreServiceTestConfig LocalServiceTestConfig] [])

21:58 zaphar_ps: dnolen: I'll give that a try

22:00 dnolen: ahh no go the datastore config class is final can't inherit from it

22:00 won't even compile

22:00 dnolen: zaphar_ps: k out of ideas :)

22:11 underdev: anyone get labrepl working under emacs?

22:26 lancepantz: anyone mind taking a look at http://www.pastie.org/884058 for me?

22:26 very basic, filter and contains? aren't behaving as i understand them

22:28 Raynes: http://github.com/richhickey/clojure/commit/29389970bcd41998359681d9a4a20ee391a1e07c

22:28 Life is good.

22:28 arohner: lancepantz: contains works on sets and maps

22:29 lancepantz: read it as 'has-key?' rather than contains

22:29 lancepantz: ah

22:30 arohner: lancepantz: make ignore-keys a set rather than a list, and it should work

22:33 lancepantz: got it, thanks arohner

22:33 arohner: lancepantz: np

22:39 slyphon: oof

22:40 No matching method found: println for class swank.util.io.proxy$java.io.StringWriter$0

22:40 uhh, wtf?

22:43 oh, duh

22:43 * slyphon mutters

22:56 defn: hmmm, how to do the following:

22:57 alexyk: Raynes: care to give an example for that commit usage?

22:57 defn: depending on the os I'd like to use function a, or function b -- I have a fn which has a (cond) statement. Should I define both functions inside this cond function?

22:57 Raynes: alexyk: Ask psykotic.

22:57 alexyk: psykotic: ^^ ?

22:57 Raynes: We were discussing this over in #clojure-casual

22:58 psykotic: alexyk: i just sent an email about it (with some suggestions for extending the current :keys binder), with a few usage examples

22:58 to the list, i mean

22:58 alexyk: kk

22:58 cool

22:58 defn: (defn which-os? [] (let [this-os (System/getProperty "os.name")] (cond (= this-os "Linux") (return a fn here?) (= this-os "Mac OS X") (same here??))))

22:59 slyphon: you can use recur without loop, right?

23:03 psykotic: slyphon: yes

23:03 zaphar_ps: defn: that seems acceptable

23:03 slyphon: ok, thought so

23:03 defn: zaphar_ps: thanks for the feedback

23:04 zaphar_ps: defn: I might name which-os? differenly though

23:04 defn: zaphar_ps: yeah i found a way to make it make more sense

23:05 (defn- open-in-browser-mac []) (defn- open-in-browser-linux []) (defn open-in-browser [] (cond...))

23:13 hmmm. am i adding this namespace wrong?

23:13 i have src/project/core.clj, and src/project/other.clj -- I would just do (ns project.core (:use project.other)) right?

23:21 maxhodak: what happens when you export a method using gen-class with a dash in the name?

23:21 does it become an underscore?

23:26 technomancy: is #"^\s*(;.*)?$" a good regex for matching lines of Clojure that don't contain code?

23:38 Raynes: technomancy: That's a good regex for making your eyes bleed late at night.

23:39 mabes: I'm trying to use use defprotocol and deftype.. For some reason I am getting "Can't define method not in interfaces: function_name" for the second function/method I add. It worked fine for the first one I added...

23:39 Does that error message sound familiar to anyone?

23:39 My code and backtrace are here: http://gist.github.com/341958

23:41 tomoj: mabes: it sounds like the method you are trying to define is not in the interface you are implementing

23:41 Raynes: It is.

23:41 tomoj: hmm, but I see it there in the protol

23:41 er, protocol

23:42 Raynes: I'm stumped.

23:42 tomoj: is this a toy? sounds interesting :)

23:42 Raynes: I wrote something similar a while back.

23:42 mabes: Yeah, the name of the project says it all :) I'm trying to implement a paper I read on it

23:44 (this is the paper: http://bit.ly/bbxMRD)

23:47 tomoj: weird, I just played klondike for the first time about an hour ago

23:47 mabes: heh, I actually learned it recently for this since playing it before never appealed to me

23:48 Raynes: tomoj: For the first time?

23:48 tomoj: oh, wait..

23:48 Raynes: If I ever hear you call me a youngster...

23:48 tomoj: no, I had played it before

23:48 much earlier, of course, naturally

23:49 my mistake came from having just installed ubuntu, and while waiting for the install to finish I played the solitaire included on the livecd (called "klondike"), and the default settings were different than actual klondike rules

23:49 I could turn one card at a time into waste but only had a limited number of redeals

23:49 so I thought "klondike" was some easier variant

23:49 Raynes: Ah.

23:49 tomoj: which would, I think, be more amenable to mathematical inquiry, actually

23:52 mabes: there are a ton of variants.. what I found that was interesting is that for klondike you are actually allowed to see all the cards in the main deck. I always thought you could only see the top one or the top three at most.

23:53 Raynes: You guys suck. Tetris is the only game that is reasonable to play while you're waiting on something to finish.

23:54 mabes: heh, I would probably agree

23:55 ttmrichter: I thought drinking games were best while waiting for compiles.

23:58 technomancy: tetris you can play without leaving Emacs, so it has my vote

23:59 psykotic: Raynes: you suck. it's all about torus trooper.

23:59 Raynes: :O!

Logging service provided by n01se.net