#clojure log - Jul 17 2009

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

0:55 skalnik: how do I check if a sequence is empty?

0:55 grrrt: empty?

0:55 ,(doc empty?)

0:55 clojurebot: "([coll]); Returns true if coll has no items - same as (not (seq coll)). Please use the idiom (seq x) rather than (not (empty? x))"

0:56 skalnik: thanks :)

0:56 grrrt: I find this website quite useful at times: http://java.ociweb.com/mark/clojure/ClojureCategorized.html

0:56 it has all (most?) clojure functions by category

0:57 skalnik: nice

0:57 grrrt: useful if you're looking for something without knowing the exact name

1:01 skalnik: yay, coded euler problem 3 :)

1:04 grrrt: metadata still has me confused. I wish I could do this:

1:04 ,(def t (ref 0))

1:04 clojurebot: DENIED

1:04 grrrt: oh allright

1:05 hiredman: erm

1:05 grrrt: I wish I could do this: (def t (ref 0)) (with-meta t {:foo "bar"})

1:05 durka42: (let [t (ref 0)] (with-meta t {:foo "bar"}))

1:05 ,(let [t (ref 0)] (with-meta t {:foo "bar"}))

1:05 clojurebot: java.lang.ClassCastException: clojure.lang.Ref cannot be cast to clojure.lang.IObj

1:05 grrrt: exactly

1:05 clearly I'm missing something

1:06 hiredman: ,(let [t (ref 0)] (alter-meta t assoc :foo "bar"))

1:06 clojurebot: java.lang.Exception: Unable to resolve symbol: alter-meta in this context

1:06 hiredman: ,(let [t (ref 0)] (alter-meta! t assoc :foo "bar"))

1:06 clojurebot: {:foo "bar"}

1:06 hiredman: ,(let [t (ref 0)] ^(alter-meta! t assoc :foo "bar"))

1:06 clojurebot: nil

1:06 hiredman: bah

1:06 grrrt: heh

1:06 hiredman: ,(let [t (ref 0)] (alter-meta! t assoc :foo "bar") ^t)

1:06 clojurebot: {:foo "bar"}

1:06 durka42: ,(let [t (ref 0)] (alter-meta! t assoc :foo "bar") t)

1:06 clojurebot: #<Ref@bdc53e: 0>

1:06 grrrt: right. So why does with-meta not work then?

1:07 hiredman: there are several meta data related interfaces

1:07 durka42: that seems like a huge bug

1:07 hiredman: with-meta effectively returns a new object with the given metadata

1:07 which is not what you want in this case

1:07 grrrt: hmm, I can see that being problematic for refs

1:07 yeah

1:07 point taken

1:08 thx hiredman ! #clojure rocks.

1:20 skalnik: hm, how do I turn a character list into a string?

1:20 grrrt: ,(str \a \b)

1:20 clojurebot: "ab"

1:21 grrrt: ,(apply str [\a \b])

1:21 clojurebot: "ab"

1:21 skalnik: hmm

1:21 thanks

1:21 yeah, apply str worked

1:21 makes sense.

1:51 grrrt: weird... back in my java days I would work on a project, writing code, code and more code. Eventually I would sit back and look at the large amount of code I had written and I'd feel pretty impressed with myself.

1:51 With clojure, I write code and more code, but then when I sit back I think "hey is that all?"

1:51 Clojure is just *so* much more expressive...

1:51 mariorz: its all the lisp

1:53 i think you work at ibm you get bonuses by kloc's though

1:53 grrrt: In my last java job we had the rule "no methods with more than 15 lines"... In clojure I don't even have to *try* to stay under 15 :)

1:53 mariorz: if you*

1:53 :P

4:49 gko: ,1

4:49 clojurebot: 1

4:49 cp2: ,42

4:49 clojurebot: 42

4:49 jdz_: strange, ain't it?

5:02 cp2: very

5:19 gko: Any user of clojure-dev (for Eclipse?)

5:19 Any user of clojure-dev (for Eclipse) ?

5:45 Fossi: hi. is there a pattern/helper for catching exceptions in lazy seqs?

6:17 cark: Fossi : you may (doall your-sequence) and souround this with a try form

6:56 Fossi: cark: that's what i figured. now i just need to find out why it's still not being catched. :)

6:57 it's still a little arkward if your data is not a simple sequence, but a nested structure

6:57 cark: maybe your sequence contains other lazy saquences ?

6:57 Fossi: that's what i suspect

6:57 so a structure-walking helper would be helpful

6:58 cark: is this only for debugging ? or do you want this for production as well ?

6:58 Fossi: i try to make compojure not throw exceptions to the frontend

6:58 cark: a quick way to make your sequence concrete is to pprint it

6:59 Fossi: well, that is a code walker :)

6:59 or data walker in that case

6:59 cark: right =)

7:00 Fossi: should be a pretty common use-case with web applications. maybe something i can give back upstream later

7:00 cark: well usually with compojure you'll build vectors instead of sequences, and these are not lazy

7:01 Fossi: hmmm

7:01 maybe somethings wrong then on some other end

7:01 cark: also it's no big deal if your exceptions fires later, you may change the error page i think

7:02 Fossi: i searched a while in the docs and also code, but i could point anything like that

7:02 *couldn't

7:03 cark: mhh

7:03 there must be !

7:03 =P

7:03 Fossi: in fact i greped for "try" and there wasn't any in the code

7:03 cark: my guess is that the web server library has the try

7:04 Fossi: might be, but since we run it on different once, that's not helping so much

7:04 *ones

7:04 no english skills today ;)

7:05 the error-pages look different on tomcat/jetty etc, so it looks like the exception just falls through to the container

7:06 cark: well then talk directly to jetty

7:06 Fossi: as said: because we run on different containers, that's not really a nice solution.

7:06 i'll decorating my app with some exception handling somehow

7:07 but first i need to somehow catch any exception

7:07 cark: then you'r bound to walk the data structures

7:07 Fossi: yeah, i guess so

7:07 cark: though you know, it's a feature in composure to be able to work with lazy sequences

7:08 Fossi: yeah, especially for streaming a doall you be real bad (tm)

7:08 cark: i remember reading a post on the google group about using this feature to update a page

7:08 ahwell you can't have the cake and eat it too =)

7:09 Fossi: i'll put the issue aside for a while and fix the cause of the exceptions first. should be easy to provoke later on.

8:41 what's the right way to 'un-keyword' something? so make :http "http"?

8:42 prolly (key (map-with-known-values)), but if i don't know them? str?

8:42 cark: ,(name :hello)

8:42 clojurebot: "hello"

8:43 Fossi: ah, cool

8:46 and the lisp-1 thing bites me again...

8:49 cark: how so ?

8:50 Fossi: having a variable called name in just that function

8:51 cark: ahwell you'll get used to it, i came from common lisp and got used to it

8:52 i'm pretty sure that variable ought to be named customer-name anyways !

8:52 Fossi: more like server-name, but yeah

8:52 cark: =)

8:53 Chouser: heh

8:53 Fossi: it's a little weird when you don't know there's a function of that name around somewhere and rename, but miss one occurence

8:53 rhickey: "name" is actually the only name that gives me Lisp-1 problems

8:54 Fossi: still compiles, but then you get a mystical "can't cast IFn to String" or something

8:55 Chouser: I see people stumbling over others, but "name" is probably the most common.

8:57 djpowell: is print-method officially usable?

8:57 i assume that print-method is just for creating arbitrary human-readable (?) print representations

8:58 Fossi: i've had val key and map as well

8:59 djpowell: i've got a vector with 'type' metadata, and if I override print-method for that type, then it works, but I notice that it also overrides the behaviour of print-dup - which isn't what I want, cause my print-method output isn't readable

9:02 cemerick: I believe print-dup falls back on print-method impls...

9:16 AWizzArd: Yes, cemerick is right. And one can add or overwrite those at runtime to get new printing behaviour.

9:22 djpowell: Is print-method output expected to be 'read'able? no?

9:23 I was just worried that by providing my own, un-'read'able print-method for a meta-data 'type'd vector, it causes print-dup to use it, rather than to use the more suitable print-dup for vector.

9:25 rhickey: djpowell: readability will only matter to a reader. The only time Clojure will print-dup/read it is when the type is a constant in code

9:33 skalnik: so I have a list of 20 booleans, how do I make sure they're all true?

9:34 nevermind :)

10:11 fsodomka: Chouser: please, don't forget about http://clojure-log.n01se.net/ -- logs are still not showing

10:11 Chouser: fsodomka: yes, thanks.

10:13 fsodomka: rhickey: I saw that in the chunks Clojure branch, you changed tests for 'range'

10:13 what is the correct behavior for range with fractions?

10:16 rhickey: fsodomka: it will be that it returns values as long as < n

10:17 fsodomka: so (range 2.5) is (0 1 2)

10:17 rhickey: right

10:18 in the future

10:18 fsodomka: future feature :-)

10:18 drewr: clojure knows the future?

10:18 excellent

10:18 rhickey: drewr: clojure is the future

10:18 drewr: even better

10:19 rhickey: or merely, clojure is its own future

10:19 drewr: self-referential future == single reality

10:19 * drewr is starting to confuse himself

10:24 fsodomka: rhickey: would it be ok, if I write Clojure tests separately in my own branch? using patches is really hard-to-work-with solution (at least for me)

10:24 commits are transparent, so other people who write tests won't do the same thing/area

10:25 http://github.com/fsodomka/clojure/commits/testclojure

10:26 once in a while, we can just merge branches to get tests in

10:26 Chouser: that merge can be done via a patch

10:28 fsodomka: yeah, that would work too

10:29 rhickey: fsodomka: we're still working on a pull mechanism for contributions, but I'm not opposed for bigger things as they are pulled into clojure, like the test lib itself. I don't want it to be harder for people once their stuff gets included. OTOH, as Chouser says, if once in a while you run git format-patch it should reconcile when you resync

10:38 fsodomka: rhickey: the most important thing for me, was to be able to do check-ins. Now since I know that every check-in doesn't have to be a patch, I can work with it. I will contribute a bigger patch once in a while :-)

10:41 Chousuke: fsodomka: there's no need to squash every commit into one if you use format-patch, though.

10:42 fsodomka: a good way to do it is to clean up the history and commit messages, but keep every logical change as a separate commit, then dump them with git-format

10:43 er, format-patch :P

10:45 stuartsierra: Has anyone made progress on Clojure + OSGi?

10:46 fsodomka: Chousuke: how or what tools do you use to do this clean up? (I am new to git) Or what git functions do this clean up?

10:47 Chousuke: well, assuming you have all your commits in a separate branch, you can do an interactive rebase for example

10:47 it allows you to delete, reorder and squash together commits.

10:47 you can think of each git commit as a single patch. it's pretty much how it works.

10:48 for example, if you are on master, do git checkout -b my-changes; then do a few commits, and try git rebase --interactive master

10:49 though, as rebase rewrites history, you should not use it on branches that you have shared with others.

10:50 it's a good way to get rid of all those "oops" and "typo" commits that happen during development, though :)

10:50 Chouser: I wouldn't personally worry too much about cleaning up the history, esp. in test directories.

10:51 rhickey: stuartsierra: I've made a bunch of changes that should help things there, but still need someone to define what exactly that means and what the expectations are

10:51 Chousuke: Well, I have perfectionist tendencies :P

10:52 if all your mistakes are local, there's no harm in cleaning up before sending a patch out

10:52 Chouser: But don't squash commits together too aggressively. If you submit a big patch with lots of commits in it, and all the commits are good but there's questions on one of them, it's relatively easy to create a new patch with that one commit left out.

10:52 drewr: Chouser: +1

10:53 small commits, isolated concerns

10:53 Chouser: that way most of a batch of changes could get merged in without being held up by a queation about one of them.

10:53 Chousuke: I'm not advocating big commits. I'm against big commits. :P

10:53 stuartsierra: rhickey: thanks. I'm just thinking about modularity & dependency management in general, and OSGi seems to be the Java standard.

10:53 Chousuke: I just don't like seeing "oops" in the logs. :)

10:53 it makes bisecting less effective, too :/

10:53 Chouser: Chousuke: yeah, didn't mean to suggest otherwise. Just pointing out the one part of "clean history" that I think is most important.

10:54 Chousuke: small commits are also easier to revert. :)

10:55 rhickey: stuartsierra: there are 2 or 3 aspects I think - one is whether or not independently loaded Clojure code with imports of classes know only in their 'module' can work, That should be much better. The other is can modules have largely independent Clojure namespaces etc. This will require getting rid of the central ns repository. Third is exposing Clojure itself as some sort of modular 'service'

10:56 dependency part a whole other can of worms, at least as far as incorporating Clojure ns deps

10:57 still have yet to have anyone describe adequately what it means to 'get Clojure running under OSGi'

10:59 fsodomka: thanks for the help with git - I will read up on it and play with it a little :-)

10:59 stuartsierra: I think, ideally, one would want to be able to distribute Clojure libraries as OSGi bundles, with declared dependencies.

11:00 Chousuke: fsodomka: http://www-cs-students.stanford.edu/~blynn/gitmagic/ is a nice tutorial

11:03 stuartsierra: What I want is CPAN-style discovery with OSGi-style dependency management.

11:05 cemerick: osgi is a big, hairy pill to swallow just to get dependency mgmt (IMO of course)

11:05 stuartsierra: cemerick: agreed, but what else is there for Java libs?

11:06 cemerick: maven, ivy, jigsaw (forthcoming)

11:06 there's other less well-known ones *shrug*

11:07 stuartsierra: But don't maven/ivy/etc handle only half the problem, finding & downloading dependencies?

11:07 They don't do nested ClassLoaders.

11:08 cemerick: right, no, they don't do that

11:08 jigsaw does, but it's vaporware at the moment

11:08 stuartsierra: ah, ok

11:09 cemerick: course, when JDK 7 hits, we'll have to see if it's going to play java.util.logging to osgi's log4j

11:10 stuartsierra: Hmm, yes.

11:11 cemerick: I'm infinitely distrustful of anything that claims to do anything like CPAN. There's lots of them, but none of them work half as well as the original (partially due to code-rot, partially due to other platforms not being like perl, partially due to bad impls).

11:12 stuartsierra: Yes, Rubygems, Python eggs, and Maven are all inferior to CPAN.

11:12 I'm trying to figure out why.

11:13 cemerick: do let me know when you've got it :-)

11:13 I generally just throw my hands up in frustration and go do something else productive. I can't stand to deal with stuff like that.

11:13 stuartsierra: Well, I'm supposed to talk about it for Philly Lambda on Tuesday. :)

11:13 cemerick: ah-ha. good motivation!

11:13 stuartsierra: yep

11:14 cemerick: Case in point, I've got a pylons app that I'd like to migrate to a different server. Unfortunately, all of its dependencies came out of the cheese shop (via easy_install/paste/et al), and it's apparently old enough that various versions of libs it requires are now gone from the cheese shop.

11:15 old enough == 2 years :-/

11:15 stuartsierra: Yes, I've had the same problem with Ruby.

11:16 cemerick: on the other hand, a colleague of mine had a 5-year-old perl script that used some CPAN modules, and he got the thing running in about 4 minutes.

11:17 I wonder if it's just a matter of stack complexity. A perl script is a far cry from a pylons/django/rails app, never mind a J2EE or Swing contraption.

11:17 ...and I don't see a lot of big, frameworky perl apps floating around

11:18 Fossi: if you come up with something useful, the world's gonna kiss your butt

11:18 stuartsierra: Perl certainly leans more toward small, independent modules rather than large frameworks.

11:18 Fossi: package management systems tend to be a bigger pita than the problem they are trying to solve

11:19 cemerick: stuartsierra: I wonder if there's any visualizations of the dependency networks of CPAN vs. the ruby/cheese shop/maven equivalents

11:19 Fossi: actually, the osgi stuff in eclipse is pretty nifty

11:19 * drewr is currently in love with ivy

11:20 cemerick: Fossi: yeah, and the netbeans module system does well, too (I forget its name). Focus certainly seems to help.

11:20 drewr: solves a direct problem in an ant-friendly way

11:20 Fossi: well, ant itself is a pita :)

11:20 but i guess nothing that a little lancet wouldn't fix

11:20 cemerick: We used ivy for about 18 months, specifically because of its ant friendliness. Using it to track internally-produced dependencies ended up being too onerous, though.

11:20 Fossi: didn't get around to actually try it out

11:21 but ifs in xml make me sick

11:21 drewr: cemerick: really? I just have my own repository and structure things the way it makes sense

11:22 really simple and without the complexity of maven

11:22 stuartsierra: Some info on CPAN dependencies: http://ali.as/top100/

11:22 cemerick: yeah, I totally agree. But for tracking dependencies between internal projects, it's way overkill

11:22 vs. git submodules, say

11:23 drewr: cemerick: perhaps, but for the "please find and download these jars and put them in lib/" it's *awesome*

11:23 cemerick: yes, definitely

11:23 drewr: i have an allergic reaction to putting jars in VCS though :-)

11:24 cemerick: we've found that git submodule do the same job for us in a more straightforward way.

11:24 Fossi: then again, it would help if people released their jars with proper meta-data :D

11:24 cemerick: I did too, but we just create functionally-related dependency repos that hold *only* jars, etc.

11:24 drewr: i suppose if I had a jar-only repo submodules would work ok

11:24 ah, yes ;-)

11:24 cemerick: e.g. a UI dependency repo, a jdbc one, a couchdb one, etc

11:24 drewr: i do that for things like internal db auth info etc.

11:29 Fossi: is there a good style for (cond (some-test? some-param) some-param (some-other-test? some-other-param) some-other-param)?

11:30 drewr: Fossi: condp could probably help there

11:31 * Fossi reads up

11:31 drewr: it gives you more of a switch-style cond

11:32 e.g. http://paste.lisp.org/display/80007,1/raw

11:33 Fossi: i don't even understand what the api wants to tell me :)

11:33 drewr: you give it the test you want to perform on the var, then the var, then the possible result->action combinations

11:34 ,(condp class 10 String :string Integer :integer :else :foo)

11:34 clojurebot: java.lang.IllegalArgumentException: Wrong number of args passed to: core$class

11:34 Fossi: yeah, but if i get it right the test must be the same then

11:35 drewr: ,(condp class 10 String :string Integer :integer :foo)

11:35 clojurebot: java.lang.IllegalArgumentException: Wrong number of args passed to: core$class

11:35 stuartsierra: drewr: you want "instance?"

11:35 drewr: ,(condp instance? 10 String :string Integer :integer :foo)

11:35 clojurebot: :integer

11:35 drewr: stuartsierra: thanks :-)

11:35 forgot it was a comparison not a predicate

11:37 Fossi: so at least if test is the same, that'll work

11:38 a kind of cond-let would be nice though

11:38 ah, seems like contrib has one

11:39 drewr: if the tests are unique then cond probably makes most sense, or a map with dispatch fns

11:47 hiredman: or multimethods

11:47 clojurebot: multimethods?

11:47 clojurebot: multimethods is what separates the boys from the men.

11:47 hiredman: clojurebot: multimethods is also <reply>multimethods are awesome!

11:47 clojurebot: 'Sea, mhuise.

11:48 Chouser: also awesome: promises

11:50 Fossi: hmmm. i wonder how a multimethod could work out

11:50 hiredman: actually most likely pretty badly if you want cond-let

11:51 Fossi: problem is i have a string and want to check whether i know a tag that's similar

11:52 drewr: Fossi: paste an example of what you have and we'll try and clean it up

11:52 lisppaste8: url

11:52 lisppaste8: To use the lisppaste bot, visit http://paste.lisp.org/new/clojure and enter your paste.

11:52 hiredman: what is a tag? a keyword?

11:53 lisppaste8: FossiFoo pasted "untitled" at http://paste.lisp.org/display/83752

11:53 Fossi: nice pastebin

11:53 hiredman: if you turn your string into a keyword you can construct a hierarchy which multimethods can use for dispath

11:54 oh

11:54 drewr: what does group-articles-by-tags return? articles?

11:54 Fossi: the tag is some other string i have stored previously

11:55 well, the group-article-by-tags isn't really relevant, as i just want the tags. just didn't refactor yet

11:55 hiredman: seems fine

11:56 Fossi: if the (.toLowerCase tag-guess) is more expensive, i'd like to let it somehow

11:58 hiredman: I doubt it's very expensive

11:59 just some subtraction

11:59 ,(int \A)

11:59 clojurebot: 65

11:59 hiredman: addition

11:59 *cough*

11:59 Fossi: no, it's not, but if i place another more expensive operation there

11:59 like a fuzzy word-search or such

11:59 hiredman: ,(char (+ 30 (int \A)))

11:59 clojurebot: \_

11:59 hiredman: :/

12:00 Fossi: i guess map and dispatch functions would be best

12:16 * technomancy wrote some codes a while ago to prompt for an unqualified class name and automatically add :import lines for matches on the classpath

12:16 technomancy: would love to get feedback: http://github.com/technomancy/swank-clojure/tree/master

12:18 Jomyoot: IS there magick with Emacs to make Clojure coding faster?

12:19 Chouser: yes, but you have to feed it your soul first

12:19 technomancy: faster than what? =)

12:19 replaca: Jomyoot: clojure-mode, of course, slime, and paredit are my magic pieces

12:19 technomancy: yes, paredit is indispensable

12:20 replaca: paredit converts parens from enemies to friends :-)

12:21 Jomyoot: How about Textmate?

12:21 Anytihng special for clojure?

12:22 technomancy: there's support, but last I heard it's fairly primitive

12:23 danlarkin: Jomyoot: it's nowhere near emacs for editing clojure code

12:23 Jomyoot: how about la clojure?

12:25 replaca: Jomyoot: don't know anything about la clojure

12:25 Jomyoot: gotta see demo for paredit

12:26 * technomancy is working on that

12:26 technomancy: slowly

12:29 replaca: Jomyoot: good thing to do is load it up, grab the cheat sheet and just play in an empty buffer. Then just start using it while writing code. At first it will be a little awkward, but pretty soon you'll get it in your muscle memory and not know how you did lisp without it.

12:29 cemerick: Jomyoot: enclojure provides maybe 60% of what you'd get in emacs w.r.t. editing s-expressions, with the additional upside that you won't go stark raving mad over time, and you'll spend time doing work instead of tweaking emacs. :-P

12:29 * cemerick ducks, runs

12:29 technomancy: re: paredit: http://p.hagelb.org/paredit-outline.html

12:32 Raynes: Looks like the AjClojure guy is looking for a new name. He said so on Twitter. Twitter don't lie.

12:32 Chouser: heh

12:32 well, it's a good sign anyway

12:32 Jomyoot: awesome

12:33 cemerick: actually, a couple of clojure wrappers around NetBeans APIs would make it possible to put together every emacs-y things within that environment.....

12:33 technomancy: feedback welcome on that outline btw; I'm going to turn it into a screencast soon

12:35 Raynes: "AjClojure is a reimplementation of Clojure ideas using C# I should change the project name, AjSharpure?"

12:37 cemerick: ugh, that's so tortured.

12:41 hiredman: clojurebot: rhickey is also <reply>"The guy is totally awesome." -- Daniel Weinreb

12:41 clojurebot: In Ordnung

12:41 cemerick: hiredman: where'd that quote come from?

12:42 hiredman: http://stuartsierra.com/2009/02/22/its-about-the-libraries#comment-42489'

12:42 er

12:42 extra ' on the end there

12:42 technomancy: he's an author of the CL spec, right?

12:42 hiredman: one of them

12:43 "Clojure is the future of Lisp" in there as well

12:43 drewr: he wrote LOOP for crying out loud!

12:43 cemerick: wow, that's a helluva endorsement.

12:44 hiredman: he did sort of qualify it with "in a production environment"

12:44 but that ain't much of a qualifier

12:44 technomancy: hiredman: especially coming from someone who likes CL over scheme

12:49 clojurebot: multiple inheritance is http://www.piratejesus.com/nerdcore/nerdcore017.gif

12:49 clojurebot: Alles klar

12:50 stuartsierra: He might have been referring to Scheme's use as an academic, teaching language.

12:53 cemerick: yeah, scheme still has an upper hand in that department, IMO.

12:53 Chouser: but it's so mutable!

12:54 cemerick: that's just an implementation detail

12:54 I think PLT cons cells are immutable now

12:54 Chouser: maybe we need a teaching-clojure that keeps all the immutable goodness, but ditches all the JVM libraries in favor of cleanliness.

12:56 cemerick: hrm. Sounds like scheme. :-P

12:56 Chouser: hm

12:57 scheme doesn't do mutable locals?

12:57 technomancy: Chouser: just don't teach people how to use any construct involving a dot, and you'll be in good shape

12:57 Chouser: setf or whatever its called?

12:57 technomancy: no need to change the language. =)

12:57 Chouser: technomancy: could be. I'm likely to have a chance to teach a kid programming and am trying to decide if clojure's a good fit or not.

12:58 technomancy: cool!

13:00 hiredman: I think a cool intro to programing class would be something like "learn lua by writing a lisp interpreter"

13:01 where lua is lua, python, ruby, javascript, or something else

13:02 drewr: heh

13:03 hiredman: so you have a very directed course, and learn about the internals of a programing language

13:04 you'd start by writing everything up in the host language, and has you get towards the end of the course you start replace bits and pieces in the implemented language

13:09 homework "now that we have macros, replace special forms x y and z with macros

13:09 danlarkin: hard class if you're not used to FP!

13:09 hiredman: I don't think so

13:10 I think it would be a great freshmen cs class

13:11 Chouser: many freshmen cs students at my school were still struggling a bit with simple loops half-way through the semester. a macro might be a lot to ask.

13:12 cemerick: we've all had our heads screwed up by typical CS stuff, when FP really isn't that hard

13:12 ...says the guy who has a particularly screwed-up head

13:13 loops are hard -- or, really, mutability is hard.

13:13 hiredman: Chouser: someone somewhere will always stuggle, best to set the bar high so everyone can struggle together :P

13:13 Chousuke: There certainly exist people who really seem to be unable to learn programming.

13:14 I don't know if it

13:14 it's because of the imperativity or not, but hm

13:15 danlarkin: I don't remember where I heard this, but supposedly programming 101 professors fully expect 50% of their students to not grasp the material

13:15 replaca: after reading through the source of enlive, Christophe has me using -> all over the place. Dunno if it's a good idea or not.

13:15 technomancy: danlarkin: that was probably a lot worse back when programming was seen as a way to get rich

13:15 Chousuke: replaca: heh

13:16 I like ->, but it's certainly easy to abuse.

13:16 replaca: yeah, I haven't really figured out "best practice" yet. I'll keep using it til I decide where the limit is :-)

13:17 ataggart: My intro CS course used a pseudocode language the whole semester. I got a D. The second semester was in java; I got an A. Not sure what to make of that.

13:17 replaca: it does have a nice "pipeline-y" feel

13:17 hiredman: eww

13:17 pseudocode

13:17 danlarkin: technomancy: heh, probably. From my experience pretty true, too. Lots of confusion about where to put semicolons versus squiggly brackets. C++ isn't the greatest intro language, granted, but still

13:18 * technomancy couldn't imagine a worse intro language, actually

13:18 technomancy: unless you count languages that are bad on purpose

13:18 danlarkin: brainf**k :)

13:18 replaca: ataggart: that's like trying to teach kids numerical analysis before 2 + 2 = 4. Noble, but flawed

13:18 hiredman: macros are actually pretty simple from the perspective of the implementing language

13:18 Chousuke: technomancy: is Visual Basic bad on purpose? :P

13:18 ataggart: lol

13:19 hiredman: thats why I am saying you start with something like lua

13:19 technomancy: Chousuke: teaching VB to beginners might be better than C++ because they'll realize how horrible it is sooner.

13:19 hiredman: function some-name (args) do-stuff-here end

13:19 technomancy: with C++ they'll just keep banging their heads against the wall thinking, "maybe I'm just not *smart enough* yet!"

13:19 hiredman: dirt simple readable syntax

13:20 Chousuke: hiredman: macros are very simple in principle. just a function of data structures to another data structure. I guess it's the details of effectively producing data structures that are also code that trip people up.

13:20 hiredman: Chousuke: it's not liked they'd have to write complicated macros, just replace a few previously (and careful selected for this purpose) "builtins" with macros

13:21 danlarkin: I think it's the runtime vs readtime that is tough

13:21 Chousuke: hiredman: like the common misconception that ` is somehow a special macro thing.

13:21 hiredman: or the hygiene issues when generating code. (which are actually completely separate from macros, as a concept)

13:22 hiredman: Chousuke: all of which would be skipped over

13:22 which will make a horrible lisp interpreter, but this is a freshmen cs class

13:22 Chousuke: but then you would not be able to write very useful macros :/

13:24 hiredman: php.lisp is about 390 lines of php

13:26 doesn't seem unreasonable for a quarter's worth of work

13:27 Chousuke: I saw a C lisp implementation somewhere once that was a single file and about a couple hundred lines of code.

13:28 it didn't have garbage collection though :)

13:28 hiredman: :|

13:28 you could always throw in boehm

13:28 Chousuke: heh.

13:28 technomancy: mine's 754 LOC

13:28 (of Ruby though, major cheating)

13:30 hiredman: php.lisp uses php arrays as lists, which is sort of cheating I guess

13:30 Chousuke: (loop [] (print (eval (read))) (recur)); Cheating? Never.

13:30 not very useful though :(

13:31 technomancy: hiredman: I tried that in mine; it took me weeks to back myself out of that mistake

13:31 hiredman: the cool thing about implementing a programing language as the class goal, is there are all sorts of doodads you can fiddle and adjust and add in and take out

13:32 Chousuke: as a final assignment you could require them to write some simple program using their interpreter :P

13:32 hiredman: if, god forbid, the class is burning through the material, just throw in type-checking

13:33 Chousuke: yeah, have them solve euler problems using it :P

13:59 rhickey_: http://clojure-log.n01se.net/ down since 7/11?

14:00 er, not down, but not logging?

14:01 cemerick: yeah, hopefully there's data somewhere. I was unceremoniously lost my connection yesterday in the middle of the binding discussion.

14:02 rhickey_: cemerick: yes, we lost you - you were saying?

14:02 cemerick: oh, I don't remember what my next step was

14:03 rhickey_: well you should now have everything you need for a neat with-binding solution

14:03 cemerick: yeah, that'll certainly work.

14:03 rhickey_: I got the batch-editibility fully going in the persistent vector last night and this morning - the perf is within 20% of ArrayList

14:04 Chouser: I've got the logs, but they're in the wrong format. I hope to get the site up this weekend.

14:04 cemerick: I thought about it for most of the night, and it seems like the general solution (short of copying bindings on the propagation of every value) is to add some functional demarcation to my cells impl. Right now, it's very open-ended, in that a particular "dataflow" can be added to at any time. Very flexible, but can lead to *really* large transactions (with-binding or not).

14:07 rhickey_: I'm still on the fence about read access to the mutable colls, e.g. there's nth! but not seq

14:07 cemerick: e.g. over *here* (/me waves his hands to the left) you've got a nest of cells that are UI-related, and over *there* you've got N other nests, each related to particular functional domains. When a value needs to be propagated from one nest to another, that should probably be a send to a "gateway" agent, which allows for some reasonable decoupling.

14:07 rhickey_: cemerick: sounds like a good idea

14:09 what's with all the "Whoa! I was listening to Sunn O))) and Rich Hickey started talking in the background and the music became creepier than before!" tweets?

14:10 cemerick: rhickey_: looks like they're all spammer accounts.

14:10 pretty odd confluence, certainly

14:10 odd bot behaviour

14:13 rhickey: with-binding will solve direct future, pmap calls, etc., but it won't help with delays, etc., right? That'd require two calls -- one to capture the current bindings, and another inside the delay to apply them...I think.

14:14 ach

14:15 heh, my proggit submission re: Weinreb's comment got buried, not surprisingly

14:29 tashafa: hello.clj

14:29 Raynes: (println "What's up?")

14:30 tashafa: help... can some please explain how preduce works

14:31 Hun: ,(doc preduce)

14:31 clojurebot: "clojure.contrib.datalog.util/preduce;[[f data]]; Similar to merge-with, but the contents of each key are merged in parallel using f. f - a function of 2 arguments. data - a collection of hashes."

14:31 tashafa: especially the (f base an-element-from the collection)

14:32 hiredman: ~def preduce

14:36 tashafa: ah... it was the fact that it uses a reduce without an inital value in the source of preduce that was tripping me up

14:46 sh10151: if: Clojure installation step failed: git clone git://github.com/kevinoneill/clojure.git

14:46 is this a temporary situation or is my code out of date?

14:46 from clojure-install in clojure-mode

14:47 the git error is "no matching repositories found"

14:48 hiredman: uh

14:48 clojure moved to git, so there is an official github repo

14:48 clojurebot: clojure?

14:48 clojurebot: clojure is far closer to perfection then python

14:49 hiredman: clojurebot: github

14:49 clojurebot: http://github.com/richhickey/clojure/tree/master

14:52 Chousuke: then :P

14:53 Chouser: hehe

14:57 hiredman: :/

14:57 clojurebot: literal [?] clojure

14:57 clojurebot: 11

14:57 hiredman: clojurebot: literal [1] clojure

14:57 clojurebot: cheating

14:58 hiredman: clojurebot: literal [7] forget

14:58 clojurebot: nothing defined

14:59 * hiredman tries to rember the syntax for this

15:01 sh10151: hiredman: so clojure-mode needs an update?

15:01 hiredman: sh10151: dunno

15:01 sh10151: huh

15:02 this was easy three months ago :-D

15:02 hiredman: where are you getting clojure-mode from?

15:02 sh10151: git://github.com/jochu/clojure-mode.git

15:02 hiredman: http://github.com/technomancy/clojure-mode/ seems to be the place

15:03 sh10151: i'm out of it for a while

15:03 and everyone gets delusions of grandeur

15:03 Chousuke: jochu's is the original but techno's is more up to date.

15:03 * hiredman doesn't emacs

15:04 sh10151: what do you use?

15:04 i understand emacs is an acquired taste

15:04 hiredman: vim

15:04 sh10151: ah

15:04 I think that's not popular at work either

15:04 Chousuke: vim is an acquired taste as well :P

15:04 cschreiner: bbbut I use emacs, and I love it

15:04 hiredman: I am not opposed to emacs per-se

15:04 sh10151: IDEA and Eclipse seem to be the systems of choice

15:04 hiredman: I just cannot be bothered

15:05 rsynnott: sh10151: for clojure?

15:05 Chousuke: I like both so I use viper with emacs.

15:08 sh10151: I'm trying to get my notebook set up with Clojure for a little presentation I'm doing

15:08 "Clojure as an Interactive Java Shell"

15:29 ti381: IDEA and Emacs make me chuckle for clojure work

15:31 tashafa: ~def memoize

15:32 how do you print the source of a fn from the repl again?

15:34 Chouser: (source memoize) -- that's clojure.contrib.repl-utils/source

15:35 tashafa: ah

15:35 thanks Chouser

15:46 sh10151: this clojure-mode clojure-install is giving me all kinds of trouble

15:47 i think i will just do it all manually

15:49 ksclarke: hmm, I have clojure-contrib in my classpath but when I try to use mmap I get: "Unable to resolve symbol: mmap in this context (NO_SOURCE_FILE:6)"

15:49 I'm a complete newbie so I know I must be missing something obvious

15:49 the require for mmap worked fine

15:50 stuartsierra: "require" only loads the library. If you want to access it without a namespace, load it with "use".

15:51 ksclarke: ah thanks!

16:05 rzoom: anyone have any advice on passing an array of java strings to a java method?

16:06 how would I construct a Java array of Java strings?

16:06 (to-array ["abc" "def"])

16:06 Chouser: ,(into-array ["abc" "def"])

16:06 clojurebot: #<String[] [Ljava.lang.String;@1673ef7>

16:06 Chouser: what are you starting with on the Clojure side? a seq of strings?

16:07 hiredman: ,(.toArray ["a" "b"])

16:07 clojurebot: #<Object[] [Ljava.lang.Object;@11e356b>

16:07 hiredman: :(

16:07 rzoom: thanks!

16:08 to-array wasn't quite working

16:08 Chouser: rzoom: right. to-array returns a Java array of Objects

16:09 hm. I mean a Java array-of-Objects

16:09 rzoom: ahh.

16:09 well, i just added create-ssl-server to contrib server-socket

16:10 Chouser: nice!

16:10 rzoom: will have to send it to the maintainer

16:10 Chouser: yep. You've seen http://clojure.org/patches ?

16:10 rzoom: i have now. reading ;)

16:25 hiredman: ~works on my machine

16:25 clojurebot: http://haacked.com/images/haacked_com/WindowsLiveWriter/IConfigMapPathIsInaccessibleDueToItsProt_1446B/works-on-my-machine-starburst.png

16:31 rzoom: ok, showing my Java ignorance: is ant multithreaded?

16:32 oh, i see that it can be.

16:40 stuartsierra: typically it isn't

16:41 rzoom: yeah, looks like the <parallel> tag is needed

17:41 rhickey: ok, if you want to play around with batch editing of vectors, the code is in the chunks branch: http://github.com/richhickey/clojure/commits/chunks

17:42 lisppaste8: url

17:42 lisppaste8: To use the lisppaste bot, visit http://paste.lisp.org/new/clojure and enter your paste.

17:42 rhickey pasted "batch editing of vectors" at http://paste.lisp.org/display/83767

17:47 mebaran151: is it possible to change the size of the agent thread pool?

17:47 hiredman: there are two agent threadpools

17:47 rhickey: mebaran151: the send-off pool grows as needed

17:52 mebaran151: alright thanks

17:58 Chouser: rhickey: looks pretty clean considuring the mutability

17:59 rhickey: Chouser: the idea is, write it the correct way, if it becomes your bottleneck, add mutable, !, !, !, immutable

18:00 some open questions are - right now I disallow normal nth/get etc on the mutable version, must use nth!/get! etc

18:00 although normal count works, hrm

18:01 I don't want these things to be very useful if 'leaked'

18:07 Chouser: right

18:08 I think that's valuable property

18:08 rhickey: I wonder how much pressure there will be for seq

18:08 I imagine these used mostly for building/creating, but people might hang on to them for an extended time

18:09 hiredman: might be useful to have scoped mutability

18:09 rhickey: you could in fact use one as the value of an agent, simply (immutable @agt) whenever you want to read, as send ensures serial access

18:10 Chouser: gotta go. I'll try to work on irc log later

18:10 rhickey: Chouser: thanks

20:29 Chouser: oh, I just got what you were saying -- leave it mutable and each time you need to read use (immutable @agt)

20:31 rhickey: right

20:31 not quite sure that will work, since there is not threading control at all

20:32 in fact, will not work

20:35 Chouser: oh, because a flying read might break while the agent it updating the value?

20:35 rhickey: immutable copy must be given by same thread as mutation

20:37 Chouser: must be same thread, or just serialized with mutation?

20:37 rhickey: serialized, but not really a good story

20:37 Chouser: yeah

20:38 thin plot, no character development.

20:38 rhickey: unhappy ending

20:40 Chouser: and agents were the best shot at leaving mutables hanging out in public -- sharing them other ways just gets worse

20:41 rhickey: there might be some variation of that idea though

20:42 not too important

20:42 the primary use is birth/batch

20:43 Chouser: are you worried about abuse? I'm not really, esp. if nth and seq fail.

20:44 I'm sure you've thought of this, but it's easier to add capability than to take it away. So if seq and nth fail for now, and people have valid use cases for them, it'll be easy enough later to allow them to work.

23:36 duck1123: How do I specify code to be run as a destructor when using gen-class

23:36 Chouser: does java even support that?

23:37 duck1123: destructors? I thought they did...

23:37 Chouser: I seem to recall something called "finallize" but that it wasn't very reliable.

23:38 duck1123: hmm... it appears you're right

23:39 I'm trying to open a connection to a xmpp server when my http server starts, and I want to make sure things are cleaned up when it shuts down

23:41 unfortunately, compojure's defservice returns immediately. otherwise I would use the with-connection macro I wrote

23:42 Chouser: hm. maybe compojure has some kind of shut-down hook?

23:57 * ksclarke wonders if it's possible to use the svn head of clojure with eclipse clojure-dev plugin

Logging service provided by n01se.net