#clojure log - Feb 20 2009

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

0:02 jhawk28: later, bedtime

0:20 technomancy: clearing up terminology: maps, sets, and vectors are all collections but not sequences... they allow you to *make* sequences from them, but they are not actually sequences, right?

0:21 hiredman: correct

0:22 * technomancy was very confused about that for quite some time

0:22 hiredman: now you know, and knowing is something something

0:41 slashus2: When playing with sorted-map, if you do (rseq (sorted-map :a 5 :b 6)) It is no longer just a sorted-map, it is a sequence. What is the idiomatic way to reverse a sorted-map and keep it a sorted-map after the reverse?

0:44 xitam: i guess you use sorted-map-by to create a new map with an opposite comparator

0:44 hiredman: what xitam said

0:45 xitam: reversing a tree is sort of an odd concept generally

0:46 slashus2: sorted-map is ordered by the order that they were added right?

0:47 By using an opposite comparator what would you compare?

0:47 xitam: they're ordered by the values of the keys, either using the default or a user-supplied comparator

0:47 slashus2: oooh

0:48 That makes sense.

9:07 AWizzArd: rhickey: is it possible to make (comment ..) a special operator, with some reader magic, which eliminates it completely from the resulting sources? Currently it can crashes for things like (comment ##) and it evals to nil. So it should not be the last form in a defn/defmacro.

9:08 or maybe a reader macro instead of comment, such as #-(this does not exist)

9:08 jdz_: #_

9:10 AWizzArd: jdz: how does it end a comment?

9:11 I can't find it in http://clojure.org/reader

9:11 jdz: it does not. it is a reader macro similar to what you wanted with #-

9:11 it is fairly recent addition

9:11 AWizzArd: but what is different compared to ; then?

9:11 ah ok, it is #_(hallo) ?

9:11 jdz: it cuts out the next "form"

9:12 AWizzArd: good, gotcha

9:12 thx

9:14 although #_(') ==> Exception

9:14 It's still very good though

9:14 jdz: it's not a comment

9:14 AWizzArd: right

9:15 ,(list 1 2 #_3)

9:15 clojurebot: (1 2)

9:15 AWizzArd: ,(list 1 2 (comment 3))

9:15 clojurebot: (1 2 nil)

9:15 AWizzArd: ,(list 1 2 #_(#))

9:15 clojurebot: No dispatch macro for: )

9:15 AWizzArd: ,(list 1 2 #_("#"))

9:15 clojurebot: (1 2)

9:15 AWizzArd: I can do #_"..." for comments then

9:15 jdz: clojure reads the form after #_ and throws it away. but it still must be a valid form, otherwise clojure wouldn't know what exactly to throw away

9:16 AWizzArd: well, it does not have to be a valid form, but at least it should not contain other reader macros

9:16 jdz: no, it *has* to be a valid form

9:17 AWizzArd: ,(list 1 2 #_(+++++))

9:17 clojurebot: (1 2)

9:17 AWizzArd: works

9:17 although (+++++) is not a form

9:17 jdz: it's a valid form

9:17 it's a call to function +++++

9:17 AWizzArd: According to Kent Pitman it is not a form.

9:17 jdz: we discussed this already

9:17 AWizzArd: yup

9:17 jdz: and that's why i said "form"

9:17 (see, air quotes!)

9:18 AWizzArd: anyway, the #_ is what I can use very well

9:18 thx J?nis

9:18 jdz: using it for comments is wrong, if you want my opinion

9:24 gnuvince: What's #_?

9:32 jdz: it's magic. it makes things disappear.

9:41 AWizzArd: gnuvince: allows you to remove inner pieces of code

9:41 without really deleting them

9:44 gnuvince: cute

9:45 Didn't know about that

9:49 cooldude127: Bracki: you here?

9:51 lisppaste8: cooldude127 annotated #75813 "much better find-path" at http://paste.lisp.org/display/75813#4

9:51 jbondeson: oy. this swank-clojure stuff is going to be the death of me.

9:51 cooldude127: slime is a scary thing sometimes

9:51 jwinter: jbondeson: what are you working on?

9:52 updating it to lazy?

9:52 jbondeson: yeah

9:52 got rid of the first classcastexception

9:52 now i have stack overflows and another classcastexception

9:52 cooldude127: jbondeson: it's progress :)

9:52 oh maybe not

9:52 jwinter: cool, is there a fork on github?

9:52 jbondeson: well, it's in other places, so that's nice.

9:53 jwinter: haven't pushed anything yet because i have a terrible hack to get around the first exception

9:53 for some reason the lisp forms that are moving around are causing issues

9:54 (quote ...) stuff isn't getting "unquoted" as it were when eval'ed

9:54 so the receiving functions are trying to consume a "quote" as a value

9:56 this totally asyc stuff is tough to debug, doubly so when you have to damn near nuke emacs to get out of some of these situations.

9:59 ,(next '(#'swank.commands.contrib/swank-require (quote (:swank-package-fu :swank-fuzzy :swank-fancy-inspector :swank-arglists))))

9:59 clojurebot: ((quote (:swank-package-fu :swank-fuzzy :swank-fancy-inspector :swank-arglists)))

9:59 jbondeson: that's the other pain

10:16 clojurebot: svn rev 1297; fixed lazy-seq constants

10:45 cooldude127: Bracki: ping

10:48 tashafa: good morning y'all

10:48 cooldude127: good morning to you

11:09 cemerick: I'll bet there's a good reason for this, but why are primitive values print-dup'ed as boxed values? e.g. (binding [*print-dup* true] (pr-str (float 5))) => "#=(java.lang.Float. \"5.0\")"

11:11 Chouser: only boxed things can be passed around anyway. 'read' can't return a primitive.

11:11 danlarkin: I think because of the way the reader works with java class literals or whatever, there's no way to "read" a primitive

11:11 Chouser: yeah, what he said.

11:11 cemerick: ah, right

11:11 Chouser: :-)

11:12 * cemerick 's forehead hits the keyboard :O

11:15 Chouser: ok, if that's solved, I've got one...

11:15 why can't I build a custom Fn class using proxy that implements the meta() method?

11:16 hm. AFn seems to kill it.

11:16 danlarkin: It's been a while since I looked at proxy, but it only lets you define methods from the interfaces you use, right?

11:16 hiredman: man, I wish Chouser was, I am sure he could answer that question...

11:17 was here

11:17 Chouser: ,(proxy [clojure.lang.IFn] [] (invoke [] :hi) (meta [] {:some :meta}))

11:17 clojurebot: java.security.AccessControlException: access denied (java.lang.RuntimePermission accessDeclaredMembers)

11:17 Chouser: whoa

11:17 cemerick: danlarkin: that was my impression

11:17 Chouser: clojurebot can't do proxy. :-(

11:18 danlarkin: so if IFn doesn't define meta() then you can't do it without adding another interface

11:18 Chouser: yeah, but I did add it.

11:19 ok, for the record: (import '(clojure.lang IFn AFn IMeta))

11:19 no, this works: ^(proxy [IFn IMeta] [] (invoke [] :hi) (meta [] {:some :meta}))

11:19 but this does not: ^(proxy [AFn IMeta] [] (invoke [] :hi) (meta [] {:some :meta}))

11:20 you can call either proxy with no args and get :hi, but only the first returns the map as metadata

11:20 the second returns nil

11:21 and looking at AFn.java, I don't see why

11:22 cemerick: Chouser: proxy might be adding its own meta impl?

11:23 Chouser: but extending IFn instead, I'd have to do more work to get 'apply' to work.

11:23 cemerick: but why only in with AFn and not IFn?

11:23 cemerick: yeah, I dunno -- just tossing darts with that one

11:24 * Chouser nods

11:24 cemerick: whoo, the protocol for deserializing print-dup'ed collections is wonderful (CollName/create items....).

11:25 Chouser: cemerick: just make sure the stream you're reading is trustworthy

11:25 cemerick: and it just falls back to looking for 'create' in the com.foo.bar.CollName namespace, so I don't have to add a real static method anywhere...

11:25 Chouser: ah, clever.

11:26 cemerick: Chouser: Yeah. Not yet a concern on that front. We don't yet consume any serialized data from the outside world.

11:26 Chouser: ok, good.

11:26 cemerick: I'm hoping to mostly depend upon the jvm's sandboxing once we get to that point.

11:26 s/once/if

11:26 Chouser: ,#=(System/exit 42)

11:26 clojurebot: System

11:26 Chouser: ,#=(java.lang.System/exit 42)

11:26 cemerick: oh, that's just mean! :-)

11:26 clojurebot: access denied (java.lang.RuntimePermission exitVM.42)

11:27 Chouser: clojurebot reads in a sandbox now

11:27 since last time I tried that. :-)

11:27 cemerick: eh, process death isn't a big problem. snooping is, though....

11:28 ,(java.net.Socket. "apple.com" 80)

11:28 clojurebot: java.security.AccessControlException: access denied (java.net.SocketPermission apple.com resolve)

11:28 cemerick: ,(java.net.Socket. "17.149.160.49" 80)

11:28 clojurebot: java.security.AccessControlException: access denied (java.net.SocketPermission 17.149.160.49:80 connect,resolve)

11:28 cemerick: good enough for me :-)

11:29 we'll just put a big ol' klaxon around any ACE's

11:33 Chouser: anybody have a hint for how I can figure this out?

11:33 AFn doesn't even implement meta()

11:33 Maybe I don't know Java well enough, but should the derived class's implementation always win?

11:34 my proxy's meta method is apparently not even called.

11:36 * Chouser tries jdb, with trepidation

11:39 danlarkin: I'm stumped. the AFn proxy _has_ a meta method

11:39 but it returns nil

11:41 hiredman: AFn also has a constructor that calls super(meta) and Object doesn't have that, and IFn is an interface, so no contructor there

11:41 Chouser: AFn extends Obj

11:42 hiredman: ah

11:42 not Object

11:42 :/

11:42 Chouser: suprise!

11:42 hiredman: ah

11:43 Obj's meta is final

11:43 Chouser: oh!

11:43 that would do it. Thanks!

11:45 and I can't seem to get to the _meta field. No declaration means it's private?

11:45 hiredman: it means it is scoped to the package

11:46 so only other stuff in clojure.lang can see it

11:46 Chouser: huh. ok.

11:46 hiredman: (I think)

11:46 danlarkin: functions will never have metadata! muhahaha

11:48 * shoover` shudders at danlarkin's evilness

11:49 Chouser: shoover`: hey, thanks again for doing that talk. Getting up in front of a roomful of .Net'ers and telling them they should use Clojure takes guts.

11:50 shoover`: Chouser: haha, you're welcome! They were there to learn!

11:50 hiredman: video of it didn't happen

11:50 or

11:51 Chouser: hiredman: it didn't happen

11:51 shoover`: you have clojure.blip.tv, you don't need me

11:52 I borrowed a lot from Rich's talk for Java programmers

11:53 WizardofWestmarc: the downside to clojure.blip.tv is the current talks are all old

11:56 shoover`: WizardofWestmarc: true, some of the APIs have changed, but the conceptual stuff is good enough that I still point people there. maybe not the sequence one any more

11:57 Chouser: but sequences rock. that's what really hooked me at first.

11:58 rhickey: Chouser: ^(proxy [AFn] [{:some :meta}])

11:59 WizardofWestmarc: true on the conceptual stuff. The java and lisp programmer talks (depending on who you're pointing to them) were both very useful.

11:59 Chouser: rhickey: ah!

12:02 rhickey: Chouser: the problem with meta on fns is not the initial meta, it's with-meta. I can't rely on clone-ability of derivees

12:03 Chouser: which is why AFn's with-meta does nothing.

12:03 but immutable metadata works fine for me in this case.

12:04 rhickey: Chouser: I think it throws

12:04 Chouser: right again

12:06 rhickey: shoover`: talk went well?

12:12 gnuvince: rhickey: do you know if your sessions at QCon are going to be video-taped?

12:12 rhickey: I think so

12:14 gnuvince: That'd be cool

12:57 nsinghal: Is there any function which gives me the first not null value: such as

12:57 (first-valid (latest) (last-active) (first-visible) (first-in list))

12:57 Currently i am doing if else logic to get my object

12:59 lisppaste8: cemerick pasted "puzzling NPE" at http://paste.lisp.org/display/75862

12:59 WizardofWestmarc: (first (filter identity list)

12:59 with your var in list's's place

13:00 cemerick: rhickey: do you have any idea about the above paste? The classname in question is a gen-class emitted by my latest genbean macro.

13:00 nsinghal: WizardofWestmarc: thx

13:00 cemerick: it looks like it never gets to the point of invoking the AOT-compiled constructor

13:00 WizardofWestmarc: nsinghal: no problem

13:00 cemerick: FWIW, (foo.bar.Classname 5 5) (e.g. with the same number of args of the right type) succeeds without a problem.

13:02 gnuvince: ,(some identity [nil nil 3 nil])

13:02 clojurebot: 3

13:03 WizardofWestmarc: huh I missed some

13:10 shoover`: rhickey: yes. I used your traditional/lisp evaluation model comparison and we broke some ground with macros. No time to show them concurrency, unfortunately

13:11 some light bulbs went off almost as soon as I drew the models

13:11 hiredman: ,(or nil nil nil 3 nil nil nil nil)

13:11 clojurebot: 3

13:11 hiredman: :D

13:14 shoover`: Chouser: yes, sequences rock, it just seems that of all the screencasts that one may be more out of date at the moment

13:16 rhickey: turns out 90 minutes is not enough time to explain all of Clojure :)

13:16 gnuvince: shoover`: did you give a talk?

13:16 technomancy: shoover`: man, don't tell me that.

13:16 * technomancy is working on a screencast to teach clojure

13:17 gnuvince: technomancy: 60 minutes?

13:17 shoover`: technomancy: one-way communication can help you there

13:17 technomancy: gnuvince: most of his have been 60 minutes, but I hope I can convince him to let this one go longer

13:17 shoover`: you mean not getting interrupted by questions? =)

13:17 slava: how do I load a source file?

13:18 technomancy: slava: generally "use" is what you want

13:18 ,(doc use)

13:18 clojurebot: "([& args]); Like 'require, but also refers to each lib's namespace using clojure.core/refer. Use :use in the ns macro in preference to calling this directly. 'use accepts additional options in libspecs: :exclude, :only, :rename. The arguments and semantics for :exclude, :only, and :rename are the same as those documented for clojure.core/refer."

13:18 hiredman: well, there is also load-file

13:18 ,(doc load-file)

13:18 clojurebot: "([name]); Sequentially read and evaluate the set of forms contained in the file."

13:18 gnuvince: slava: if it's the mandelbrot thing, (load-file "/path/to/mandelbrot.clj")

13:18 shoover`: technomancy: yep. in an interactive session people consume at different speeds. also, you get to edit the pauses and throat clearings :)

13:19 technomancy: load-file is independent of classpath, right?

13:19 gnuvince: technomancy: yes.

13:19 technomancy: shoover`: yeah, the advantage of a screencast is people can pause and go back over stuff that they didn't get the first time around

13:19 can't do that in real life without time travel

13:19 shoover`: gnuvince: yes, for the indyalt.net group

13:20 slava: gnuvince: load-file is what I was after, thanks

13:20 gnuvince: shoover`: do you have slides of your talk? I'd also love to hear your experience talking to other programmers about Clojure.

13:20 slava: happy to help.

13:20 shoover`: gnuvince: if by slides you mean an org-mode file with links to code snippets and REPL history, yes

13:20 gnuvince: shoover`: :)

13:20 technomancy: does load-file work with paths relative to the current file or what?

13:21 gnuvince: technomancy: yes

13:21 technomancy: oh, that's handy

13:21 gnuvince: technomancy: (load-file "../../foo/bar/baz.clj") should work

13:21 technomancy: no need to worry about the classpath then.

13:22 shoover`: gnuvince: my textual materials will go here this weekend or early next week: http://indyalt.net/cms/meeting/february-2009/clojure

13:23 it's a fun challenege talking to other programmers. Some have never seen anything outside of C#, some started with Fortran and have seen it all. They all have different expectations and questions based on that experience

13:24 This group came with an open mind, so we had awesome discussions comparing to other languages and in the context of different businesses

13:25 technomancy: and now it actually looks like it might be viable on .net

13:25 shoover`: I can't wait

13:25 also, I got to meet Chouser. that was not challenging

13:26 gnuvince: shoover`: very cool

13:27 * danlarkin worries about losing the benefit of java libs if the .net port gets enough traction

13:27 slava: gnuvince: my dynamically-typed version that uses complex number objects in factor runs in 6.8 seconds. the clojure code runs in 2.4 seconds

13:27 gnuvince: What I like about Clojure is that you don't need to be "defensive" when people start talking about current IT investments and things like that.

13:28 technomancy: danlarkin: wouldn't be too hard to have a wrapper that talks to various RT-specific backends for certain kinds of libs.

13:28 gnuvince: slava: pretty impressive. Are you gonna try with just doubles and ints like the other programs?

13:29 shoover`: danlarkin: I will accept that code that uses libs might not be portable across VMs and just be happy that I can use Clojure's lispness, data structures, and concurrency on either VM that I happen to be on at the time

13:30 slava: gnuvince: that kind of defeats the point, you may as well use fortran or C if you'll be declaring machine types explicitly

13:31 danlarkin: well right now we have this great ecosystem of easy interpolation with any java lib out there. But if the .net port becomes full-featured and active I think there's going to be temptation to only write pure-clojure (or clojure that only interfaces with "native" code in some yet-to-be-defined "safe" way) in the interest of compatibility

13:32 slava: gnuvince: if i remove type declarations from the clojure version it runs in 89 seconds :)

13:33 gnuvince: adding a single type coercion to the factor code brings it down to 4.5 seconds. that's about as fast as it will get without low level tricks

13:35 Chouser: danlarkin: I wouldn't worry about it. The existence of ClojureScript hasn't hurt Clojure much. :-D

13:35 danlarkin: I don't want to see, "oh sorry, this is clojure.net code only/java clojure code only" because that sucks... splinters the amount of accessible code... but I also don't want to see "oh I want this code to be cross platform so I won't use any existing non-clojure libs" because that's reinventing the wheel, and what's the point of java/.net interop if we can't use it and expect others to be able to use it

13:35 hahah maybe I'm just a miser

13:37 slava: are there any plans to write an optimizing compiler for clojure?

13:38 Chouser: but seriously, I think that if someone wants to try to port clojure to whatever VM, there's no real way to stop them. All you can do is deem the port "unofficial", and what does that buy you?

13:38 slava: hotspot is an optimizing compiler for clojure. ;-)

13:39 slava: Chouser: well, clojure doesn't get very good numerics performance it seems

13:39 Chouser: on boxed numbers?

13:40 slava: on dynamically-typed code

13:40 whether or not you do boxing is an implementation detail

13:41 Chouser: Near the top of Rich's wish-list for the JVM is that it support tagged numbers. In my understanding, that would help a great deal.

13:41 slava: that wouldn't help here

13:41 you can't fit a float into a tagged pointer

13:42 what you want is type inference of some sort

13:42 Chouser: doesn't sound very dynamic

13:42 technomancy: danlarkin: it may be enlightening to look at how Ruby has handled the situation

13:42 slava: the user shouldn't have to declare types

13:42 shoover`: danlarkin: or look at it another way... if I can only use .NET I will never contribute any useful Clojure libs you can use. If I'm on ClojureCLR, there's a good chance I'll interface to .NET libraries *and* break out some pure Clojure libs

13:42 slava: the compiler should try to infer types where possible, and do runtime dispatch on the remainder

13:42 rhickey: slava: they don't have to

13:42 technomancy: there's definitely breakage between the JVM and C versions, but the most popular libraries have been ported.

13:42 slava: instead of boxing and dispatching for everything

13:44 has anyone written a version of mandelbrot for clojure that defines a complex data type with complex+ complex* etc. functions?

13:44 leafw: slava: I find that declaring types wherever I care for performance is rather simple.

13:44 slava: that would be a good to help guide future compiler improvements

13:45 leafw: i'm interested in writing high-level code. sometimes I can't declare types because the code is actually polymorphic

13:46 but you might still want the compiler to specialize a function at different call sites, like C++ templates do

13:46 danlarkin: technomancy: but it's different for clojure... take file access for instance. In ruby there's probably a file IO library or whatever, so that can be ported to the JVM so the API is identical. But in clojure the file library is java.io and that isn't going to be ported to .net -- they'll use whatever the file library there is

13:46 slava: that's the trick to making dynamic code fast, you clone it and propagate types

13:47 leafw: slava: once I wrote a macro to decorate my code with specific types I was interested in -- had to do with processing images made of short[], float[] and double[].

13:47 technomancy: danlarkin: right; obviously some wrappers are needed

13:47 leafw: I just had to pass that as an arg.

13:47 rhickey: slava: only if you want to spend your time on such things

13:48 Raynes: rhickey: Hi :)

13:49 rhickey: hi

13:49 danlarkin: technomancy: but should every class in the standard library be wrapped? and what about cases where functionality is different. I donno... like rich said, the JVM isn't an implementation detail, it is part of the language. ClojureCLR won't be a port, it'll be an entirely different language with strikingly similar syntax and semantics

13:49 slava: rhickey: that's fine

13:50 technomancy: danlarkin: I suspect stuff will get wrapped as people need it; that's usually how these things happen. =)

13:50 personally I'd prefer to use a wrapper for the standard lib stuff, though it's not onerous the way it currently is

13:50 rhickey: danlarkin: I think it is more subtle than that - Clojure was designed to be hosted. From the start, it abstracted away JVM/CLR. There will be two levels of libs, those that encapsulate the host and those that expsoe/embrace it

13:51 technomancy: yeah, as long as you're explicit upfront about which kind of lib it is, it shouldn't be a problem.

13:51 Chouser: I don't expect it will be much work to make contrib portable, and the set of wrappers it provides for itself to use will be a good starting point for other libs.

13:51 technomancy: any more than "people are writing code in a language I'm not using" is a problem. =)

13:51 Chouser: most apps probably won't have to be portable at all

13:52 rhickey: danlarkin: I don't see any point in trying to do portable UI for instance, but if you look at libs using Swing/SWT/QT they aren't portable either at that level

13:53 danlarkin: but file access would be wrapped I assume?

13:53 rhickey: but things like most of contrib, datalog etc, easily portable because written on portable core

13:53 danlarkin: I really don't think people will need to write portable applications

13:54 danlarkin: rhickey: but don't you think they'll want to if clojureCLR is popular enough?

13:54 Chouser: line-seq would have to work on both, or the port of Clojure's not complete, but are there libs that open files for themselves?

13:54 rhickey: but if you've got a job to do for a .Net client, you can do it in Clojure

13:55 danlarkin: no, I see portability ending at the library level, apps working with frameworks inevitably marry them

13:55 leafw: danlarkin: so clj will cross that bridge eventually. Writing for nonexisting needs never lead anywhere in my experience.

13:56 technomancy: applications that need to be portable seem like a big deal, but in practice they're definitely in the minority

13:56 they're mostly just sample apps that people install to play around with and learn from. =)

13:57 rhickey: I was originally worried about bifurcation, now that I see the kinds of things people are doing, I'm less concerned

13:57 leafw: technomancy: you have just dismissed about the most widely used apps out there (firefox comes to mind)

13:57 technomancy: leafw: the most widely used apps are *definitely* in the minority

13:58 danlarkin: Hm, well I guess we'll see what happens, hopefully y'all are right and my concerns are unwarranted :)

13:58 Chouser: and it's odd sort of portability anyway -- not so much about the customer's physical or OS platform as the development company's investment in a virtual platform.

13:58 technomancy: leafw: but C is a completely different beast. no question about it.

13:58 rhickey: Chouser: exactly

13:59 technomancy: leafw: besides, firefox is a platform, not an app. =)

13:59 WizardofWestmarc: yeah remember, portability across OSes already exists in clojure as is.

13:59 rhickey: all the fib micro-benchmarks will be portable :)

13:59 slava: WizardofWestmarc: the OSes that J2SE runs on, that is :)

13:59 technomancy: rhickey: so people doing uninformed "speed comparison" blog posts will have access to everything they need; that's good to know!

13:59 rsynnott: slava: that'd be basically all of them, surely?

13:59 WizardofWestmarc: what runs .NET and not java?

13:59 leafw: technomancy: I know, you are right

14:00 rsynnott: (excluding the smaller phones and things from more than two decades ago)

14:00 slava: rsynnott: iphone, windows ce and *bsd being the notable exceptions

14:00 rsynnott: what, there's no j2se compatible java impl for bsd?

14:00 are you sure?

14:00 leafw: slava: *bsd run java fine, thanks.

14:00 slava: well, you have to compile openjdk from source, or something

14:00 there's no official java 6

14:01 hiredman: uh

14:01 leafw: that never stopped anyone

14:01 hiredman: yes there is

14:01 rsynnott: no sun-issued one, perhaps

14:01 but I'm sure there are binaries

14:01 hiredman: clojurebot is running on freebsd jdk1.6

14:01 rsynnott: anyway, .NET certainly does not run on bsd :)

14:01 (the mono thing might, I suppose)

14:02 leafw: slava: http://www.freebsd.org/java/

14:02 WizardofWestmarc: Mono's what, .NET 2 compliant?

14:02 slava: looks like there aren't any binaries

14:02 hiredman: slava: there are

14:02 slava: and this is freebsd only, not netbsd or openbsd

14:03 hiredman: well, speaking for freebsd users, open and net kind of suck

14:04 slava: well, that's just your opinion, other people like using them

14:04 hiredman: *couhg*

14:04 slava: and there's no decent j2se on those platforms

14:05 and what about iphone :)

14:05 hiredman: well, in the future when saying "*bsd" inthe future just say "*bsd, except FreeBSD which runs great and cooks my emergency bacon"

14:05 technomancy: the iphone is hopelessly locked-down.

14:05 rsynnott: slava: there's certainly no .NET for iphone

14:05 leafw: guys: this is not about clojure anymore.

14:05 Chouser: but opera runs clojurescript just fine.

14:05 * Chouser ducks

14:06 slava: rsynnott: mono runs on the iphone

14:06 rsynnott: (apple have shown some signs that they may allow Sun and Adobe to put Java and Flash on it)

14:06 rhickey: People will branch at JVM/.Net at the point they specifically want JVM/.Net, i.e. to satisfy client requirement or leverage existing knowledge/investment in a specific platform. I would recommend people without a specific investment in either use Java, which is why I chose that when I went to one

14:06 rsynnott: slava: oh, jailbroken

14:06 hiredman: ~google mono on the iphone

14:06 clojurebot: First, out of 232000 results is:

14:06 Mono on the iPhone - Miguel de Icaza

14:06 http://tirania.org/blog/archive/2008/Mar-10.html

14:06 slava: rsynnott: nope

14:06 mono can generate binaries so that gets around the apple store restrictions

14:07 rsynnott: "No iPhone APIs have been exposed, so you get the very basic foundation."

14:07 ah, I see

14:11 _metaperl_: Clojure, the Lisp that makes the JVM dynamic.... and functional... and concurrent!

14:11 fix that topic :)

14:12 technomancy: _metaperl_: don't forget the CLR too.

14:12 leafw: _metaperl_: JVM is already concurrent.

14:12 _metaperl_: CLR?

14:12 what does that stand for?

14:13 WizardofWestmarc: Common Language Runtime, aka the .NET runtime

14:13 slava: although if you want your code to run fast, you need type declarations and its not dynamic anymore :)

14:14 rsynnott: slava: well, you can do so selectively

14:14 as people have been doing in lisp for some decades

14:14 with the result that you get most of the benefit of both worlds

14:14 rhickey: slava: you can save those declarations for inner loops, leaving the vast majority dynamic

14:15 slava: not every program has a spiked performance profile

14:15 think about a web browser for example, every part has to be fast

14:15 rhickey: slava: not so at all

14:15 rsynnott: slava: really? Tell that to Firefox :P

14:15 but seriously, in practice most of the glue code won't need type declarations there

14:16 slava: rsynnott: I'd like to see how well firefox would perform were it written in a JVM language...

14:16 technomancy: leafw: actually, thinking about Firefox, it's a great example of non-portable code. since FF is an application written in XUL and JS (spidermonkey), but it would never run if you tried to use it on KJS or opera's JS engine.

14:16 slava: rsynnott: the issue is that glue code is uninteresting and easy to write anyway. you want the hairy algorithmic stuff to be high level and maintainable, and not overly inflexible from hand-coded optimization

14:16 technomancy: the fact that the runtime is portable is enough

14:18 rsynnott: slava: I would disagree

14:18 the glue code tends to be where things break

14:19 modules which do one specific thing break less often, and are far easier to test

14:19 slava: but low-level code is harder to read and write

14:19 I like using abstractions to make code simpler to understand

14:19 so its pretty silly if abstractions run slower than hand-optimized code

14:19 rhickey: slava: a lot of people will be running on multicores soon, where some compiler micro-optimization will be dwarfed by the ability to split up the job - i.e. optimization at the level you are suggesting is quickly going to become uninteresting compared with auto-parallelization

14:20 slava: rhickey: none of this is mutually-exclusive

14:20 rhickey: true

14:20 but it all takes time

14:20 rsynnott: slava: what would suggest, anyway? Just using static typing?

14:20 rhickey: I am not going to spend my life on micro-optimization - life's too short

14:20 slava: if program A is 10x slower than program B, but A scales across cores, well you need 10 cores at least

14:20 technomancy: I don't think anyone's saying they don't want inference; it's just not a priority now.

14:20 rsynnott: you can use static typing in clojure/common lisp/erlang/whatever when you need it, anyway

14:21 slava: rsynnott: not at all, I'm talking about the opposite: making the implementation run dynamic code faster

14:21 technomancy: well, people should say that, instead of trying to justify the current state of affairs

14:21 just say that its planned and move on :)

14:22 rhickey: slava: not planned- volunteers welcome :)

14:22 technomancy: slava: yeah, maybe if we get you worked up about it you would submit a patch. =)

14:23 danlarkin: is this where we all say in unison, "hindley-milner"?

14:23 hiredman: slava: I don't think anyone is justifying anything except their own use of time.

14:23 slava: well, whenever I read clojure advocacy I see claims about the high performance of the JVM. but if you're not going to exploit that, its a bit disingeneous to say that clojure is a lot faster than scripting languages on one hand, but then explain that this is only the case for low-level Java-like code on the other hand

14:23 rhickey: because some of this will fall out of enhancements to the HotSpots - they can get rid of ephemeral objects, automatically generate multiple paths etc

14:24 slava: only numerics are slower than Java, Clojure _is_ a lot faster then most scripting languages, and with type hints, as fast as Java on numeric inner loops - that's a lot of range today, even if not all of it is automatic

14:25 slava: so the best approach then is to just be honest and focus on Clojure's true strengths: clean semantics, concurrency, JVM integration, etc

14:25 performance doesn't soundl ike something you guys care about, which is fine

14:25 rhickey: slava: oh, please - I'm happy to use type declaration to get the fastest perf - that doesn't mean I don'tcare

14:26 slava: then you can say that clojure offers performance comaparable to scripting languages, but if you use a Java-like subset, then you can get good performance. that's similar to the situation in CL and many people are happy with that

14:26 rhickey: People using C++ have to do much more work

14:27 slava: in CL, you can use declarations and disable safety and you're basically writing C

14:27 and SBCL's codegen generates pretty decent code for that

14:27 but there's very little compile-time analysis of dynamic code to remove unused generality automatically

14:27 rhickey: slava: thta's still not true, its 5x faster than Python with no declarations

14:27 slava: and that's what makes high-level languages interesting, IMHO

14:28 rhickey: but I don't need to say anything - people are trying it on their problems and are satisfied

14:28 slava: well, not you, specifically, just bloggers and so on

14:28 bitbckt: rhickey: Quite.

14:28 * Chouser decides against repeating his sentiments on Clojure's speed.

14:28 * technomancy is happy with 10x ruby speed for sure

14:29 WizardofWestmarc: technomancy: to be fair, 10x faster then dirt isn't really fast <_<

14:29 bitbckt: Ouch.

14:29 technomancy: WizardofWestmarc: I didn't say I had high expectations. =)

14:29 for speed anyway.

14:29 WizardofWestmarc: heh heh

14:29 technomancy: expressivity on the other hand...

14:30 WizardofWestmarc: heh yeah

14:30 * WizardofWestmarc used to prefer python for his programming tasks, so feels ya there.

14:30 WizardofWestmarc: though I'm still using python for the webdev stuff I'm playing with, since Compojure is still a bit new/green for my taste.

14:31 but any background processes tied to it will be in clojure >_>

14:31 rsynnott: are there really that many compilers for dynamic languages which make significant improvements on the dynamic stuff?

14:32 even mature common lisp compilers tend to rely significantly on the user giving type hints where necessary

14:37 * zakwilson has been doing image processing in Clojure. It's not slow.

14:37 zakwilson: And the fact that a lot of tasks can be made parallel simply by using pmap instead of map is a huge win.

14:38 leafw: zakwilson: same here. But I use pure java data structures for the pixels ( ij.ImagePlus, ij.ImageProcessor and friends).

14:39 gnuvince: leafw: can I get a link for that lib?

14:41 leafw: gnuvince: we use fiji ( http://pacific.mpi-cbg.de ) but the lib itself is ImageJ ( http://rsb.info.nih.gov/ij ), see code diectly here: http://pacific.mpi-cbg.de/cgi-bin/gitweb.cgi?p=ImageJA.git;a=summary

14:41 gnuvince: there's a tutorial on using ImageJ with clojure here: http://pacific.mpi-cbg.de/wiki/index.php/Clojure_Scripting

14:42 slava: are you implementing the actual image processing algorithms in clojure or just using it to glue together java code?

14:42 gnuvince: Wow

14:42 That's a long tutorial, I'm impressed

14:42 leafw: slava: I use clojure to use java code at high level.

14:43 slava: only occasionally I'd use clojure as well for low-level -- but it works very well, with type declarations. Is just that immutability is a problem with "areduce", when arrays are gigabyte-long.

14:43 zakwilson: Pretty fancy, leafw.

14:44 slava: leafw: sounds like clojure's compiler needs to implement some fusion optimizations :)

14:44 leafw: gnuvince: for ImageJ itself, there is a data structure tutorial here: http://albert.rierol.net/imagej_programming_tutorials.html

14:44 zakwilson: thanks, took some time.

14:44 slava: eliminate all those intermediate arrays

14:44 zakwilson: I'm doing operations directly on a BufferedImage with getRGB/setRGB.

14:45 leafw: zakwilson: it's possible :) but ImageJ has all these built-in filters that are so useful, and ability to work transparently with rois.

14:46 zakwilson: leafw: I'll be taking a look at it.

14:46 leafw: zakwilson: there's sometimes people at #fiji-devel ready to explain ImageJ basics if you need so.

14:47 I'm afraid they don't use clojure though : mostly jython and jruby.

14:47 zakwilson: Awesome.

14:49 No matter - the background on imagej will be helpful if I end up using it.

14:49 leafw: zakwilson: we even added a clojure launcher for fiji: ./fiji --main-class clojure.lang.Repl would do it ... and ./fiji some-script.clj will launch it. All jars into the classpath automatically :)

14:50 zakwilson: I'm working on a program for doing things to directories full of images. Currently, I have a greyscale filter and nothing more. My intent is to provide multiple filters, resizing, etc...

14:50 hiredman: ,(Collections/shuffle '(a b c d))

14:50 clojurebot: java.lang.UnsupportedOperationException

14:51 rhickey: One of the things that hasn't yet happened, is that people can leverage the low-level stuff inside a macro-package that makes it declaration-free, without any compiler enhancements. i.e. as long as the perf is reachable, some more abstraction can be added via macros

14:51 leafw: zakwilson: I'd say all of that is doable with ImageJ rather easily

14:53 zakwilson: leafw: Sounds like it. Some time later, I'm going to play with it later. I'm interested in seeing if its greyscale filter is faster than mine.

15:15 danlarkin: rhickey: saw your post on the list, we love you too!

15:18 rhickey: :)

15:20 gnuvince: Speakinf of contribution, I sent my C.A. yesterday

15:21 clojurebot: svn rev 1298; return unmodifiableList from ASeq.reify()

15:21 Chouser: gnuvince: hooray! Have you talked to Stuart S. about his json lib?

15:21 danlarkin: :-o

15:21 gnuvince: Chouser: no, why?

15:21 Chouser: um

15:21 I may be confused.

15:22 danlarkin: sorry

15:22 gnuvince: momentarily got you confused with danlarkin there.

15:22 gnuvince: no problem :)

15:22 danlarkin: to answer your question, no I haven't talked to him

15:22 Chouser: And danlarkin's already got his CA in.

15:23 danlarkin: do you want me to mediate or something?

15:23 danlarkin: haha

15:23 sure!

15:24 maybe there's benefit to there being two... his is a lot simpler after all

15:25 Chouser: I agree that there may be benefit, but I'd hate for the efforts to be going on without any communication.

15:25 the right answer may be two json libs, but I can't imagine that the right answer is not talking to each other at all.

15:26 danlarkin: yeh you're probably right

15:27 Chouser: and if there should be two json libs, I don't know why they shouldn't both be in contrib, unless there's a licensing issue.

15:28 * jkantz has got to find a way to avoid stomping function names with let bindings

15:31 danlarkin: alright then, set it up!

15:38 shoover`: rhickey: proud and lucky, indeed. An indyalt.net attendee made a point of mentioning a couple times that the community support is a great feature

15:43 fffej: sorry, silly question coming up - what's the Clojure equivalent of importing java.util.* - i can't find a way to express * at the moment :(

15:44 hiredman: there is none

15:44 just import what you need

15:44 fffej: ok, that makes me feel better for not finding it - thanks

15:55 slashus2: no need to pollute the namespace

15:58 fffej: true, but it's useful when you're lazy and exploring code without having to look up the ns of everything

16:00 * jkantz is just now seeing the virtues of cl's multiple namespaces for what a symbol designates w/in a package

16:00 lisppaste8: cemerick annotated #75862 "untitled" at http://paste.lisp.org/display/75862#1

16:01 WizardofWestmarc: meh, having to litter your code with crap like Funcall sucks

16:01 cemerick: rhickey: I tracked down the cause of the NPE I got earlier today. See the paste above for info.

16:03 Bracki: Is there anything that'll give me a files basename or extract the dirname from a file?

16:03 jkantz: WizardofWestmarc -- it's a trade-off that buys you 1) not having to worry about polluting namespaces or shadowing things unintentionally

16:03 slashus2: cemerick: He may be the one with double underscores in his name.

16:04 cemerick: slashus2: well, if we have three Riches now (rhickey, rhickey_, and rhickey__), that should help things along!

16:04 ;-)

16:04 * jkantz will just have to live with naming argumens "astr"

16:05 hiredman: what about "string"

16:05 rhickey: cemerick: ok, but if you want something other than an NPE when you pass nil and something non-nil is expected...

16:05 Bracki: Can duck_streams be considered as the "file utils" package for clojure?

16:06 cemerick: rhickey: an NPE is fine, but with some explanation of what's going on would be nice. This is a class of error that is not present in java because javac doesn't allow null to be passed as a primitive arg.

16:06 (modulo whatever happens with "unboxing" a ref to a java.lang.Float, but I've never tried that)

16:06 a ref to a null java.lang.Float, I mean

16:08 hiredman: ,(Float. nil)

16:08 clojurebot: java.lang.NullPointerException

16:10 jkantz: hiredman, :) ... a better example, "avec"

16:10 cemerick: hiredman: that NPE is coming out of the Float(String) constructor, as it attempts to parse the null -- the presence of that stack frame makes determining the problem a lot easier than the NPE coming out of clojure-land.

16:12 OK, so in Java, calling a fn that takes a float with a null Float results in a bare NPE as well (I hardly ever use boxed primitives, FWIW).

16:13 I guess the only difference is the stack trace coming out of clojure, not an application source file.

16:14 rhickey: cemerick: if your call is in a file you'll get the source line of the failing call in the trace

16:19 silkarn: does Clojure's concurreny constructs really help that much? aren't you tied to Java's way of concurrency anyhow somehow?

16:19 can you ahve concurrency in Clojure without using Java threads?

16:19 hiredman: uh threads are not the issue

16:20 the issue is unsafe mutable data

16:20 silkarn: and refs/atoms/agents/whatnot can help you with that?

16:20 hiredman: yes

16:20 silkarn: put a lock on a thread someow?

16:20 hiredman: nope

16:21 you don't like threads

16:21 silkarn: what do you do, start a thread inside a ref?

16:21 hiredman: no

16:21 silkarn: how do you know i odnt like threads?

16:21 i dont know wyat i like

16:21 id like automagic concurrency :)

16:21 hiredman: I did not imply that you did

16:22 you mentioned java threads, and I said threads are not the issue

16:22 java threads or otherwise

16:22 a ref is an indirect reference to data

16:23 you can deref it and get the data, but in order to change the value the ref has, you have to do it inside a transaction

16:24 jkantz: an alternative to the evaluation rule for symbols in function position: always look for var in current namespace, if you want the lexical binding in the function position you add quote which is consistent with the way quote strips away the namespace ('lex-fn-name arg1 arg2)

16:24 hiredman: eh?

16:25 I hardly see what that gains?

16:26 slashus2: I wonder if the default sorting algorithm will be psort in the future?

16:26 I mean core, not default.

16:26 hiredman: ~def sort

16:27 slashus2: sort just uses

16:27 java.util.Arrays/sort

16:27 jkantz: you can have functions with arguments [a & rest] and call rest from within the function

16:27 slashus2: psort is a parallel sort?

16:27 jkantz: and so on

16:28 hiredman: jkantz: the fix for that is really simple, do use rest

16:28 do not

16:28 :P

16:28 slashus2: hiredman: So psort isn't better?

16:28 jkantz: well yes that is one fix :)

16:29 hiredman: slashus2: I have no idea

16:29 jkantz: if your functions are getting so large that you are having name collisions inside the functions it may be time to decompose into several smaller functions

16:31 zakwilson: isn't rest getting replaced by next/more anyway? (I haven't kept entirely up to date on that)

16:31 Chouser: rest is still a builtin fn name

16:31 hiredman: ,(doc rest)

16:31 clojurebot: "([coll]); Returns a possibly empty seq of the items after the first. Calls seq on its argument."

16:36 jkantz: no it's not a matter of function size, just a matter of getting used to no punning allowed

16:38 hiredman: jkantz: you seem to be all over, punning in this channel usually refers to nil punning, which doesn't seem to have any thing to do with name collisions inside a function

16:39 so are you moving on to something else? using terminology I don't understand?

16:39 jkantz: something like (fn [list] (list (first list))) is often called punning

16:40 hiredman: I see

16:40 I call it confusing, and don't do it

16:41 Chouser: is this a lisp 1 vs. 2 thing?

16:41 jkantz: yeah

16:42 I bet you do it half-way at some point :)

16:42 Chouser: I enjoy not having to specially quote function names when passing them -- that's required in a lisp 2 usually, isn't it?

16:42 jkantz: if you use a library you have to know all the function names in the library and never name one of your arguments that name

16:42 WizardofWestmarc: not quoting per se, but you do have to expressly indicate it's a symbol from the function NS

16:43 Chouser: jkantz: no, you can leave libraries in their own namespaces

16:43 jkantz: or bring in just the names you want

16:43 hiredman: ^-

16:43 jkantz: so is it better then to not bring in whole libraries but just pull in the symbols you want?

16:44 seems like it would be the case

16:44 hiredman: it is better to use :as

16:44 Chouser: yeah, I'm against the unqualified use of 'use'

16:44 jbondeson: Chouser: i'd just like to say at this moment that i love you for zipfilter.xml.

16:44 just sayin

16:44 Chouser: ha!

16:44 well, that's nice

16:46 jbondeson: course i have to add some != functions since i need exclusions, but it has saved me a whole mess of time

16:47 Chouser: well, adding functions is the main reason to not use xpath.

16:47 jbondeson: i've spent way too much time in xpath hell.

16:47 * jbondeson shudders

16:48 Chouser: oh, really? you prefer xquery or something?

16:48 jbondeson: oh no, hate it all

16:48 equal opportunity xml technology hater

16:48 don't get me wrong, xml is fine and dandy in many cases, but the tech around it all sucks

16:49 xpath2 is leaps and bounds better than xpath1, but not everything supports it.

16:49 so to be at all compatible you just suffer through xpath1

16:51 Chouser: i'm glad zip-filter has (so far) escaped your wrath. :-)

16:51 jbondeson: i'm sure that keeps you up at night ;)

16:52 WizardofWestmarc: hey, he could be one of those devs who takes the mantra to heart "Write your code like the person who comes after you is a serial killer" >_>

16:56 * jbondeson hides his butcher knife

16:57 jbondeson: now if there one programming team i could take out it's the Microsoft XML team... those bastards have caused me so pain over the years.

16:57 WizardofWestmarc: depends, are they responsible for the xml engine in SQL Server too? If so I'd like to join in <_<

17:01 technomancy: you mean like this? http://achewood.com/index.php?date=07052007

17:01 jbondeson: yes.

17:24 cp2: how can i generate a map from a list, where the keys are the values returned by a method called on each member in the list (they are java objects) ?

17:24 eg, value x in a list would be key: (.someMethod x) value: x

17:25 in th emap

17:25 Chouser: (zipmap (map #(.someMethod %) lst) lst)

17:25 cp2: aye, i could have come up with that

17:25 thanks, i was thinking about zipmap

17:25 but wasnt too sure...

17:25 jbondeson: i think that Chouser just hovers waiting for people to give him a challenge...

17:32 cp2: jbondeson yeah, seems so :)

17:37 * shoover` wonders if zipmap should be on clojure.org/data_structures for creating maps

17:39 Chouser: hm, I would certainly think so.

17:39 and maybe 'into'?

17:39 though probably not 'reduce', I guess.

17:42 lisppaste8: cp2 pasted "why is this happening" at http://paste.lisp.org/display/75886

17:42 cp2: ^

17:43 hiredman: you are calling a function that takes a Set on a List

17:44 so it says "Hey, this is not a Set"

17:44 shoover`: Chouser: if you put 'into' in one of the data structure-specific sections, it would need to go in them all

17:44 Chouser: yes

17:44 annoying

17:45 cp2: hiredman: where though?

17:45 i dont see it

17:45 Chouser: ok, added zipmap

17:45 cp2: oh my

17:45 oh, nevermind

17:45 shoover`: but I do tend to forget that one a lot, so maybe in the general collection summary where it talks about conj?

17:45 cp2: (as far as my "oh my")

17:45 problem still stands

17:45 hiredman: I am unfamilar with set functions so I am unable to say

17:45 Chouser: Collections probably needs a related functions section for conj, disj, into, etc.

17:46 count conj and seq are there, but don't stand out if you're skimming the page.

17:46 shoover`: Chouser: fair enough

17:46 Chouser: gotta go. bbl.

17:51 cp2: so, anyone have any ideas

17:52 shoover`: cp2: can you annotate with a print of @class-hierarchy?

17:52 hiredman: that would be helpful

17:53 also a print of superclassname

17:53 prn would be best

17:53 cp2: ok, give me a sec

17:53 have to do something real quick

17:53 shoover`: I have to believe someone stuck a list in there

17:54 hiredman: actually

17:54 are you sure that exception is even coming from that line?

17:56 cp2: well, the place it is thrown is in core (in disj)

17:56 hiredman: ~def disj

17:56 cp2: ill give you a stack trace

17:57 lisppaste8: cp2 pasted "stack trace" at http://paste.lisp.org/display/75887

17:58 hiredman: ~def clojure.set/select

17:58 wow

17:58 I am surprised that worked

17:59 yeah

17:59 cp2: ah, i dont think its coming from where i thought

17:59 hiredman: so select takes a predicate and a set

17:59 cp2: just stuck a few printlns in my code to see how far it gets

17:59 hiredman: *tada*

17:59 cp2: sec

18:00 hiredman: ,(clojure.set/select identity '(a b))

18:00 clojurebot: (a b)

18:00 hiredman: ,(clojure.set/select #(not % 'a) '(a b))

18:00 clojurebot: java.lang.IllegalArgumentException: Wrong number of args passed to: core$not

18:00 hiredman: er

18:00 ,(clojure.set/select #(not= % 'a) '(a b))

18:00 clojurebot: java.lang.ClassCastException: clojure.lang.PersistentList cannot be cast to clojure.lang.IPersistentSet

18:01 cp2: nevermind, its definitely coming from where i thought, but for the wrong reason i assumed

18:01 mmt: Hi all, gotten fairly far a long in setting up clojure & swank, ran into this snag:

18:01 cp2: first iteration goes as planned, but when i add a definition to the set it borks

18:01 mmt: java.lang.Exception: Unable to resolve symbol: lazy-seq in this context (core.clj:70)

18:01 hiredman: cp2: my guess would be that it isn't a set anymore

18:02 cp2: it should be though, thats whats getting me

18:02 (dosync (commute class-hierarchy conj class)))

18:02 hiredman: at some point you are performing some operation that returns a list

18:02 cp2: is the last thing performed before the next iteration

18:02 mmt: That error comes out of (require 'swank.swank), if anyone has seen it before, please let me know :)

18:02 cp2: class is an instance of class-relation

18:03 hiredman: place some (doto set prn) throughout

18:03 and see if it stays a set

18:04 shoover`: mmt: sounds like your swank and clojure are out of sync

18:04 mmt: that's what it's beginning to look like

18:05 When I launch it from emacs using M-- M-x slime, it instead complains about

18:05 there being no such namespace "clojure"

18:05 hiredman: uh

18:05 mmt: which apparently means I have a very old swank hanging out somewhere

18:05 hiredman: I guess so

18:05 clojure got moved to clojure.core many moons ago

18:05 mmt: ah, I think I found it

18:06 Had an older copy sitting earlier in the classpath, time to clean house :)

18:06 shoover`: hiredman: I don't quite get why your select returned different results based on the selection pred

18:06 * Raynes beats the swank out of mmt!

18:07 hiredman: shoover`: it has to do with disj

18:07 er

18:07 shoover`: hiredman: in both cases, it's receiving a list and not a set

18:07 hiredman: well, select only tries to disj if something fails the pred

18:07 cp2: thats interesting hiredman: after my inc-subclass-count is invoked (which looks much like update-role in http://en.wikibooks.org/wiki/Clojure_Programming/Concepts#Mutation_Facilities ), the ref points to nil

18:07 and then it becomes a list from the next function doing stuff

18:07 so, i think the problem is there :)

18:09 hiredman: ,(doc clojure.set/union)

18:09 clojurebot: "([] [s1] [s1 s2] [s1 s2 & sets]); Return a set that is the union of the input sets"

18:09 shoover`: ah, so when the pred is identity, it never calls disj

18:09 cp2: yeah hiredman

18:09 hiredman: shoover`: correct

18:09 cp2: thats what goes wrong

18:09 the two selects i perform before the union both return an empty set

18:09 shoover`: should select check and throw?

18:09 cp2: so union ends up returning nil

18:09 hiredman: *shrug*

18:10 cp2: and then it gets foobar'd from there

18:10 i think i can fix it

18:10 oh, that makes much sense

18:11 the set is empty initially so no wonder the 2 selects return an empty set

18:11 leafw: is anybody here using a java-only db, that would recommend? I need to embed a simple db into an app ... can't ask users to install postgres.

18:13 cp2: ok hiredman, im getting closer!

18:13 NPE now

18:13 zakwilson: leafw: No, but I think BerkeleyDB is what you're looking for.

18:14 hiredman: you must be passing nil into select now

18:14 Bracki: leafw: go for dqlite

18:14 sqlite

18:14 hiredman: ,(clojure.set/select identity nil)

18:14 clojurebot: nil

18:14 cp2: yeah, this will be easier for me to track down now that i know what to look for

18:14 hiredman: huh

18:14 maybe not

18:14 cp2: well, im hoping

18:15 this time its thrown for my code

18:15 no library functions

18:15 well, not a library function*

18:15 leafw: "Berkeley DB JE is not a relational engine built in Java." -- I'd rather not depend on anything else

18:16 hum the website contradicts itself

18:16 hiredman: Berkeley DB JE is not a relational engine, built in Java

18:16 zakwilson: It doesn't contradict itself: Berkeley DB is not a relational engine.

18:16 Berkeley DB JE is built in Java.

18:17 redalastor: According the Eclipse Public License under which Clojure is licensed I cannot distribute an app under any license other than the EPL :(

18:17 hiredman: redalastor: are you sure that is correct?

18:17 redalastor: http://www.eclipse.org/legal/eplfaq.php#USEINANOTHER

18:17 The FAQ entry seems clear to me...

18:18 hiredman: you can license your code however you want though

18:18 zakwilson: redalastor: I think you're misreading it. You can distribute an app under any license you want, though if your app is a modified version of Clojure itself, you must comply with the terms of the EPL.

18:19 And if you bundle Clojure with your app, you're bound by the EPL, but the EPL only covers Clojure itself; it does not attach itself to code that uses Clojure.

18:19 redalastor: Wouldn't the app technically be a derivative?

18:20 Linux had to include an exception in its license that says "linking against the kernel is considered normal use and is not covered by this license".

18:20 hiredman: nope

18:20 well, linux uses a different license

18:20 technomancy: redalastor: yeah, that's probably only relevant with the GPL

18:21 redalastor: According to the latest entry on the FAQ, linking with GPLed code is *not* okay.

18:22 hiredman: well, clojure doesn't link :P

18:23 gnuvince_: Does anyone else get a StackOverflow exception when starting slime?

18:23 redalastor: True and if I am the copyright holder then I can add an exception saying that it's okay for my app to link to clojure.

18:23 hiredman: uh

18:23 No

18:23 well, actually

18:23 maybe

18:23 talk to a lawyer

18:24 Law is serious business

18:24 redalastor: It's in the GPL, there's a section on additional terms I might want to include.

18:24 cp2: hiredman: i fixed, in one sense of the word "fixed" or another :)

18:24 fixed it*

18:25 zakwilson: redalastor: I think your question is best answered by http://www.eclipse.org/legal/eplfaq.php#PROPPROD

18:25 hiredman: if you picked a license that was more free, then you don't really have to worry about the clash

18:26 :)

18:26 redalastor: Free is subjective.

18:26 hiredman: So is the GPL

18:27 redalastor: Actually, it's pretty detailed so it doesn't leave a lot of room to interpretation.

18:27 zakwilson: I think you can use the GPL for your app and bundle Clojure if you like.

18:27 hiredman: ...

18:28 I was being a smartass, I meant the GPL

18:28 subjugates

18:30 dreish: I think it's pretty clear-cut that a program written in a language is not a derivative work of that language's compiler, but if you aren't comfortable you can always get yourself a lawyer.

18:32 redalastor: dreish: Actually, according to the FSF lawyers, it can be if there is code from that language being mixed in.

18:33 technomancy: well of course it's possible to make a derivative if you copy code

18:33 that doesn't really have anything to do with the question at hand

18:33 dreish: http://www.gnu.org/licenses/gpl-faq.html#InterpreterIncompat

18:34 * p_l is not sure if a licence that takes away rights is "free"

18:34 dreish: I write in an additional permission under GNU GPL version 3 section 7, but it's probably not strictly needed.

18:34 technomancy: the only thing that doesn't take away rights is public domain

18:34 which isn't a license

18:34 redalastor: According to the GPL FAQ: "If you want your program to link against a library not covered by the system library exception, you need to provide permission to do that."

18:35 technomancy: and doesn't even exist in all jurisdictions.

18:35 dreish: Yes, and clearly Clojure itself is covered by the system library exception.

18:35 Contrib, probably not.

18:35 hiredman: dreish: clojure is interpreted

18:35 p_l: technomancy: Not necessarily. MIT is probably as close as you can get in current legal system to giving freedom and avoiding giving up your rights to the code

18:35 hiredman: er

18:35 damn it

18:36 dreish: clojure is not interpreted

18:36 it is compiled

18:36 redalastor: System or not, I have the option of providing the permission.

18:36 dreish: Who said it was interpreted, other than you?

18:36 technomancy: p_l: even that takes away your right to remove copyright notices etc.

18:37 dreish: I guess the FAQ appears to be restricted to addressing interpreted languages.

18:37 p_l: technomancy: erm, normally you don't have right to remove copyright notice from source.

18:37 technomancy: p_l: my point being that there's no such thing as Absolutely Free. everything must be framed in terms of trade-off

18:38 hiredman: dreish: well, yeah, I was assuming you had read the link you posted :P

18:38 technomancy: p_l: sure you do: you can remove anything you want from public domain

18:38 dreish: 'The run-time libraries ... are "System Libraries" as GPLv3 defines them, and as such they are not considered part of the Corresponding Source.'

18:38 p_l: technomancy: Yes, I just consider GPL to be particularly non-free compared to other existing licenses :-)

18:38 dreish: hiredman: That's crazy talk.

18:39 technomancy: p_l: well why didn't you say that up front then. =)

18:39 p_l: technomancy: BTW, in countries where certain "pro-IP" activists haven't done too much damage yet, everything enters public domain after certain time

18:40 technomancy: p_l: right, but in some countries you don't even have the legal right to place something you have complete copyright over in the public domain.

18:40 so it's all about trade-offs.

18:41 mmt: Hi all, thanks for your help earlier. I have the latest svn/git checkouts of swank-clojure, clojure-mode and clojure...

18:41 p_l: technomancy: Everything is about tradeoffs...

18:41 mmt: But I still get Unable to resolve symbol: lazy-seq

18:41 When I launch swank in Emacs

18:41 hiredman: I think clojurebot has something about "tradeoffs" in one of its clojure factoids

18:41 redalastor: Someone wrote the WTFPL to solve the problem of not being able to put stuff in the public domain.

18:42 It basically says "You are authorized to do whatever the fuck you want."

18:42 gregh: heh

18:42 hiredman: ~clojure

18:42 clojurebot: clojure is cheating

18:42 technomancy: redalastor: sure, but I bet there's some jurisdictions where even that wouldn't be honored

18:42 p_l: redalastor: Is it "What The Fuck Public License"? :)

18:42 hiredman: ~clojure

18:42 clojurebot: clojure is far closer to perfection then python

18:42 hiredman: ~clojure

18:42 clojurebot: "[Clojure ...] feels like a general-purpose language beamed back from the near future."

18:42 hiredman: ~clojure

18:42 clojurebot: "[Clojure ...] feels like a general-purpose language beamed back from the near future."

18:42 hiredman: bah

18:42 forget it

18:42 technomancy: redalastor: like maybe in some religious governments legal documents with swearing aren't admissable in court or something... =)

18:43 redalastor: technomancy: You can argue in court that the intent is crystal clear :)

18:43 hiredman: YANL

18:44 clojurebot: YANL is <reply>You Are Not Lawyers

18:44 clojurebot: Ik begrijp

18:45 hiredman: two people who are not lawyers, trying to argue technical points of law, let alone international law, is just plain silly

18:45 technomancy: redalastor: there are some pretty crazy legal systems out there.

18:45 that's all I'm saying

18:45 your assumptions probably don't hold worldwide

18:45 hiredman: technomancy: why don't you help mmt with his swank

18:45 I would, but I don't swank

18:45 mmt: :)

18:45 technomancy: hiredman: what, and be productive? why break my streak?

18:45 hiredman: or emacs

18:45 mmt: so, is lazy-seq still part of clojure?

18:45 technomancy: mmt: you're seeing that error when you launch emacs?

18:45 not when you open a clojure file?

18:45 mmt: when I launch slime

18:46 technomancy: ok

18:46 mmt: I have clojure-mode opening on load, then I run M-- M-x slime

18:46 redalastor: technomancy: Yeah but I don't really have to bother with what people in crazy systems do with my code :)

18:46 mmt: I was following:

18:46 http://bc.tech.coop/blog/081023.html

18:46 technomancy: mmt: and it's showing up as an elisp-level error or a slime backtrace?

18:46 mmt: It's a Java lang exception

18:46 java.lang.Exception: Unable to resolve symbol: lazy-seq in this context (core.clj:70)

18:47 technomancy: mmt: do you do CL at all? because those instructions are more complicated than necessary in order to support using CL and Clojure at the same time.

18:47 mmt: well, I've played with CL

18:47 I can avoid it, is there a better set of instructions around?

18:47 technomancy: mmt: if you don't need CL compatiblity with SLIME the easiest thing to do is M-x clojure-install with the latest clojure-mode

18:47 though unfortunately I haven't gotten around to testing this with the lazy changes yet

18:48 although I think gnuvince has?

18:48 mmt: sounds good

18:48 So, do you think I'll need to back out of any of my .emacs changes?

18:48 gnuvince_: technomancy: when I try to start SLIME, StackOverflow

18:48 technomancy: mmt: all you need is clojure-mode, you can get rid of your other changes

18:48 mmt: including swank-clojure?

18:49 technomancy: yes

18:49 mmt: though actually... unless you *need* the lazy stuff, it might be better to roll back to an older revision

18:49 for at least a week or so

18:49 mmt: ah, these are recent changes

18:49 technomancy: yes, from this week

18:49 mmt: so, is there a simple SVN command or such to grab me an appropriate version, or should I troll around for an old zip?

18:53 technomancy: mmt: if you've got git clones of each repository, you can easily rollback to the SHA1s mentioned in this post: http://groups.google.com/group/clojure/browse_thread/thread/2acedf58af32de77/a6a42b82442e64dd?lnk=gst&q=test-is+slime#a6a42b82442e64dd

18:53 just "cd ~/src/clojure; git checkout d866f14" etc; for each of the four projects

18:53 [clojure, contrib, slime, swank-clojure]

18:58 schoppenhauer: hello. has anybody expieriences with stringtemplate and clojure?

19:00 i am currently trying to create a generated list, but stringtemplate expects a class with apropriate fields set to the values it should insert. actually, i have tried to create a proxy defining getter- and setter-methods, but this doesnt work. I also considered gen-class, but i dont really understand it. is there something inverse to (bean ...)?

19:03 mmt: technomancy: Is clojure hosted on git-hub now? I was using that SVN checkout

19:03 technomancy: mmt: it's mirrored on github

19:04 M-x clojure-install uses that so you have the complete history available to you

19:04 very handy in situations like this where you need to roll back easily; you could even do it w/o network

19:05 mmt: *nod* I'm a fan of git

19:06 schoppenhauer: seems like the getter- and setter-methods of my "proxy" are not even existant

19:06 hiredman: schoppenhauer: proxy can only change behaviour of existing methods, not make new methods

19:07 schoppenhauer: hiredman: is there any other way of creating new methods and fields?

19:07 hiredman: schoppenhauer: gen-class and AOT

19:07 er

19:07 AOT Compilation

19:08 schoppenhauer: hiredman: as I said, i dont actually understand gen-class. i only found a strange example...

19:10 hiredman: clojurebot: compilation?

19:10 clojurebot: It's greek to me.

19:10 schoppenhauer: hiredman: I think I need :factory for what I want to do. But I cannot find any example of how to use it

19:10 hiredman: ~google clojure compilation

19:10 clojurebot: First, out of 2890 results is:

19:10 Clojure � compilation

19:10 http://clojure.org/compilation

19:10 schoppenhauer: hiredman: yes, I know this page, but :factory isnt explained

19:11 hiredman: never heard of :factory

19:11 schoppenhauer: hiredman: http://clojure.org/API#gen-class to me it seems like this is what I need when I want to create fields

19:11 hiredman: but I dont know, I could be wrong

19:12 mmt: technomancy: thank you for your help! things are working now

19:12 hiredman: schoppenhauer: why do you need fields?

19:12 cooldude127: Bracki: ping!

19:12 schoppenhauer: hiredman: stringtemplate seems to need them

19:12 mmt: oh, except now I can't edit .clj files! hah

19:13 Wrong type argument: stringp, nil

19:13 in the minibuffer

19:13 hiredman: ew

19:13 are you sure?

19:13 mmt: My .emacs contains:

19:13 (autoload 'clojure-mode "clojure-mode" "A major mode for Clojure" t)

19:13 (add-to-list 'auto-mode-alist '("\\.clj$" . clojure-mode))

19:13 and:

19:14 (require 'swank-clojure-autoload)

19:14 cooldude127: that looks correct

19:14 mmt: I could comment those out. If I switch into clojure-mode manually there's not such error

19:14 schoppenhauer: hiredman: I want to access templates of the form $foo.bar$ - therefore I need a class with the field ".bar". I dont know if it also works with a setBar-Method.

19:16 mmt: hmph, well, I have to run, thank you for your help! I'll be back later

19:16 * mmt is away

19:25 * camperman is a new clojure user - still a bit awed by the deep elegance of it all

19:26 gnuvince_: camperman: welcome :)

19:26 technomancy: weird; never seen that stringp error

19:27 camperman: gnuvince, thank you - pretty sure I read your blog the other day :)

19:28 technomancy: the nice thing about a young language is that by blogging about it you can increase the amount of available material on a topic by a nontrivial percentage. =)

19:28 schoppenhauer: When I created a class using gen-class, how can I create instances of it?

19:28 camperman: heh - true true

19:28 * technomancy picks some low-hanging fruit and takes a big juicy bite out of it.

19:28 technomancy: nom nom nom

19:29 camperman: the only problem I have with clojure is I've despised Java (the language) for years and now need to get to grips with the libraries

19:29 technomancy: camperman: same

19:30 liking clojure doesn't mean you accept that Java libraries all have good APIs though. =)

19:30 camperman: technomancy, sure - it's just that I'm clueless about the basics like Swing and sockets and everything else really

19:30 schoppenhauer: Seems like gen-class doesnt do anything

19:31 technomancy: camperman: there's a server-socket library in contrib is pretty nice to deal with

19:31 haven't done clients yet, but I'd search contrib first

19:31 camperman: technomancy, ah thx - didn't know that

19:31 hiredman: you have to (compile ...) for gen-class to work

19:32 technomancy: camperman: guis are probably going to be a pain no matter what though; no real way around that

19:32 schoppenhauer: hiredman: wah... it does have to have its own file?

19:32 hiredman: cant i do this "instantly" somehow?

19:32 hiredman: nope

19:32 camperman: technomancy, right

19:32 p_l: technomancy: GUIs in Delphi weren't that much of a PITA....

19:32 schoppenhauer: ok, thats not sweet.

19:32 camperman: this concurrent ant sim is a work of art

19:32 hiredman: clojurebot: gen-class?

19:32 clojurebot: No, hiredman, you want gen-interface + proxy

19:33 camperman: I have tried something similar years ago in C with threads and went mad

19:33 technomancy: C will do that to you.

19:34 schoppenhauer: hiredman: can I do this instantly using gen-interface?

19:34 technomancy: camperman: I've made a solemn oath never to manually manage memory again. It's saved my sanity countless times.

19:34 I would suggest a similar thing to all programmers.

19:34 camperman: C + threads + deadlocks + mutable state did it to me - I was nodding and laughing all the way through the talk

19:34 technomancy: Except kernel devs and hotspot maintainers, I guess.

19:34 hiredman: schoppenhauer: no, but you can add methods and stuff with an interfcate then "implement" it using proxy

19:34 camperman: will have to take that oath soon

19:35 schoppenhauer: hiredman: why should I use clojure for this? defining an interface should be easier with java.

19:36 hiredman: schoppenhauer: *shrug*

19:37 schoppenhauer: hiredman: i just mean: defining an interface with clojure which i have to compile anyway - then I can also use java and use "proxy" with it ^^

19:37 hiredman: I have only gone down the gen-interface road once

19:37 clojurebot: mkbean?

19:37 clojurebot: It's greek to me.

19:37 hiredman: bah

19:37 schoppenhauer: actually, i wonder why there is no possibility to generate classes on-the-fly.

19:37 afaik, this is possible

19:38 hiredman: actually clojure pre-AOT compilation could

19:38 schoppenhauer: but thats not the lisp-way...

19:38 hiredman: but you will have to talk to rhickey to find out why it was removed/changed/etc

19:38 schoppenhauer: yes,

19:38 its just a pity atm

19:39 hiredman: like I said, it has only every come up once

19:39 (for me)

19:40 schoppenhauer: hm. but without it, the java-interops are not complete.

19:41 hiredman: schoppenhauer: are you really sure stringtemplate needs field access?

19:41 I have heard or stringtemplate before so I assumed it was a decent lib, but requiring public field access is, uh, bad

19:41 heard of

19:48 schoppenhauer: hiredman: i dont know stringtemplate in detail. it should be satisfied with getter/setter-methods. but i cannot provide them "on the fly" either

19:52 silkarn: how is the automatic dispatch in multimethods done in clojure? is this inside the language parser or wrtten on top of the core?

19:55 hiredman: ~def defmulti

19:56 huh

19:57 weird

19:58 technomancy: hiredman: is that like source?

19:58 hiredman: should be

19:59 I think clojurebot is out of sync right now

19:59 it uses a local svn tree to try and guess what revision of clojure it is running before it uses (:line (meta ...))

20:00 technomancy: I didn't really understand the usefulness of metadata until I realized you could use it to find where stuff is def'd. so handy!

20:01 rockbiter: holy mackerel, lotta people here

20:02 which rhickey is the real one

20:03 hiredman: ~seen rhickey?

20:03 clojurebot: rhickey was last seen quiting IRC, 122 minutes ago

20:03 rockbiter: is clojurebot written in clojure?

20:03 ~fessup

20:03 clojurebot: I don't understand.

20:03 rockbiter: ~show me your rusty innards

20:03 clojurebot: show is clojure.contrib.repl-utils/show

20:08 schoppenhauer: wah... clojure's way of compiling classes is really annoying.

20:09 hopefully, in a future version there will be a better way ^^

20:10 weavejester: Why is it annoying?

20:12 schoppenhauer: Because it cannot create them on-the-fly, you have to compile your clj-file explicitly, and therefore, have to set paths so that it can find the clj-file

20:12 Its something you dont want to do ;-)

20:13 At least I dont. There are classes to compile java-code on-the-fly (never done this, i have to admit), I wonder whats the problem with clojure, or why this was decided.

20:13 weavejester: So, you're thinking of something like Python's pyc files?

20:14 schoppenhauer: I dont know pythons pyc-files

20:14 I am thinking of generating interfaces during runtime rather than AOT

20:15 weavejester: Basically Python saves its compiled bytecode so that the next time you run a Python script, it doesn't have to recompile everything.

20:15 Oh, you mean genclass?

20:15 schoppenhauer: yes

20:15 technomancy: weavejester: hi

20:15 weavejester: technomancy: hi there

20:16 technomancy: (it's Phil from the compojure ML)

20:16 schoppenhauer: No, thats not what I mean

20:16 thats like .fasl-files in common lisp

20:16 technomancy: just wanted to let you know I haven't forgotten about compojure. =)

20:16 schoppenhauer: but i dont need this

20:16 weavejester: Hey Phil

20:16 schoppenhauer: s/need/mean

20:16 technomancy: I'm going to be headed back to web-ish stuff once I wrap up the screencast I'm working on.

20:17 weavejester: technomancy: You're not obliged to remember, but it's nice to know anyway :)

20:18 schoppenhauer, if I used genclass more than I do, I'd probably agree with you

20:19 technomancy, what's the screencast of?

20:19 schoppenhauer: weavejester: well, it would be a nice feature to have something like on-the-fly-class-generating (or interface-generating). I mean the "Proxy"-command is very elegant. Having a genclass-command being as elegant as this would be nice.

20:21 technomancy: weavejester: just on learning clojure

20:21 targeted towards users of dynamic languages

20:21 http://peepcode.com/pages/upcoming

20:22 * technomancy heads home

20:27 stuhood: i miss nil punning =(

20:28 weavejester: Out of all the code I've written, I've actually only nil-punned twice

20:28 ... that I know of

20:29 schoppenhauer: whats nil-punning?

20:30 is it that nil behaves like the empty list?

20:30 stuhood: exploiting the fact that an empty sequence used to be nil in a conditional

20:30 yea

20:30 schoppenhauer: hm. well, thats also something i would like to have in clojure ^^

20:31 weavejester: Unfortunately, nil-punning is incompatible with lazy lists

20:31 Since you need to check whether its empty or not

20:32 schoppenhauer: I can live with that. What I cannot really live with is that I have to compile source Ahead of Time.

20:32 Thats not Lisp :(

20:32 cooldude127: schoppenhauer: why do you have to?

20:32 schoppenhauer: cooldude127: see backlog

20:33 cooldude127: it seems not to be possible to create a new interface on run-time. i hope this feature will be added someday.

20:34 cooldude127: schoppenhauer: oh, i hadn't noticed, i only use the lispy part of clojure mostly

20:34 schoppenhauer: cooldude127: well, its java-interop... it would be good if it was usable in a "lispy" way, too.

20:35 actually, I dont know much about the clojure-internals, but i am sure it has something like a JIT-Bytecode-Compiler.

20:35 so this shouldnt be a too big problem

20:36 maybe there are other reasons, dont know

20:37 weavejester: Does anyone know if there is a general-purpose REPL library for Clojure that operates over a network socket?

20:44 Oh, there seems to be one in clojure.contrib.server-socket

20:53 stuhood: how does one type hint for an inner class?

20:54 rockbiter: "hint for an inner class"

20:54 yw

20:55 stuhood: ah, $

20:56 thanks

21:13 cp2: ah, damnit

21:13 no wonder this wasnt working

21:13 take-while only conjs while the predicate is true, i thought it added on a per-element basis (and went through the whole list)

21:14 i guess i should read more carefully

21:14 what im looking for is filter ;)

21:18 silkarn: how do i do in the chnanel

21:19 * silkarn jumps

21:20 cp2: silkarn /me i think is what you want

21:20 might be /action or /describe on some other clients

21:39 nullman`: i'm trying convert the following clisp code behaviour to clojure: (funcall (intern "my-function"))

21:39 anyone know how?

21:41 hiredman: ((symbol "inc"))

21:41 ,((symbol "inc"))

21:41 clojurebot: java.lang.IllegalArgumentException: Wrong number of args passed to: Symbol

21:41 hiredman: ,((resolve (symbol "inc")))

21:41 clojurebot: java.lang.IllegalArgumentException: Wrong number of args passed to: core$inc

21:41 hiredman: ,((resolve (symbol "inc")) 1)

21:41 clojurebot: 2

21:42 nullman`: hiredman: thank you

23:58 blbrown: what is the opposite of take. is there a function to take the last N items from a sequence

Logging service provided by n01se.net