#clojure logs

2010-09-11

00:24sprousttomoj/ihodes: another way to define simple zip: (partition 2 (interleave coll1 coll2))
00:25tomojlooks more than 3 times slower
00:25sproustThis one _does_ use Clojure's slightly odd form of cons (interleave defined recursively via lazy-seqs)
00:25sprousttomoj: does it?
00:25tomoj,(time (dorun (partition 2 (interleave (range 10000000) (range 1000000)))))
00:25sproustOuf...
00:25clojurebot"Elapsed time: 6054.071 msecs"
00:25tomoj,(time (dorun (map vector (range 10000000) (range 1000000))))
00:25clojurebot"Elapsed time: 2309.176 msecs"
00:25sproustYup.
00:28chouser,(time (dorun (map-indexed vector (range 10000000))))
00:28clojurebotExecution Timed Out
00:28chouser:-(
00:28sproustThis clojurebot friend is pretty resilient :-)
00:48sproustHmmm ... I have a function that is implemented as two nested for loops, which produces side effects (writes out files).
00:49sproustAn enclosing (dorun/doall is not enough to force execution of the inner for loop.
00:49sproustWhat's the idiomatic solution to this?
00:50sproust(I've patched it up with a (doall) around the inner loop, but my sense of aesthetics thinks it stinks. Curious to know what's the word from the pros.)
00:52tomojuse doseq instead?
00:52tomojfor?
00:52clojurebotfor is not a loop
00:55sprousttomoj: interesting; the similarity btw for and doseq never came to mind. Thanks.
00:57sproustI guess what I want really is doseq.
00:57sproustWorks like a charm!
01:09quotemstr_What would be the canonical way, in Clojure, to wait for a counter to descend below a certain value, then accept() a connection?
01:09quotemstr_I'd normally use a condition variable for that sort of thing.
01:10tomojis the counter in a ref/atom?
01:10tomoj(what would it mean to wait for it to descend otherwise?)
01:13quotemstr_Let's say it's a ref.
01:16tomojd'oh
01:21quotemstr_Would an atom be better here?
01:21quotemstr_It's the waiting-until-decremented part that's the issue.
01:22quotemstr_Should I just create an agent and fire off something every time I'd decrement a counter?
01:27tomojwhat are you counting?
01:28quotemstr_Connections.
01:28quotemstr_There are 1024 connection slots (protocol-bound), and it's not good to accept() a connection if there are no slots available.
01:28quotemstr_I just thought I'd ask about the canonical Clojure approach. More traditionally, you could use a condition variable, or a semaphore.
01:28quotemstr_(The counting semaphore is the classic solution to this problem.)
01:30tomojideally you wouldn't have any state :)
01:32quotemstr_And ideally, I wouldn't have to work, and I'd have a Cessna, and a beautiful wife, and be on the cover of Newsweek every month.
01:32quotemstr_:)
01:32quotemstr_But IO is a fact of life, alas.
01:34tomojthat you're doing IO doesn't mean you need an atom
01:34tomojbut I don't understand what you're doing
01:35tomoj(nor is it likely that I will if you try to explain it, sorry)
01:36quotemstr_Fair enough.
01:37quotemstr_But global knowledge isn't necessary. :)
01:37_mstI'd be tempted to have a main thread calling accept() on the socket and then push the accepted socket onto a blocking queue for the workers to take off (fairly traditional again...)
01:37_mstthat feels fine to me in terms of being idiomatic :)
01:38quotemstr__mst: That's cleaner, but the problem is that the consequences are externally visible.
01:38quotemstr__mst: A client can call connect() then hang. It's better not to complete the accept() at all until resources to back that connection are available.
01:39_mstahh I see
01:44_mstso ideally you'd like the worker processes to be calling accept() when they're actually ready?
01:44quotemstr_Yeah.
01:45quotemstr_... should I just create 1024 workers?
01:47_mstI guess it makes life easier just to statically create them all at startup
01:49quotemstr_That might solve this particular problem, but it doesn't tell me how to create the equivalent of a counting semaphore.
01:53_mstoff the top of my head I can't think of how I'd implement one using clojure's concurrency abstractions, but in reality I'd probably go straight to java.util.concurrent.Semaphore if I was sure that's what I wanted
01:53_mstnot very helpful, sorry :)
01:55quotemstr_Thanks anyway. :)
02:31amalloyi'm not sure i get the github philosophy. i've made a fix to the documentation for clojure.core; how do i submit it for approval?
02:54sproustWhen I eval a (ns) directive, are the files referred to loaded every time? Is there not a cache of Clojure modules? How does that work?
03:09amalloysproust: i'm not sure, but i think this depends what you mean. (ns foo) itself doesn't load anything, of course; (ns foo (:use (bar baz))) loads bar.baz exactly once over the lifetime of your program no matter how many times you write that form
03:10KirinDaveI think I need a clojure t-shirt.
03:11KirinDaveI think that's the best way I could get better at clojure.
03:11amalloyI went to clojure-conj and all I got was this (promise 'shirt)
03:13KirinDaveamalloy: We need something really good.
03:13KirinDavenone of this erlangfactory shit.
03:13KirinDaveWe need something that ugmonk could sell.
04:48n2n3,(|)
04:48clojurebotjava.lang.Exception: Unable to resolve symbol: | in this context
06:19kjeldahlAny pointers for doing simple unbuffered text file output in Clojure? Do I have to dive into the java libs?
06:20mrBlissmaybe spit is what you need
06:21mrBlissnever mind
06:21kjeldahlYeah, it closes the file as well...
06:23kjeldahlBut the source of it shows it's pretty simple, even if using the java libs, so I might become inspired by it. Thanks for the pointer.
06:25raekthe java classes are still used
06:25raekhowever, there are some functions in clojure.java.io that makes it simpler
06:33raekwith, c.j.io only the .write call has to be in java... (or if you use spit, none)
06:36raek(use '[clojure.java.io :only [writer]]) (with-open [f (writer "file/path")] (doseq [x some-coll] (.write f (make-some-string x))))
06:45raekthis is buffered though... if you need unbuffered output, you have to use the java classes directly (and pass output as java arrays)
06:53kjeldahlraek: Thanks. It's for a logging type class though where each clojure program runs as a separate process and communicates with a java host through stdout. The java host filters _all_ io, which is why the clojure programs has to log to a file.
06:53kjeldahlraek: Which means that with-open might not be ideal for this use case.
06:57raekyes, with-open would not be very useful in that case
06:57raekmight be better to just define the writer as a global var
06:57kjeldahlYeah, I'll use the with-open source for "inspiration".
06:59raekthe only io-related calls it makes is to .close the file when done (or when a exception is thrown)
07:02raek(def log-writer (writer "file/path")) (defn log [s] (doto log-writer (.write s) .newLine .flush)) ; simple example I just made up
07:03raekand then (.close log-writer) should be called when the application exits
07:06ChousukeYou might want to use an agent to serialise access to te log-writer if you have any parallelism.
07:19kjeldahlThanks for the help. Raek's code looks fine (haven't tested yet, but will do so shortly).
07:31kjeldahlraek: Code works fine. Thanks.
07:43raek(def logger (agent (writer "log.txt"))) (defn log-line [log-writer s] (doto log-writer (.write s) .newLine .flush)) (send logger log-line "test")
07:53RaynesMorning.
09:16edbondhow to use non-maven jars with leiningen?
09:25edbondI did mvn install:install-file
09:27Raynesedbond: Note that doing that sort of thing kinds of kills the point of dependency management in the first place. If you have open source jars that aren't already on a maven repository somewhere, you can also upload them to clojars.
10:04insomniaSalthi all
10:07insomniaSaltc, java, emacs-lisp, starting clojure as of today
10:07insomniaSaltxD
13:04Anniepoo_why doesn't (def (symbol "foo") 7) work? I'm expecting it to be (def foo 7)
13:05wtetzner_because you're trying to set the form '(symbol "foo") to 7
13:06wtetzner_def doesn't evaluate it's first argument
13:06Anniepoo_ah, light bulb goes on
13:07Anniepoo_(it's a surface mount LED)
13:11Anniepoo_depressingly, I'm doing just enough clojure that each new project I'm a noob again
13:11KirinDaveAnniepoo_: Relish that feeling
13:12UtopiahAnniepoo_: tried taking notes?
13:13Anniepoo_@Utopiah not sure how I'd structure 'notes' - it's more that I lose the 'clojure mindset'
13:14UtopiahI dont know how you'd structure them either but I know that it helps me in most tricky situation, precisely because I have to structure my thoughts and can re-access recurrent problems anytime efficiently
13:17insomniaSaltfor me, this is facilitated in emacs' org-mode
13:18UtopiahinsomniaSalt: yes, there a plenty of good tools, the only bad answer IMHO is "well right! Im going to do one right away in Clojure (or whatever problem Im trying to solve)!" ;)
13:19Anniepoo_I have a freemind mind map with all my emacs knowledge in it
13:21Utopiahbut nothing on Clojure?
13:22Anniepoo_I have a directory full of snippets of clojure goodness
13:23Anniepoo_including 'chouser explains state' and 'jesusthisisawkward'
13:32Blackfootis there a way to define a struct or record such that trying to use undeclared keys will result in an exception? or even better, a compile time check if they key is known?
13:33Anniepoo_Blackfoot - you could iterate thru the keys and check that each is present in some list of allowed keys, but
13:33Anniepoo_I suspect you're trying to write java in clojure.
13:34Anniepoo_ah, I misread your question
13:34Blackfootmain motivation is to simply avoid making typos in key names, since they are not checked
13:35Anniepoo_the think of undefined keys just returning nil has it's plusses and minuses
13:35Blackfootright, i don't mind it while iterating/developing
13:37RaynesBlackfoot: http://gist.github.com/575379 might be helpful.
13:40Anniepoo_It'd be nice to have a tool in the editor that had a list of symbols. Whenever you typed one that wasn't on the list it'd underline in red or something
13:40Anniepoo_same tool could do autocomplete
13:40Blackfootyes, that'd be a start for the editor
13:40Anniepoo_it'd have some 'add this to symbols' key
13:41Blackfootwell vim, and i'm sure emacs, can autocomplete from any token it has previously seen
13:42Anniepoo_it can? I didn't know that! how do I activate that?
13:42BlackfootRaynes: I think the core issue is enforcing a protocol... so maybe i should just be using a protocol
13:42Blackfoot^N or ^P in vim
13:43herdrickquestion regarding compojure:
13:43herdricki tried to run the hello world on the compojure site
13:43herdrickdidn't work
13:43Anniepoo_M-/
13:43herdrickdo i need to install jetty / does the project.clj deps not include jetty itself?
13:44BlackfootRaynes: imagine i am reasonably sure that every Circle record has a diameter, I don't want a NullPointer exception way down the line when I type (:diameer circle)
13:45Anniepoo_I think they unit testing folks would say that should get caught by unit testing
13:47herdricksorry, i'm back now - bad connection
13:47herdrickthe error i got was "Exception in thread "main" java.lang.ClassNotFoundException: clojure.main"
13:50Blackfootherdrick: i have not done the tutorial, but i would make sure a) project.clj has a :main key, b) the namespace in which your main function exists has a :gen-class key, and c) the main function in the namespace is named correctly (usually -main)
13:52herdrickhi Blackfoot: no, there's no :main anything in my project.clj
13:52herdricknor 'main' anywhere else
13:52herdricki think compojure doesn't need it
13:53herdrickin any case, it looks like i do need to download jetty separately no mention of that in the 'getting started' hello world docs....
13:55Blackfootah ok
14:03herdrickoops, no it did include jetty already
14:03herdrickcrud
14:03herdrickwell, it appears the hello-world example is broken
14:03herdrickor something
14:04herdrickor i am incorrectly pasting the code or config stuff in...
14:05herdricksigh
14:07chouserherdrick: I'm sorry -- I know it can be frustrating. Unfortunately I've never used compojure at all so I'm in no position to help.
14:07herdrickchouser: no worries - thanks anyway!
14:07chouserclass not found "clojure.main" suggests clojure.jar itself is not in your classpath
14:07chouserbut I don't know lein well enough to tell you where to look to fix that
14:10tomojthe repl task doesn't take any arguments
14:10tomojand it should be src/hello_www/core.clj, not src/hello-www/core.clj
14:11raekbetter to do just do "lein repl" followed by "(require 'hello-www.core)" in the repl
14:12raekthe lein repl command has never officially been taking two args
14:12raekthat just happened to work due to its implementation for some versions
14:12raekso yes, the example is broken.
14:13raek*one arg
14:28herdricktomoj: ok - thanks
14:28herdricklein repl by itself breaks for me in the same way
14:28herdrickso it can't even find the clojure jar?
14:28herdrickodd
14:29Rayneschouser: Also, it wasn't the multimethods causing that weird memory leak in sexpy.
14:29tomojherdrick: did you run `lein deps` ?
14:29RaynesJust letting you know. I figured it might have been something weird going on there.
14:29herdrickyes
14:30tomoj`lein -v`?
14:30herdrickLeiningen 1.1.0 on Java 1.6.0_20 Java HotSpot(TM) 64-Bit Server VM
14:31tomojwell, that's pretty old
14:31herdrickah ok!
14:31herdrickthanks
14:31tomoj`lein upgrade`
14:31herdrickyeah, doing that now, thanks!
14:32herdrickthis is probably the problem
14:32tomojdunno.. the repl task shouldn't have done that in 1.1.0 either
14:33raekI have sent a PM on github to James Reeves (the author of compojure) about the lein usage (which was erroneous anyway)
14:39herdrickhot dog - that worked
14:39herdrickthanks tomoj:
14:40herdrickand raek: thanks, the (require 'hello-www.core) was necessary starting lein with 2 args still doesn't work
14:40tomojherdrick: are you an emacs dude by chance?
14:40herdrickyep
14:40herdrickwell, i use it i like it ok ;)
14:41tomojI usually replace the (run-jetty example {:port 8080}) with something like (defonce server (run-jetty #'example {:port 8080 :join? false}))
14:41tomojthen you can C-c C-k the file and the server will stay running and pick up the changes
14:41raekinteractive development with slime is really handy for web programming
14:42raekno need to restart the server
14:42raekas long as you remember to var quote the handler function (as tomoj's example does)
14:42herdrickok, that is exactly the kind of thing i love
14:43herdricktomoj: what's that run-jetty function?
14:43raeklein swank in the terminal and M-x slime-connect in emacs
14:43tomojit's from ring.adapter.jetty, it just starts jetty with a ring handler
14:43raekafter adding :dev-dependencies [[swank-clojure "1.2.1"]] to project.clj
14:44Rayneschouser: Ping me when you get a moment.
14:44raekit starts the http server
14:44herdrickraek: ok, thanks and then (require 'hello-www.core) to start the server?
14:44herdrickor run-jetty ?
14:45raekthat depends on whether your hello_www/core.clj contains the run-jetty call :)
14:45raekthe require line loads and evaluates everything in the file
14:46raekso, I would recommend adding tomoj's line to the core.clj file (replacing the old one)
14:47raekand starting it with (require 'hello-www.core)
14:47raekrunning require again will not re-evaluate the file
14:47raek(unless you pass the :reload option)
14:49raekin emacs, when connected with slime, you can evaluate code (and redefine functions) with C-x C-e or C-M-x
14:50raekthe C-c C-k tomoj mentioned basically does a (require '... :reload) for the current buffer
16:33chouserRaynes: pong
16:35Rayneschouser: Apparently, there wasn't a 'memory leak' at all. I was able to reproduce it on a small scale just by reloading clojure.java.io around 300 times and watching the memory usage rise. However, I decided to try to make sexpbot run out of memory by reloading, but eventually it appears to stabilize and even lower quite a bit at some point.
16:36RaynesI'm not sure why, but it doesn't appear to be a real problem.
16:36chouserhm, so perhaps it was just GC behavior
16:36chouserthough that doesn't explain the live object counts going up
16:36RaynesCalling the GC manually doesn't do anything.
16:36RaynesIf that means anything.
16:38Raynes<raek> the java process increases its memory usage when I run (dotimes [_ 1e7] (fn [] 1))
16:39raekI think it stopped to increase after a while
16:39RaynesJust like in sexpy.
16:40raekyupp, it stops at 227 MB
16:40RaynesI don't give sexpbot much breathing room as far as memory goes.
16:40chouserwatching the jvm
16:40RaynesProbably why it didn't take long for it to stop rising.
16:40chouserwatching the jvm's use of memory from the OS perspective doesn't tell you much about what's going on inside
16:40chouserbut I thought using yourkit to watch the live object counts *did* mean something.
16:41RaynesIt tells me that sexpbot is unlikely to explode if a user reloads two hundred times in a session. :>
17:02arohnerdoes clojure-1.3 with pst break swank-clojure?
17:02arohnerI'm using C-c C-l to load files, and when I get a compile error, I don't get a stacktrace anymore
17:02arohnerthis worked before changing from 1.2 to 1.3
17:02ChousukeI suppose it might've broken swank
17:02Chousukesince the stacktrace format changed
17:03Chousukethough hm. I suppose that depends on what swank does to get the stacktrace.
17:04arohnercompile errors in the swank repl also don't work
17:04arohnerthis is really easy to check, one sec
17:09arohneryeah, clojure-1.3 snapshots with pst break slime
17:09arohnerI can reproduce the error solely by switching clojure jars
17:17kjeldahl_In the following line: (defmacro dbg[x] `(let [x# ~x] (println '~x "=" x#) x#))
17:17kjeldahl_What does x# mean?
17:17Chousukeit's an autogensym
17:18Chousukemeaning it gets replaced with something unique whenever the macro is expanded
17:18raekit becomes a symbol with a unique suffix
17:18raek,`foo#
17:18clojurebotfoo__5254__auto__
17:18kjeldahl_Ah, ok, thanks.
17:18Chousukeit's there to avoid clashes with names that might already exist.
17:19kjeldahl_Got it, thanks.
17:19raekall instances of x# will become the same autogensymed symbol, since they're in the same syntax-quoted expression
17:19kjeldahl_Just the keyword autogensym lets me google it. :-)
17:19technomancyarohner: could you open an issue?
17:19arohnertechnomancy: sure
17:19arohnertechnomancy: I was a little reluctant without a patch :-)
17:20raek[(list `foo# `foo#) `(foo# foo#)]
17:20raek,[(list `foo# `foo#) `(foo# foo#)]
17:20clojurebot[(foo__5257__auto__ foo__5258__auto__) (foo__5259__auto__ foo__5259__auto__)]
17:20technomancyarohner: oh, don't be shy about that
17:20technomancywe're not jumping straight to 1.3 at work, so I'm not sure when I'll be able to take a look at it, but it's good to have it tracked somewhere
17:20technomancymark mcg. doesn't do IRC, does he?
17:33jjido(hello "everyone!")
17:33jjidoI am looking at the examples in the Clojure distribution. Are [] the same as ()?
17:35RaynesThose are two different data structures.
17:35Raynes[] is a vector and () is a list.
17:35bozhidarjjido: [] denotes a vector
17:35bozhidar() - a list
17:35bozhidarvectors are optimized for random access
17:36Raynes-> (conj [2] 3)
17:36sexpbot=> [2 3]
17:36Raynes-> (conj '(2) 3)
17:36sexpbot=> (3 2)
17:37Raynes-> [(cons 3 '(2)) (cons 3 [2])]
17:37sexpbot=> [(3 2) (3 2)]
17:38bozhidarI don't think that cons-ing was a particularly illustrative example :-)
17:38bozhidarone has to be aware of the fundamentals of data structures
17:38bozhidarnot clojure itself to understand the difference between vectors and lists
17:39Raynesbozhidar: The example was for me. :p
17:40bozhidarRaynes: hehe, yep it's a bit tricky that cons returns a seq
17:40bozhidarsome people are surprised at the beginning
17:43jjidoand when the vector has just one element eg. loop [match (re-find m)]
17:43jjidommh bad example
17:44jjido(defn minutes-to-millis [mins] (* mins 1000 60))
17:46raekin macros/special syntax (like let and defn) vectors are often used when the first element does not represent an operation (as in ordinary function application)
17:47raekmuch like some scheme interpreters allow [] as ()
17:48raekhowever, in clojure they're not just syntactic sugar, but actually different data structures
17:49jjidook so in the above [match (re-find m)] is not a function application
17:50jjidocode/examples/sequences.clj
17:53raekexactly
17:53raekjust like in (defn square [x] (* x x)), [x] is not a function application
17:54raekjjido: have you programmed in any Lisp before?
17:54jjidoI feel that makes sense
17:54jjidoraek: very little in my uni years
17:54raekloop is a special form
17:55jjidodoes it mean it is like quote?
17:55raeknormal evaluation rules do not apply to macros and special forms
17:55raekyes, in the sense that you don't need to quote the symbol in defn
17:56jjidook
17:56jjidoI may be interested in learning more about loop. I came to Clojure because
17:56raekvariable lookup is never done on the symbol "match" in that case
17:57jjidoI am looking to write a compiler for my functional-oriented language
17:58jjidook I understand
18:00raekmuch (if not most) of clojure is described at http://clojure.org/Reference (same as the links in the left sidebar)
18:00raekthe special forms (loop and friends) are described here: http://clojure.org/special_forms
18:02raekwhen I learned clojure, I mostly studied the clojure.org page and these videos: http://clojure.blip.tv/posts?view=archive&amp;nsfw=dc
18:02raekI would also recommend the book "Programming Clojure" by Stuart Halloway
18:04raekthe example you are looking at are from that book :)
18:10jjidoraek: correct, forgot it came from there
18:11jjidoI already tried using Java. People I showed the code were: "oh, my eyes!" ;) The main function is some initialisation then: while (true) next = next.eval();
18:12jjidothat was a program I tried converting from my language to Java. I think Clojure will be a better match
18:15jjidommh metadata
18:15jjidothat's nice
18:51jjido"Defines a function (fn). Fns are first-class objects that implement the IFn interface. The IFn interface defines an invoke() function that is overloaded with arity ranging from 0-20."
18:52jjidois that 20-args limitation a problem for anyone?
18:53chouserI've never come close
18:55jjidois there a way to extend that number. I think that may cause me trouble
18:55jjidoI want to program using CPS
18:56_ato,(fn [a b c d e f g h i j k l m n o p q r s t & [u v w x y z]] 1)
18:56clojurebot#<sandbox$eval5264$fn__5266 sandbox$eval5264$fn__5266@1500b26>
18:57jjido_ato: yes thanks
19:05Chousukejjido: the limit might drop to ten at some point so keep that in mind
19:09jjidoChousuke: which point?
19:09Chousukewith primitive support I think? so in 1.3
19:10jjidoChousuke: why not keep it to 20 for non-primitive types?
19:11ChousukeI don't know the reasoning
19:11Chousukeonly that rhickey was planning to do it to limit the number of methods a bit. But now I'm not even sure if he did it or if he found another solution.
19:11jjidoit could be even enlarged. I think when there is a primitive type arg you get a combinatorial explosion
19:12jjidobut all non-primitive is fine
19:12Chousukein any case you can always use a rest arg
19:13RaynesHow can one kill a jetty server started with run-jetty?
19:13Chousukewhich allows an infinite number of arguments
19:13Chousuke(literally, you can apply a function to an infinite sequence :P)
19:13jjidolol
19:13jjido"Note that recur is the only non-stack-consuming looping construct in Clojure. There is no tail-call optimization and the use of self-calls for looping of unknown bounds is discouraged." that is important!!
19:16MayDanielRaynes: (.stop server), assuming that's what you meant by kill.
19:17RaynesMayDaniel: Does that actually kill it, or just stop it so it can be started again later?
19:17MayDanielIt's just stops it.
19:17RaynesI've got to kill that sucker!
19:21raekjjido: it is possible to do CPS by using trampoline
19:22jjidoraek: what is trampoline? something that preserves stack?
19:32raek,(doc trampoline)
19:32clojurebot"([f] [f & args]); trampoline can be used to convert algorithms requiring mutual recursion without stack consumption. Calls f with supplied args, if any. If f returns a fn, calls that fn with no arguments, and continues to repeat, until the return value is not a fn, then returns that non-fn value. Note that if you want to return a fn as a final value, you must wrap it in some data structure and unpack it after trampoline r
19:37jjidoraek: looks like my while (true) next = next.eval();
19:37jjidoI was going to write it: (loop [next] (recur (next)))
19:46kirasso i'm trying to make a text editor, which i've never done before, using clojure, which i've never written a real program in before... i have some questions regarding with-open and also file io/buffers/etc. in clojure/java...
19:46kirasfirst, i'm thinking it probably makes sense to keep a file open until the user closes it, right? i mean, you wouldn't typically open it and close it again every time you wanted to read something from it or write to it... so from there i was thinking it would make sense to do something kind of like this: http://gist.github.com/575669 instead of using with-open, at least for the files that are going to be edited by the user.
19:47kirasam i totally off in my approach to this?
19:49Chousukekiras: don't use map for side-effects
19:49Chousukekiras: map is lazy so your side-effects might never happen
19:49Chousukekiras: use doseq
19:49kiraschousuke: i considered using doseq, but got complaints about recursion in finally
19:49Chousukehmmh
19:50Chousukeweird
19:50kiraschousuke: i could probably just force map or no?
19:50Chousukeoh well, then wrap the map call in dorun
19:50kirasok, i'll do that
19:51kirasis my overall approach ok though?
19:51kirasi really couldn't see how to use with-open in this situation
19:52ChousukeI think it'll do for at least a simple editor
19:52ChousukeThere's no real way to use with-open.
19:52Chousukehere
19:53kirasso keep going until any shortcomings become apparent?
19:53ChousukeI suppose.
19:53Chousukekeeping the files open all the time might not be optimal but it's probably good enough to start with
19:53kirasah
19:54kirasin what way would it be less than optimal?
19:54kirasi figured i'd probably use lazy sequences with them, so they'd need to stay around?
19:55Chousukelazy sequences and IO don't mix very well, so be careful.
19:55kiraseither that or i'd have to open the file, read the entire contents (not sure what to do if the file is too large?)...
19:55jjidoHow do you do currying in Clojure?
19:55Chousukepartial application is done with partial
19:56kirasi may have to think more about that then
19:57jjidoChousuke: thanks!
19:58ChousukeDon't overuse pointfree style in Clojure though, it's not as idiomatic as in Haskell :)
19:59kiraswould it make more sense to just read the file into a buffer, then close it and open it again for writing?
19:59ChousukeI've seen some pretty hairy code trying to avoid using named parameters :P
19:59Chousukekiras: probably not, that wouldn't work well for large files
19:59Chousukekiras: I suppose most OSes can handle a large amount of open files anyway
20:00kiraschousuke: at this point, probably
20:06ChousukeI wonder if this bit of trivia on Wikipedia is true:
20:06ChousukeThe name "currying", coined by Christopher Strachey in 1967, is a reference to logician Haskell Curry. The alternative name "Schönfinkelisation", has been proposed as a reference to Moses Schönfinkel.[2]
20:07jjidothanks god the first was chosen!
20:07jjido:)
20:07ChousukeThat might be a troll but it's an amusing one.
20:09ChousukeThere is a reference though.
20:09jjidono native support for declaring classes in Clojure?
20:09ChousukeThere's gen-class
20:10Chousukebut that's Java interop, not Clojure
20:11Chousukethe closest to a class you can get without resorting to java-land things is a record
20:11jjidoI want something with a "field": message which can be "overriden"
20:11jjidois struct-map is a record?
20:11Chousukeso you should just have a map or a record with a message key
20:11Chousukeno, defrecord
20:11Chousukestruct-maps are pretty much deprecated
20:11jjidook
20:12Chousukenote that records don't support inheritance either. you need to structure your logic differently :)
20:12jjidothis is where I saw struct-map: http://clojure.org/data_structures
20:13Chousukeyeah. They've been in Clojure for a long time
20:13Chousukebut records do everything struct maps did, with better performance :P
20:13jjidothe page should be revised
20:15jjidoHow do I change a value associated with a key in a record?
20:15jjido(without mutating of course)
20:15Chousukeassoc works, records work like maps
20:16ChousukeAt least I think assoc works
20:16Chousukebut I'm getting too tired to think straight now
20:16Chousukeso good night :P
20:16jjidogn
20:17kirasnight
20:17kirasty for your help
20:27zoldarhello, how do I read session contents when using ring.middleware.session? I have routes defined using defroutes but I don't know how to pass the whole session map as a single argument to the handler function. Configuration of my routes: http://paste.lisp.org/display/114460
20:35jjidois there a shorthand for a function without parameter eg. (fn [] 33)
20:37jjidounquote?
20:41jjidojava.lang.IllegalStateException: Var clojure.core/unquote is unbound. (NO_SOURCE_FILE:0)
20:44jjidoI found the shorthand, #(33)
21:02chouserjjido: nope
21:02chouser,#(33)
21:02clojurebot#<sandbox$eval5279$fn__5280 sandbox$eval5279$fn__5280@755d27>
21:03chouser,(let [f #(33)] (f))
21:03clojurebotjava.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn
21:03chousermaybe constantly
21:04jjidoweird.
21:04jjido,(#(33))
21:04clojurebotjava.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn
21:04jjido,(#(+ 3 33))
21:04clojurebot36
21:07tomoj#(foo) is (fn [] (foo))
21:13jjidook I see ((fn [] (33)))
21:14jjidois there the equivalent of (rest list) for a sequence [1 2 3]?
21:14jjidoI want [2 3]
21:22jjido(subvec [1 2 3] 1)
21:24tomojpop works, but backwards
21:26sproustHmmmm... clojure.string.replace collides with clojure.core.replace
21:27tomojthat happens
21:28sproustI'm not enough of a local to say anything like that yet... but may I suggest unique names across all the core?
21:28tomoj"core" is probably a bad word
21:28sproustThen again, this saves me: (:refer-clojure :exclude [replace])
21:28tomojoh, no it's not
21:28tomoj(:require [clojure.string :as string])
21:29sproustSure, I was "using" instead.
21:29sproustBut :only.
21:29sproustI'm sure you know what I mean :-)
21:31tomojthere's also :rename
21:33sprousttomoj: I like your thinking. Do you always :require everything? Do you :use anything?
21:33tomojI :use, but I feel bad about it afterwards :P
21:34sproustHahahha :)
21:34tomoj:only is good
21:34tomojI don't know why I care anyway, I can just M-.
21:35tomojguess it's useful when you're looking at code without slime
21:35sproustM-. rules.
21:35sproustHow _dare_ you suggest one should use a computer without an Emacs running on it.
21:36tomojI wouldn't think of it
21:36tomojbut sometimes you don't have a jvm handy to load the code into, or you have a jvm but for whatever reason it's not handy to load the code into it
22:02tufflaxI followed http://riddell.us/ClojureOnUbuntu.html this guide to setting up clojure, but when I try to run the command "clj" I get back: clj-env-dir: command not found. What's wrong?
22:04tufflaxrunning ./clj-env-dir when im in the correct dir works btw
22:05tufflaxBut I'm a linux noob so I don't know what I should do to get the clj alias working
22:15mefestotufflax: you can copy or symlink it to a dir in your path
22:16mefestotufflax: for me, I have $HOME/bin in my path so I just copied it there as 'clj'
22:17jjidoHow do I exit a program without exception? (.exit System 0) does not work
22:17mefestojjido: (System/exit 0)
22:19jjidomefesto: that's it! Thank you.
22:33jjidoI got my program to run. http://pastebin.ca/1938589
22:33jjidoBut it displays 8 messages instead of 7!
22:34tomojjjido: has someone already complained about your parenthesis style?
22:34jjidolol sorry :-(
22:35tomojI don't want to bug you about it if you've already heard and decided to stick with it
22:35tomojif not, http://mumble.net/~campbell/scheme/style.txt is a good read
22:35jjidothanks.
22:36tomojputting closing parens on their own line will get you people like me telling you not to do that
22:36tomojbut if you really want to, I won't stop you :)
22:38tomojdid you use '_return and '_throw to avoid clobbering^?
22:39jjidoyes
22:39jjidothey are my return and throw continuations
22:42tomojwhat is the (loop [a (vals 0) ...] ...) thing?
22:42tomojoh, I see
22:43tomojI thought it was #'vals from clojure.core
22:43jjidodon't know that one
22:43tomoj,(vals {1 2 3 4})
22:43clojurebot(2 4)
22:43jjidoit was values first but my editor made it keyword color
22:44jjidoI will change to numbers?
22:44tomoj'vals works just fine, I just wasn't reading closely enough
22:45tomojI think clobbering things in core is actually acceptable style
22:46tomojwhy did you go for (subvec vals 1) instead of (rest vals) ?
22:47tomojI think I remember you wanted a vector back? but why?
22:47jjidothe interpreter gave me out a list with (rest vals)
22:47tomojwhy isn't a list OK, though?
22:48tomoj(it's not actually a list)
22:48jjidoI suppose I have that old-fashioned idea that the type of a variable should not change (not used to Lisp really)
22:48tomoj,(class (rest [1 2 3]))
22:48clojurebotclojure.lang.PersistentVector$ChunkedSeq
22:48tomojwell, one of clojure's big focuses is the seq abstraction
22:49tomojif you're doing the kind of sequence processing where it doesn't matter whether you have a vector or a list or whatever, you just use the seq abstraction
22:49jjidook
22:50jjidohow about (next vals)?
22:50tomojnext is good
22:51tomojhmm, what should (strictly-ascending [1 2 3] :yes :no) return?
22:51jjido:yes
22:51tomojfor me, it returns :no
22:54tomoj,(letfn [(strictly-ascending [vals _yes _no] (if (every? (fn [[a b]] (< a b)) (partition 2 1 vals)) _yes _no))] (strictly-ascending [1 2 3] :yes :no))
22:54clojurebot:yes
22:54jjidoI made a mistake
22:55jjidoI had (tail 1) and changed it to (first tail)
22:55jjidoshould be: (recur b (tail 1) (next tail))
22:56tomojanother idiom is to avoid explicit loop/recur and use the seq functions when possible
22:57jjidothe algorithm should compare the first two elements in the list and shift the list 1 element
22:59tomoj,(let [vals [1 2 3 3 5 4]] (map #(< %1 %2) vals (rest vals)))
22:59clojurebot(true true false true false)
22:59tomoj,(let [vals [1 2 3 4 5]] (every? true? (map #(< %1 %2) vals (rest vals))))
22:59clojurebottrue
23:00rhudsonThere's actually a much simpler way to do it. All the Clojure comparison operators are n-ary, not binary.
23:00jjidocoool
23:00rhudson(apply < [1 2 3 4 5])
23:00rhudson,(apply < [1 2 3 4 5])
23:00clojurebottrue
23:00rhudson,(apply < [1 2 2])
23:00clojurebotfalse
23:00tomojnice
23:01jjidoah it is already built-in. I did not try it with a vector
23:03tomojthat's 10x as fast, too https://gist.github.com/01bb734fc4aa8d87acb0
23:03jjidoI still have the "bug"
23:04jjido_loop is called one too many time
23:05tomojwhy do (strictly-ascending [n 7] foo bar) instead of (if (< n 7) foo bar) ?
23:06jjidobecause the latter is not CPS
23:06rhudsonWhy is CPS important to you?
23:07defnDoes anyone know if clojure-conj holds the promise of putting presentations online through a service like confreaks?
23:07jjidorhudson: I want to compile a CPS-based language for the JVM
23:07defnI am always hearing about rhickey giving talks on Clojure but am almost always disappointed to find out they're not online anywhere for the public.
23:08jjidoreplacing with if (< n 7) takes care of the bug
23:14tomojthat's strange
23:14tomojI thought they'd be equivalent
23:14jjidogot it!
23:15tomojjjido: how is (if (< n 7) yes no) not CPS if (strictly-ascending [n 7] yes no) is?
23:16jjidotomoj: in fact I should return #(strictly-ascending [n 7] yes no)
23:17jjidothe problem was that the 1st arg (yes branch) was evaluated
23:19tomojso #(if (< n 7) yes no) counts as CPS?
23:21jjidowell, what I do is that the main loop takes a continuation and runs it waiting for the next continuation
23:22jjidousually with CPS you just directly call the next continuation
23:22jjidobut that grows the stack
23:22rhudson,(doc trampoline)
23:22clojurebot"([f] [f & args]); trampoline can be used to convert algorithms requiring mutual recursion without stack consumption. Calls f with supplied args, if any. If f returns a fn, calls that fn with no arguments, and continues to repeat, until the return value is not a fn, then returns that non-fn value. Note that if you want to return a fn as a final value, you must wrap it in some data structure and unpack it after trampoline r