#clojure logs

2009-11-29

01:18JomyootWhat's simplest way of loading a webpage from clojure?
01:20hiredmanloading as in pulling down?
01:21hiredmanhttp://gist.github.com/119375 there maybe something in contrib
01:21Jomyootyes
01:21Jomyootloading and saiving it
01:21_atouse duck-streams and (slurp* "http://clojars.org/") if you want a string
01:22hiredmanif you want to drive a website, htmlunit is pretty nice
01:24JomyootIS there no built in or contrib?
01:24_ato(with-open [out (java.io.FileOutputStream. "/tmp/index.html")] (copy (.openStream (java.net.URL. "http://clojars.org/")) out))
01:25_atoJomyoot: clojure doesn't replace the java standard library
01:26_ato(again copy is in clojure.contrib.duck-streams)
05:32JomyootIs there a data store built using clojure?
05:42_atoJomyoot: there's tons of options for data stores, depending on what kind of data store you need: cupboard (clojure data structures on BDB), contrib.sql/clojureql/clj-record (relational databases), mongocongo (mongodb doc db), clutch/clojure-couchdb (couchdb doc db), redis-clojure (redis key-value store), clojure-rdf/rdfm (RDF tuple store), sdb (amazon simpledb)
05:42Jomyootbdb has that license thing right?
05:43_atolicense thing?
05:44_atohttp://www.oracle.com/technology/software/products/berkeley-db/htdocs/jeoslicense.html
05:44_ato^ that's the license
05:44Jomyoothmm
05:44Jomyootis that equivalence of?
05:46_atoit's sort of similar to the GPL
05:46JomyootLGPL?
05:46_atonot exactly
05:46Jomyootdoes it force my app into opensourcing too?
05:46_atoyes
05:48_atoJomyoot: if you're just storing small amounts of data, simply writing Clojure data structures to a string with "prn" and reading them back with "read" should work fine
05:50_atowhere "small" means "fits in RAM" and your happy to keep it all in RAM
05:52Jomyoottoo small :(
05:55_atooh and of course you can use lucene as data store if you want full-text search, which I don't think there's any wrapper for but it's easy to use from clojure
09:22ankouhi, is there sth. similiar to a zip function? (sth. like (zip [:a :b] [:c :d]) => [[:a :c] [:b :d]]
09:23nanodust,(map vector [1 2] [3 4])
09:23clojurebot([1 3] [2 4])
09:24ankouah okay
09:37arjI'm trying to read a list of structs using read-string from a file that I dumped with prn, but I get Unreadable form. Any ideas?
10:02arjgot it :)
10:02arjwas because I had a File stuck in the structs
10:20wlrankou: not what you asked for but sometimes handy is (zipmap [:a :b] [1 2]) => {:b 2, :a 1}
12:50aldebrnTrying to build VimClojure; I get the standard error when attempting to build: "java.lang.ClassNotFoundException: clojure.contrib.pprint.PrettyWriter (pprint.clj:14)" despite having built the clojure-contrib.jar using "ant -Dclojure.jar=/path/to/clojure-1.0.0.jar"
13:07chouseraldebrn: make sure your local.properties file has the right path to your clojure-contrib.jar
13:08chouseraldebrn: if it does, then look inside your clojure-contrib.jar to make sure it has a PrettyWriter.class file in it.
13:13rhickeyurk - paste.lisp.org down?
13:14rhickeyI've been planning protocol defs in deftype, defprotocol gens interface when AOT
13:15chouserhm!
13:16chousermethod sigs in deftype but not implementations
13:16chouser?
13:16rhickeyhttp://gist.github.com/244998
13:16rhickeydefprotocol will define sigs, deftype can have impls
13:16rhickeyso impls of interfaces and/or protocols
13:17chouserI bet if you wrote on the google group with a list things to be documented, or even the task to produce a list of "major changes" since 1.0, people would jump right in.
13:17rhickeywhen AOT-compiled, defprotocol generates coresponding interface
13:18rhickeyso we need grouping per protocol/interface
13:18rhickeythis is better for interfaces too, because CLR doesn't merge by name the way Java does
13:19rhickeydeftype will see if the protocol has an interface and gen different code if it does/doesn't
13:19chouserok, I see it. it'll do that for each protocal/interface group named in the deftype.
13:20rhickeyright
13:20rhickeystill not sure about the this and . stuff
13:20rhickeyit is a very clean story without interfaces or interop though
13:21rhickeyessentially, if you know you need to support some protocols when you define the type, you can do so right there, for some perf advantage
13:21rhickeyAOT compiling of protocols enables the perf advantage
13:21rhickeybut perf advantage still there if dynamically re-deftyping
13:22rhickeyonly hitch is dynamic re-defprotocol
13:23rhickeyneed some change-detector, if unchanged interface will still work, if changed it won't, and dependent code (impls of the protocol and callers) will need re-eval
13:23rhickeybut no restart
13:24rhickeythe let in the extend-type is to allow the body to presume implicit fields, for lack of symbol-macros
13:25rhickeybut will this unification confuse people?
13:25rhickeywill the presume they can reify protocols?
13:25rhickeyor extend-type to interfaces?
13:30chouserThe potential for confusion is definitely there.
13:30chouserBut when the required code to take advantage of these features is so simple and consistent, I'd like to believe it's just a matter of explaining it properly.
13:31rhickeythe alternative is explicitly created definterfaces
13:31rhickeydeftype can only implement interfaces
13:31rhickeydefprotocol gets back :on AnInterface
13:31chouserMost people don't need to fully understand the exact requirements for re-eval in order get best performance.
13:32chouserThey'll play with it at a REPL to get the functionality working, but if the performance matters on deployment will at least re-eval everything if not just restart the JVM.
13:33rhickeyI had hoped to 'fix' a few interface things by having the interface under the hood - first, name munging, second, possibly protocol-prefixing names to avoid name merging, third, since deftype is implementing protocol, no isA presumption
13:33rhickeychouser: it ends up all the perf will be there as long as you don't re-defprotocol
13:33rhickeypresuming you AOTed the protocol
13:33rhickeyso still pretty dynamic
13:34chouserthe few who really care about maximum perf with minimal re-eval will be willing to dig in and learn the details.
13:34rhickeybeing able to 'reach' a protocol with reify is interesting and useful
13:35rhickeynot a good story with the implicit interfaces
13:36rhickeyso, I'm on the fence - :on is in there and fast, and deftype does interfaces, could be done right now, just seems like a lot more work to make protocol 'fast', seems second-class to interfaces
13:37rhickeyand the code change to move from external extend-type to impl interface in deftype is not nothing
13:38rhickeychouser: yes, as it stands you could never AOT during dev ad just AOT for delivery with better perf
13:39rhickeywith the gist code a clojure-only app with no interop requirement need never talk about interfaces
13:39Chousukehmm.
13:39rhickeyyou would just be told implementing a protocol in deftype is easier and faster if you can do it
13:40rhickeyextend-type just for types you don't control
13:41rhickeyreify might be made to understand the munging/interface game and work with protocols
13:45mscalahi all. quick question: I've just found google's android scripting environment, and now have a python intwrpreter running n my droid. is there any hope that there will be a clojure interpreter?
13:45rhickeychouser: the re-eval of impls and callers on re-eval of protocol won't be optional for perf, the old code will be used until re-eval
13:51ChousukeI think defining the protocols and interfaces together with the type is going to be quite a common case, so it makes sense to make it fast as well.
13:52the-kennymscala: I think someone has managed to run clojure on android.
13:53mscalaah, good. google hasnt turned up any info yet.
13:54the-kennymscala: There's an example-project somewhere on github. The author mentioned the slowness of the program ;)
13:57noidihow could I unzip a zipper up to the root node, and get a zipper structure?
13:57noidiI still haven't quite wrapped my head around these zipper things, but apparently zip/root returns the data at the root, and not a zipper
14:00noidiah, got it... I'm dealing with XML, so (= d (zip/xml-zip (zip/root d)))
14:00chouserrhickey: so if you add a method to a protocol and then extend it, but re-eval only the extend, you'd get an error?
14:01noidiI must say, clojure.contrib.zip-filter is the coolest way of dealing with XML I've ever seen
14:01noidiso thanks chouser :)
14:02chousernoidi: zip/root will zip up to the root, but will return a node, not a zipper
14:02chousernoidi: you're welcome!
14:03chousernoidi: be aware though that if you use zip-filter to get at multiple nodes, those are separate trees and "changes" to one won't show up in the others.
14:04chouserthis is an unfortunate detail that I didn't realize until well after the design and implementation was complete.
14:04noidigood to know... luckily I'm only parsing an XML document and not changing anything
14:05chouserthat was my primary use case
14:05rhickey_chouser: if the protocol wasn't AOTed, redefs of the protocol (e.g. add a method) will leave existing callers (whixh won't be calling the new method) and existing impls (which don't yet implement) still working
14:06chousercgrand's enlive fixes that problem, but it's designed to work on html not xml, so requires some tweaking for xml.
14:06rhickey_if protocol was AOTed, not a very different story - impls will have implemented behind-the-scenes interface and callers will be calling the interface. Once a caller is re-evaled, won't work with old impls, and vice versa
14:07rhickey_re-eval of everyone will take the interface out of the loop
14:07rhickey_i.e. no interface when non-AOT
14:11rhickey_hmm, what would reify of non-aot protocol do?
14:12rhickey_if reify works with protocols then the story becomes really good, no talk of interfaces until linterop
14:13chouserwould reify create a map with a gen'ed :type and ... add it to the protocol fns?
14:14chousertemporarily.
14:14chouserprotocol fns could have a final case of asking the object for specific implementations, which reify could create
14:14rhickey_chouser: meta type?
14:14chouserthat was a bad idea. skip it.
14:15rhickey_protocols can't work with meta types since they cache based on class
14:15rhickey_I need to clarify that, deftype should mean the end of meta types
14:16chouserreify on a non-aot protocol could return a #^{:protocol-fn-map {:SeqableProtocol/seq-me (fn [this] ...)}} {:a 1 :b 2}
14:16chouserprotocol fns could fall back on calling those :protocol-fn-map functions directly
14:16rhickey_reify creates a class now, so no reason not to just extend the protocol to that class
14:17chouseroh
14:17rhickey_I was concerned about on-off classes filling the caches, but it isn't a real issue
14:17rhickey_one-off
14:17rhickey_it's not as if there is a new class each call, just one per reify site
14:19rhickey_transparent access to closed-overs might be a problem
14:19rhickey_for non-aot protocol
14:19rhickey_with deftype the fields are enumerated declaratively
14:22rhickey_actually np, since fns in method map will be closures too
14:22chouserclosures currently expose closed-overs as public fields. is this a real feature or a implementation detail?
14:23rhickey_chouser: I don't think we need to leverage that, the fns will just closed over the same things
14:24rhickey_(let [a 1 b 2] (reify [AProtocol (foo [this] (use a b)]))
14:24rhickey_when foo is moved out (not a method) the fn object will just close over the same environment
14:24rhickey_where a and b will mean the same things
14:26chouserok
14:29rhickey_extend being a function is really wild - you can do (let [x (reify)] (extend (class x) ...) x)
14:54rhickey_erm, no, while a and b will be same as instance, not same forever for all instances
14:54rhickey_will probably have to tap into fields of reify class
15:35developernotestrying to understand the rules that cause the following to return the value of :brown as the first element:
15:36developernotes(first #{:the :quick :brown :fox})
15:36developernoteswhy is :brown the first item?
15:36somniumsets are unordered
15:36chouserIt's a hash-set -- the order is meaningless pretty much by definition
15:37developernoteschouser: gotcha.
15:38chouserdevelopernotes: there is a sorted-map, if that helps.
15:38developernoteschouser: thanks.
16:04fliebelWhat is a good way to learn Clojure for Python users? I did some Java long ago, but it's quite rusty. After watching 10 movies on youtube I more or less get the concept of Clojure, but when opening an interactive shell even concatenating strings takes me minutes to figure out.
16:06the-kennyfliebel: Clojure isn't like Java, it's totally different.
16:06fliebelI know that… I quite like the syntax, although I have to go back every time to put parentheses before things...
16:06somniummany people find solving project euler problems helpful
16:07fliebelI had my own little adventures in mind to master the language. I'm not talking about 3D games, okay? :P
16:07arbschtfliebel: that will pass
16:08fliebelI was thinking about this code as data thing… Should be fairly trivial to represent XML with code using some macros and things.
16:09the-kennyfliebel: There's already clojure.contrib.prxml to print xml out of sexp's
16:09the-kenny;)
16:09the-kenny,(prxml (:foo (:bar 42)))
16:09clojurebotjava.lang.Exception: Unable to resolve symbol: prxml in this context
16:09chouserfliebel: but yes, many many people have done exactly that.
16:09hiredmanI'm kind of thinking of switching 9-( and 0-) in my keymap
16:09fliebelYea, but I guess there are hundreds of scripts solving project euler problems as well…
16:10the-kenny,(clojure.contrib.prxml/prxml (:foo (:bar 42)))
16:10clojurebotjava.lang.ClassNotFoundException: clojure.contrib.prxml
16:10the-kennyhm.. forget it
16:10somniumhiredman: I mapped my useless menu key to open-paren
16:11somniumhave that useless windows key too... hmm
16:12hiredmanI have those both already mapped
16:12fliebelthe-kenny: So, is there a lib like that? (I find exceptions in Clojure horribly unclear, by the way)
16:13the-kennyfliebel: http://richhickey.github.com/clojure-contrib/prxml-api.html
16:13patrkrisHi. What is the primary reason, that vectors are used for the function parameter list?
16:14hiredmanthe parameter list is not a function call, macro call, or special form
16:16patrkrisOk. So in Clojure-world, it leaves vectors as the most sensible option? My supervisor, an experienced schemer, keeps pointing to all these 'inconsistencies' in the syntax in Clojure compared to Scheme (e.g. using [ and ] for vectors and specifically for the function parameter list). I'm not an experienced Lisp/Scheme/Clojure-programmer, so I don't really know what to respond to that.
16:17hiredmanpatrkris: ignore him
16:17the-kennyIn my opinion, clojure is *much* easier to read than common lisp or scheme just bevause of this "inconsistencies" in the syntax
16:18patrkrishiredman: hehe, yeah
16:18hiredmanhe is belly aching about nothing, so just let him do it in a corner somewhere
16:18arbschtpatrkris: the best response would be a question: "can you explain why you think it is inconsistent?"
16:18chouserpatrkris: Rich said somewhere that scheme is an "atomic" language, in that it provides only the minimal features needed.
16:18chouserpatrkris: ...but that he's not interested in writing in an atomic language, he wants one that provides more than that.
16:18chouserClojure is not Scheme.
16:19rhickey_definitely not
16:19patrkrisI agree that Clojure programs are really easy to read, even compared to a minimalist language like Scheme (just compare cond and let in the languages)
16:19fliebelIs this sensible Clojure code? I cant think of another way…
16:19fliebel(apply str (concat
16:19fliebel ["<html"]
16:19fliebel (map (fn [attr]
16:19fliebel (str " " (first attr) "=\"" (last attr) "\""))
16:19fliebel {"hallo" 3 "a" "hoi"})
16:19fliebel [">" "hallo wereld" "</html>"]))
16:20arbschtlisppaste8: url
16:20lisppaste8To use the lisppaste bot, visit http://paste.lisp.org/new/clojure and enter your paste.
16:20lisppaste8pepijn pasted "untitled" at http://paste.lisp.org/display/91244
16:21fliebelI was trying to piece together attributes from a map...
16:21hiredmanI'd use reduce
16:23fliebelhttp://clojure.org/api#reduce This one? (is that page really all that makes up Clojure?)
16:23arbschtfliebel: there are a number of html and xml libraries for clojure
16:23hiredman,(reduce #(format "%s%s=\"%s\" " %1 (name (key %2)) (val %3)) "" {:foo 1 :bar 2})
16:23arbschtclojurebot: libraries
16:23clojurebotjava.lang.IllegalArgumentException: Wrong number of args passed to: sandbox$eval--7844$fn
16:23clojurebotGabh mo leithscéal?
16:23hiredmanurgh
16:23hiredman,(reduce #(format "%s%s=\"%s\" " %1 (name (key %2)) (val %2)) "" {:foo 1 :bar 2})
16:23clojurebot"foo=\"1\" bar=\"2\" "
16:24arbschtclojurebot: libraries is http://clojure.org/libraries
16:24clojurebotIn Ordnung
16:25fliebelhiredman: That looks awesome, but I got no clue what is actually happening… Except that those % look like Python things.
16:25KirinDaveI wish I could get my friends more excited in clojure. Most of them are into (hurl) Python or if they are into an alt jvm language they're into Scala.
16:26the-kennyKirinDave: Show them awesome things like scriptjure :)
16:26fliebelKirinDave: sound like me...
16:26Chousukescare the scala people a bit
16:26Chousuke~scala
16:26Chousukehmm :(
16:26chouserfliebel: % in clojure isn't % in python
16:26Chousukeclojurebot: scala
16:26Chousukeignoring me, huh :(
16:26hiredmanclojurebot: tell us about scala!
16:26clojurebot{((x: Any, y: Any) => (f: Function2[Any, Any, Any]) => f(x, y))(1, 2)((x: Any, y: Any) => x)}
16:26Chousukeah, okay.
16:27chouserfliebel: "foo" % [a, b] in python is (format "foo" a b) in clojure
16:27KirinDaveBut to lose to Python?
16:27somnium~python
16:27clojurebotpython is ugly
16:27KirinDaveI can think of few worse fates.
16:27the-kenny~c++
16:27clojurebotExcuse me?
16:27hiredmanclojurebot: scala {((x: Any, y: Any) => (f: Function2[Any, Any, Any]) => f(x, y))(1,2)((x: Any, y: Any) => x)}
16:27clojurebotAny = 1
16:27KirinDavePython is even more of a baby-talk language than java.
16:27chouserreally?
16:27fliebelI quite like Python.
16:27ChousukeKirinDave: meh. python is fine. :)
16:27hiredmanfliebel: the % are params for the special #() anonymous function syntax
16:27chouserIf you don't mind mutable things (and I do, now, I really do) both python and ruby have a lot of merit.
16:28KirinDaveI am a big fan of Ruby.
16:28somniumI would rather do python than java
16:28ChousukeIn my mind python and ruby are about equivalent.
16:28fliebelhiredman: Wher do I learn al this stuff in a way understandable from a non-lisp perspective?
16:28Chousukeas far as I can tell, the differences are superficial
16:28KirinDavesomnium: You don't find python insulting?
16:29KirinDaveAnother language designed around your presumed stupidity.
16:29hiredmanfliebel: embrace the lisp perspective
16:29somniumit has real first class functions
16:29Chousukefliebel: http://www.defmacro.org/ramblings/fp.html ? :)
16:29Chousukehiredman: it's difficult to embrace when you don't know what it is.
16:29KirinDavesomnium: Uh, pretty sure they're not strictly first class functions. You pass refs to named functions around.
16:30KirinDavesomnium: It does have anonymous statements, but they're almost macros.
16:30fliebelChousukeL Indeed… Although I did watch some lengthy videos about it.
16:30technomancyKirinDave: as Adam Keys puts it, it's amazing how Guido is trying to corner the market on people who have been programming for less than an hour.
16:31chouserpython has first-class functions, generators, a clean syntax, strong support for dynamic metaprogramming (though not of the macro variety)
16:31KirinDavetechnomancy: While at the same time, in private mailing lists, talking at length about things he claims he cannot understand.
16:31hiredmanfliebel: dive right in, you can start by pasting that reduce into an editor somewhere, and teasing it apart to see what it does
16:32hiredmanthe unladen swallow guys are having a hard time because python is so dynamic
16:32somniumKirinDave: I mostly did ruby before clojure, Im just saying, I would rather do python than java/C++
16:32fliebelI'll try that later, I'm to tired to absorb anymore information today.
16:36technomancyhiredman: I get the feeling that has more to do with "we haven't gotten around to reading the papers on smalltalk/self VM design" than "python is hard to optimize"
16:36hiredmantechnomancy: possibly, but the goal of keeping complete backwards compat with cpython and all the extensions in C for it complicates things
16:37JAS415,(number? 1010B)
16:37clojurebotInvalid number: 1010B
16:37JAS415why doesn't that return false
16:38hiredmanit doesn't get that far
16:38chouser,1010B
16:38clojurebotInvalid number: 1010B
16:38KirinDaveYeah
16:38JAS415ooh
16:38hiredmanthat is a reader exception
16:38JAS415how would i secure my web app against that
16:38JAS415assuming i'm taking arguments as strings
16:39Chousukecatch the exception? :P
16:39JAS415hmm
16:39JAS415ok
16:39ordnungswidrigwould the reade be used for that?
16:42ordnungswidriga bind wrapping a defn will not make the binding available when calling the function, right?
16:43technomancyso it looks like using clojure.main with the -e arg disables *command-line-args* ?
16:43chouserordnungswidrig: 'let' would, but not 'binding'
16:43patrkrisI came across ClojureQL recently. It made me, a n00b Lisp programmer, aware of how inferior a language like e.g. C# is (well ok, I'm generalizing). But think of the effort they made in putting in LINQ into the language. You don't have to change Clojure to get something similar - you don't need to. That was a cool experience for me.
16:43hiredmanordnungswidrig: fn's capture lexical scope, not dynamic scope
16:44Chousukepatrkris: when talking about non-lisps, you can use "Blub" to avoid offending anyone
16:44patrkrisChousuke: thanks
16:45patrkrisbut is such an experience a milestone on the path to enlightenment as Eric Raymond writes about?
16:45hiredman:|
16:45JAS415you can also use blub to offend everyone
16:45ordnungswidrigchouser: clutch uses a config binding wich can be set by using a "with-db" macro. I'd like to do sth. like (with-db db (foo (fn [x] use-db) (fn [y] use-db))), the anonymouse functions will make use of the binding.
16:46ordnungswidrigchouser: that fails. But I cannot use let without rebinding the config using with-cb in every function
16:46ChousukeJAS415: heh.
16:47hiredmanordnungswidrig: this is why it annoys me that everyone that writes some kind of db wrapper in clojure uses binding
16:48ordnungswidrighiredman: what would be a better method? reader monad?
16:48chouserordnungswidrig: I having a hard time thinking of a solution other than a macro to do the with-db for you. :-/
16:48hiredmanno
16:48hiredmanjust pass in the db as a method param
16:48hiredmanas if we were programming with functions!
16:48hiredmanthat take parameters!
16:48hiredmanand are composable!
16:49Chousukebut then you'll need to pass it to almost every function :P
16:49hiredmansure
16:50chouserproviding an *optional* var to rebind might be ok, but having that as the only way is indeed a bit annoying.
16:50the-kennyordnungswidrig: use my fork clojure-couchdb! It has a parameter for the db-server! :p
16:50hiredman(fn [db y] (binding [*db* db] (dostuff y)))
16:51ordnungswidrigthe-kenny: I heared clojure-couchdb was throwing exception event on update/delete-conflict?
16:51the-kennyordnungswidrig: hm.. I think so, but I'm thinking about removing all these exceptions
16:51ordnungswidrighiredman: that could event be reused as a macro, right?
16:51hiredmansure
16:52ordnungswidrighiredman: ok, that _is_ basically clutch's with-db
16:52chouserhiredman: ah, of course. good.
16:52hiredmanordnungswidrig: inside out
16:53ordnungswidrighiredman: yes, that was what I meant.
16:53hiredmanclojurebot: binding?
16:53clojurebotPardon?
16:54hiredmanclojurebot: binding is <reply>:|
16:54clojurebotAlles klar
16:54ordnungswidrighiredman: I think I'd like the other way round better. Haven the functions take a db-parameter and optionally wraping them with some binding and a macro that pull the default.
16:56hiredmanpassing parameters via function application is the best choice (as usual)
17:00ordnungswidrigAm I right that the more idiomatic way is to defmethod on :default and rais an error instead of checking the method arguments in the dispatch function?
17:09technomancyit would be really nice if clojure.main let you specify a namespace to have loaded and its -main function run with *command-line-args* without AOTing.
17:13the-kennyIs there a way to access the metadata of a fn passed as an argument? Eg. (defn foo [obj] (meta (var obj)))
17:15Chousukethe-kenny: fns don't have metadata.
17:15the-kenny,(meta (var +))
17:15clojurebot{:foo 1, :ns #<Namespace clojure.core>, :name +, :file "clojure/core.clj", :line 654, :arglists ([] [x] [x y] [x y & more]), :inline-arities #{2}, :inline #<core$fn__4742 clojure.core$fn__4742@161f77c>, :doc "Returns the sum of nums. (+) returns 0."}
17:15Chousukethat's not th fn, that's the var :)
17:15KirinDaveI wish the clojure compiler could give me better line numbers for bad source. :(
17:16Chousukethe-kenny: what you want is to 1) resolve a symbol(!) to a var and 2) then look up the metadata for that.
17:16KirinDave"java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Symbol" with a stack trace into the compiler doesn't really help me figure out where my error is
17:16Chousuke,(meta (resolve '+))
17:16clojurebot{:foo 1, :ns #<Namespace clojure.core>, :name +, :file "clojure/core.clj", :line 654, :arglists ([] [x] [x y] [x y & more]), :inline-arities #{2}, :inline #<core$fn__4742 clojure.core$fn__4742@161f77c>, :doc "Returns the sum of nums. (+) returns 0."}
17:17Chousuke(var foo) is of no use if applied on a local because it doesn't evaluate its argument
17:20ghegdeHello everyone, has anybody used the enclosure plugin for clojure dev?
17:20ghegdei am a newbie.. am having some problems with compilation
17:22somniumKirinDave: usually that means theres a symbol that should be a list/vector being passed to a macro, often in (ns ...
17:23the-kennyChousuke: hm.. Chousuke I'm hacking on swank-clojure and try to specialize the inspector for functions. To display the parameter list etc. When I try to inspect for example =, I get the evaluated value for =, not the symbol... is there a way I can get the metadata for =? Something like reverse-lookup or so :p
17:29somnium,(meta '=)
17:29clojurebotnil
17:29somnium,(meta #'=)
17:29clojurebot{:ns #<Namespace clojure.core>, :name =, :file "clojure/core.clj", :line 516, :arglists ([x] [x y] [x y & more]), :inline-arities #{2}, :inline #<core$fn__4668 clojure.core$fn__4668@152c0d>, :tag java.lang.Boolean, :doc "Equality. Returns true if x equals y, false if not. Same as\n Java x.equals(y) except it also works for nil, and compares\n numbers and collections in a type-independent manner. Clojure's immutable data\n
17:29the-kenny,(let [foo =] (meta (var foo)))
17:29clojurebotjava.lang.Exception: Unable to resolve var: foo in this context
17:29the-kennysomnium: That's the problem ;)
17:30somniumlet doesnt create vars
17:30the-kennysomnium: Yeah, I'm aware of this. It was just an example.
17:30the-kennyI don't have access to the original symbol, I get the evaluated value
17:32somnium,(let [foo '=] (meta (resolve foo)))
17:32clojurebot{:ns #<Namespace clojure.core>, :name =, :file "clojure/core.clj", :line 516, :arglists ([x] [x y] [x y & more]), :inline-arities #{2}, :inline #<core$fn__4668 clojure.core$fn__4668@152c0d>, :tag java.lang.Boolean, :doc "Equality. Returns true if x equals y, false if not. Same as\n Java x.equals(y) except it also works for nil, and compares\n numbers and collections in a type-independent manner. Clojure's immutable data\n
17:32the-kennysomnium: Yeah, that works. But then the user has to type '= instead of = for M-x slime-inspect
17:33Chousukeyou can use a macro then
17:33Chousuke(defmacro inspect [sym] `(meta (resolve ~sym)))
17:34the-kennyChousuke: I think you don't understand the problem.. sorry
17:35hiredmanI don't understand
17:35hiredman,(-> "=" symbol resolve meta)
17:35clojurebot{:ns #<Namespace clojure.core>, :name =, :file "clojure/core.clj", :line 516, :arglists ([x] [x y] [x y & more]), :inline-arities #{2}, :inline #<core$fn__4668 clojure.core$fn__4668@152c0d>, :tag java.lang.Boolean, :doc "Equality. Returns true if x equals y, false if not. Same as\n Java x.equals(y) except it also works for nil, and compares\n numbers and collections in a type-independent manner. Clojure's immutable data\n
17:36Chousukethe-kenny: only vars have metadata in this case
17:36Chousukethe-kenny: so you need a symbol, from which you get to the var by using "resolve", and then you can get the metadata.
17:36Chousukethe-kenny: the actual function itself is completely irrelevant
17:37the-kennyChousuke: Yeah, but I only have the actual function. That's the problem
17:37Chousukethen you have no way to access the metadata.
17:37the-kenny:(
17:37hiredman,(-> = class .getDeclaredMethods ((partial map #(.getName %))))
17:37clojurebot("getRequiredArity" "doInvoke" "invoke" "invoke")
17:37Chousukethough if the user types in "=" then you do have the function name
17:37hiredman,(-> = class .getRequiredArity)
17:37clojurebotjava.lang.IllegalArgumentException: No matching field found: getRequiredArity for class java.lang.Class
17:38hiredman,(-> = .getRequiredArity)
17:38clojurebot2
17:38hiredmanhmmm
17:38hiredmanmust be minimal required
17:40the-kennyChousuke: No, M-x slime-inspect evaluates its argument
17:40Chousukeah.
17:40Chousukeoh well, you're screwed then.
17:40Chousukefunction objects don't have metadata.
17:41the-kenny:( No beautiful summary page for functions then
17:42rhickey_the-kenny: you could build a reverse-lookup map from fn values to the vars for a ns
17:43the-kennyrhickey_: hm.. I think this is a bit too much for this.
17:44the-kennyIs there a reason whu function objects don't have metadata?
17:44the-kennys/whu/why/
17:44somniumM-x slime-inspect #'= works here, is it so bad?
17:45rhickey_the-kenny: because fns can't support with-meta generally
17:46rhickey_and originally meta and with-meta were in the same interface, now not, so possible
17:53hiredmanthe-kenny: building a reverse map should not be too hard using clojure.org/namespaces
18:03rhickey_how painful if protocols must always be AOT compiled?
18:03rhickey_would be the same for interfaces
18:16hiredmanrhickey_: I think it would kind of put the breaks on the race to protocols, not stop it, but slow it down, which seems ok to me
18:16hiredman(not everything needs to be protocols)
18:16technomancythere _is_ a ticket for adding metadata to functions
18:17technomancythe-kenny: as much as I like the idea for what you're trying, it would be much easier to wait till that's fixed in clojure
18:17the-kennytechnomancy: hm.. yeah, I'll wait.
18:18rhickey_hiredman: hmm, if it slows it down what will people do instead?
18:19hiredmanrhickey_: write functions hopefully, use multimethods
18:19rhickey_hrm, multimethods that do the same job are inferior in almost every way
18:20rhickey_multimethods should be reserved for things protocols can't do
18:20hiredmanrhickey_: except they work, don't require AOT, and are available in 1.0 and are documented and examples exist everywhere
18:21rhickey_hiredman: well, that's really an argument against the AOT requirement
18:21technomancynot requiring AOT makes multimethods more likely to be used in smaller projects that don't have a build scripted yet
18:21rhickey_protocols work and are documented, btw
18:21technomancyin the (as-yet-hypothetical?) situation where protocols require AOT
18:22hiredmanrhickey_: ok
18:22rhickey_technomancy: yeah, I'm loathe to lose the start-fiddling aspect they currently support
18:22rhickey_just trying to satisfy all the requirements, reifying protocols would be awesome, since most designs will become protocol-based
18:23rhickey_but reify of protocol w/o aot is troublesome
18:23technomancytricky trade-off =\
18:28chouserin what way is it troublesome?
18:30rhickey_chouser: the issues we discussed before, not knowing what is closed over, intervening once only to bind type to protocol, when should that be revisited (if protocol was modified)
18:31technomancydid https://www.assembla.com/spaces/clojure/tickets/193 only get moved off the 1.1 list because the patch was misformatted? if so, would a correctly-formatted patch put it back in the running, or has the 1.1 list already been decided?
18:33rhickey_chouser: because reify both creates the class (when compiled) and the object (every time), the semantics are trickier than with an interface, presumed unchanging relative to creation of class
18:34rhickey_could do same for reify of protocol
18:34rhickey_but reify code has to participate in knowing about protocols
18:34rhickey_macro can;t yield anything that will run every time
18:35rhickey_vs the deftype case emitting an extend-type
18:38chouserdid you see my idea for putting the implementation in the object? I guess that doesn't help the closing-voer problem.
18:45rhickey_chouser: protocols cache based on class/dynamic type, adding looking for on-object would slow things down, also a semantic problem as caching is based upon class
18:47rhickey_if on-object, user would have to ensure all objects of same class had same impl
18:47chouseryeah, that sounds worse. I guess I don't understand the context fully yet
19:19cgordonI have another functional n00b question. If I have a function like "(defn test [coll] (lazy-seq (cons (first coll) (test (rest coll)))))", the recursive call isn't in the tail position (cons is), but yet this doesn't blow it's stack, and doesn't run out of memory. Is Clojure somehow switching things around so that the recursive call is in the tail position?
19:22the-kennycgordon: I think lazy-seq does the trick
19:23rlbcgordon: I believe lazy-seq just returns the remaining (unevaluatedsequence, so there's no stack growth.
19:23rlbi.e. there's no immediate recursive call
19:23cgordonright, I think I just figured that out. I removed "lazy-seq" and it blew up on me
19:23cgordon:)
19:24rlbThe code isn't executed until you do something like (first coll) or whatever.
19:24rlb(and then only up to the next lazy-seq)
19:24cgordonhow does this work in Lisp (which I presume doesn't have "lazy-seq")?
19:24rlbcgordon: it doesn't I don't think (at least not in common lisp)
19:24rlbdepending on what you mean by "work"
19:25cgordonrlb: so this would just blow your stack in CL?
19:25rlbcgordon: yes, iirc.
19:25cgordonrlb: is there a way to rewrite it so that the recursive call is in the tail position?
19:26rlbcgordon: you would probably use loop, a trampoline, or otherwise manage what would otherwise be on the stack yourself.
19:26rlbi.e. pass in the list you're building, whatever.
19:26cgordonrlb: alright, thanks, that helps
19:26rlb(as an arg)
19:26cgordonthe hardest part of learning functional programming seems to be understanding the cost of various operations
19:27Chousukethe thing is that lazy-seq just returns a thunk, so the recursive call returns immediately
19:27Chousukeand the next recursive call is made only when the thunk is evaluated.
19:27somnium~haskell
19:27clojurebothaskell is Yo dawg, I heard you like Haskell, so I put a lazy thunk inside a lazy thunk so you don't have to compute while you don't compute.
19:27rlbcgordon: cl doesn't even promise tail call optimization, so you might blow the stack even if you were tail recursive.
19:27rlbnice
19:27Chousukewhich is only after the first call has finished :)
19:28Chousukeso there's no stack growth
19:28rlbcgordon: whereas scheme does guarantee tco.
19:28cgordonChousuke: so the seq is never kept in memory, it just has the current head and the thunk for the rest?
19:28rlbcgordon: right
19:28rlbthough of course you can get in to trouble if you hang on to the head
19:29cgordonrlb: that's because of the linked structure, right? It can't GC it until there are no refs to the linked structure anywhere?
19:29rlbcgordon: exactly -- if there's *any* way to reach something, it can't be gc'ed.
19:29Chousukecgordon: the results of evaluating the thunks are cached, so if you evaluate the seq further than just the head, those thunks will "disappear" and be replaced with just their values
19:31Chousukethere won't be stack growth but you can still blow the heap if you keep too much stuff in memory :)
19:33cgordonChousuke: yes, I'm trying to understand what circumstances cause things to be held in memory
19:33cgordonI think I need to read more about seqs first though
19:35Chousukewell, seqs are linked structures so they're like normal linked lists in that regard. Though it's possible to write code that looks like you don't have a reference to anything but in fact still do
19:36cgordon,(type '(1 2 3 4))
19:36clojurebotclojure.lang.PersistentList
19:36cgordon,(type (seq '(1 2 3 4)))
19:36clojurebotclojure.lang.PersistentList
19:36Chousukefor example (fn [aseq] (let [aseq (drop 1000 aseq)] "the original reference is still here preventing GC, just shadowed"))
19:36Chousukecgordon: persistentlists happen to be seqs themselves.
19:37cgordonah, so they implement ISeq?
19:37Chousukebut vectors aren't for example
19:37Chousukeyeah.
19:37cgordon,(type '[1 2 3 4])
19:37clojurebotclojure.lang.PersistentVector
19:37cgordon,(type (seq '[1 2 3 4]))
19:37clojurebotclojure.lang.PersistentVector$ChunkedSeq
19:37cgordoninteresting
19:42cgordonChousuke: can you elaborate on your example. I can't figure out where the reference is being held
19:42rzezeskiChousuke, can you elaborate on your example above? Are you saying that simply the fact that aseq is function argument causes it to have a hidden reference? Or are you saying the let form is causing the head to be held? If the latter, you would just do #(drop 1000 aseq) instead, right?
19:42cgordon:)
19:42rzezeskiand then call (aseq) in your body anytime you needed the sequence
19:43Chousukerzezeski: the function argument aseq is the reference. That let shadows the *name* doesn't change the fact that the reference is there
19:45rzezeskiGotcha, so in that case, when you want to avoid holding on to the head, should you just pass around functions returning seqs? So that the function argument would be a function itself, and in the let you would do [aseq #(drop 1000 (aseq))]?
19:47Chousukewell, the correct way would be not to have the let at all. locals are cleared on tail-call, so (fn [aseq] (someotherfn (drop 1000 aseq))) would not have the problem.
19:47ChousukeCould be optimised away with a smarter compiler, but no-one's motivated to improve the current one especially because the long-term plan is to rewrite it in Clojure anyway
19:48Chousukeso it's just some unintuitive behaviour you need to be aware of for now. :)
19:50carkso the head of a parameter seq is always retained unless there's a recur ?
19:50hiredmanno
19:50Chousukeit's not specific to seqs though; it matters to all references
19:51hiredmana tail call is a tail call, recur has to be in the tail position, but it does not define what a tail position is
19:51rhickey_cark: no, as Chousuke just said, locals (including params) are cleared on tail calls
19:52carkso if i map an infinite sequence, it only works because there is a tail call inside map
19:52ChousukeI guess it could be said that the reference always exists within the form it was created in until an expression in tail position is evaluated
19:52rhickey_cark: no Clojure library functions have head-holding problems
19:53rhickey_you can look at their sources to see how they do it
19:53carkight i know that, i wasn't sure why
19:53rhickey_most often, they need to do nothing
19:53cark+r
19:54carkok thanks
19:56cgordonChousuke: I'm still missing something. You said "well, the correct way would be not to have the let at all. locals are cleared on tail-call, so (fn [aseq] (someotherfn (drop 1000 aseq))) would not have the problem", but I don't see any tail call in that function.
19:57rzezeski(defn uhoh [big-seq]
19:57rzezeski (dorun big-seq)
19:57rzezeski (filter odd? big-seq))
19:57rzezeskiI think the above illustrates the point?
19:58rzezeski(uhoh (repeat 1)) ; will cause OutOfMemory
19:58cgordonsorry, just realized that hiredman already answered that question
20:00Chousukeyeah. a tail call is a tail call if it happens in a tail position. recur is just clojure's special form for making tail calls that don't grow the stack.
20:01cgordonChousuke: just to make sure I understand, the problem with your initial code was that aseq continued to point at the head of the seq throughout the body of the let, despite the fact that the aseq in the let only pointed at the 1001st item. Is that right?
20:02cgordonIn the subsequent code, "someotherfn" had a pointer to the 1001st item and presumably returns a lazy seq, which then returns out of the anonymous function, thereby freeing up the first 1000 items for GC?
20:03cgordonor are the first 1000 items freed up *before* someotherfn is called?
20:04cgordon(I realize I'm using the term "pointer" incorrectly here, but I'm not sure what the right term is)
20:04hiredmanfreed implies the gc has run and freed the memory
20:05cgordonhrm, good point, I was trying to say, "available to be freed", I think
20:05hiredmanthe term is reference
20:05rzezeskicgordorn, yea I felt like the let was confusing things, I offered my example above as a parallel. In my example dorun does not hold onto the head, and my tail call is lazy. Therefore I should not experience OutOfMemory when passing it (repeat 1), but should just burn the CPU. However, I did recieve an OOM, confirming what Chosuke is saying...I believe.
20:06rzezeskierm, I called it at the repl though, that could be my problem :(
20:07Chousukecgordon: well, since it's gc you never know when it's freed but in the corrected version, there is no reference while someotherfn is executing, while with the let there is.
20:07cgordonalright, I get it now, thanks for your patience
20:07ChousukeWell, it's good practice trying to explain this to other people :P
20:08ChousukeI'm still not sure if I completely understand it myself either :D
20:08cgordonHeh, yes. I just put up a blog post about my experience writing a little Servlet in Clojure. I didn't realize how little I understood what I did until I tried to write it down :)
20:08rzezeskiChosuke, would you agree my example is demonstrating the same thing, but without the let?
20:10cgordon"Writing is nature's way of letting you know how sloppy your thinking is." - Guindon
20:10Chousukerzezeski: well, it's not good because the dorun would get stuck even if you weren't holding to the head, but... yeah.
20:10rzezeskiOh right, didn't even think of that
20:11Chousukein fact, because you're holding on to the head you'll just run out of memory at some point. if you had no head-holding problems it'd be an infinite loop :)
20:12rzezeskiyea, that's what I was trying to get at
20:12ChousukeI wonder which one is worse :P
20:13rzezeskiYour example just confused me, because I didn't realize that the fn arg caused an implicit ref, and I thought you were demonstrating that the let form caused a ref that will be helf for the remainder of the function (because I've ran into that problem before).
20:15rzezeskithis is good, because I've been having laziness problems lately, and I think it was this very thing that is causing me grief
20:20lusory[5~[5~
21:49Drakesoncan incanter be compiled headlessly?
21:49liebkeDrakeson: yes, use the incanter-core ant task
21:50DrakesonI don't get processing then, do I?
21:51liebkeif you want processing, you can just use the normal build. I fixed the bug the caused problems on headless machines
21:56qedhey all
21:58Drakesonliebke: i see, thanks
21:58qed'lo tomoj
22:00tomojhello
22:03j3ff86is there an easy way to turn a seq collection like ((1 2)(3 4)) into a vector [[1 2][3 4]]?
22:06j3ff86nm, mapped the vec function
23:51qedAre there any active documentation projects ongoing?
23:51qedI'm interested in adding examples to the api documentation
23:53paancatch23: which graphs do you guys talking about?
23:53paansorry, wrong channel :(
23:57qedlet's say I take some input from a user and i want to use that as a regex in the function, how do I say #"user-input-goes-here"
23:58qedlike (defn abc [s] (let [regex #"s"]))
23:59_mst,(java.util.regex.Pattern/compile (str "hello" "world"))
23:59clojurebot#"helloworld"