#clojure log - Oct 24 2010

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

1:03 defn: oh my god. so much email to catch up on post-conj

2:01 wooby: defn: sup!

4:51 _ulises: morning

5:50 how can I reset an ns so that I don't get illegal bindings?

6:54 raek: _ulises: either (in-ns 'some-other-ns) (remove-ns 'the-ns) or (ns-unmap 'the-ns 'conflicting-var)

7:54 _ulises: raek: thanks

8:10 ulises: why am I getting 'unmatched delimiter )' here: http://paste.lisp.org/display/115855

8:10 :(

8:14 MayDaniel: ulises: The metadata needs to come before the namespace.

9:07 raek: _ulises: also, it is possible to do it like this: lastfm-clj.core

9:07 eh

9:07 (ns lastfm-clj.core "Core functions for lastfm-clj" {:author "Ulises Cervino Beresi"} ...)

9:41 bytesource: Hi all! I am currently reading the chapter on HBase of 'Clojure in Action'. I downloaded HBase but have no idea of how to install it on Linux. I couldn't find a simple manual either on the web. Does anybody know how to do the install? I am using Leiningen and Emacs.

9:46 kumarshantanu: ubuntu has apt-get for HBase/Hadoop?

9:48 tomoj: no

10:02 ulises: MayDaniel: thanks

10:32 Sweetshark: How do I access the static "class" member of a class object, i.e. what I write "Object.class" in Java returning the type?

10:33 _ulises-: I believe it's class

10:33 ,(class "foo")

10:33 clojurebot: java.lang.String

10:33 tomoj: ,String

10:33 clojurebot: java.lang.String

10:33 _ulises-: oh, wait

10:33 (,String/class)

10:33 ,(String/class)

10:33 clojurebot: java.lang.NoSuchFieldException: class

10:34 _ulises-: ,String/class

10:34 clojurebot: java.lang.Exception: Unable to find static field: class in class java.lang.String

10:34 _ulises-: hrm

10:34 tomoj: ,(class String)

10:34 clojurebot: java.lang.Class

10:34 kumarshantanu: ,(String/getClass)

10:34 clojurebot: java.lang.NoSuchFieldException: getClass

10:35 tomoj: Sweetshark: (just write "Object")

10:35 kumarshantanu: ,(.getClass "Whatever")

10:35 clojurebot: java.lang.String

10:37 Sweetshark: tomoj: actually (class String) looks like what I want ...

10:41 meh, not quite ... but (Class/forName "java.lang.String") should do for now ...

10:43 _ulises-: Sweetshark: what are you trying to do anyway?

10:44 Sweetshark: _ulises-: http://api.openoffice.org/docs/java/ref/com/sun/star/uno/UnoRuntime.html#queryInterface%28java.lang.Class,%20java.lang.Object%29

10:44 tomoj: Sweetshark: what?

10:44 ,(= (Class/forName "java.lang.String") String)

10:44 clojurebot: true

10:44 tomoj: just write "String"...

10:45 _ulises-: right

10:48 rdeshpande: anyone else having issues getting labrepl to 'lein deps'?

10:50 Sweetshark: tomoj _ulises-: well it parses of the repl, thanks so far ...

10:52 _ulises-: rdeshpande: I've cloned a fresh labrepl and doing lein deps as we speak

10:52 so far, no issues

10:57 rdeshpande: right, lein deps has finished without issues, what issues are you encoutering? what arch? which version of labrepl? etc.

11:03 defn: hey all

11:06 _ulises-: hey defn

11:08 rdeshpande: _ulises-: im seeing this http://pastie.org/1245060 - but where is 1.2.0beta1 coming from? i dont' see 'beta1' anywhere grepped in the repo. shouldn't it just be getting 1.2?

11:09 raek: http://build.clojure.org/releases/org/clojure/clojure/ it exists here

11:09 _ulises-: this is what I have on my project.clj: http://pastie.org/1245065

11:09 see if there's anything different with yours?

11:10 maravillas: perhaps it's a transitive dependency

11:12 rdeshpande: _ulises-: nope, same exact ting

11:12 maravillas: is your labrepl up to date?

11:12 rdeshpande: yep

11:12 just cloned

11:12 _ulises-: rdeshpande: tried pulling from ... oh

11:13 I can also see you're on OS X, like me :/

11:13 maravillas: hm, i just grabbed its deps and got 1.2, not beta1

11:13 oh, nevermind

11:13 _ulises-: same for me

11:13 maravillas: it's a dev-dep

11:13 rdeshpande: could it be something in my home dir?

11:13 maravillas: either autodoc or swank-clojure must depend on it

11:14 regardless, though, i was able to grab it

11:14 rdeshpande: hmm

11:14 very odd

11:15 maravillas: hm, nope

11:15 well, that's beside the point anyway

11:15 actually, i bet i had mine cached locally

11:18 _ulises-: rdeshpande: I suppose that telling you to start afresh is pointless?

11:19 rdeshpande: not sure how much fresh it could be :/

11:19 *how much more

11:19 _ulises-: did you *just* do a clone?

11:19 I did mine when you asked the question actually

11:20 defn: Can someone refresh my memory on :use in the (ns) macro

11:20 specifically how to use :as with :use

11:20 maravillas: _ulises-: the latest isn't working for me either, after i deleted the cached copy in ~/.m2

11:21 defn: (:use clojure.contrib [io :as foo])

11:21 _ulises-: maravillas: oh :(

11:22 what about leiningen? do you have the latest version?

11:22 maravillas: i don't understand why, unfortunately, since beta1 is still available on the build site

11:27 rdeshpande: as a workaround, you could try downloading clojure-1.2.0-beta1.jar, .jar.sha1, .pom, and .sha1 from http://build.clojure.org/releases/org/clojure/clojure/1.2.0-beta1 and putting them in ~/.m2/repository/org/clojure/clojure/1.2.0-beta1

11:27 it's not the right answer...someone else might have more insight

11:32 wooby: defn: http://gist.github.com/284277

11:32 KLll: guys

11:33 I have a vector

11:33 (def some-vec [1 2 3])

11:33 what's the best way to modify it

11:33 defn: wooby: !!

11:33 _ulises: KLll: you don't?

11:33 KLll: (def some-vec (assoc some-vec 2 3))

11:33 or what?

11:33 defn: wooby: you sir, are a saint

11:34 _ulises: why do you need to modify it?

11:34 KLll: I want to add to it

11:34 or change it

11:34 for instance I have a vector of maps or listeneres to events

11:35 _ulises: assoc is possibly what you want

11:35 wooby: KLll: in clojure the modification of things by re-deffing them is discouraged, there are special types for handing variables that can change over time. atom is probably the one you should check out

11:35 KLll: adding a listener requires changing a map, then associng that map into the vector, then I have to rebind the vector

11:35 _ulises: keep in mind that if you do (assoc [] 1 1) you'll get out of bounds exceptions

11:35 also what wooby said

11:35 wooby: (def my-vec (atom [1 2 3]))

11:36 KLll: http://clojure.org/atoms

11:37 i now giggle every time i see fib used as an example anywhere

11:38 maravillas: it's now possible to reference fib ironically

11:39 KLll: the thing is

11:39 kumarshantanu: is it possible to access clojure.repl/source in code? (instead of REPL)

11:39 KLll: in nearly every program I have some state

11:39 kumarshantanu: ,(source source)

11:39 clojurebot: java.lang.Exception: Unable to resolve symbol: source in this context

11:39 KLll: that changes

11:39 so the atoms are the way to do it?

11:39 kumarshantanu: ,(clojure.repl/source source)

11:40 clojurebot: Source not found

11:40 raek: keyword args question: if I do a (foo :a 1 :b 2) call, I want to get 'options' bound to {:a 1, :b 2}. is (defn foo [& {:as options}] ...) the correct way to do that?

11:40 wooby: kumarshantanu: (use 'clojure.contrib.repl-utils) (source atom)

11:41 raek: or, I guess my question is "when does function arguments automagically become maps="

11:41 wooby: KLll: not always - there are also refs and agents

11:41 KLll: how do you decide between using an atom and using a ref

11:42 raek: KLll: refs are for when you might need to coordinade changes of multiple refs

11:42 with atoms, you can't do that

11:42 KLll: I see that

11:43 raek: so, if you have something internally that only you use, (like a counter or something) you could use an atom

11:43 but when others need to use it too, it might be better to use refs to be on the safe side

11:44 wooby: good screencasts that cover the use cases for refs/atoms/agents: http://www.pluralsight-training.net/microsoft/olt/course/toc.aspx?n=clojure-concurrency-tutorial

11:44 bmh: does clojure have a function like Haskell's zip or zipWith? (map over two collections simultaneously)

11:45 opqdonut: ,(map + [1 2 3] [4 5 6])

11:45 clojurebot: (5 7 9)

11:45 bmh: oh. That's convenient.

11:45 opqdonut: ,(map vector [1 2 3] [4 5 6])

11:45 clojurebot: ([1 4] [2 5] [3 6])

11:46 wooby: bmh: there's also zipmap

11:46 opqdonut: which is mostly unrelated

11:46 wooby: does the haskell thingy not return a map?

11:46 bmh: it doesn't

11:47 wooby: ah

11:47 raek: zip returns tuples

11:47 bmh: The type of zip is: [a] -> [b] -> [(a,b)]

11:47 wooby: ignore me :)

11:47 opqdonut: haskell's zip does what map vector does

11:47 zipWith does what clojure's map does

11:48 bmh: sometimes I think programming in clojure would be easier if I didn't know scheme/haskell

11:48 I'd have read the manual.

11:54 KLll: hi

11:56 sup

11:56 TheAnimal4: Yo yo yo KLll

12:01 defn: wooby: fib is important to programming

12:01 factorial is also really important to what we do everyday.

12:02 thinking out loud: im not sure what i'd do if i didnt have factorial, probably just code hello world over and over

12:03 rdeshpande: bmh: what is your impression so far coming from haskell?

12:04 bmh: rdeshpande: from scheme might be a little more fair. I really dig the loop-recur construct

12:04 multimethods are wonderful

12:07 defn: i like functions :D

12:07 _ulises: I recently found a use for protocols ... go figure :D

12:07 defn: im making a conscious effort post-conj to use some more protocols in my code

12:07 _ulises: well, more like I just came across a case where I thought "thank god for protocols"

12:08 defn: chouser's finger tree code makes some nice use of protocols

12:09 jarpiain: Ok, my port of the clojure compiler into clojure seems now capable of compiling itself. Time to release :)

12:09 http://github.com/jarpiain/cljc

12:09 bmh: rdeshpande: I think the interop is my favorite feature. At the absolute worst, it makes clojure as good as java.

12:09 Praise be to Technomancy for giving us Lein.

12:09 defn: don't forget the cake :)

12:10 gfrlog: clojure is not as good as java at worst

12:11 it lacks most of the static benefits

12:11 defn: if i wanted to use statics i wouldnt be using clojure in the first place

12:11 opqdonut: why not

12:12 defn: i want a dynamic language.

12:12 gfrlog: my point was that if I'm going to resort to using clojure by just calling java, I'll get a lot more benefit out of using java as java

12:12 opqdonut: clojure could be a great dynamic language with optional static features

12:12 common lisp is quite good at being both static and dynamic

12:12 defn: gfrlog: it depends.

12:12 bmh: I want a type system ;-)

12:13 gfrlog: defn: what do you mean?

12:13 bmh: It's absurd that the jvm doesn't support tco

12:13 gfrlog: bmh: it makes sense to me, assuming they designed it for java

12:13 defn: gfrlog: it depends on what you care about. if you're only concerned with the benefits of statics then okay, but who the heck cares about just one thing?

12:14 i want an expressive language. i want maintainable code.

12:14 bmh: gfrlog: Not in the slightest. Java is an OO language. You program in an OO language by calling methods.

12:14 gfrlog: defn: nobody of course, but static benefits are huge

12:14 defn: I'm assuming a hypothetic world (i.e., "at worst") where the best use you can make of clojure is to pretend it's java using the interop

12:14 bmh: gfrlog: If you don't have tail-calls, eventually your method calls smash the stack. Therefore, you can't write OO java!

12:14 KLll: I find my code less maintainable in clojure

12:15 defn: gfrlog: yeah, in the real world things are a bit different ;)

12:15 gfrlog: bmh: clearly you can -- you use for loops instead of recursive algs

12:15 defn: they are. I spend too much time on theory sometimes.

12:15 KLll: any recursion can be changed into iteration

12:15 somnium: bmh: have you read GVR's manifesto against tail calls and fp in general?

12:15 kumarshantanu: any CCW user here?

12:16 bmh: somnium: I did. I don't think much of him.

12:16 somnium: Have you read Xavier Leroy's rants about kernel threads in Ocaml?

12:16 defn: who is GVR

12:16 oh... nvm

12:16 bmh: Guido

12:16 defn: guido

12:16 if you have a link ill entertain it :)

12:16 somnium: bmh: I have not. I just wanted to mention my amazement that a language designer would be openly hostile to such fundamentally useful features

12:17 bmh: somnium: I think Guido is a turd.

12:17 defn: somnium: the human condition sucks

12:17 you make a decision so you have to hate all other decisions or something

12:17 it's ludicrous

12:18 gfrlog: sunk cost fallacy

12:18 or something similar

12:18 _ulises: perhaps larry wall is the king of inflammatory remarks

12:18 bmh: Xavier is a bit of a different story. Fire up your favorite GNU/Linux distro and type 'man pthread'

12:18 defn: perhaps larry wall is the worst speaker i've ever seen

12:18 bmh: "linuxthreads-0.10 by Xavier Leroy", it makes his opposition to kernel threads seem slightly less insane

12:18 gfrlog: $ man pthread

12:18 bmh: defn: I agree entirely.

12:18 gfrlog: No manual entry for pthread

12:18 bmh: pthreads, sorry

12:18 defn: bmh, did we meet yesterday?

12:19 gfrlog: much better

12:19 bmh: defn: We didn't.

12:19 defn: heh sorry -- im trying to do post-conj association

12:19 so many twitter handles and nicks and names in my head atm

12:19 bmh: I last saw Larry Wall speak in... 2007?

12:19 gfrlog: I was that guy sitting in one of the chairs

12:19 defn: gfrlog: omg. same.

12:20 gfrlog: defn: damn, we should've talked

12:20 defn: i know. next time you're at a conference talk to the guy in the chair, that'll be me.

12:20 gfrlog: okay

12:20 defn: unless he's not, in which case: keep trying.

12:20 gfrlog: two or three tries max I'm sure

12:21 * defn chuckles

12:21 defn: the sarcasm is palpable

12:21 gfrlog: and sticky

12:21 defn: indeed. *investigates the palp closely*

12:22 as in palpus

12:22 bmh: Does clojure have a function like "conj-with" for shoving things into a map? (i.e. If a key already exists, then use some function to combine the values)

12:22 _ulises: bmh: merge-with

12:22 ,(doc merge-with)

12:22 clojurebot: "([f & maps]); Returns a map that consists of the rest of the maps conj-ed onto the first. If a key occurs in more than one map, the mapping(s) from the latter (left-to-right) will be combined with t...

12:23 defn: will be combined with the mapping in the result by calling (f val-in-result val-in-latter).

12:24 KLll: Hi

12:24 TheAnimal4: Greetings KLll

12:24 KLll: my greeter bot :P

12:24 defn: epic.

12:24 Hi

12:24 TheAnimal4: Greetings defn

12:24 KLll: :P

12:24 gfrlog: clojurebot: hey

12:24 clojurebot: hey is for horses

12:25 * defn does an irc bot dance

12:25 bmh: _ulises: sure, but merge with noms a pile of maps, oh, I guess it'll work

12:25 KLll: hello

12:25 TheAnimal4: Greetings KLll

12:25 KLll: sup

12:25 TheAnimal4: Yo yo yo KLll

12:25 _ulises: bmh: you can always use {} as one of the maps

12:25 bmh: I suppose you could also use reduce?

12:26 defn: heh -- any new language, if it wants to be successful, needs to have a separate channel for the inevitable irc bot experimentation that will occur

12:26 _ulises: I'm not familiar with conj-with unfortunately

12:26 KLll: next up: let's plug it into Warhammer item database so it will quote stats into the channel :P

12:26 bmh: KLll: why don't you write a bot that finds arbitrage opportunities in Warhammer? ;-)

12:26 KLll: maybe I should look into some textual analysis

12:27 defn: linkparser maybe?

12:27 KLll: so it picks out buzzwords out of random chat

12:27 then repeats statements about that buzzword from weeks ago

12:27 defn: "web 2.0", "agile", etc.

12:27 KLll: that would troll many people

12:28 defn: set up some future/promise or agent type thing that, when someone responds, tells them in no uncertain terms they have been trolled

12:28 KLll: hahahah

12:29 defn: there's this hillarious library for clojure that generates business BS, like "synergizing business ROI with gold futures"

12:29 err for ruby, it's called "faker"

12:30 KLll: something like that

12:30 I recall a channel where they had a bot named

12:30 gothgirl19

12:30 or something like that

12:31 it regurtiated back statements converted into questions

12:31 defn: heh yes ive seen that trolling mechanism in action -- i used to know someone who did a similar thing with a bot named "cutie5484"

12:31 KLll: when they looks at chat logs there were a surprising amount of people trying to pick up the bot and talking to the bot for hours

12:32 kumarshantanu: is it possible to get the name of a function as string? map? --> "map?"

12:32 defn: sure

12:33 gfrlog: um

12:33 really?

12:33 kumarshantanu: defn: how?

12:33 gfrlog: is it in the metadata?

12:33 somnium: kumarshantanu: from the runtime representation?

12:33 defn: there are a few ways

12:33 * defn pulls up his repl

12:33 defn: ,(str (:name (meta #'and)))

12:33 clojurebot: "and"

12:34 kumarshantanu: ,(str (:name (meta map?)))

12:34 clojurebot: ""

12:34 KLll: why the #'?

12:34 defn: interesting...

12:34 KLll: isn't ' enough??

12:35 gfrlog: '(let [my-fun vector?] (str (:name (meta #'my-fun))))

12:35 KLll: ,(str (:name (meta 'map?)))

12:35 clojurebot: ""

12:35 gfrlog: ,(let [my-fun vector?] (str (:name (meta #'my-fun))))

12:35 clojurebot: java.lang.Exception: Unable to resolve var: my-fun in this context

12:35 gfrlog: I suck at commas

12:35 defn: ,(meta 'map?)

12:35 clojurebot: nil

12:35 defn: ,(meta #'map)

12:35 clojurebot: {:ns #<Namespace clojure.core>, :name map, :file "clojure/core.clj", :line 2079, :arglists ([f coll] [f c1 c2] [f c1 c2 c3] [f c1 c2 c3 & colls]), :added "1.0", :doc "Returns a lazy sequence consisti...

12:35 gfrlog: ,(let [my-fun vector?] (str (:name (meta my-fun))))

12:35 KLll: ,(str (:name (meta #'map?)))

12:35 clojurebot: ""

12:35 "map?"

12:35 defn: there ya go :)

12:35 KLll: ,(meta 'map)

12:35 clojurebot: nil

12:35 defn: there's another way too but im failing to remember it

12:36 KLll: seriously, what's the difference between ' and #'

12:36 raek: ,(class 'conj)

12:36 clojurebot: clojure.lang.Symbol

12:36 raek: ,(class #'conj)

12:36 defn: quote, var quote

12:36 clojurebot: clojure.lang.Var

12:37 kumarshantanu: how do I #" inside a macro?

12:37 defn: KLll: #' is var quote, ' is quote

12:37 somnium: ah, map? is defined with `def', not `defn', so I guess the metadata doesn't get attached to the function object?

12:37 raek: the metadata usually go on the var object rather than the fn object

12:37 KLll: could be

12:38 raek: but since 1.2, fns can have metadata too

12:38 defn: ,(meta #'map?)

12:38 clojurebot: {:ns #<Namespace clojure.core>, :name map?, :file "clojure/core.clj", :line 149, :arglists ([x]), :doc "Return true if x implements IPersistentMap", :added "1.0"}

12:38 somnium: I think defn commutes the metadata now

12:38 ,(meta map?)

12:38 clojurebot: {:line 153}

12:38 defn: gotta var quote

12:38 kumarshantanu: defn: how can i var-quote inside a macro?

12:39 defn: kumarshantanu: i have code somewhere, one sec

12:39 kumarshantanu: #'~fn-name

12:39 wooby: jarpiain: re: compiler, neat!

12:39 somnium: defn: if you don't know the name it's hard to var-quote :P

12:39 KLll: does clojure have date stuff, or do I have to use java.util.Date?

12:39 defn: ;)

12:39 raek: kumarshantanu: it is not known at macro expansion time what var the symbol fn-name will refer to

12:39 defn: somnium: oh right

12:40 raek: KLll: clj-time is a neat lib (a wrapper for Joda time)

12:40 javas date classes are a mess

12:40 defn: no doubt

12:41 KLll: not really once you use GregorianCalendar :P

12:41 raek: joda time makes the dates immutable, so they work pretty well with clojure

12:41 KLll: I really like the mutators on GregorianCalendar

12:41 they are really neat

12:42 * defn reads Lisp in Small Pieces to death

12:42 defn: im outta here, folks

12:42 raek: kumarshantanu: if you have the symbol foo and want "foo", you can simply use the function 'name'

12:42 ,(name 'foo)

12:42 clojurebot: "foo"

12:43 kumarshantanu: raek: I am passing a function to a macro, and want to find out the name inside that macro

12:44 defn: kumarshantanu: where does the function come from

12:44 what if you get an anonymous function?

12:44 raek: kumarshantanu: the fn object itself does not know wich names are bound to it

12:44 kumarshantanu: actually I am trying to diagnose some defects -- so the macro asserts few values and then (should) tell which function failed -- so I need the name

12:45 raek: a macro could of course look at the unevaluated argument and if it is a symbol, treat that as the name for it

12:45 somnium: ,(meta (resolve 'map?))

12:45 clojurebot: {:ns #<Namespace clojure.core>, :name map?, :file "clojure/core.clj", :line 149, :arglists ([x]), :doc "Return true if x implements IPersistentMap", :added "1.0"}

12:45 KLll: (re-find #"time" "don't have time")

12:45 ,(re-find #"time" "don't have time")

12:45 clojurebot: "time"

12:46 raek: kumarshantanu: you could store the unevaluated argument. in that case, you get the code for the expression that failed

12:46 somnium: ,(let [fname 'map?] `(prn ~(meta (resolve fname))))

12:46 clojurebot: (clojure.core/prn {:ns #<Namespace clojure.core>, :name map?, :file "clojure/core.clj", :line 149, :arglists ([x]), :doc "Return true if x implements IPersistentMap", :added "1.0"})

12:46 somnium: kumarshantanu: perhaps that will work?

12:47 kumarshantanu: AH! got it -- (:name (meta (resolve (quote ~f?))))

12:48 f? is the function name the macro accepts

12:50 somnium: raek: thanks

12:50 KLll: !time

12:50 somnium: kumarshantanu: cheers

12:50 KLll: !time

12:53 !time

12:53 Upper: I need a help here pleaseI can't find the error - http://pastebin.com/JvZgH1E7

12:54 was created a loop/when to print a different message in each iteration

12:55 KLll: so if I do (defn fun1 ....)

12:55 then make some vector [fun1]

12:55 and then re-def it (defn fun1 something else ...)

12:55 the vector now holds the old one ?

12:56 !time

12:56 TheAnimal4: Time is java.util.GregorianCalendar[time=1287939389109,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Europe/Prague",offset=3600000,dstSavings=3600000,useDaylight=true,transitions=141,lastRule=java.util.SimpleTimeZone[id=Europe/Prague,offset=3600000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=2,startMonth=2,startDay=-1,startDayOfWeek=1,startTime=3600000,startTimeMode=2,endMo

12:56 raek: Upper: you don't have any call to recur

12:56 KLll: oops :P

12:57 raek: Upper: see http://clojure.org/special_forms#Special%20Forms--%28recur%20exprs*%29

12:58 Upper: hm right

13:01 raek: Upper: the basic code building block of a functional programming language is an expression, not a statement

13:01 (+ 2 i) means take i and add two and return that. it does not change i

13:14 kumarshantanu: is it a bug that pos? throws exception on nil?

13:15 ,(pos? nil) ; expected false, right?

13:15 clojurebot: java.lang.NullPointerException

13:15 gfrlog: ,(pos? "haha I'm a string")

13:15 clojurebot: java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Number

13:15 gfrlog: ,(num nil)

13:16 clojurebot: nil

13:39 riddochc: Anybody got suggestions for decent reading material to understand Java IO, nio, netty, etc. from a Clojure context? Got a little project I'm playing with, and aleph seems nicely suited to it, but I'm running up against a pretty steep learning curve here.

13:41 I suspect non-Clojure contexts would do, too, since I'm familiar enough with the Clojure side of things to be able to translate it... but I'm not very familiar with the Java APIs, and they seem tremendously more complicated than I would've expected.

13:47 rhudson: riddochc, I suspect you'd do well to start with the netty documentation.

13:47 I don't think you really have to understand the details of nio (thankfully!) to grok netty

13:48 All you really need to know about nio to start with is that the asynch stuff is based on the OS select

13:49 riddochc: rhudson: Hm. I'll try reading it again, then.

13:49 rhudson: Is it just me, or does everything seem to assume that a protocol will be layered on top of HTTP?

13:50 rhudson: Seems the way of the world these days...

13:50 The advantage is that the server only needs to open ports 80 & 443

14:00 KirinDave: Hey

14:00 gfrlog: hi

14:00 KirinDave: Earlier someone had been linking some new screencasts to all different parts of clojure

14:00 Like several on vars, several on refs, etc

14:00 Does anyone still have that link? I lostit

14:01 maravillas: the full disclojure screencasts?

14:01 raek: this one? http://www.pluralsight-training.net/microsoft/olt/course/toc.aspx?n=clojure-concurrency-tutorial

14:01 maravillas: http://vimeo.com/channels/fulldisclojure

14:01 KirinDave: raek: Those, idneed.

14:01 Thanks

14:01 raek: KirinDave: this is a goldmine: http://alexott.net/en/clojure/video.html

14:02 KirinDave: Dang

14:02 That's solid.

14:03 TakeV: What is exactly meant by "synchronous" and "unsynchronous" when talking about the difference between refs and atoms? And coordinated for that matter.

14:04 gfrlog: I can explain it after this chess game

14:05 TakeV: Sure. :)

14:05 KirinDave: So my webmachine->clojure port is in basic working order.

14:05 It doesn't handle everything and the tests aren't there, but I'm considering open sourcing it.

14:05 gfrlog: crap I lost

14:05 KirinDave: I'm not sure if I should do so today or tomorrow.

14:06 Like today is the tail-end of the conj, so...

14:06 gfrlog: TakeV: refs and atoms are both synchronous, so I think that issue should only come up when comparing either to agents

14:06 does that sound right?

14:06 KirinDave: gfrlog: Yeah

14:07 TakeV: gfrlog: I'm not sure what that term means, though. Likewise when discussing if they are coordinated or not.

14:07 gfrlog: TakeV: okay, so a for the synchronous ones (refs/atoms)

14:07 KirinDave: TakeV: Where did you see this?

14:08 gfrlog: they are evaluated in the current running thread, so your code doesn't proceed until the expession is finished evaluating

14:08 * TakeV nods

14:08 gfrlog: in contrast, when you send a function to an agent, the (send) call returns immediately, and the function gets evaled later on some other thread

14:09 so that's the sync/async distinction -- did it make sense?

14:09 TakeV: It does. Sounds somewhat like how locking works.

14:09 gfrlog: I think the explainer part of my brain is a bit muddled

14:09 KirinDave: TakeV: While it might involve locks, that's not what's going on

14:10 TakeV: Agents receive work queues.

14:10 TakeV: Atoms and refs do not.

14:10 TakeV: Agents work in the threadpool, atoms and refs do not

14:10 * TakeV nods

14:10 gfrlog: the fns sent to atoms and refs get evaled immediately while your thread execution waits

14:11 TakeV: What about coordination?

14:11 gfrlog: only refs are coordinated

14:11 TakeV: What does it mean?

14:11 gfrlog: what it means is that you can update several at once, and the whole action is atomic, like a database transaction

14:11 KirinDave: If you make a transaction over multiple refs, they all get updated or do not

14:12 gfrlog: and no other thread can see them in some intermediate state

14:12 * TakeV nods

14:12 TakeV: Thank you for the explanations. :)

14:12 gfrlog: no probalo

14:14 ,(deref (ref 10))

14:14 clojurebot: 10

14:15 gfrlog: ,(detain (tain 10))

14:15 clojurebot: java.lang.Exception: Unable to resolve symbol: detain in this context

14:38 * Nafai gets back to the labrepl tutorials

14:49 polypus: ~ping

14:49 clojurebot: PONG!

14:49 Upper: what the difference between (juxt) and (do) ? with both I can execute two operations

14:49 gfrlog: woah

14:50 Upper: i dont know juxt exectly

14:50 gfrlog: juxt combines some functions into a new function

14:50 ,(juxt first last)

14:50 clojurebot: #<core$juxt$fn__3661 clojure.core$juxt$fn__3661@11a74ef>

14:50 gfrlog: so that returns a new function

14:50 (let [f (juxt first last)] (f [6 7 8 9 10]))

14:51 Upper: hmm i got

14:51 gfrlog: ,(let [f (juxt first last)] (f [6 7 8 9 10]))

14:51 clojurebot: [6 10]

14:51 Upper: cool

14:51 gfrlog: the new function calls both of the functions supplied to it and returns a vector of the results

14:51 raek: Upper: do is useful when you need to do side-effects

14:51 gfrlog: ,(do (+ 3 4))

14:51 clojurebot: 7

14:52 gfrlog: hmm

14:52 raek: (defn trace [x] (do (println "value: " x) x))

14:53 Upper: you can then wrap that trace function around an expression to make clojure print it when it is evaluated

14:53 rhudson: ,(let [f (first second last)] (f [1 2 3 4 5]))

14:53 clojurebot: java.lang.IllegalArgumentException: Wrong number of args (2) passed to: core$first

14:53 Upper: interesting

14:54 rhudson: ,(let [f (juxt first second last)] (f [1 2 3 4 5]))

14:54 clojurebot: [1 2 5]

14:54 raek: Upper: however, function bodies alreade has an "implicit do", so you don't need to write the do in that case

14:56 Upper: usually I use do like a "then" of a cond, If I just open two parenthesis the second turn an else

14:57 I understood

14:58 raek: ah, ok... sorry for over-explaining... :)

14:58 serabe: hi

15:01 raek: anyone happen to know if a java.net.Socket is completely closed when both its InputStream and OutputStream are closed? or do I have to close the Socket object too?

15:02 somnium: raek: you might need an AbstractSocketCloserFactoryFactory to really be safe

15:03 raek: :P

15:04 man... factory-factories... do they really exist?

15:05 no wait. don't tell me. I don't wanna know...

15:05 dakrone: raek: http://ws.apache.org/xmlrpc/apidocs/org/apache/xmlrpc/server/RequestProcessorFactoryFactory.html

15:05 somnium: http://www.docjar.org/docs/api/org/outerj/pollo/xmleditor/FactoryFactory.html

15:05 firepoet: Ouch

15:14 rata_: hi

15:15 Upper: can i break a code in clojure? I need to stop because it is returning two values.

15:16 drewr: Upper: (throw (Exception.))

15:18 Upper: :) works

15:19 rata_: Upper, for debugging?

15:28 Upper: no. to final use

15:28 lazy to find a good solution

15:30 gfrlog: creating an infinite seq of primes elegantly is surprisingly tricky

15:31 rata_: gfrlog, why?

15:32 gfrlog: rata_: particularly if by "elegantly" we mean something you can create with (iterate), such that it doesn't require much memory and doesn't compute in large chunks, and is efficient (i.e., doesn't use division)

15:35 it took me several tries over the course of the conj

15:35 Upper: , (doc yield)

15:35 clojurebot: Excuse me?

15:35 gfrlog: clojurebot: are your responses hard-coded?

15:35 clojurebot: It's greek to me.

15:35 Upper: lol

15:35 gfrlog: clojurebot: you mean coded in greek?

15:36 clojurebot: excusez-moi

15:48 technomancy: icey: I think I missed you at the conj; bummer.

15:48 how goes the plugin task?

15:54 polypus: anybody here done server push (comet, websockets, etc) from clojure?

15:58 Upper: are the something wrong here? (dotimes [n 100] (test 0 1 n))

15:58 it returns "nil" executing 1 time only

15:58 neither call my function

15:58 jackdempsey: technomancy: fwiw that deps issue didn't matter. (use 'compojure) is no longer valid i guess since 0.4 or something. thx for the help

15:59 qbg: Upper: Are you sure your function isn't being called?

16:00 Upper: i guess, my function always return a message with println

16:00 technomancy: jackdempsey: good to know.

16:01 Upper: exist other ways to make a loop?

16:01 qbg: Upper: Post the code that isn't working

16:02 Including the definition of test

16:02 Do you get an error when loading your code? test is also the name of a function in clojure.core

16:06 Upper: qbg: see http://pastebin.com/g2HkDdP4 - and I do (loopTest 100)

16:09 qbg: It looks like quadradoPerfeito is broken

16:12 When I run your code it is throwing the exception that you throw, so that is why it is only being run once

16:13 Upper: ah maybe

16:13 qbg: Also, the cond has two :else conditions statements

16:13 *conditions

16:13 And the return value of the cond form isn't even used!

16:14 If the first :else case of the cond is ever invoked, you will get a NullPointerException because you have an extra set of parens

16:15 That first :else condition also does some math, but then throws away the value

16:16 The code is also not formatted idiomatically

16:17 Upper: tks, i will try to fix it

16:29 jjido: What are the dates of the Clojure conj? Is it finished?

16:30 FFUser: yep

16:30 jjido: was it good?

16:31 qbg: There are reports that it was very good

16:32 nickik: form what I read on twitter it was fantastic

16:32 im really waiting for the videos

16:32 jjido: nickik: thanks

16:33 qbg: Does anyone know of a syntax-rules implementation for Clojure?

16:37 rata_: I don't understand why when I compile a file for the first time in swank, it goes smoothly, but when I compile it for the second time the test (is (expression? p)) fails, but nothing has changed

16:41 gfrlog: clojure conj featured muffins

16:46 technomancy: ivey: I must have missed running into you at the conj; how goes?

16:46 ivey: technomancy: nah i wasn't there, sadly.

16:47 it's going well.

16:47 how was it?

16:52 amalloy: afternoon, jackdempsey

16:56 FFUser: ok I have a problem here

16:56 let's say you have a fn

16:56 and you have this: (dotimes [num (count some-list)]

16:56 (let [elem (some-list num)]

16:57 ivey: technomancy: i spent the conj fighting with google reader XML. working on a tool to fetch my starred items and send them to readitlater, but reader API is undocumented.

16:57 FFUser: (if (= (:name elem) the-search-string) elem nill)

16:58 the problem here is of course that this doesn't make the function return the right element

16:58 but just the result of the last if

16:58 in other words how do I jump out of the loop and return the result

16:58 raek: I think you are reimplementing 'some'... :)

16:59 or a more specialized variant of it

16:59 FFUser: doesn't some just return true/false?

16:59 MayDaniel: ,(some #{3} [1 2 3])

16:59 clojurebot: 3

16:59 rata_: ,(doc some)

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

16:59 qbg: ,(some #(= (:name %) "foo") [{:name "bar"} {:name "foo"}])

16:59 clojurebot: true

16:59 FFUser: see? true / false

17:00 qbg: ,(some #(if (= (:name %) "foo") %) [{:name "bar"} {:name "foo"}])

17:00 clojurebot: {:name "foo"}

17:00 FFUser: oh ok

17:00 still in general

17:00 rata_: is it possible that (class obj) returns x and (instance? x obj) return false?

17:00 FFUser: how do you deal with loops and lack of return / break statement?

17:00 amalloy: FFUser: can you make a gist or something? i can't quite follow what you're trying to ask

17:01 FFUser: nm, i see it was answered already; i was stuck in some scrollback :P

17:01 qbg: FFUser: loop/recur would be primitives to use

17:01 raek: FFUser: loops return, unless you do a recur

17:01 FFUser: ok

17:02 so basically if I want to end loop prematurely I can't use stuff like doseq and dotimes

17:02 qbg: Most functions that you would want are just a composition of some pre-existing ones though.

17:02 FFUser: Don't try to think in terms of loops

17:02 raek: FFUser: also, there is rarely any need to iterate over the indicies of the items and then get the item of that index

17:02 FFUser: ok but I need that

17:02 mrBliss: when you do (first (something-lazy ...)) it also ends prematurely

17:03 FFUser: I can find if item is in the coll (some) but I also need the index

17:03 because I want to swap it

17:03 qbg: ,(first (filter #(= (:name %) "foo") [{:name "bar"} {:name "foo"}]))

17:03 clojurebot: {:name "foo"}

17:03 rata_: FFUser, you need the function indexed and some

17:04 raek: FFUser: you happen to have the book "Programming Clojure"? it has an exmaple of just that

17:04 FFUser: I have a vector of maps and I want to update the map with :name = parameter

17:04 basically replace it with a new map

17:05 raek: FFUser: ah, that chapter is available for free: http://media.pragprog.com/titles/shcloj/flow.pdf

17:05 qbg: FFUser: only the first one with (= :name parameter) or all of them?

17:06 FFUser: first one will suffice

17:06 raek: FFUser: 2.6 "Where's My for Loop", page 7

17:06 or 72, if you follow the books own page numbering

17:06 FFUser: I have Clojure in Action

17:07 rata_: FFUser, (for [m maps] (assoc m :name parameter))

17:07 raek: (defn indexed [coll] (map vector (iterate inc 0) coll))

17:07 amalloy: or (map #(assoc % :name param) maps)

17:08 rata_: for is lazy, so it doesn't matter whether you want the first one or everyone... it will do you just the work you need

17:08 (map also)

17:09 qbg: (defn foo [pred f coll] (map #(if (pred %) (f %) %) coll))

17:09 rata_: is it possible that (class obj) returns x and (instance? x obj) return false?

17:09 qbg: Where pred is a predicate function for updating, and f is the update function (applies to all matches)

17:10 rata_: Do you have a case where that happens?

17:10 FFUser: :)

17:10 I think I like the solution where you append indexes :)

17:10 I better not time this solution though

17:10 so many allocations it will make your head spin :D

17:14 amalloy: rata_: no, that should be impossible

17:14 qbg: (defn foo [x] (instance? (class x) x)) will throw a NullPointerException if you pass in nil though

17:15 rata_: qbg, yes, but it's difficult to make a gist of that

17:16 qbg: Due you use classloaders?

17:16 rata_: the most weird thing about it is that when I compile it for the first time it works perfectly

17:18 I really don't get it... it seems to be a problem with swank

17:18 maybe I use (ns ... (:use ...)) too much

17:21 if I compile the file twice, the (instance? x obj) doesn't work anymore

17:21 `_´

17:21 qbg: What is x?

17:22 I suspect either x or obj are being redefined and the other isn't

17:23 Nafai: Are there any tools that use nREPL yet? It's an interesting looking project.

17:23 rata_: x is Agent where Agent is (defrecord Agent [...])

17:24 qbg: Reevaluating defrecord will replace the old class with the new one

17:24 (IIRC)

17:25 amalloy: qbg: that's correct

17:25 qbg: If obj isn't being redefined, that could be it

17:26 Sweetshark: Hi all, I want to call stuff in a clojure jar from Java. I created a jar in netbeans with enclojure and it compiles just fine. I added the jar file to the project where I want to use it from. I see the symbols and everything compiles fine. However, when I run it, the call fails. With a Java jar file it works fine the way I did it. Any hints?

17:28 qbg: Sweetshark: Are you using a class generated in Clojure from Java, or are going through clojure.lang.RT to invoke a function?

17:30 rata_: qbg, and is there any way to make defrecord not to generate a new class when it already exists one?

17:31 Sweetshark: qbg: I tried both (I am now using RT). Right now I have a Java class in the clojure jar but it does not even get enter that (plain Java) method. Hang on, I have a suspicion ...

17:33 qbg: If you are going through RT, make sure the namespace has been required

17:33 Sweetshark: ... *puff* there goes my suspicion: no, that was not the problem ...

17:34 qbg: How? Do you have a link?

17:34 qbg: I've only done this once, but I just invoked require from clojure.core

17:34 (probably a better way)

17:36 rata_: is there any way to make defrecord not to generate a new class when it already exists one?

17:36 Sweetshark: well, I now have a plain java wrapper class in the clojure jar an call that ... should at least that always work?

17:37 FFUser: can someone tell me if I'm using clojurebox, where do I have to put my Irc.clj with namespace spur.irc to get it to load in repl with require spur.irc

17:37 amalloy: rata_: i don't think so. you could probably wrap the defrecord in a (when) of some kind that checks whether the class already exists?

17:38 but then if you changed the field list, that would prevent it from getting updated on your next compile

17:43 * Raynes is home.

17:44 amalloy: hey Raynes, wb. did you end up having pants leftover after the flight? :)

17:44 rata_: amalloy, I prefer that it doesn't get updated than this annoying problem with its redefinition

17:44 Raynes: amalloy: I kept them all, actually.

17:45 amalloy: well done. i left you a present on sexpbot

17:45 Raynes: I'm sick as hell at the moment.

17:45 I'll probably get to that tomorrow if I feel like it.

17:45 Thanks. <3

17:45 amalloy: aww

17:47 rata_: I'm looking now for a function that check if a class is defined... I don't like try and catch :P

17:52 qbg: rata_: Reflection?

17:52 rdeshpande: howdy all

17:54 rata_: qbg, do you know of a way to do it?

17:54 mister_roboto: rata_: what do you mean "defined"? if it's available on the classpath to be loaded?

17:54 rata_: I was hoping java.lang.Class/forName could help, but it throws ClassNotFound

17:54 jackdempsey: amalloy: hey there, just got internet back

17:54 how's it goin

17:54 rata_: mister_roboto, if it's in the environment

17:55 mister_roboto: rata_: the JVM can't possibly tell you about classes that are not on the classpath since it doesn't magically know about them. The "environment" is the classpath

17:56 Sweetshark: qbg: got a bit further, however now i get an "Var clojure.core/refer is unbound" error. Any idea on how to fix that?

17:56 mister_roboto: rata_: i guess you could go around and open every jar you can find at the OS level and see if it contains the class :)

17:56 amalloy: jackdempsey: nothing special. i've been here since june, and this is the first time it's rained. need to buy an umbrella, i guess :P

17:56 rata_: mister_roboto, after you do a (defrecord x ...), x is in the environment

17:57 jackdempsey: amalloy: wow ok. i was going to say, is it like this? feels like a light storm

17:57 mister_roboto: rata_: ah, ok. i thought you meant regular java classes from outside your program

17:57 rata_: mister_roboto, no

17:58 mister_roboto, that'd require some magic

17:58 mister_roboto: rata_: exactly :) aren't there namespace functions to search for such bindings? (clojure newbie here)

17:59 rata_: mister_roboto, I hope so, but I don't know either

18:00 mister_roboto: rata_: does this help? http://stackoverflow.com/questions/2012651/clojure-namespace-method-to-see-defined-objects

18:03 rata_: mister_roboto, no, that's only useful for vars, not for classes

18:03 (i.e., records)

18:05 amalloy: rata_: you could check for the instance of the var you don't want redefined

18:05 presumably if you don't want the class redefined it's because you have a var that's an instance of the old class already

18:07 rata_: amalloy, I don't even understand why the var doesn't get updated when I compile it for the second time

18:08 maybe :import should go before :use

18:10 no, putting :import before :use doesn't help either

18:12 :reload-all goes after :use? :import? :require?

18:15 Raynes: (:use my.stuff :reload-all)

18:20 rata_: yes, it seems to work now with (:use ... :reload-all) :) the only negative side-effect it's that now takes ~20 secs to run the tests, because it has to recompile everything

18:23 FFUser: time

18:23 TheAnimal: FFUser: 25.10.2010 12:24:00 +0200

18:24 FFUser: debugging clojure is challenging

18:31 zakwilson: I'm trying to upload files with compojure/ring. I'm not sure how to access the uploaded file (it appears to be a string containing the filename)

18:33 FFUser: can someone give me some pointers

18:33 http://pastebin.com/YMSy62sZ

18:34 I find myself losing track of what's a data structure and what's a function

18:34 since it's all same nameing convention

18:34 rata_: FFUser, are you using emacs?

18:35 FFUser: yep

18:35 rata_: in which function do you have the problem?

18:36 FFUser: just general readability problem

18:36 the code works fine

18:36 nickik: format your code write for one

18:37 FFUser: with java I usually keep things organised by splitting into classes

18:37 and by limiting the number of public methods

18:38 which limits the amount of way the classes can interact with each other

18:38 rata_: in clojure you have namespace and private and public functions

18:38 FFUser: loose coupling

18:39 in OOP you want the classes loosely coupled and I have to somehow make my clojure programs do the same

18:40 rata_: yes, in dynamic languages you have loosely coupled objects by default (IIRC)

18:40 FFUser: not really

18:40 it's a design thing

18:40 nickik: in clojure everything is loosly coupeld because every function (should) be indipendend

18:40 FFUser: one that my coworkers fail badly

18:40 amalloy: FFUser: not an answer to your actual question, but i notice you do the following a lot: (first (filter #(= (:name %)) coll))

18:40 FFUser: that's not what loose coupling is

18:40 rata_: FFUser, why?

18:41 FFUser, what's loose coupling for you?

18:41 amalloy: this can be replaced with (some (comp #{target} :name))

18:41 (where target is the name you're looking for)

18:42 FFUser: in OOP it is when classes (larger unit of functionality than function) have limited number of

18:42 nickik: @amalloy wanted to say that to

18:42 *too

18:42 FFUser: exposed methods through which other classes can influence them

18:42 in clojure every function can pretty much call any other function usually

18:42 rata_: FFUser, that's not true if you use namespaces and private functions

18:43 nickik: define data and some functions on those data then put that stuff in a namespace and define some of the functions privat and some public

18:43 FFUser: thanks ammaloy

18:43 rata_: also, you definition of loose coupling resembles more the one of encapsulation

18:43 nickik: true

18:43 FFUser: they are related concepts

18:45 nickik: just think of it like this in FP a Class is a namespace. Then you can define private and public functions with defn or defn-. Its the same as in java just without protected.

18:46 rata_: FFUser, they don't seem to be related: http://en.wikipedia.org/wiki/Loose_coupling

18:47 FFUser: nickik: in that case I'd easily split my code into 4 namespaces with 3 functions each

18:47 rata_: loose coupling is the use of interfaces in Java

18:47 nickik: i agree that the are related if you encapsulate a object the write way its easy to have loose coupling

18:47 FFUser: if you asked me to craft classes out of it

18:48 yes that's what I meant

18:49 rata_: FFUser, then do that if you want your code more organized

18:49 FFUser: seems like it

18:49 I was also looking for some kind of coding convention

18:49 like in C++ you have hungarian notation

18:50 mister_roboto: FFUser: Hungarian notation is for encoding types in the name. functions are just functions though

18:50 nickik: @FFUser that seams to be alot. namespaces a usually a little bigger for conventions you can look at http://www.assembla.com/wiki/show/clojure/Clojure_Library_Coding_Standards

18:50 zakwilson: Loose coupling means that if A doesn't need to know about B, it doesn't. How you communicate that in your code is up to you, though namespaces do provide a mechanism to make it easy.

18:51 FFUser: mister roboto: clojure doesn't have types but it has vars that are bound to data, vars bound to FNs and vars bound to mutables (atoms, refs)

18:52 zakwilson: Clojure has types. They're attached to the data, not the variable.

18:52 mister_roboto: zakwilson: loose coupling means something a bit stronger than that. it means that if A uses B, it doesn't depend on how B is implemented. i think that falls out of FP automatically if your function is referentially transparent

18:52 FFUser: it was my idea to make different name prefixes for these 3 kinds

18:53 nickik: i would do that look into :"Follow clojure.core's example for idiomatic names like pred and coll" in the document i linked

18:54 in general: functions should read like verbs and data should read like nouns

18:54 FFUser: yeah I use same thing in java

18:55 sometimes these names can be hard to craft though

18:55 rata_: mister_roboto, that isn't it... it that if A uses B, probably you mean that A uses an interface that have the methods you need

18:55 mister_roboto: FFUser: why would you need a special idiom for mutable var names when you already have to use a special form to access them? doesn't that tell you everything?

18:55 FFUser: making function name verb-like but not too vague often results in extremely long names :D

18:56 it tells me everything when reading correct code

18:56 mister_roboto: rata_: the only reason interfaces enable loose coupling is BECAUSE they make it impossible to depend on the implementation

18:56 FFUser: the problem is forgetting to use the special form

18:56 the compiler won't warn me

18:57 mister_roboto: rata_: the only visibility you have to the "used" class is the "protocol"

18:57 rata_: yes, that is

18:58 OOP is about procedural abstraction

18:58 mister_roboto: rata_: oops is about many things. encapsulation, data hiding, inheritance, locality of data and methods which operate on the data, etc

18:59 s/oops/OOP/

18:59 sexpbot: <mister_roboto> rata_: OOP is about many things. encapsulation, data hiding, inheritance, locality of data and methods which operate on the data, etc

18:59 rata_: I think a good read about that is http://www.dcc.uchile.cl/~etanter/ooplai/adt-oo.html

19:00 I don't think encapsulation, data hiding, inheritance and locality of data are much related to OOP in general... they are related to some kinds of OOP implementations

19:01 mister_roboto: rata_: http://en.wikipedia.org/wiki/Object-oriented_programming like I said, OOP is about many things. sure you can leave out the bits you don't want to talk about but they are still part of OOP

19:01 rata_: FFUser, I think you'll enjoy this article (by Stuart Halloway): http://www.nofluffjuststuff.com/blog/stuart_halloway/2009/08/rifle_oriented_programming_with_clojure

19:02 nickik: the three thinks alan kay said are the base of OO are: Encapsulation, Subtype polymorphism, Object inheritance

19:04 FFUser: too bad people I work with only use Encapsulation and even that one badly

19:04 rata_: nickik, then every language that's based on delegation instead of inheritance isn't object-oriented?

19:04 I don't think so

19:05 nickik: no, I'm just pointing out what the original definition is. Today everthing is diffrent.

19:06 FP isn't the same as it was 40-50 ago.

19:06 FFUser: imagine a bunch of void return methods on a single class named "processSomething" with no arguments, which load stuff from DB and then mutate half a dozen huge java beans, some dealing with state (data) storage and some dealing with UI state

19:06 rata_: nickik, thus I think the core of OOP is message passing and procedural abstraction

19:06 mister_roboto: rata_: i think the key thing is that some features of traditional OOP, like reuse through inheritance only, is bad. so delegation is preferred. however, even a modern OOP like java and .NET has inheritance.

19:07 rata_: FFUser, that's gonna be difficult to test for sure

19:07 FFUser: I am tasked with adding functionality to such existing projects

19:07 nickik: thats the problem with descutions like this everybody means something else when he sais OO or FP

19:07 FFUser: I have absolutely no idea which beans any of these functions affects under which conditions

19:08 rata_: mister_roboto, that's not modern OOP... also inheritance and classes is just one way to implement OOP

19:08 mister_roboto: FFUser: you mean like adding new functionality without changing the existing code? that kind of code isn't testable

19:09 FFUser: adding new business logic into existing UI

19:09 well JSFs

19:09 and I don't understand the business logic already implemented, it's domain specific and you need experts to make specifications

19:09 mister_roboto: rata_: what is a modern OOPL that you are talking about then that doesn't have inheritance, for example?

19:10 FFUser: anyway, clojure is like my vacation from work

19:10 and work is my nightmare

19:10 mister_roboto: FFUser: that's a bad spot to be in, but all too common. can you modify the existing code to start injecting dependencies?

19:10 rata_: JavaScript doesn't use inheritance... Scala uses inheritance and is more modern than Java or C#

19:10 FFUser: don't have enough hours allocated to refactor code

19:11 mister_roboto: rata_: javascript uses prototype based inheritance

19:11 FFUser: bonus points: people who did this call me an academic when I talk about OOP. Needless to say, none of them have an actual degree in CS

19:12 rata_: mister_roboto, that's not inheritance, that's delegation

19:13 this is an interesting topic, but I'm going now to eat something... see you later guys :)

19:13 mister_roboto: rata_: prototype inheritance is still reuse by depending on implementation of the prototype

19:14 rata_: i suggest reading about javascript and inheritance

19:14 nickik: @FFUser i'm doing boring database IO with ASP classic thats no fun either

19:15 rata_: one has to be cautious when reading about those topics... there's a lot of people (even academics) out there that mix up ADTs and objects

19:15 mister_roboto: FFUser: i know exactly the kind of code you're dealing with. if you can't refactor, at least try to write some good tests before modifying it

19:15 FFUser: although it's damn hard to even test such code

19:16 FFUser: everything is a giant integration test - can't tease apart the components in a big ball of mud

19:16 rata_: if they confuse ADTs and objects, to mix up inheritance and delegation would be even easier

19:17 FFUser: I'm not optimistic about the future of dealing with other developers

19:17 nickik: so good night i have to get up early to do some more boring stuff at work :)

19:18 FFUser: in my coutry about 10% of developers have BS in CS, 45% have associate's degree(I think that's what it's called) in CS and 45% have high school education

19:21 mister_roboto: rata_: http://www.cs.rit.edu/~atk/JavaScript/manuals/jsobj/ javascript prototype inheritance is true inheritance. you aren't holding onto a prototype handle and delegating to it, unless you also count c++ vtables as holding on to ancestor references and doing delegation

19:21 FFUser: time

19:21 TheAnimal: FFUser: 25.10.2010 01:22:18 +0200

19:28 mister_roboto: FFUser: and in every other country, more and more development is outsourced to countries with lots of degreed programmers who, unfortunately, just started programming professionally on the program you're giving them :)

19:31 FFUser: It's terrible here. And the CS faculty had 180 spots, 360 applicants and you needed to be a mixed C grade/D grade student to get in.

19:31 a lot of them drop out and work as programmers

19:32 now imagine dropouts who had high school math graded C work as programmers

19:33 anyway, enough griping about the state od development around here

19:33 good night

20:03 yayitswei: Is there a way to splice a list into arguments (what the splat operator in Ruby does) without using a macro? I'm trying to turn a list into arguments for recur.

20:04 amalloy: apply

20:05 though i'm not sure that works for recur. recur is probably a special form

20:05 ,(doc recur)

20:05 clojurebot: Gabh mo leithscéal?

20:05 yayitswei: it is a special form

20:05 so I don't think I can use apply

20:05 amalloy: no, you can't

20:06 jackdempsey: is it a variable list? can't destructure it

20:06 amalloy: i think the usual way to do this would be destructuring

20:07 ,(loop [[a b] (range)] (if (= 10 a) b (recur (map + [a b]))))

20:08 clojurebot: Execution Timed Out

20:08 amalloy: er, that's not what i meant

20:08 ,(loop [[a b] (range)] (if (= 10 a) b (recur (map inc [a b]))))

20:08 clojurebot: 11

20:10 amalloy: yayitswei: does that help?

20:10 yayitswei: amalloy: still reading it :)

20:13 amalloy: what's the (range) for?

20:13 amalloy: just a convenient initial value for the loop

20:13 sets a=0, b=1

20:14 yayitswei: oh i see

20:15 so the recursive function should take one argument, a list, instead of arbitrarily many

20:16 amalloy: right

20:16 and then pull apart the list however you want

20:17 yayitswei: amalloy: got it-- thanks!

20:17 amalloy: or, have your arbitrarily-many function public, internally implemented as a loop around a list

20:17 yayitswei: if I really wanted to make it a

20:17 oh yeah that's what i was just going to ask

20:23 rata_: mister_roboto, I think that link shows how to simulate inheritance in javascript

20:23 many features of class-based languages, such as inheritance, can be simulated in a delegation-based language

20:23 * rata_ comes back after eating something

20:24 rata_: http://en.wikipedia.org/wiki/Prototype-based_programming

20:24 mister_roboto: rata_: no, it shows how inheritance DOES work in Javascript. it's just showing how to you structure that sort of inheritance hierarchy, comparing Java to Javascript, where the first is class-based inheritance and the second is prototype-based inheritance

20:24 rata_: that's just how it works. look up constructors and prototypes in javascript. that's what they are for

20:25 rata_: mister_roboto, look at the prototype-based programming article in wikipedia

20:26 mister_roboto: reading

20:28 rata_: ok, so i'll buy that it's an ambiguity :) it's not like typical delegation where you are explicitly delegating calls to some delegate, however. you only reference the prototype in javascript typically to set up the prototyype chain so this inheritance of behavior happens automatically when you construct an object

20:29 rata_: the rest of the time you just use the instance directly. if you still want to call that delegation, it seems to me that it's j ust a non-useful blurring of concepts

20:31 rata_: mister_roboto, that's why I said that use of prototypes is an emulation of inheritance :)

20:31 also the OOPLAI book (a work in progress yet) explains the differences between class-based and prototype-based languages very well IMHO http://www.dcc.uchile.cl/~etanter/ooplai/

20:32 do you have read PLAI?

20:32 mister_roboto: rata_: ok ok, i see your point. if the language is hiding the "delegation" from you when you are accessing an instance behavior, it seems to me no different than c++ hiding it by internally accessing the vtable

20:32 rata_: i mean insofar as discussing whether a language has "inheritance" proper

20:33 rata_: it's just an implementation detail. to call it "emulated" doesn't enhance understanding of what it is or does

20:34 rata_: what does inheritance mean if not having behavior and properties automatically propagate through the chain of dependent objects?

20:34 rata_: it's not hiding the delegation at all... it's just using it to implement inheritance-like constructs

20:35 mister_roboto: rata_: when i call jsobject.someproperty, i don't know if it's a local or coming from the prototype

20:35 rata_: that's not hiding it?

20:35 rata_: that's not hiding it... that's how delegation works

20:36 inheritance definition depends on classes

20:36 mister_roboto: or setting up the prototype chain

20:36 my example... is that not hiding the delegation?

20:36 rata_: yes, that's not hiding the delegation

20:37 mister_roboto: rata_: ok, then i guess we cannot agree on that point

20:38 rata_: if object jsobject doesn't know how to interpret the message 'someproperty', then it's going to delegate that message to other object

20:38 we can't agree on that point

20:38 mister_roboto: rata_: just like the c++ object delegates via the vtable. it's a language implementation detail of how to locate hte property

20:38 i totally agree with what you just said

20:39 rata_: the important difference between them is that delegation occurs between objects and inheritance happens between classes

20:39 the vtable is an implementation detail

20:47 mister_roboto: this is actually kind of interesting because earlier you were claiming that inheritance isn't part of OOP but you seem to be saying that class-based OOP is actually the only way to do inheritance

20:50 rata_: yes, I was saying inheritance isn't part of OOP, but part of class-based OOP

20:52 amalloy: ummmm, no offense guys, but could you take this discussion to #oop or something? i don't want to miss any clojure-related messages in the flood

20:52 mister_roboto: sorry amalloy, you're right

20:52 rata_: sorry amalloy

20:53 ymasory: why is there no "lein run"? what am i missing?

20:53 mister_roboto: my final statement is only that i think it is pointless to draw a line between "true" and "emulated" inheritance. i will shut up now

20:54 amalloy: ymasory: how does lein know what function you want to run? or do you want it to start up a repl and then eval everything in your project, maybe?

20:55 rata_: just-in-time for the clojure-related question :)

20:55 ymasory: amalloy: not sure if there's a dedicated start point in clojure. sbt runs the first main function it can find with the matching signature

20:56 it seems like a pretty slow procedure to say lein repl and then type out a start point

20:57 amalloy: ymasory: you can specify the main function in project.clj, and then when you java -jar the result of lein jar, it should call that function

20:57 ymasory: thanks

20:57 raek: there is some feature to set the starting namespace. I do not know if that also automatically requires that namespace

20:59 Adamant: clojurebot: do you have a neural net processah lahk Ahnold?

20:59 clojurebot: Huh?

20:59 mister_roboto: amalloy: how does that work? does it put that function inside a main()?

21:00 amalloy: mister_roboto: every clojure function turns into a java class. i imagine it renames the main class's function main, and it certainly puts an entry in the jar manifest

21:00 raek: if you add :main your-namespace-here, the repl will start in that namespace

21:01 ah, and there's also :repl-init-script

21:02 amalloy: raek: cool. does that affect swank too?

21:03 raek: no idea :)

21:03 mister_roboto: if I had to decide between using lein or cake, is there any clear advantages to choosing one? i haven't used them, only did some reading and they seem to do the same thing

21:05 rata_: raek, where do you put that ":main your-ns"?

21:05 amalloy: mister_roboto: one nice feature of cake is that it will keep jvms running in the background to speed up launch time of all cake tasks

21:05 otoh, if you're strapped for RAM, it's probably inconvenient to keep killing those

21:06 raek: ymasory: one common way seems to be to only have function and constant definitions at the top level of the source files. (i.e., when you load a file, the application doesn't start.) then, you provide a -main function to start your application.

21:06 rata_: in your project.clj file

21:07 but still, when launcing the repl you have to type stuff

21:07 mister_roboto: amalloy: so if you're not tight on RAM then cake has the lead :)

21:07 rata_: raek, in (ns ...)?

21:08 amalloy: that's been my experience. but lein is a little older and more stable/tested. they also have incompatible plugin architectures, so if someone's written a lein plugin you really want...

21:08 but for the most part they're compatible so it should be easy to switch if that happens

21:08 raek: rata_: I'm sorry... what in (ns ...)?

21:08 amalloy: rata_: no, in the project.clj file at the top level of your lein/cake project

21:09 rata_: raek, that ":main your-ns"

21:09 ah ok

21:09 sorry

21:09 read only the first msg

21:11 raek: ok, I can confirm that setting the main namespace will cause that namespace to be loaded when you start the repl

21:12 so, you could see the main namespace as a startup script, if you want to

21:34 mister_roboto: how do i make an entity bean using cake? (kidding!) is it a fairly typical thing to use any old editor (emacs or whatever) to create the code and then use lein/cake to package it for release?

21:34 hiredman: yes

21:36 amalloy: mister_roboto: yep, pretty normal. CCW users might have their own thing, but a lot of us use emacs/cake

21:37 mister_roboto: amalloy: so far i only used CCW to build fairly small programs that i just ran at the repl by typing it in. i really need to go to the next step of having a full automated build process and i cake seems to be a very good choice

21:38 amalloy: it certainly is a good choice. but laurent might have something that integrates better with eclipse, i don't know

21:39 mister_roboto: amalloy: when i use CCW, i tpically just execute the clj file and leave the resulting repl running. then i've been copy/pasting new code down into the repl rather than killing it and re-running the script file(s). this sounds clumsier than emacs with its repl integration (Swank?) but i haven't tried that approach

21:41 hiredman: thats fine for dev

21:41 but when you deploy you build a jar

21:52 mister_roboto: hiredman: right. i've been doing java development for too many years now :)

21:53 hiredman: maven and ant before that. need something for clojure now and i guess it's gonna be cake

21:59 amalloy: mister_roboto: cake and lein are both built on top of maven

22:00 eg, lein/cake pom creates a pom.xml file you can manage with maven if you prefer

22:01 mister_roboto: amalloy: that's good in that i'll understand what's going on underneath and i can point it to our in-house artifactory repo for the dependencies. however, i think all the management looks like it will be best done via project.clj

22:11 ymasory: why can't clojure put in the "recur" bit by itself? at least in some simple cases?

22:16 somnium: ymasory: there are a few threads on the mailing list about it. the principle reason seems to be that since it would only be possible in some cases, better to make it explicit everywhere.

22:17 ymasory: plus you can always use scheme :P

22:19 ymasory: gotcha. thanks. seemed a little funny in the simple cases

22:22 can i get the previous line back in the repl?

22:28 mister_roboto: install rlwrap like here: http://programmingzen.com/2010/07/13/how-to-setup-clojure-from-scratch/ or use "cake repl" like here: http://github.com/ninjudd/cake

22:29 ymasory: maybe there's an easier way but rlwrap worked well for me. a standalone repl is annoying without history

22:33 ymasory: no kidding, thanks

22:35 while i'm at it. why doesn't clojure allow forward-references to functions? other lisps do

22:38 mister_roboto: ymasory: you mean like this or something else? http://en.wikibooks.org/wiki/Clojure_Programming/Concepts#Mutual_Recursion

22:40 somnium: ymasory: you can use declare for forward declarations

22:41 ymasory: somnium: do other lisps require forward declarations?

22:41 somnium: ymasory: I don't think so

22:42 I don't know how CL does it, but I do think R6RS scheme really got that part right (scoping of top levels)

22:42 still, adding (declare ...) isn't so painful

22:45 ymasory: painless as C :)

22:49 somnium: ymasory: aw, surely Clojure isn't in the same league as C in terms of inflicting pain on programmers :)

23:36 ymasory: what does the & mean in function signatures?

23:37 dsantiago: It means any number of additional arguments, which will all be put into the name given after the & as a list.

23:38 ymasory: ah thanks

Logging service provided by n01se.net