#clojure log - Oct 10 2009

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

0:17 icey: i've been trying to get my emacs configured using http://technomancy.us/126

0:17 but i keep getting errors stating swank.clj can't be found when i try to run slime

0:17 i've tried on a couple of machines; is there something wonky with the current git versions?

0:47 qbg: So it seems like I get NullPointerExceptions after taking a sufficiently large number of elements from an infinite sequence.

3:13 LauJensen: Morning gents

3:14 G0SUB: LauJensen: Good Morning Sire!

5:48 namor: Wasn't there an online-clojure compiler somewhere?

6:02 ambient: ,(+ 1 2)

6:02 clojurebot: 3

6:03 Chousuke: ,#=(System/getProperty "java.class.path")

6:03 clojurebot: System

6:03 Chousuke: hm

6:04 that wasn't what I expected :P

6:14 Kyromancer: ,(repeat 3)

6:14 clojurebot: Eval-in-box threw an exception:java.lang.OutOfMemoryError: Java heap space

6:14 Kyromancer: oic

8:33 Guest92834: hmm... I have downloaded a clojure library I would like to use from my project. how do I do that?

8:35 fyuryu: Guest92834: the same way you would use a java lib in a project. Is this lib a in a .jar?

8:35 Guest92834: nope... it's a collection of .clj files

8:36 fyuryu: Guest92834: are they placed in a folder stucrure such as: some/library/file.clj?

8:36 serp_: fyuryu: yup

8:37 fyuryu: serp_: then you have to add the folder containing those folders to your classpath

8:38 serp_: that is, apart from having clojure.jar in you classpath, add "/path/to/folder"

8:39 serp_: aha let me try

8:39 fyuryu: serp_: then you'll be able to "use" and "require" those libraries

8:43 serp_: eh doesn't work... I'll have to read a little

8:43 thanks

8:45 fyuryu: serp_: I don't know how well are you familiar with java (classpath in particular)

8:45 serp_: how does the commnd with which you run clojure repl/script looks like?

8:46 serp_: I use vimclojure

8:46 and start the server with java -cp penumbra/src/penumbra:clojure.jar:clojure-contrib.jar:vimclojure.jar com.martiansoftware.nailgun.NGServer

8:47 then, in my file lol.clj I start with this: (ns lol (:require opengl))

8:48 there is a file named opengl.clj in penumbra/src/penumbra

8:48 ambient: perhaps just use java -cp penumbra/src and (ns lol (:require 'penumbra.opengl))

8:48 fyuryu: serp_: penumbra is the opengl lib, I think it needs some more libs (including native ones)

8:49 ambient: yes, you need to link the native libs too, eg. -Djava.library.path=c:\path\to\penumbra\lib\windows

8:51 serp_: ambient: is java.library.path different from classpath?

8:51 ambient: i dont know

8:51 serp_: ok

8:51 fyuryu: serp_: it should be: (ns lol (:require penumbra.opengl))

8:51 ambient: its just what i

8:51 ve used

8:51 fyuryu: without the quote

8:53 serp_: hmm got a little further

8:54 #<CompilerException java.lang.ClassNotFoundException: javax.media.opengl.GL2 (core.clj:9)>

8:54 now I got that

8:54 but I'll have to figure it out later... I've gotta go

8:54 thanks for your help guys

8:54 fyuryu: serp_: np

8:54 ambient: you sure you're linking the right binaries? 32 bit or 64 bit

8:54 it has to match the jvm

11:30 it's pretty cool what F# does how it gets core features of laziness, functionality and immutability included in core .NET

12:05 voodoomonkey55: i have a noob-like question for anyone willing to listen

12:08 i need some help with the lazy-cons function

12:18 Makoryu: voodoomonkey55: What's your question?

12:19 voodoomonkey55: am i supposed to import some library to use it or is it in clojure.core

12:19 ?

12:20 because I've written some code that tries to use it but it won't run, saying that it can't find the symbol "lazy-cons"

12:21 Makoryu: voodoomonkey55: It's been replaced by the more general-purpose lazy-seq

12:21 voodoomonkey55: oh ok

12:22 could i use cons in place of lazy-cons? and how would i do that?

12:22 Makoryu: voodoomonkey55: Inside the body of a lazy-seq macro, just use cons where you would use lazy-cons

12:23 voodoomonkey55: ok

12:23 i'll try that

12:23 thank you

12:24 Makoryu: ,(doc lazy-seq)

12:24 clojurebot: "([& body]); Takes a body of expressions that returns an ISeq or nil, and yields a Seqable object that will invoke the body only the first time seq is called, and will cache the result and return it on all subsequent seq calls."

12:25 voodoomonkey55: oh cool

12:25 that helps a lot

12:25 thanks

13:33 Makoryu: Is there any reason (apart from "Java doesn't support it already") that the underscore can't be used as intra-token "whitespace" in numeric literals?

13:58 Chousuke: Makoryu: what do you mean?

13:59 Makoryu: Some languages (Perl and Ruby, for example) allow 1_000_000 for 1000000

13:59 Chousuke: I think it'd look weird and complicate parsing a lot :/

14:00 Makoryu: Nah, just stick with the existing "\d starts a numeric literal" rule, and add an "s/_//g" pass (whatever the Java equivalent of that is)

14:00 Since there's nowhere in numeric literals where underscores are already allowed, and the tokenizer already sees it as one token, it'll be fine

14:05 chouser: Makoryu: I don't think there's any technical problem -- it's been suggested before, but I think rhickey was uninterested.

14:06 Makoryu: chouser: Hrm....

14:08 kmurph79: i'm trying this while learning clojure: (map (fn [a b c] (a + b - c)) [1 2 3] [1 2 3] [1 2 3]) i want it to return (1 2 3) but i get an error when I try it. help?

14:08 Makoryu: ,(1 + 2 - 3)

14:08 clojurebot: java.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn

14:09 Makoryu: Is that your error?

14:09 chouser: kmurph79: you need to use prefix notation for + and - too, not infix like you have.

14:09 kmurph79: yes

14:09 rongenre: yeah, fix the fn

14:09 kmurph79: ohhhhhh

14:09 rongenre: (+ a (- b c))

14:09 kmurph79: blah

14:09 haha

14:09 Makoryu: ,(- (+ 1 2) 3)

14:09 clojurebot: 0

14:09 kmurph79: whoa, clojurebot is cool

14:10 hiredman: ~botsnack

14:10 clojurebot: thanks; that was delicious. (nom nom nom)

14:10 rongenre: I end up writing python by mistake too, especially in arithmetic stuff.

14:10 and I've been dabbling in lisp for like 20 years. I think it speaks to its usability.

14:10 Chousuke: hiredman: you need to bind *read-eval* to false in the sandbox-eval function btw

14:11 ,#=(eval (def foo 5))

14:11 clojurebot: #'sandbox/foo

14:11 Chousuke: ,foo

14:11 clojurebot: 5

14:11 rongenre: ,first

14:11 clojurebot: #<core$first__4158 clojure.core$first__4158@1a1644b>

14:12 Chousuke: hiredman: also, add alter-var-root and alterRoot to the bad form list :P

14:12 ,hiredman.sandbox/*bad-forms*

14:12 clojurebot: #{alterRoot intern load-reader load-string clojure.core/addMethod eval alter-var-root def}

14:13 * Chousuke added those using the exploit ;(

14:13 chouser: Makoryu: http://clojure-log.n01se.net/date/2008-03-30.html

14:13 so apparently I'm remembering incorrectly

14:14 itistoday: Think i've discovered a bug in this documentation: http://clojure.org/functional_programming

14:14 Makoryu: chouser: Oh, awesome. Better remind him :p

14:14 chouser: Makoryu: we probably just did.

14:14 hiredman: hiredman.sandbox is so crufty

14:14 Makoryu: chouser: :p

14:14 itistoday: although could my lack of clojure knowledge, but isn't the variable 'x' not used in the make-adder function?

14:15 hiredman: itistoday: it is

14:15 the value of x is bound to y

14:16 itistoday: hiredman: ah, gotcha, sorry, i thought that meant something else, thanks!

14:18 is there a reason why let is used? I tried removing let and just having it return (fn [z] (+ x z)) and that worked as well

14:19 hiredman: it is an illustration of lexical scoping

14:20 itistoday: hiredman: i guess i mean to say, isn't removing the let still lexical scoping?

14:20 hiredman: or is there some difference?

14:21 hiredman: yes, but there are 3(?) ways to interact with lexical scope, and the exmple illustrates all three of them

14:21 kmurph79: in the repl, how do I cancel a command?

14:21 Chousuke: kmurph79: you have to kill the repl :p

14:21 kmurph79: ah ok

14:23 hiredman: lexically scoped names can be cated by calling a function and using let, lexicallybound names can be captured by creating a fn

14:23 itistoday: hiredman: so, just to make sure (as I'm trying to learn clojure by reading these documents), I would not define make-adder that way with the 'let' normally, as that would be redundant?

14:23 hiredman: sure

14:24 itistoday: hiredman: thanks, do you happen to know of a document somewhere that goes over these issues? and stuff like gensym? for clojure?

14:24 i know of a great scheme tutorial that has a section dedicated that stuff

14:25 (this is the scheme tut i'm referring to: http://www.ccs.neu.edu/home/dorai/t-y-scheme/t-y-scheme-Z-H-7.html#node_chap_5)

14:25 hiredman: you're looking at the clojure document

14:25 clojure.org

14:26 itistoday: is there a section on it that i've missed?

14:26 hiredman: you are looking at the section on lexical scoping right now

14:27 itistoday: well it doesn't explain what it is, it just reference sit

14:27 *references it

14:27 i.e. it assumes the reader already knows about it

14:27 hiredman: "You can create local names for values inside a function using let. The scope of any local names is lexical, so a function created in the scope of local names will close over their values:"

14:28 itistoday: like i said... that doesn't explain anything

14:28 it doesn't define what lexical means

14:28 and it gives an example that you just said was redundant

14:28 yet it doesn't mention that

14:28 hiredman: eh?

14:29 the example illustrates the text

14:29 itistoday: so just reading that i would be under the impression to always surround (fn) with (let) to make it lexical

14:29 .....

14:29 *points gun to head*

14:29 hiredman: I read that, and I was never under that impression

14:29 itistoday: it doesn't explain what lexical scoping is, nor does it explain any of the issues with it

14:30 hiredman: *shrug*

14:30 I don't see how the clojure docs should be responsible for teaching programming 101

14:31 Chousuke: http://java.ociweb.com/mark/clojure/article.html this might have a bit more detail

14:31 then again, it might not :P

14:31 itistoday: Chousuke: thanks! that was actually next on my reading list

14:31 hiredman: if you want to know what lexical scope is, wikipedia has an article on it

14:31 itistoday: hiredman: i'm not saying the clojure docs should be responsible, i originally asked where i could find a document that addresses these issues (clojure specific)

14:32 hiredman: this scheme tutorial does a great job: http://www.ccs.neu.edu/home/dorai/t-y-scheme/t-y-scheme-Z-H-7.html#node_chap_5

14:32 but i was asking because it's scheme-specific

14:32 referencing functions like fluid-let

14:32 let*

14:32 gensym

14:32 macros, etc

14:33 all of that stuff could be different in clojure, hence my questioning

14:33 hiredman: Chousuke: do you know of any lexical scope issues specific to clojure?

14:33 Chousuke: can't think of any

14:33 hiredman:

14:33 itistoday: heh

14:34 Chousuke: fluid-let is kind of like the binding macro I guess

14:34 which is another kind of scoping entirely :P

14:34 Makoryu: ,(doc gensym)

14:34 clojurebot: "([] [prefix-string]); Returns a new symbol with a unique name. If a prefix string is supplied, the name is prefix# where # is some unique number. If prefix is not supplied, the prefix is 'G__'."

14:35 itistoday: so clojure doesn't have a fluid-let?

14:35 Chousuke: (doc binding)

14:35 clojurebot: "([bindings & body]); binding => var-symbol init-expr Creates new bindings for the (already-existing) vars, with the supplied initial values, executes the exprs in an implicit do, then re-establishes the bindings that existed before. The new bindings are made in parallel (unlike let); all init-exprs are evaluated before the vars are bound to their new values."

14:36 hiredman: itistoday: check the api page

14:36 or even better

14:36 ,fluid-let

14:36 clojurebot: java.lang.Exception: Unable to resolve symbol: fluid-let in this context

14:36 Chousuke: I don't know if binding corresponds directly to fluid-let but it seems similar

14:36 itistoday: it might be called something different, but yeah, binding seems similar, thanks Chousuke

14:38 and if it doesn't, the tut gives the implementation: http://www.ccs.neu.edu/home/dorai/t-y-scheme/t-y-scheme-Z-H-10.html#node_sec_8.3

14:38 crazy macro

14:39 that's something else i need to get good at, is writing macros. in newLISP they're f-exprs, which are identical to functions except the function arguments are quoted (aren't evaluated)

14:39 Chousuke: that's what they are in Clojure too? :/

14:39 itistoday: clojure has f-exprs?

14:39 Chousuke: except the result of the function call is evaluated.

14:40 ambient: wth are f-exprs?

14:40 Chousuke: no, but a macro is essentially a function that takes forms as parameters and returns another form

14:40 which is then evaluated by the compiler

14:41 itistoday: Chousuke: sorry, i don't understand what you meant by "they are in Clojure too". aren't clojure's macros the same sort as lisp and scheme?

14:41 ambient: im thinking of writing a lisp that doesnt have macroes, nor even lambda

14:41 Chousuke: ambient: it's not lisp then anymore :P

14:41 itistoday: ambient: they are identical to functions except the function arguments are quoted (aren't evaluated)

14:41 ambient: well it is if the language is homoiconic, nested lists

14:42 itistoday: ambient: newLISP "macro": (define-macro (my-macro x y) (println x " " y)) (my-macro x y) => 'x 'y

14:42 ambient: vs: (define (my-func x y) (println x " " y)) (my-macro x y) => nil nil

14:43 ambient: sorry, that last part should be (my-func x y) => nil nil

14:43 ambient: (because x and y weren't defined yet)

14:43 Chousuke: itistoday: so when is the println call done?

14:44 itistoday: Chousuke: when you call my-macro/my-func?

14:44 Chousuke: that's not a macro then :/

14:44 itistoday: yeah i know, it's an f-expr

14:44 newlisp still calls them macros

14:44 ambient was asking what f-exprs were

14:44 Chousuke: itistoday: anyway, hm, binding is not quite like fluid-let I think

14:45 itistoday: Chousuke: what's the difference?

14:45 Chousuke: binding dynamically rebinds vars, not locals

14:46 say you have (def *x* 5), (defn foo [] (println *x*))

14:46 then (let [*x* 3] (foo)) will print 5, but (binding [*x* 3] (foo)) will print 3

14:47 the binding is thread-local, and only in effect within the binding form, of course

14:47 itistoday: Chousuke: isn't that the same as the fluid-let example? i don't see the difference

14:48 sure scheme doesn't have vars (and i haven't gotten to reading about them yet), but the example results in the same values as the fluid-let example

14:49 Chousuke: itistoday: it says that fluid-let talks about lexical variables so I'm not sure

14:50 binding will as a side-effect shadow any lexicals too, but it's meant to allow dynamic scoping of *global* bindings

14:51 hm, the earlier sentence was a bit unclear :P

14:51 itistoday: Chousuke: yeah i'm still parsing it :P

14:51 it's not a big deal though, i'm sure i'll get to it eventually and figure it out

14:52 i think for now i'll just assume they're "similar" and see where that assumption leads me

14:52 ordnungswidrig: hi

14:53 does anybody know about a validation lib for clojure? sth. I can use for input parameter validation?

14:53 Chousuke: itistoday: I guess the difference with fluid-let is that it uses the set! thing which works with lexical locals too in scheme

14:54 itistoday: but in clojure, there is no way to change locals :P

14:55 itistoday: Chousuke: so would it be fine to think of fluid-let as having "all of the functionality of binding, and then some"?

14:55 i.e. it can be used to change locals?

14:56 Chousuke: well, somehow I doubt the changes are thread-safe like in clojure, but otherwise I guess that's right.

14:56 itistoday: right, yeah, they're definitely not thread-safe ;-)

15:11 poet: is whole-numbers a built in sequence?

15:11 Clojure=> (take 10 (whole-numbers))

15:11 #<CompilerException java.lang.Exception: Unable to resolve symbol: whole-numbers in this context (REPL:5)>

15:12 itistoday: ok, why does conj behave different for lists verse vector? for a list it prepends, and for a vector it appends? wtf?

15:12 serp_: ,(+ 2 3)

15:12 clojurebot: 5

15:12 serp_: ,(whole-numbers)

15:12 clojurebot: java.lang.Exception: Unable to resolve symbol: whole-numbers in this context

15:12 itistoday: ,(nth (conj '(1 2 3) 4) 0)

15:12 clojurebot: 4

15:12 itistoday: ,(nth (conj [1 2 3] 4) 0)

15:12 clojurebot: 1

15:13 itistoday: seems like a silly decision to me

15:15 hiredman: itistoday: it's useful, you can build stuff up recursivly using vectors and not have to call reverse when you are done

15:16 serp_: ,(conj [1 2 3] 4)

15:16 clojurebot: [1 2 3 4]

15:16 serp_: ,(conj '(1 2 3) 4)

15:16 clojurebot: (4 1 2 3)

15:16 serp_: ,(5 .4)

15:16 clojurebot: java.lang.Exception: Unable to resolve symbol: .4 in this context

15:16 itistoday: hiredman: it's inconsistent, and i don't think that just because you can "do something" in some particular situation is a good reason to introduce this sort of inconsistency

15:17 hiredman: *shrug*

15:18 itistoday: docs for last also says it takes linear time in the api docs, really? even for vectors? and lists could be linear time as well if you kept a pointer to the tail...

15:18 hiredman: vectors and lists are different datastructures with different chracteristics

15:18 itistoday: ,(doc last)

15:18 clojurebot: "([coll]); Return the last item in coll, in linear time"

15:19 hiredman: coll there should be changed to sequence

15:20 the reason it is linear time is last operates are sequences

15:21 itistoday: weird...

15:21 is there a way to get the last element in constant time?

15:21 (for lists also?)

15:21 hiredman: no

15:21 not for lists

15:21 itistoday: i guess it's not too bad considering there are vectors...

15:22 hiredman: ,(let [v [1 2 3]] (v (dec (count v))))

15:22 clojurebot: 3

15:22 itistoday: yeah

15:22 hiredman: hmm

15:22 ,(doc peek)

15:22 clojurebot: "([coll]); For a list or queue, same as first, for a vector, same as, but much more efficient than, last. If the collection is empty, returns nil."

15:22 hiredman: ↑ there we go

15:22 itistoday: nice! thanks! :-)

15:22 hiredman: ,(peek [1 2 3])

15:22 clojurebot: 3

15:23 itistoday: so clojure has implicit indexing too?

15:23 ,([1 2 3] 0)

15:23 clojurebot: 1

15:23 itistoday: ,([1 2 3] -1)

15:23 clojurebot: java.lang.IndexOutOfBoundsException

15:23 itistoday: eh.. doesn't do that though :-p

15:23 ,('(1 2 3) 0)

15:23 clojurebot: java.lang.ClassCastException: clojure.lang.PersistentList cannot be cast to clojure.lang.IFn

15:23 itistoday: doesn't do that either...

15:23 not very list friendly for a lisp

15:24 hiredman: lists are not functions

15:24 they are associative

15:24 itistoday: neither are vectors...

15:24 hiredman: yes they are

15:24 itistoday: vectors are functions?

15:24 hiredman: sure

15:24 itistoday: docs?

15:25 (news to me)

15:25 (hehe, then probably most of what you tell me will be news, as i'm just learning clojure)

15:25 hiredman: on clojure.org

15:26 since vector is a datastructure, I would checkout the datastructure page

15:27 vectors and maps are functions of their indices and keys

15:27 ,([1 2 3] 0)

15:27 clojurebot: 1

15:27 hiredman: ,({0 1 1 2 2 3} 0)

15:27 clojurebot: 1

15:27 itistoday: hiredman: thanks! "Vectors implement IFn, for invoke() of one argument, which they presume is an index and look up in themselves as if by nth, i.e. vectors are functions of their indices."

15:28 although i don't see why implicit indexing couldn't be done for lists as well

15:29 hiredman: lists are not indexed

15:29 itistoday: yeah but it doesn't mean you can't use implicit indexing on them

15:29 newlisp does it :P

15:30 Chousuke: yeah, but it's slow :P

15:30 hiredman: so?

15:30 if newlisp jumped off a cliff would you?

15:30 Chousuke: it's better not to allow it so that people don't do it accidentally.

15:30 itistoday: hey, you don't have to like it, i just thought it'd be a nifty addition to the language

15:30 Chousuke: itistoday: but conceptually, it doesn't make sense since lists aren't associative :)

15:31 itistoday: hiredman: if newlisp jumped off a cliff i would not follow suit, but if it did it would be quite surprising behavior for it ;-)

15:31 Chousuke: what do you mean by associative?

15:31 hiredman: they aren't functions

15:32 itistoday: neither are vectors!

15:32 hiredman: a map is a function that maps keys to values

15:32 Chousuke: itistoday: a vector associates a numerical index with a value. similarly, a map associates a key with a value

15:32 hiredman: vectors are maps with numerical keys

15:32 Chousuke: itistoday: lists do neither

15:32 itistoday: yeah sure, but this is just conceptual jibber jabber

15:32 a list can associate a value to another

15:32 you define the position in the list as the key

15:32 and what's at that position as a value

15:32 boom

15:33 perfectly mathematically valid

15:33 *how* it's done doesn't matter

15:33 hiredman: that is not a list any more

15:33 Chousuke: itistoday: mathematically that's equivalent to a vector though :P

15:33 hiredman: you can call it a list, but it isn't one

15:33 itistoday: Chousuke: yes, my point though ;-)

15:33 hiredman: how is it not a list?

15:33 Chousuke: itistoday: but in a programming language, thinking that a list is a vector is a bad thing.

15:34 hiredman: it's no longer just a linear collection of things

15:34 itistoday: hiredman: really? then what is it?

15:34 hiredman: or rather do you mean to say it *is* a linear collection of things, but can be thought of as more too? in which case it's still a linear collection of things

15:34 hiredman: it's a numbered linear collection of things

15:35 itistoday: yeah, just like a vector is ;-)

15:35 Chousuke: itistoday: that's the thing. a vector can be thought to be a list with no trouble, but the reverse is not true.

15:35 itistoday: indexing a list by position is stupid

15:36 sometimes easier than the non-stupid thing, yes, but generally stupid :P

15:36 hiredman: since the list doesn't have indexed access, you have to walk it to find the nth thing

15:36 itistoday: yes, i understand that it's inefficient to get to the middle

15:36 fine, ok, i'll back off since clojure supports implicit indexing for vectors

15:36 hiredman: if you want indexed access use a vector

15:36 itistoday: and it probably uses them a whole lot more often

15:36 Chousuke: yeah :)

15:37 itistoday: :-)

15:37 hiredman: having a plurality of datastructures with different characteristics is a good thing

15:37 Chousuke: the list function is not very popular :P

15:37 using a vector is more idiomatic

15:37 itistoday: see, this is news to me, as in newlisp they're almost all you use

15:37 hiredman: functions * datastructures

15:37 itistoday: and actually, in newlisp, functions *are* really lists

15:38 Chousuke: functions are lists in the original lisp too :/

15:38 itistoday: you can actually do this: ((fn () (println "hello")) 0) => "hello"

15:38 Chousuke: wait, what, 0?

15:38 ambient: ehm, you can do that in clojure too

15:39 ((fn [x] (+ x 1)) 0)

15:39 itistoday: ,((fn [x] (+ x 1)) 0)

15:39 clojurebot: 1

15:39 itistoday: hmmm

15:39 why doesn't this work though:

15:40 ,((fn [] "hello") 0)

15:40 clojurebot: java.lang.IllegalArgumentException: Wrong number of args passed to: sandbox$eval--3883$fn

15:40 ambient: that doesn't make any sense

15:40 Chousuke: itistoday: you're passing an argument to a function that takes none :)

15:40 itistoday: whoops

15:40 Chousuke: ,((fn [] (print "this works")))

15:40 itistoday: sorry, lol

15:40 hiredman: 1 vs. 0

15:40 clojurebot: this works

15:40 itistoday: wait.. i've confused myself and all of you

15:40 let me fix my newlisp example...

15:41 (nth 0 (fn () (println "hello"))) => ()

15:41 ambient: clojure doesn't have call/cc though afaik

15:41 itistoday: (nth 1 (fn () (println "hello"))) => (println "hello")

15:41 that's what i meant to do

15:41 Chousuke: itistoday: that's not exactly new.

15:41 itistoday: Chousuke: yeah, i'm not saying it is, was just illustrating that in newlisp functions are lists

15:42 hiredman: is newlisp compiled?

15:42 itistoday: no

15:42 newlisp is a neat language though, i'm not bashing clojure or saying newlisp is better, just that it's nifty

15:43 hiredman: I just can't imagine that having good performance, even in an interpreted lisp

15:43 itistoday: and that i'm coming to clojure from newlisp, and that's why i was surprised when it supported implicit indexing for vectors but not lists

15:43 hiredman: newlisp is fast as hell

15:43 ambient: what does fast as hell mean?

15:43 Chousuke: hiredman: the interpreter probably stores the original code somewhere and keeps an internal object for the actual function

15:43 itistoday: it's extremely fast for an interpreted language

15:44 meaning, it's faster than most other interpreted languages

15:44 ambient: for all intents and purposes, clojure seems like interpreted language to me also

15:44 itistoday: and i've done some rudimentary benchmarks between it and clojure, and they were comparable there, but better benchmarks would be useful

15:44 slashus2: As fast as a pyroclastic flow rolling down a hillside. hehe

15:44 ambient: i don't see any significant difference

15:44 hiredman: clojure is compiled

15:45 everything is turned into jvm bytecode

15:45 itistoday: yeah, there's a big difference

15:45 ambient: hiredman but the application development speed and the power inherent to the language is equal or greater than what interpreted languages have

15:46 itistoday: ambient: what?

15:46 newlisp is fast because it doesn't implement some things that slow clojure and other languages down

15:46 ambient: it used to be that with interpreted languages it was nice to write code, but they were slow. high performance languages were pita to write code

15:47 but in today's world, i don't see any benefit in interpreting, unless one is just building up a new language

15:47 slashus2: itistoday: What slows clojure down?

15:47 itistoday: ambient: it's a good point, but actually clojure can't do some things newlisp can because it's compiled

15:47 ambient: newlisp is very dynamic because it's interpreted

15:47 hiredman: itistoday: if newlisp has comparable to python, then clojure code written with an eye towards peformance should smoke it

15:48 ambient: itistoday i doubt that it's a lot more dynamic than clojure, very much

15:48 clojurebot: clojure is like life: you make trade-offs

15:48 itistoday: hiredman: i would bet that newlisp beats python

15:48 slashus2: I mean clojure can run a live REPL and allows you to inject new code into a running program. That is very dynamic.

15:48 ambient: python isn't exactly the fastest around. compare to lua instead

15:48 itistoday: slashus2: two things i know of are garbage collection and lexical scope

15:49 Chousuke: newlisp doesn't do garbage collection?

15:49 itistoday: slashus2: newlisp has no garbage collection and is dynamically scoped

15:49 icey: what does newlisp interop with? or what does it's library ecosystem look like?

15:49 Chousuke: what does it do then? :|

15:49 slashus2: ahh... well garbage collection algorithms continue to improve, and given the benefits, I don't think that the speed is hit by it as much as you think.

15:49 Chousuke: the JVM's garbage collector is already awesome

15:49 itistoday: icey: it can integrate directly with C very easily

15:50 icey: it's standard library is fantastic too

15:50 Chousuke: lack of lexical scoping worries me though.

15:50 slashus2: The performance argument against garbage collection is not very relevant anymore.

15:50 hiredman: I saw some papers by early lispers that said "hey, we have more and more memory, stop the world gc sucks, so lets just not gc"

15:50 icey: so you can drop to C for speed like you can in python, or java in clojure... is there any ecosystem outside of the standard library?

15:50 ambient: SBCL seems to provide the best performance/power ratio, only thing missing is library support :p

15:50 kotarak: If it has no GC it not interesting...

15:50 icey: that's a big concern for me when i'm writing software; i hate having to rewrite the wheel all the time

15:50 itistoday: icey: what do you mean "ecosystem" there are libraries written for newlisp, yes

15:51 icey: not as many as clojure though

15:51 hiredman: clojure is not targeted at "scripting" either, it is targeted at building large software systems, the same niche as java

15:51 itistoday: hiredman makes an excellent point

15:51 icey: itistoday: like, say on any given day i need an html parser, some way to interop with tokyo cabinet, oauth interop

15:51 itistoday: icey: right, don't use newlisp

15:52 icey: itistoday: gotcha; thanks

15:52 itistoday: btw, don't let the dynamic scope and lack of gc put you off newlisp

15:52 ambient: hiredman although i might just use it for scripting, and thing it could work very well for that. i cant see why not

15:52 hiredman: so it's a scripting language with no libraries...

15:52 itistoday: hiredman: it has libraries, just not as many

15:52 icey: itistoday: do you have to deal with gc yourself? how does it free memory?

15:52 itistoday: icey: no

15:52 hiredman: itistoday: it really sounds like newlisp is a throw back to very early lisps

15:52 which is ok, I guess

15:52 itistoday: just, hold on

15:52 let me explain the gc thing

15:52 hiredman: dynamic scope and lack of gc

15:52 itistoday: in newlisp it's not like C or C++

15:52 memory management is not an issue

15:53 newlisp uses once-only-referencing

15:53 ORO

15:53 or, OOR, don't knwo

15:53 heh

15:53 anyway, most of the time data is copied by-value

15:53 data passed between built-in functions is passed by reference

15:53 Chousuke: http://www.newlisp.org/MemoryManagement.html aha.

15:53 itistoday: yes

15:53 icey: chousuke: reading it now actually haha

15:53 hiredman: early lisps where typically dynamicly scoped

15:53 itistoday: data passed between user-defined functions is copied by value

15:53 clojurebot: functions are maps

15:54 itistoday: hiredman: yes, newlisp is new though

15:54 hiredman: clojurebot: botsnack

15:54 clojurebot: thanks; that was delicious. (nom nom nom)

15:54 Chousuke: itistoday: that sounds fairly inefficient :P

15:54 itistoday: i know

15:54 hiredman: itistoday: if all its ideas are old, how can it be new?

15:54 Chousuke: itistoday: unless it's a functional language.

15:54 itistoday: just, trust me on this, it's fast

15:54 the decisions to not have a GC and use dynamic scope make it fast

15:55 you can benchmark it yourself

15:55 slashus2: newLisp appeared in 1991...hmm

15:55 itistoday: the author is not an idiot

15:55 he consciously chose to forego a GC and use dynamic scope

15:55 (and use fexprs instead of macros)

15:55 hiredman: I'm not saying he is, I am saying newlisp isn't very new

15:55 itistoday: the language is *great* for scripting purposes

15:56 1991 is pretty new for lisp

15:56 hiredman: and hardly modern

15:56 icey: people who like newlisp *really* like newlisp. it just seems to have limited usefulness which isa problem for lazy people like me.

15:56 itistoday: newlisp has its niche where it shines

15:56 i do not recommend it for making huge backends with lots of fancy libraries and whatnot

15:56 hiredman: itistoday: regardless of the creation date, dynamic scope and lack of gc make it sound very similar to the lisps that predated the lisp machines

15:56 itistoday: (which is why i'm learning clojure)

15:57 icey: i'm sure it's earned its fans

15:57 itistoday: hiredman: that's interesting to know

15:57 hiredman: I think scheme was actually the first lisp to popularize lexical scope

15:58 itistoday: The Evelution of Lisp is a great paper to read, Guy Steele and Some Other Dude

15:58 itistoday: newlisp is very useful as a scripting language because of it's built-in library (which has a lot of stuff) and it's extremely small size

15:58 * ambient loves scheme

15:58 itistoday: newlisp is like... about 200k

15:58 *200kb

15:58 it's so small you can actually "link" your script to the binary and send it off to someone

15:59 hiredman: ambient: I had no idea that scheme was originally built to explore the actor model of computation

15:59 ~clojure

15:59 clojurebot: clojure is a very attractive hammer with a nice heft to it

15:59 itistoday: hiredman: thanks for the suggestion

15:59 hiredman: ~clojure

15:59 clojurebot: clojure is not scheme

16:00 kotarak: Richard Gabriel was the "other guy"

16:00 hiredman: kotarak: thanks

16:01 itistoday: just thought it'd be a recommendation here in case you guys are looking for a lisp scripting language, it's worth checking out i think

16:02 it beats the pants off using bash and the others ;-)

16:02 ambient: python is way too good for that for me to consider anything else

16:02 itistoday: ambient: yeah, i like python too, but i already know newlisp and don't have the time to learn python

16:02 kotarak: itistoday: speaking of scripting: did you try scsh?

16:02 * hiredman has written a lot of shell code

16:02 itistoday: kotarak: no...

16:02 icey: you can literally learn a useful amount of python in a week if you know any other programming language

16:02 erm s/week/weekend

16:03 itistoday: kotarak: is that different from tcsh?

16:03 hiredman: ~python

16:03 clojurebot: Gabh mo leithscéal?

16:03 hiredman: bah

16:03 itistoday: icey: yeah, it's very readable, but it has too much syntax, newlisp is more readable i think ;-)

16:03 icey: i had to teach it to myself for a project due in my AI class

16:03 clojurebot: for is not a loop

16:04 ambient: python is basically pseudo-code with very little actual syntax imo

16:04 itistoday: icey: in 3 hours i: 1) learned the language 2) wrote a game in it for the AI class

16:04 icey: itistoday: i wasn't talking about newlisp, you said you didn't have time to learn python and I said it would take a weekend to learn a useful amount of it

16:04 kotarak: itistoday: scsh means scheme shell. http://www.scsh.net/

16:04 hiredman: ~literal [7] clojure

16:04 clojurebot: far closer to perfection then python

16:05 ambient: python isn't perfect, doesn't try to be, and that's one of its strenghts actually :)

16:05 * hiredman is not a python fan

16:05 itistoday: python is a nice language, i definitely agree

16:05 kotarak: itistoday: has nothing to do with tcsh

16:05 hiredman: python has got to be one of the ugliest languages I have ever seen

16:05 itistoday: kotarak: thanks, that looks interesting i'll have a look

16:05 hiredman: I hate it, and I hate that everyone uses it everywhere

16:06 itistoday: hiredman: lol

16:06 ambient: that's not necessarily a very pragmatic approach to things

16:06 itistoday: i like it for how it's readability and relative lack of syntax compared with the other popular scripting languages like Ruby and whatnot

16:07 but i love the concept of lisp - virtually no syntax. it's like heaven after years of C/C++ programming

16:37 wavis: is there a way to get the arity of a function?

16:37 example (if (= 0 (arity the-fn)) (the-fn) the-fn)

16:42 ambient: there seems to have been a way (:arglist ^#'myfunc) but that doesn't seem to work anymore because it exposed actual implementation details

16:44 slashus2: wavis: What are you trying to accomplish?

16:45 wavis: You could overload the function to take multiple number of arguments and "dispatch" from that function to call other functions.

16:46 (fn ([] (print "hi")) ([x] (print x)) ([x y] (print x y)))

16:47 wavis: ,(apply max (map count ((meta #'map) :arglists)))

16:47 clojurebot: 6

16:47 wavis: i think i just answered my own question :)

16:48 i'm trying to build a dumb repo which, when an object is fetched, will call it if it is a function and doesn't accept args

16:49 so as to allow some things not to be stored, but still be accessible

16:49 hiredman: that only works for functions created with defn

16:49 wavis: oh

16:49 hiredman: #'map is the var that the name symbol map refers to

16:49 the metadata is stored on the var

16:51 wavis: this is true. actually my solution should be to use metadata anyway. so i can (put-repo (with-meta (fn [] nil) {:call-with ["one-arg" "and another"]}))

16:52 slashus2: there you go

16:53 wavis: :)

16:56 itistoday: ,(def x [1 2]) (== x [1 2])

16:56 clojurebot: DENIED

16:56 itistoday: well, it would have said false

16:56 why?

16:56 slashus2: use =

16:56 itistoday: i don't understand what the doc says

16:57 slashus2: it does .equals

16:57 rongenre: ,def

16:57 clojurebot: java.lang.Exception: Unable to resolve symbol: def in this context

16:57 rongenre: ,(doc def)

16:57 clojurebot: DENIED

16:57 slashus2: == is for numbers

16:57 rongenre: ,(doc first)

16:57 clojurebot: "([coll]); Returns the first item in the collection. Calls seq on its argument. If coll is nil, returns nil."

16:57 slashus2: , (let [x [1 2]] (= x [1 2]))

16:57 clojurebot: true

16:57 itistoday: slashus2: that's it?

16:58 rongenre: (let [x [1 2]] ) (== x [1 2]))

16:58 er..

16:58 itistoday: ,(let [x [1 2]] ) (== x [1 2]))

16:58 clojurebot: nil

16:58 rongenre: ,(let [x [1 2]] ) (== x [1 2]))

16:58 clojurebot: nil

16:58 itistoday: == is for numbers?

16:58 slashus2: ,(doc ==)

16:58 clojurebot: "([x] [x y] [x y & more]); Returns non-nil if nums all have the same value, otherwise false"

16:58 slashus2: You can use = for numbers too if you want.

16:58 itistoday: so uh, i'm missing the point of == then

16:59 slashus2: It is the same as java's ==

16:59 itistoday: but doesn't java's =='s compare primitives?

16:59 rongenre: ,(.intValue 3)

16:59 clojurebot: 3

16:59 rongenre: Is it a weird autoboxing thing?

16:59 itistoday: and clojure doesn't have primitives right?

17:00 so why would it have ==?

17:00 rongenre: (== 3 3)

17:00 ,(== 3 3)

17:00 clojurebot: true

17:00 slashus2: ,(== (.intValue 3) (.intValue 3))

17:00 clojurebot: true

17:00 ambient: ,(== (int 3) 3)

17:00 clojurebot: true

17:00 wavis: ,(with-meta (fn [] 7) {:stuff true})

17:00 clojurebot: java.lang.UnsupportedOperationException

17:00 rongenre: ,(let [x [1 2]] (== x x))

17:00 clojurebot: false

17:00 rongenre: whoa

17:00 itistoday: wow

17:00 rongenre: that's surprising

17:00 slashus2: itistoday: You can cast things to primitives. Just like ambient just did.

17:01 rongenre: so object identity's a bit weird, huh

17:01 ,(new Object)

17:01 clojurebot: #<Object java.lang.Object@bade60>

17:01 slashus2: ,(let [x [1 2]] (= x x))

17:01 clojurebot: true

17:01 itistoday: slashus2: where did he do that?

17:01 rongenre: ,(let [x (new Object)] (== x x))

17:01 clojurebot: false

17:02 itistoday: ok, i think == needs more than the sentence that's dedicated to it in the docs...

17:02 rongenre: ,(let [x 666] (== x x))

17:02 clojurebot: true

17:02 rongenre: Yeah, object identity's confusing me here.

17:03 ambient: (== [] [])

17:03 ,(== [] [])

17:03 clojurebot: false

17:03 rongenre: Even the same object instances don't == to true.

17:03 slashus2: Just use =.

17:03 =

17:03 itistoday: lol

17:03 rongenre: Well yes ;-)

17:03 itistoday: i'm just wondering wtf this =='s is...

17:04 rongenre: I'm just curious about =='s looking at. And is there unnecessary scaffolding being constructed

17:04 itistoday: you know, google won't even let me search for "=="

17:04 slashus2: It uses (. clojure.lang.Numbers (equiv x y))

17:05 rongenre: google's getting pretty cuil lately isn't it

17:05 slashus2: ,(clojure.lang.Numbers/equiv 5 5)

17:05 clojurebot: true

17:05 rongenre: slashus2: thanks. So if I wanted to look at pointer equality, ='s the way to go.

17:05 slashus2: ,(clojure.lang.Numbers/equiv [] [])

17:05 clojurebot: false

17:06 itistoday: ,(let [x [1 2]] (= x [1 2]))

17:06 clojurebot: true

17:06 rongenre: ,eq

17:06 clojurebot: java.lang.Exception: Unable to resolve symbol: eq in this context

17:06 rongenre: ,eq?

17:06 clojurebot: java.lang.Exception: Unable to resolve symbol: eq? in this context

17:06 slashus2: Yes, because this is only checking for numerical equivalence.

17:06 itistoday: ,(let [x (new Object)] (= x (new Object)))

17:06 clojurebot: false

17:06 slashus2: rongenre: All you need is =

17:07 rongenre: slashus2: = corresponds to java ==, then? Pointer equality, about as fast as you can get?

17:07 itistoday: i don't think so?

17:07 i don't think clojure has java's ==?

17:07 kotarak: (doc identical?)

17:07 clojurebot: "([x y]); Tests if 2 arguments are the same object"

17:07 slashus2: It is different because == only checks for number equality in clojure.

17:08 rongenre: ,(let [x (new Object)] (identical? x x])

17:08 clojurebot: Unmatched delimiter: ]

17:08 rongenre: ,(let [x (new Object)] (identical? x x)

17:08 clojurebot: EOF while reading

17:08 itistoday: ah, yes, identical? is java's ==

17:08 ,(let [x (new Object)] (identical? x x))

17:08 clojurebot: true

17:08 rongenre: done. Cool.

17:09 There's a certain level of 1992 in wondering if I should be using an emacs irc mode.

17:10 itistoday: thanks all, i think i get it, and i now know to simply not use ==. think they should remove it in fact to avoid confusion. ;-)

17:10 slashus2: It is probably faster for number comparison...

17:10 itistoday: slashus2: ok, that would be a good reason to use it.. if true

17:10 slashus2: But, looking under the hood, it looks like clojure.lang.Util/equiv just does an k1 == k2 sort of thing.

17:11 ambient: rongenre no you shouldnt, you should use emacs console, in which you would run screen irssi ;)

17:11 or was it M-x term i forget

17:11 rongenre: ,(identical? 3 3)

17:11 clojurebot: true

17:12 slashus2: Because = will eventually call Numbers.equiv(k1,k2) if k1 is an instance of number.

17:12 Probably little advantage.

17:12 itistoday: how do you use dotimes?

17:12 slashus2: to none

17:13 ,(dotimes [x 5] (print x))

17:13 clojurebot: 01234

17:13 itistoday: gotcha, thanks

17:14 slashus2: chouser: Why does == still hang around? Is it the way the core.clj was implemented?

17:14 rongenre: , (identical? 3 (/ 6 2))

17:14 clojurebot: true

17:15 slashus2: ,(* 1/2 1/3)

17:15 clojurebot: 1/6

17:15 itistoday: ok, found some very interesting results

17:15 check this out

17:15 ,(time (dotimes [n 100000000] (== 3 3)))

17:15 clojurebot: "Elapsed time: 190.169 msecs"

17:15 itistoday: ,(time (dotimes [n 100000000] (== 3 3)))

17:15 clojurebot: "Elapsed time: 10.612 msecs"

17:15 itistoday: ,(time (dotimes [n 100000000] (= 3 3)))

17:15 clojurebot: "Elapsed time: 449.279 msecs"

17:15 itistoday: ,(time (dotimes [n 100000000] (= 3 3)))

17:15 clojurebot: "Elapsed time: 361.286 msecs"

17:15 itistoday: ,(time (dotimes [n 100000000] (identical? 3 3)))

17:15 clojurebot: "Elapsed time: 569.936 msecs"

17:15 itistoday: ,(time (dotimes [n 100000000] (identical? 3 3)))

17:15 clojurebot: "Elapsed time: 583.892 msecs"

17:15 itistoday: so.....

17:15 identical? does not do what we thought

17:15 it's the slowest

17:15 == is the fastest

17:15 chouser: == is for numbers. = for all other value comparisons

17:16 itistoday: yeah

17:16 but check that out

17:16 identical? is super slow!

17:16 why?

17:16 ,(doc identical?)

17:16 clojurebot: "([x y]); Tests if 2 arguments are the same object"

17:16 itistoday: see, wouldn't know that from the doc

17:16 chouser: hm

17:16 slashus2: chouser: I mean there isn't much advantage of using == over = with number comparisons, correct?

17:16 = is very universal

17:16 ambient: in theory with copy-on-write immutable structures it shouldn't be that hard to do an equality test

17:16 itistoday: slashus2: there is, it's faster

17:17 hiredman: ambient: egal

17:17 clojurebot: egal?

17:17 clojurebot: egal is http://home.pipeline.com/~hbaker1/ObjectIdentity.html

17:17 itistoday: why is identical? super slow? anyone know?

17:17 chouser: I believe == can work directly with primitive number types, while = doesn't.

17:17 slashus2: micro-benchmarks don't really do it justice with the jit and everything under the hood.

17:17 * ambient got hit critically with a wall of text for 58 HP and loses conciousness

17:18 slashus2: chouser: Well under the hood = eventually calls Numbers.equiv(k1, k2)

17:18 and Numbers.equiv is overloaded to support primitives.

17:18 hiredman: 1d10

17:18 clojurebot: 5

17:18 hiredman: sorry

17:18 chouser: yeah, that's it: = will always box its args. == can take many combinations of primitive numbers directly

17:18 (show clojure.lang.Util "equiv") vs (show clojure.lang.Numbers "equiv")

17:19 slashus2: if(k1 instanceof Number)return Numbers.equiv(k1, k2);

17:19 Is called from clojure.lang.Util/equiv

17:19 itistoday: ,(time (dotimes [n 100000000] (clojure.lang.Util.equiv 3 3)))

17:19 clojurebot: java.lang.ClassNotFoundException: clojure.lang.Util.equiv

17:19 itistoday: ,(time (dotimes [n 100000000] (clojure.lang.Util/equiv 3 3)))

17:19 clojurebot: "Elapsed time: 441.838 msecs"

17:20 itistoday: ,(time (dotimes [n 100000000] (clojure.lang.Util/equiv 3 3)))

17:20 clojurebot: "Elapsed time: 327.715 msecs"

17:20 itistoday: ,(time (dotimes [n 100000000] (clojure.lang.Numbers/equiv 3 3)))

17:20 clojurebot: "Elapsed time: 219.285 msecs"

17:20 itistoday: ,(time (dotimes [n 100000000] (clojure.lang.Numbers/equiv 3 3)))

17:20 clojurebot: "Elapsed time: 11.967 msecs"

17:20 itistoday: ,(time (dotimes [n 100000000] (clojure.lang.Numbers/equiv 3 3)))

17:20 clojurebot: "Elapsed time: 10.613 msecs"

17:20 itistoday: you know what's fucked up? the incredible performance increase of running it twice

17:20 even though it's doing the same thing 100000000 times

17:20 chouser: itistoday: that's hotspot for you

17:20 hiredman: it's called a JIT

17:20 ambient: why? it got jitted

17:20 slashus2: That is the jit kicking in

17:21 itistoday: yeah i know

17:21 i'm saying that you'd think it'd jit it on the first call

17:21 slashus2: nooo

17:21 itistoday: oh, right

17:21 "hotspot"

17:21 gotcha

17:21 i get it

17:21 lol

17:21 hiredman: maxine compiles everything :)

17:21 no interpreter

17:21 chouser: itistoday: but note you're working with boxed numbers in all those examples.

17:21 hiredman: but I can't get maxine to build

17:22 slashus2: itistoday: Run this on your computer compared to the other (dotimes [x 3] (time (dotimes [n 100000000] (clojure.lang.Numbers/equiv (int 3) (int 3)))))

17:22 itistoday: (dotimes [x 3] (time (dotimes [n 100000000] (clojure.lang.Numbers/equiv (int 3) (int 3)))))

17:22 ,(dotimes [x 3] (time (dotimes [n 100000000] (clojure.lang.Numbers/equiv (int 3) (int 3)))))

17:22 clojurebot: "Elapsed time: 81.941 msecs" "Elapsed time: 2.726 msecs" "Elapsed time: 0.043 msecs"

17:22 itistoday: ,(dotimes [x 3] (time (dotimes [n 100000000] (clojure.lang.Numbers/equiv (int 3) (int 3)))))

17:23 clojurebot: "Elapsed time: 8.832 msecs" "Elapsed time: 2.599 msecs" "Elapsed time: 0.043 msecs"

17:23 itistoday: ,(dotimes [x 3] (time (dotimes [n 100000000] (== (int 3) (int 3)))))

17:23 clojurebot: "Elapsed time: 9.388 msecs" "Elapsed time: 2.644 msecs" "Elapsed time: 0.046 msecs"

17:23 itistoday: yeah == is that function

17:23 ,(dotimes [x 3] (time (dotimes [n 100000000] (== 3 3))))

17:23 chouser: itistoday: please consider running that on your own repl and/or pasting to lisppaste

17:23 clojurebot: "Elapsed time: 192.242 msecs" "Elapsed time: 5.216 msecs" "Elapsed time: 0.045 msecs"

17:23 hiredman: yeah

17:23 please

17:23 itistoday: sorry, k

17:23 but that last result is interesting

17:24 i guess the compiler figured out to not box it or something?

17:24 slashus2: It is a micro-benchmark, it will vary depending on the current computer load.

17:24 itistoday: still, these are consistent numbers

17:24 chouser: probably not. there's so much going on in the JVM, your real results are probably getting lost in the noise.

17:25 hiredman: clojurebot is not a benchmarking platform

17:25 slashus2: haha

17:25 chouser: garbage collection pauses, for example, can make a huge difference.

17:25 itistoday: yeah, i'm just trying to figure out what the heck is going on here

17:25 and i still haven't found out why identical? is so slow

17:26 which means i don't really know what it's doing

17:27 slashus2: Look at core.clj to figure it out. It gives good insights to how the code works under the hood.

17:27 itistoday: slashus2: thanks, will do

17:28 hiredman: identical? is in RT.java actually

17:28 slashus2: Yeah, I just saw that.

17:30 itistoday: is this it: http://pastie.org/649805

17:30 because if it is i'm still at a loss..

17:34 slashus2: itistoday: You would probably have to ask Rich Hickey about it. I wouldn't worry about it too much. The concurrency constructs make up for any performance loss in little things in the language. Overall it is very fast.

17:35 hiredman: I wonder if it just the difference between comparing Objects and primitives

17:35 itistoday: slashus2: k, thanks for the advice. should I ask him on IRC or send email to devlist?

17:35 hiredman: java's == should be comparing primitives (memory addresses) no?

17:35 ambient: what worries me though that with simple processes in other imperical languages i've been able to get ~90% speedups but by using clojure constructs that seems way lower

17:35 in embarassingly parallel problems

17:35 hiredman: itistoday: by the time it gest to java's == the ints are boxed

17:36 gets

17:36 look at the method signature for invoke

17:36 equiv ultimately unboxes before doing the comparison

17:36 itistoday: hiredman: ok, fine, but then why is = still faster?

17:36 boxing still occurs there..

17:37 on my machine it's over twice as fast

17:38 sorry, i'll ask hickey ... if i see him on the channel i guess

17:38 hiredman: itistoday: I haven't checked, but I imagine = is distpatching to equiv

17:38 where the numbers are unboxed before being compared

17:39 itistoday: i can't see how that would speed it up though

17:39 as both box the numbers

17:39 and identical? just compares the pointer values

17:40 chouser: identical? is about 10x faster than = for me.

17:40 oh. when the answer is false, anyway.

17:41 itistoday: hmm... i'm using the git checkout from git://github.com/richhickey/clojure.git

17:41 alpha of 1.1.0

17:41 hiredman: it's possible the jvm has some kind of scary optimizer for primitive comparisons

17:42 itistoday: what are you using identical? for?

17:42 itistoday: or... perhaps it's the other way around, it has some kind of scary inefficiencies in comparing pointers?

17:42 hiredman: i'm just learning

17:42 was experimenting with: (time (dotimes [n 100000000] (identical? 3 3)))

17:43 wanted to see the various comparison functions in clojure and what the differences were

17:43 hiredman: so you aren't actaully doing anything with it

17:44 itistoday: i'm not "actually doing" anything with clojure yet, but i hope to

17:44 and it seems like identical? could be a very useful function to know about

17:44 hiredman: not really

17:44 Chousuke: it is useful, but it's mostly for optimisation

17:44 itistoday: well, comparing things for equivalency is pretty common

17:44 hiredman: I don't thing I've ever used it

17:44 itistoday: that is what = is for

17:45 Chousuke: ,(identical 3 3)

17:45 clojurebot: java.lang.Exception: Unable to resolve symbol: identical in this context

17:45 Chousuke: ,(identical? 3 3)

17:45 clojurebot: true

17:45 Chousuke: ,(identical? 3 (long 3))

17:45 clojurebot: false

17:45 Chousuke: you need to be *very* careful with it.

17:45 chouser: ,(identical? 3 (Integer. "3"))

17:45 clojurebot: false

17:45 itistoday: ,(identical? 3 (int 3))

17:45 clojurebot: true

17:45 itistoday: Chousuke: i know

17:45 hiredman: clojurebot's source and the checkout of ring I have laying around both don't have any any calls to identical?

17:46 compojure is also free of calls to identical?

17:46 chouser: I've sometimes used == instead of = for optimization, but never resorted to 'identical?'

17:46 * kotarak would like to see working code instead of all the "optimised" code (most of the time "optimised" means "slow and broken").

17:46 chouser: I think I've only ever used 'identical?' for sentinel comparisons.

17:46 itistoday: i just saw hickey use it in his talk on sequences, so that's where i know of it

17:47 Chousuke: hmm

17:47 hiredman: well, that must be the only place it's used

17:47 Chousuke: ,(identical? :foo (keyword "foo"))

17:47 clojurebot: true

17:47 itistoday: lol

17:47 Chousuke: I think that's guaranteed :)

17:47 so identical? should be okay for keyword comparisons at least.

17:48 hiredman: but why?

17:48 itistoday: they're singletons?

17:48 kotarak: = does a == anyway?

17:48 itistoday: kotarak: no

17:48 == is for numbers, it calls something else

17:48 hiredman: itistoday: not why is that true, why bother to use identical? on keywords?

17:48 kotarak: itistoday: I mean the Java ==

17:48 itistoday: hiredman: ah

17:48 chouser: ,(let [not-found (Object.)] (if (identical? not-found (get {:a nil :b false :c 1} :d not-found)) "not found" "found it"))

17:48 clojurebot: "not found"

17:49 itistoday: kotarak: = calls .equals

17:49 newbie question: what does (Object.) mean?

17:49 hiredman: clojurebot: new

17:49 clojurebot: new Class(x) is (Class. x)

17:49 itistoday: ah, shorthand for (new Class)?

17:49 Chousuke: yeah

17:49 itistoday: k thanks

17:52 kotarak: itistoday: The first thing = does in Util/equiv is checking Java ==

17:53 mrpika: what's the difference between symbols and keywords?

17:53 aren't they pretty much the same thing?

17:53 kotarak: mrpika: keywords evaluate to themselves

17:53 ,:foo

17:53 clojurebot: :foo

17:53 kotarak: ,foo

17:53 Chousuke: also you can have multiple instances of the same symbol

17:53 clojurebot: 5

17:53 Chousuke: kotarak: haha, got lucky.

17:53 kotarak: And hence Symbols can carry metadata, while keywords cannot

17:54 * Chousuke def'd that foo earlier

17:54 mrpika: what's the significance of having multiple instances?

17:54 kotarak: mrpika: metadata

17:54 mrpika: and as for the self-evaluation, why not just get friendly with the quote?

17:54 hiredman: ,(prn 'f)

17:54 clojurebot: f

17:54 hiredman: ^- how do you read that back in?

17:54 Chousuke: mrpika: it's not as nice if you're using keywords as map keys :)

17:55 kotarak: mrpika: print a keyword and read it back, you get the same. Read with hiredman does and see the problem with Symbols.

17:55 itistoday: kotarak: thanks, didn't know that. (though i thought you meant clojure's ==, not java's ==)

17:55 Chousuke: actually

17:55 ,(read-string "f")

17:55 clojurebot: f

17:55 Chousuke: is there a problem? :)

17:55 kotarak: itistoday: I tried to clarify that...

17:55 mrpika: okay

17:55 i see the point

17:56 thanks, been wondering about that for a while

17:56 itistoday: kotarak: ah, i see that, sorry! :P

17:56 mrpika: i've never seen a keyword in scheme

17:56 Chousuke: mrpika: I guess keywords are mostly a convenience

17:56 kotarak: mrpika: there are no keywords in Scheme.

17:57 Chousuke: mrpika: you could do without them, but why should you. they're great for maps

17:57 mrpika: i know, that's why i wondered about the usage in lisp

17:58 hiredman: common lisp has them, I think

17:58 mrpika: yeah

18:01 itistoday: hey i just found something really cool, check this out:

18:01 ,(def x =)

18:01 clojurebot: DENIED

18:01 itistoday: arg!!

18:01 Chousuke: heh

18:02 ,#=(def x #=(eval =))

18:02 clojurebot: EvalReader not allowed when *read-eval* is false.

18:02 Chousuke: ooh, yay

18:02 it's fixed.

18:03 itistoday: so what's cool?

18:03 itistoday: ,(x = x)

18:03 clojurebot: java.lang.Exception: Unable to resolve symbol: x in this context

18:03 itistoday: ,(def x =)

18:03 clojurebot: DENIED

18:03 itistoday: eh

18:03 Chousuke: heh :P

18:03 itistoday: you get the idea ;-)

18:04 or (= x =) ; <-- TIE fighter

18:05 mrpika: (let [x =] (x = x))

18:05 ,(let [x =] (x = x))

18:05 clojurebot: true

18:05 itistoday: thanks :-)

18:05 shoulda seen that

18:05 mrpika: np

18:05 itistoday: Chousuke: what did you do there? #=(def x #=(eval =))

18:06 can't figure it out from here http://clojure.org/reader

18:08 um... what would happen if i typed ,(while true)?

18:08 would clojurebot die?

18:09 if anyone doesn't want me to type ,(while true) speak now or forever hold your peace

18:09 whoppix: itistoday, it's most likely secured against that kind of simple attack :)

18:09 itistoday: let's see...

18:09 ,(while true)

18:09 ,(+ 1 1)

18:09 mrpika: is there an admin that can restart it

18:09 clojurebot: Execution Timed Out

18:09 mrpika: ?

18:09 clojurebot: 2

18:09 itistoday: oh nice

18:09 mrpika: nice

18:10 long running fuctions prohibited

18:10 functions

18:10 whoppix: itistoday, most eval bots of that kind fork off, cage the process in a chroot/jail/vm, restrict it's filehandle/ptrace it, put an alarm to kill it after a while, something more tricky like that.

18:10 itistoday: whoppix: thanks, good to know

18:11 whoppix: itistoday, have a stab at buubot in #buubot, it evals about 20 different languages (not clojure yet, though)

18:11 itistoday: whoppix: it auto-detects the language?

18:12 whoppix: itistoday, nope, you have to tell it what language you want.

18:12 itistoday: gotcha

18:12 will do some other time, gotta get back to reading clojure docs

18:12 whoppix: Have fun

18:12 itistoday: will do

18:14 mrpika: would there be any value in having a reader macro for dosync

18:14 so instead of (dosync alter ...) you could just type %(alter ...)

18:14 ?

18:14 or similar

18:15 Chousuke: mrpika: often dosync contains multiple expressions so a reader macro like that wouldn't be very useful

18:15 and I don't think dosync is so special that it needs a reader macro :)

18:15 mrpika: ah

18:33 Luyt: I guess that as easy it is to use java libraries from within clojure, it's also easy to use clojure functions from java?

18:34 javajeff: Lyut - there are some examples of calling clojure from Groovy at http://groovy.codehaus.org/Calling+Clojure+from+Groovy

18:34 itistoday: how does class? work?

18:35 ,(doc class?)

18:35 clojurebot: "([x]); Returns true if x is an instance of Class"

18:35 itistoday: what class..?

18:35 clojurebot: class

18:35 clojurebot: To use an inner class Foo.Bar, import it with (import 'Foo$Bar), and you can refer to the class as Foo$Bar

18:36 faux: ,(class 123)

18:36 clojurebot: java.lang.Integer

18:37 itistoday: not class but class?

18:37 heh, that sounds funny if you read it as a question

18:37 Luyt: javajeff: Thanks for the pointer.

18:38 faux: ah well that would be a comparison to the class Class

18:41 itistoday: faux: ah thanks, how do you do instanceof?

18:42 kylesmith: does anyone know the status of the rdf stuff?

18:43 faux: itistoday: look at isa?

18:43 itistoday: faux: thanks

18:44 that looks like it

18:45 kotarak: (doc instance?)

18:45 clojurebot: "([c x]); Evaluates x and tests if it is an instance of the class c. Returns true or false"

18:45 kotarak: ,(instance? String "foo")

18:45 clojurebot: true

18:45 kotarak: ,(isa? String "foo")

18:45 clojurebot: false

18:46 kotarak: ,(isa? String (type "foo"))

18:46 clojurebot: true

18:46 itistoday: :-), i was just about to say...

18:47 faux: much better

18:48 itistoday: ,ints

18:48 clojurebot: #<core$ints__6041 clojure.core$ints__6041@100e398>

18:48 itistoday: err

18:48 ,(doc ints)

18:48 clojurebot: "([xs]); Casts to int[]"

18:48 itistoday: how do you use that?

18:48 Luyt: ,(doc doc)

18:48 clojurebot: "([name]); Prints documentation for a var or special form given its name"

18:51 kotarak: ,(ints (to-array [1 2 3]))

18:51 clojurebot: java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [I

18:52 kotarak: ,(ints (into-array Integer [1 2 3]))

18:52 clojurebot: java.lang.ClassCastException: [Ljava.lang.Integer; cannot be cast to [I

18:52 kotarak: hmmm...

18:52 ,(ints (into-array Integer/TYPE [1 2 3]))

18:52 clojurebot: #<int[] [I@1347991>

18:52 Luyt: ,(println (str "codepad" "." "org"))

18:53 clojurebot: codepad.org

18:53 itistoday: kotarak: and then what do you do with the output of ints?

18:54 kotarak: itistoday: (defn foo [x] (let [x (ints x)] ...)) ... (foo (into-array Integer/TYPE [ 12 3])) might be a use

18:54 hiredman: ~performance

18:54 clojurebot: http://clojure.org/java_interop#toc46

18:54 kotarak: itistoday: ints avoids boxing in tight loops.

18:56 itistoday: ah gotcha

18:56 hiredman: thanks

18:56 so aget is what i was looking for

18:56 ,(doc aget)

18:56 clojurebot: "([array idx] [array idx & idxs]); Returns the value at the index/indices. Works on Java arrays of all types."

18:57 itistoday: peace all

22:09 icey: so have any of you guys switched over to using clojure as your primary web stack yet?

22:51 solussd: I'm trying to configure a clojure dev environment in emacs using 'M-x clojure-install'. After it sets everything up and I run "M-x slime" it works, until I restart emacs. Any suggestions?

22:52 tomoj: did you add the stuff to your .emacs?

22:57 solussd: what is "the stuff"? :)

23:07 The wiki (http://en.wikibooks.org/wiki/Clojure_Programming/Getting_Started#Emacs_.2F_inferior-lisp) doesn't talk about adding anything to my .emacs when using 'clojure-install'.

23:16 arbscht: solussd: supposedly, when clojure-install completes, it will give you some instructions on what to add to your emacs init file

23:17 solussd: I'll run the install again and see if I can catch that.

23:18 arbscht: "Add a call to \"\(clojure-slime-config\)\"

23:18 to your .emacs so you can use SLIME in future sessions."

23:18 something like that

23:23 solussd: yep. that was it. thanks!

23:24 One more question- I'm still not able to "C-c C-e" to evaluate a line. When I run that I get "Slime Eval:" instead of it running the sexp in the repl

23:24 arbscht: C-c C-c to evaluate a top level form

23:25 well, compile and eval

23:25 well, compile and eval are different

23:25 typically you compile from a buffer and eval in a repl

23:27 solussd: I'd like to have the behavior rich hickley has set up in emacs- where he evaluates a line in this source file in the repl by hitting a key combination

23:27 arbscht: C-M-x will eval a top level form

23:29 solussd: excellent. thanks again

23:29 arbscht: C-x C-e will eval the last expression

23:30 solussd: ah, that's what i was looking for

Logging service provided by n01se.net