#clojure logs

2009-10-19

00:02technomancy,(macroexpand-1 '(def #^{:foo :bar} heya 1))
00:02clojurebotDENIED
00:02technomancyso that expands to (def heya 1)
00:03technomancywhat happens to the metadata?
00:03hiredmanit is on heya
00:03hiredmanand def transfers it from heya to the var
00:03hiredman(I think)
00:03technomancyhiredman: so it just isn't readable?
00:03hiredman#^ is a reader macro
00:04hiredmanthe reader puts the metadata on the heya symbol
00:04technomancyyeah, but 'heya expands to (quote heya)
00:04technomancyI would expect other reader macros to expand similarly
00:04hiredmanit depends on what the reader macro does
00:05technomancyis that just an optimization then? so it doesn't involve a runtime call to with-meta?
00:05hiredmanI dunno
00:05technomancyI guess that makes sense
00:05technomancymakes it kinda tricky to debug though
00:17solussdwhat is the difference between (meta str) and (meta #'str) ?
00:18solussd,(meta str)
00:18clojurebotnil
00:18solussd,(meta #'str)
00:18clojurebot{:ns #<Namespace clojure.core>, :name str, :file "clojure/core.clj", :line 334, :arglists ([] [x] [x & ys]), :tag java.lang.String, :doc "With no args, returns the empty string. With one arg x, returns\n x.toString(). (str nil) returns the empty string. With more than\n one arg, returns the concatenation of the str values of the args."}
00:19solussdI guess a better question would be, what does #' do?
00:19hiredman#' gets the var named by the symbol
00:19hiredman,(var str)
00:19clojurebot#'clojure.core/str
00:19hiredman,(meta (var str))
00:19clojurebot{:ns #<Namespace clojure.core>, :name str, :file "clojure/core.clj", :line 334, :arglists ([] [x] [x & ys]), :tag java.lang.String, :doc "With no args, returns the empty string. With one arg x, returns\n x.toString(). (str nil) returns the empty string. With more than\n one arg, returns the concatenation of the str values of the args."}
00:20mikem`solussd: it's a var quote; see "Reader Macros" at http://clojure.org/cheatsheet
00:21solussdso it is metadata on the var itself instead of the object the var refers to?
00:24solussd,(meta #' (with-meta [1,2,3] {:foo true}))
00:24clojurebotjava.lang.ClassCastException: clojure.lang.PersistentList cannot be cast to clojure.lang.Symbol
00:24solussd(meta #' (with-meta '[1,2,3] {:foo true}))
00:26radsis the source available for any compojure sites? I'm relatively new to clojure/FP and I'm looking for somewhere to get started
00:28hiredmansolussd: vars are named by symbols
00:28hiredmanyou can't get the var named by a vector
00:28solussdyeah, I see that now. :)
00:29solussd,(def x (with-meta '[1,2,3] {:foo true})) (meta #'x)
00:29clojurebotDENIED
00:29solussdwhoa
00:30solussd(def x (with-meta '[1,2,3] {:foo true})) (meta x)
00:30hiredmanclojurebot doesn't allow def's
00:30solussdk
00:30hiredmanno need to quote that vector
00:30hiredmanor use those commas
00:31solussdyeah, that's left over from my previous thing. I program in java all day, it'll take awhile to break the comma habit. :)
00:31hiredman,^(with-meta [1 2 3] {:foo true})
00:31clojurebot{:foo true}
00:31solussd,(meta #'(with-meta [1 2 3] {:foo true}))
00:31clojurebotjava.lang.ClassCastException: clojure.lang.PersistentList cannot be cast to clojure.lang.Symbol
00:32hiredmansolussd: you just did the same thing
00:32solussdguess I actually have to have a var
00:32hiredmanand a symbol naming the var
00:32hiredman#' gets the var named by a symbol
00:32hiredman,(meta (with-meta [1 2 3] {:foo true}))
00:32clojurebot{:foo true}
00:36solussdso for (def x 1), the symbol is x, the var the symbol names is user/x, and both can have their own metadata?
00:36hiredmanthey can
00:36hiredmanuser/x is a namespace qualified symbol
00:37hiredmana var by itsself doesn't have name
00:38solussdok, that makes more sense.
00:39hiredman#' can be read as "var bound to"
00:39hiredman#'x => var bound to x
00:42solussdIt'll take me a bit to get used to all the subtly different reader macros that start with #. so far i've seen #{}, #'symbol, #^type-hint, #'regex'
00:43hiredmanI don't recall ever using #' in actually code, besides clojurebot's doc macro
00:43tomojat least you don't have to get used to custom ones people made up for their files :P
00:44hiredmanand it's #"regex"
00:44solussdthis is true. My lisp exposure is pretty slim, but I can see that driving me nuts
00:45hiredmanusing ' where you mean " won't do what you want
00:45hiredman,(cons 'a' 4)
00:45clojurebotjava.lang.IllegalArgumentException: Don't know how to create ISeq from: Integer
00:45hiredmanhmmm
00:45solussdright. I've stumbled on that a few times. damn python.. :)
00:46hiredmanindeed
00:46solussdso the :tag reader metadata key for type hinting... You can use it for both the return value and arguments to the function?
00:48hiredman(defn #^SomeObject f [#^SomeOtherObject x] stuff)
00:48hiredmanunless profiling indicates the need for type hints, I wouldn't bother
00:49solussdok, but if they are different (the arg type(s) and the return value) which gets assigned to the :tag
00:49solussd?
00:49hiredmanuh
00:49hiredmanI though I just demo'ed that
00:50hiredman#^SomeObject is the type hint for the function's return, it goes before the symbol that names the function
00:50hiredman#^SomeOtherObject is the type hint for the argument x
00:51solussdI understand that, but if I weere to look at the reader metadata for f, would :tag be someObject or someOtherObject?
00:51hiredmanreader macros that start with # usually apply to the following object
00:51hiredmansomeObject
00:51hiredmanthe type hint goes on the var, not the symbol or the function
00:52solussdok. If i were to look at the var metadata for the arg x inside of my function, it would have a :tag value of someOtherObject
00:52gilbertleunghi
00:52hiredmannope
00:53gilbertleungi have this function that works fine when i "require" it from the repl
00:53gilbertleungbut when i wrap it with (with-test )
00:53hiredmanlocal names (function parameters, let bound names, etc) are not symbols, vars, etc
00:53tomojso, given a var foo, what's #^Foo foo evaluate to?
00:53hiredmanthe compiler just uses the type hints durring code generation
00:54gilbertleungand i run tests within the repl, it starts complaining that "no matching ctor found for class X"
00:54tomojthat metadata on the var just gets thrown out after the var is evaled, I guess?
00:54gilbertleungeven though i've imported class X alredy
00:54hiredmantomoj: the metadata is added to the symbol foo
00:54gilbertleungam i running the tests wrong or something?
00:54solussdso arguments to a function are like things bound with 'let'?
00:54technomancyI'm seeing a test "failure" where the thing I'm checking with "is" evaluates to true, but for some reason it's being marked as a failure: http://p.hagelb.org/odd-failure.html
00:54hiredmandef just copies metadata from the symbol to the var
00:55tomojoh, I see
00:55technomancyany idea what could cause that?
00:55tomojah, yes:
00:55tomoj,^(quote #^Foo foo)
00:55clojurebot{:tag Foo}
00:57hiredmantechnomancy: maybe put in an (= true …)
00:57technomancyhiredman: same deal
00:57technomancyeven an (is true) fails
00:57hiredmanwhat about (is :pass)
00:57technomancyexpected: true\n actual: true
00:58technomancysame brokenness
00:58technomancybizarre
00:59tomojif that test worked it would be the coolest test ever
01:00technomancyit's got to be a broken test runner or something
01:00technomancymaybe a bug in build.xml
01:00hiredmantechnomancy: nah, deftest is a macro built on other macros
01:01hiredmansomething else is in the chain is clobbering the symbol's metadata before def can copy it to the var
01:01technomancyhiredman: I can copy an is assertion from other tests that pass right there, and it fails
01:02technomancyhiredman: even assertions that don't involve metadata are broken
01:02hiredmantechnomancy: I don't understand
01:02hiredmanlook at the metadata of the var bound to can-add-metadata-to-tests
01:03hiredmanno :has-meta because something somewhere is doing it's own meta thing
01:03technomancyhiredman: http://p.hagelb.org/test-brokenness.html
01:03technomancynothing to do with metadata
01:03technomancythe first passes, the second fails
01:06hiredman(deftest some-test (is true "foo")) ;passes with no failures here
01:07technomancyhiredman: did you add it to Clojure's test suite?
01:07hiredmannope
01:07technomancyof course, that works fine if I add it to my own project
01:07hiredmanwell, you never mentioned clojure's test suite
01:08technomancyoh my bad...
01:08technomancycontext is I'm adding a feature to deftest
01:09hiredmanwell, be sure to use vary-meta instead of with-meta
01:10hiredmantechnomancy: I added it to the other-functions tests and it passed
01:11hiredmanhave you recompiled? I dunno, maybe the tests are AOT'ed?
01:12technomancyyeah, checked that
01:12technomancythanks for the tip; I had (vary-meta name assoc :test `(fn [] ~@body))
01:12technomancyI mean, I had (with-meta name (assoc ^name :test `(fn [] ~@body)))
01:13hiredmaneveryone using with-meta just steps on eachother's toes
01:14hiredmanlemme git pull and try again
01:15tomojin the one example the expected value looked like it was quoted
01:15tomojoh, but (= 'true true), nevermind
01:16hiredman0 failures
01:17technomancy(is true "should pass") <= fails
01:17technomancy(is true "Should pass") <= passes
01:19hiredman [java] 0 failures, 0 errors.
01:20hiredmanhave you tried a fresh checkout?
01:20technomancytrying that next
01:21technomancyaha... so test.clj has a custom-report defined
01:21technomancythat acts totally differently from the built-in report
01:21technomancytake a look at around line 100
01:22hiredman*shrug*
01:23hiredmanI still get 0 failures
01:23technomancyany tests defined in test/clojure/test_clojure/test.clj that don't have their message set to "Should pass" will not pass.
01:24hiredmanah
01:24hiredmanso putting the tests in inside test/clojure/test_clojure/other_functions.clj neatly bypasses that
01:24technomancywell at least I'm not going insane
01:24technomancythanks for following my wild goose chase. =)
01:25hiredmanwell, I am watching seinfeld, and irc is just right there...
01:52abbehi everyone
01:53abbewhat is the difference between 'require' and 'use' at REPL ?
01:53abbeor in general.
01:54abbeAfter executing "(use 'clojure.contrib.http.connection)" I can invoke "http-connection" function, but not after "(require 'clojure.contrib.http.connection)".
02:32hiredmanabbe: use aliases the bound vars in a namepsace into the namepsace where use is called
02:32hiredmanrequire just loads a namepspace
02:32hiredmanyou can still the functions, you just have to use the full namespace
03:48abbehiredman, thanks for the explanation.
06:09octehttp://java.sun.com/javase/7/docs/api/java/nio/file/WatchEvent.Kind.html how do i access that class in clojure?
06:09octe(WatchEvent/Kind) or (import (java.nio.file WatchEvent.Kind)) would make sense to me
06:09octebut that does not work
06:13arbschtthat looks like an interface, not a class
06:14arbschtnested classes can be accessed with a $ separator, anyway
06:14arbschtWatchEvent$Kind
07:55eevar2did anything change in the google groups' spam settings recently? there's been 3-4 spam mail in the last few days
08:01rhickey_chouser: what do you mean by 'function params will ever support :as' ?'
08:37chouserrhickey_: I mean that fn params currently support & like destructuring vectors do, but they don't support :as in the same way
08:39chouserit seems to me that they could, though it would be a bit of a lie since whatever object was bound by :as wouldn't actually be the exactly the same object used for passing the args
08:39chouserso I was just curious if it was in the "maybe eventually" or the "never gonna happen" category.
08:43cgrandchouser: there's the ugly [& [a b & etc :as all]] :-p
08:44chousercgrand: ah, good point.
08:44cgranddoesn't support multiple arity though
08:45chouserI'm not sure how useful of a feature it is; I was thinking more about consistency.
08:45chouserright now there are two different contexts where & works, but :as only works in one of them.
08:46cgrandchouser: I understand
08:48cgrand:as would play the same role as arguments in javascript -- but while I use it frequently in js, I never needed it in clojure because of arglist destructuring I guess
08:51rhickeyare you talking about, given (fn [a b & c :as d]...) fabricating an object d holding (list* a b c)?
08:51chouseryes
08:51rhickeyhrm
08:52rhickeyI wouldn't think that would be half as desired as some way to get rest-as-map
08:53chouserfor keyword args?
08:53rhickeyjust to automate & xs ... (let [m (apply hash-map xs)...
08:54rhickeynot exactly the same as keyword args but good enough if you could destructure it
08:55chouseras far as actual desire, you're probably right. I was just curious if the consistency argument carried any weight with you.
08:55rhickeyon another topic so the design for datatypes + protocols moved forward significantly this weekend
08:55rhickeychouser: there never was a d, so not a consistency thing IMO
08:55chouseronly came up because I found myself explaining the difference between destructuing & and parameter list &
08:56rhickeythat's the difference - in destructuring there was one thing
08:56chouserok, that's all I was asking, thanks.
08:56chouserso -- protocols?
08:57rhickeyI have to organize my notes (keeping only the move forward ideas and not some of the speculative ones)
08:57chouserah, sure.
08:57rhickeyIt starts with datatypes, if you don't do interface + impl then you need fast access. This also ties into the desire to first-class-ize structs, re compilation etc
08:58rhickeyso (deftype org.clojure.Foo fred #^int ethel #^String lucy)
08:58rhickeygives you a proper class, with three fields
08:58rhickeyall final
08:58rhickeya ctor
08:58rhickeyequality and hashCode
08:59chousermap interface?
08:59rhickeyILookup-style access via keywords corresponding to :fred :ethel :lucy
08:59chouseror strictly interop for access?
08:59chouserok
08:59rhickeyI'm not sure yet about full Associative/expando
09:00rhickeyI also have ideas about field aliases, so you could also say name was foaf:name
09:00rhickeythis allows for true attribute polymorphism, not just accidentally same local names
09:01chousernice
09:01rhickeya long standing problem IMO is classes defining their own languages, this separation of code + data, plus uri-identifiable attributes, solves that
09:02rhickeyyou'll also get a constructor fn Foo, and possibly nth support, so could destructure with [f e l]
09:02rhickeymetadata support
09:03abbeclosures aren't possible in clojure, right ?
09:03chouserabbe: yes they are.
09:03rhickeythis would be a properly compiled class, but I want to support synamic use without precompilation, subject to the must reload on change
09:03rhickeydynamic
09:04abbechouser, sorry, i mean with mutable bindings. like iterator functions.
09:04rhickeyno inheritance of any sort
09:05chouserabbe: locals are immutable, but you can bind a local to a mutable thing (like an atom or ref) and close over that.
09:05abbechouser, oh, okay.
09:05abbethanks chouser
09:06Chousukethat's not very idiomatic in clojure though.
09:06chouseran iterator isn't, but I don't think there's anything wrong in general with using closures to control access to your mutable state, is there?
09:07rhickeydatatypes being proper host classes with typed fields means that manipulation code written in Clojure will be fast, not tying that to the inside of reify
09:08chouserrhickey: yeah, I figured this would mean a finger tree rewrite. :-)
09:08rhickeychouser: should just be moving things around a bit
09:09chouserbut it's good -- I initially wrote the basics using a map for each node
09:09rhickeyso, datatypes are nice, immutable, fast, strongly typed but with fast dynamic access
09:09rhickeyI imagine something like the new string switch for the keyword lookup
09:09chouserconverting that to using reify and closures for performance seemed an unfortunate step.
09:10rhickeythis gives people the type they want for structs
09:10rhickeyand a compilation story
09:10rhickeyplus primitive members if needed
09:10rhickeyso that's the data side, pretty much I think
09:11chouserI'm a bit surprised you're ok with the reload-jvm-on-change.
09:11rhickeywhatever is fastest will require that
09:11chouserwe've had a few runs at that with gen-class and gen-interface, and walked them both back.
09:11rhickeyin the reify story that would have been interfaces
09:12rhickeyi.e. interfaces would be static, defined up front, and not dynamically alterable
09:13rhickeyyou simply can make something dynamic that's competitive with field access
09:14rhickeybut this way that speed is readily available to all future code, not just at-birth method code
09:15cemerickadd Associative to this mix, and it's exactly what we've been pining away for. :-)
09:15rhickeychouser: i.e. you won't have to move your ft code to map-like code, you can use .this and .that
09:15rhickeyjust move your impls from methods to protocols or ordinary fns
09:16rhickeycemerick: associative meaning lookup or expando?
09:17cemerickheh, I had never heard of "expando"
09:17cemerickBut yes, having that is incredibly convenient.
09:17cemerickso much so that I don't think I'd want to back away from having it in most cases.
09:19rhickeyexpando is on the fence right now, one issue is implementing it without datatypes becoming instanceof map/associative
09:19rhickeywhen associative is a protocol there will be different options
09:20rhickeyopps, just noticed above: you simply *can't* make something dynamic that's competitive with field access
09:20cemerickwell, I'm in late, so I don't know the background on 'datatypes'. I suspect they're one step below the level of abstraction we'd use directly.
09:21rhickeydatatypes are just typed holders for data - no methods
09:21rhickeyso, then protocols
09:21rhickeythese are groups of functions, polymorphic using single dispatch
09:21rhickeyyou create one specifying the method names and sigs
09:22rhickeythen implement for various types
09:22rhickeyimplementation is just (implement AProtocol AClass {:methodA afn :methodB bfn})
09:23rhickeythis will allow for handy reuse of impls without any derivation junk
09:24rhickeymost of the things Clojure now uses interfaces for will be protocols
09:24cemerickIn that case, implementing "expando" would be straightforward if we could define an impl for assoc for a given datatype.
09:24rhickeycemerick: not quite, as you'll need a slot for the expando map in the data
09:25rhickeyand integration with the lookup logic
09:25rhickeyso, best if built-in
09:26rhickeybut it does highlight an important aspect of protocols, they can't require additional data
09:26cemerickugh, I shouldn't get in so late. This is parallel to reify, right?
09:27rhickeythe reify work will probably become uber-proxy, a host interop thing you can use to keep doing Java-style
09:28rhickeybut I think proxy can be made fast and has a number of important attributes
09:28rhickeyseparation of code and data
09:28rhickeyindependent extension
09:28rhickeyreuse w/o derivation or composition
09:28rhickeyor adapter generation
09:29rhickeyoops protocol, not proxy
09:29cemerickOK, you really had me confused for a minute.
09:29rhickeyyou can implement a protcol on nil
09:30chouseryou'd have to, so you can cons onto it. :-)
09:30rhickeyin order to enable bridging to Java hierarchies, you'll be able to define a protocol on an interface
09:30rhickeythat opens the dreaded multiple inheritance of implementation hole
09:31rhickeyI haven't decided yet how best to plug it. It could be - an arbitrary choice, which should work since both impls must have same semantics
09:32rhickeyor, something like the prefers system on the protocol level
09:33rhickeychouser: yes, many of the core abstractions are defined for nil, it's one of the things in the RT if/else stuff I want to make go away
09:34rhickeyprotocols will be fully reified, and have useful properties like (aprotocol :amethodname) -> a polymorphic fn
09:34rhickeyand (aprotocol AClass) -> a method map
09:35rhickeyprotocols are fully dynamic
09:36rhickeynot sure how clever we can be with protocol mods not disturbing existing impls, but no restart ever required, just re-eval impls
09:37rhickeycombining datatypes and protocols, you'll have fast access to the data in the impl
09:38rhickeybut new protocols can be defined and implemented on existing datatypes at any time by 3rd parties, solving the expression problem
09:39rhickeyyou can define more generic protocol impls by using :name instead of .name, or even better, :uri-name
09:40rhickeyanyway, that's the basic idea
09:41rhickeyI've started on datatype, it's Clojure code in gen-class, lifting lots from there
09:41chousersounds emitently doable.
09:41rhickeyI could use help, there will be many discrete things like implementing hashCode, equals, fast keyword lookup...
09:42rhickeyI imagine there is some sample bytecode for the new String in switch feature of Java 7 we could mimic for the latter
09:42chouserI think people will understand how to use it easily (the basics anyway, even if they don't immediately grasp the full flexibility)
09:42rhickeythen protocol could be defined in terms of datatype
09:43chouserit == datatypes + protocols.
09:43rhickeychouser: I think so, this will be a major benefit, something most people want even with generic functions, some higher level abstraction mechanism to gather methods
09:44rhickeyprotocols roughly map to interfaces without the instanceof and at-definition-time aspects
09:44chouserright
09:44chouserand people already try to do many datatype-like things with structs
09:44rhickeydatatypes just do the right thing immutability-wise, and otherwise look like structs, or maps when convenient
09:45rhickeyright, this gives more structure vs structs, types etc
09:45rhickeythe dynamic use thing is important, not so much the redef/reload, but just not needed precompile
09:46rhickeyit's tricky, possibly the best way to support it is to require a compilation target dir during development. with a target dir in the classpath, deftype can gen to file, and the class can be picked up (once) via normal classloading, and thus generally visible under those rules
09:47chouseryes, I very much agree. precompile brings a whole batch of configuration complexity that is nice to postpone until someone is fully hooked on the usage.
09:47rhickeywith gen-to-memory though there will always be visibility issues
09:47rhickeyso I'm favoring gen-to-disk but would like feedback
09:49chouseroh, so datatypes wouldn't work at all without the classes dir setup?
09:49rhickeyi.e. dynamic use requires write-access to dir in classpath
09:49rhickeychouser: there's no way to expose a loaded-from-memory class generally to all possible consumers due to classloader issues
09:50rhickeyat least not without wrapping the entire Clojure process in a custom loader
09:51chouserthat's where I see people struggling, though, trying to get the dir created, given in Clojure config, given in classpath, all at JVM startup time (which means each editor/IDE has their own mechanism)
09:51rhickeyI'm open to suggestions, but rootClassloader didn't really work
09:51chouseryeah
09:52chouserCan't we get the JVM to include a load-from-memory method in the normal classloader?
09:52chouser:-P
09:52cemerickrhickey: FWIW, hot-reloading of code through a remote repl in NetBeans RCP works like a charm...never any visibility issues as far as I can tell
09:52rhickeythere's simply no standard way to make a loaded-from-memory class available to the base loaded
09:52cemerick(that's with thread context classloader, BTW)
09:52rhickeycemerick: every one of those environments has a non-standard enhanced classloading system
09:53cemerickyeah, I know, just offering up a data point
09:54rhickeycemerick: without Netbeans platform or OSGi or something else in the mix, I don't see a way other than wrapping Clojure process, itself full of caveats
09:55chouserwhat's a common example of visibility failure?
09:55rhickeycemerick: also note that Clojure code easily reloads and shares because the actual classes are never exposed, only the shared IFn interface loaded with Clojure
09:56rhickeythese datatypes will be referenced explicitly by name
09:56cemerickoh, and deftype would create and expose a new named class com.foo.Datatype
09:56cemerickor, interface?
09:56rhickeyno interface
09:57cgrandwhat about providing a clojure-specific system classloader through -Djava.system.class.loader? Thus simple settings wouldn't need to write to disk.
09:58chouserI'm wondering if it would be resonable to prefer the gen-to-disk route, maybe even print a warning if it fails, but fall back to in-memory to help people get more success early before having to deal with directory and classpath issues.
09:58rhickeycgrand: yes that's the wrap-the-process I was talking about. I don't have much experience with it, but it should be possible
09:59rhickeythe bigger question is, what is the target for dynamic use - is it just interactive development or some sort of dynamic deployment?
09:59rhickeyfor the latter I'm happy to say precompile deftypes
10:00rhickeybut I imagine the wrapping classloader is incompatible with netbeans et al
10:01rhickeychouser: so rootclassloader as fallback?
10:03chouseryes
10:03rhickeythe biggest issue with all dynamic solutions is they often don't work in production without specific bridges to the application host (netbeans, osgi, netkernel etc). Precompilation make the problem go away completely, and there really isn't any such thing as a (useful) dynamic datatype in production
10:04rhickeythis is another nice thing about breaking it up this way (data is most static)
10:04chouserfallback to baseLoader is only useful if the visibility problem is rare enough during simple dynamic development scenarios.
10:04rhickeychouser: but you agree dynamic is mostly about dev-time?
10:06chouserI think so. If you actually need dynamic deployment and restarting the JVM isn't an option, you've got a whole lot of other concerns that you'll expect to have to spend effort solving.
10:06chouserusing a new name for your "updated" datatype for example, and making that work with all your running code. ...at that point getting the classpath set right is the least of your worries.
10:07rhickeyyes, but dynamic code still fine, in fact easier than ever with protocols
10:08chouseryes, if your data isn't changing (or it you accepted the performance impact of a regular map up front), then protocols, multimethods, and regular var fns give you a lot of dynamic deployment options.
10:09chouserbut that's also outside my experience -- I've never tried to do real dynamic deployment.
10:10rhickeyI should play more with -Djava.system.class.loader, it would be easiest for standalone and other repls, would just need some coordination with IDe folks for per-IDE solutions
10:11cemerickTotally aside from the technical issues, requiring stuff like messing with the system classloader, setting up designated compilation dirs, etc., is all suicide for new update IMO.
10:13cemerickack. uptake*
10:14konrGuys, I've got a function that prints some data. How can I make it return this data instead of printing it?
10:15chouserkonr: wrap it in (with-out-str ...)
10:16chouserthough that may be taking your question too literally.
10:16rhickeycemerick: well, there's always rootclassloader and its limitations. Perhaps they won't really come to fore in dev only. Most of its problems were in deploy in environments like OSGi etc. So the story would be, precompile before going there
10:19cemerickrhickey: I think RCL is totally appropriate in development, and IDEs like enclojure and slime/swank can do what they need to to set things up properly for those environments. I know that I wouldn't bother with any casual programming in a language that required knowing about such things up front.
10:19rhickeycgrand: I've been thinking about #org.clojure.Foo{:fred 1 :ethel 2}
10:20rhickeycemerick: yes, the flipside is the confusion that results when it doesn't work
10:20cgrandyes, dedicated reader support looks nice
10:21chouserfwiw, I'm in favor of late confusion over early complexity here.
10:21cemerickwell, hopefully Joe programmer only hits that when he's nearing deployment time, at which point he's well into internalizing the awesomeness of clojure.
10:21cemerick+1 chouser Gotta keep the learning curve as gentle as possible.
10:22cemerick(modulo the pedagogical references to reify wiki pages and such ;-) )
10:23ttmrichterI have a pretty clueless newb question here: where do I get a version of clojure-contrib that compiles under clojure 1.0.0-?
10:23chouserIt may be worth a warning by default -- if you (deftype ...) at the REPL and gen/load from disk fails, print "Classpath config is not optimal -- see foo if class is not visible later."
10:23chouseror something.
10:25ttmrichterSorry. Not compiles. Works with.
10:25ttmrichterMy bad.
10:26chouserttmrichter: there's a compat-1.0 branch of the contrib github repo that should work.
10:27Chousukerhickey: the #foo.bar{} reader syntax for datatypes would disallow using any letters for # dispatch, though :/
10:28rhickeyRCL for datatypes might not be as bas as RCL for code was - a big problem for RCL was code loaded there couldn't see other parts of the world, or could load classes then not seen, but here there will be no code other than self-referencing methods
10:28rhickeyas bad
10:30ChousukeMaybe something like #Cfoo.bar{:key val :key2 val2} wouldn't be too bad (C for constant)
10:31rhickeyChousuke: not necessarily, most CL #letter thing specify what must follow, so more letters would mean this isn't #letter
10:32rhickeye.g. #p"...", #c(..), #nA ...
10:32rhickeybut yes, it would complicate things
10:35ttmrichterOK, I was right the first time. Compiling clojure-contrib isn't working with the 1.0.0- version of Clojure.
10:36ttmrichterIs there a release of clojure-contrib that is known to work with clojure 1.0.0-?
10:36chouserttmrichter: there's a branch on contrib in the github repo that's compatible with clojure 1.0
10:36ttmrichterThanks chouser.
10:46dmiller2718rhickey: Any thought to the CLR implications of all this?
10:47cemerickbah, found yet another instance where I screwed up the class/symbol :tag metadata in a macro
10:52chousercemerick: it seems like instances of Class could be supported there. Have you asked?
10:53cemerickchouser: no. I've just considered it a mental problem on my part. That, and I try to make sure that I ring the bell on important stuff.
10:54cemerickWhen we get to HEAD sometime around 2014, I'll probably submit a patch for it.
10:54cemerick:-/
10:56AWizzArdcemerick: did you decide which framework you want to use for your rest webservice?
10:56cemerickAWizzArd: it's largely not my call, I probably won't be doing the frontend work.
11:06triddellAnyone else here use clojure with IBM jvms? As far as I know issue #104 (http://www.assembla.com/spaces/clojure/tickets/104-GC-Issue-100--gen-class-creating-non-compliant-field-names-) still has not been addressed.
11:07triddellalthough there was some discussion in sept on the list: http://groups.google.com/group/clojure/browse_thread/thread/ce2b067acb60526f/93db150588425575?lnk=gst&amp;q=issue+100#93db150588425575
11:12headiuslove those IBM JVMs
11:12headiusthey're more stringent on method names too
11:12peregrine81Hey I'm trying to learn Clojure and do some of the Project Euler stuff. and I keep running into this http://pastie.org/660665
11:12peregrine81Has code + error
11:13headiusI'd guess it's the "Find the.." string, but I don't actually know clojure
11:15peregrine81headius: thats actually the function comments
11:15konrDo Java objects use some sort of different *out*? I'm failing to capture what it prints with (with-out-str ...)
11:17triddellheadius: well, the initial suggested patch replaces "-" with "$" in the method names, which has worked for me in the past... I just didn't know there were deeper issues to be looked at from the gurus
11:17cemerickkonr: rebinding *out* doesn't change System.out, AFAIK
11:17headiusI think it was - I ran into an issue with too
11:17headiusor one of the other operators...maybe +
11:18headiusactually I have a couple questions about gen-class, if anyone cares to chat
11:18headiuswe're looking at building something similar for jruby
11:19headiushave it working basically...but the lack of joint compilation or circular dependency mgmt is a hassle
11:19somniumperegrine81: its the (e), e is an int, when you wrap it in a list clojure thinks its a function call
11:19headiusdoes clojure's gen-class do anything more than just spit out a pseudo-class that's implemented with clojure code?
11:20cemerickheadius: gen-class classes don't contain any impl -- that's all still in clojure-land
11:20peregrine81somnium: THANKS! That makes perfect sense.
11:20headiusso they classload something-or-other though, right?
11:20peregrine81somnium: thanks again, it seems so obvious now
11:20headiusin JRuby it's similar...the generated class just embeds (as strings, no less) the source you tell it to
11:20headiusstatic load of the class evaluates the sources and then you're off to the races
11:21somniumperegrine81: np
11:21cemerickheadius: yeah, they load and bind against the namespace you specify in the gen-class form (which ns provides a reasonable default for)
11:21headiusbut the circularity issues are yet to be resolved, so you can declare two classes with cross-dependencies
11:21headiusmmm ok
11:21cemerickjoint compilation is tricky though. I think groovy has that nailed, but I've no idea if the implementation there is reusable at all.
11:22headiusit's not as far as I know
11:22headiusthere was some discussion on creating an uber-compiler at JVMLS, but I don't know if it has progressed
11:22headiusif there were a top-level compiler that handled depedency resolution and queried language-specific plugins for the types their sources exposed, almost all jruby's "class" generation would be done
11:23ericthorsenhas anyone played around with JParsec (java parser combinator) and clojure?
11:24ericthorsenMakes heavy use of generics and I seem to be having some problems right out of the gate with class access to support classes I'm not directly calling
11:24cemerickI'll bet something like that could be put together in short order if all the principals got in a room (e.g. without any Sun/JCP involvement)
11:25headiuscemerick: probably
11:25headiusI need it for duby's compiler too
11:26headiusso far I've been doing it myself, but implementing Java Lang Spec method dispatch is...interesting
11:27cemerickpresumably the trickiest issues would be around boxing off javac properly.
11:27headiusvery likely
11:28cfoxwho *
11:35rhickeydmiller2718: should be very straightforward on CLR, I'm not relying on JSR292 or anything. This stuff is on the path to cinc and the many benefits it has for portability
11:35jlillystupid clojure-learning-weekend and it affecting my work code.
11:35jlilly:-P
12:01somniumjlilly: the pain of not using clojure?
12:01jlillysomnium: I'm using python, so its not too bad.
12:02jlillybut I wrote a function that accepts functions as an argument etc etc
12:02somniumjlilly: I mostly do ruby, used to think blocks and define_method were amazing, now they just seem broken ... :(
12:03somniumclojure will set you free
12:26hiredmaneclipse's java compiler might be nicer to use for a project like a super compiler
12:40rhickeyhttp://www.assembla.com/wiki/show/clojure/Datatypes
12:41hiredmanclojurebot: datatypes is <reply>http://www.assembla.com/wiki/show/clojure/Datatypes
12:41clojurebotOk.
12:44rhickeyfeedback welcome
12:47chouserwith-meta would copy all fields?
12:47stuartsierrainteresting, esp the URI bit
12:47rhickeychouser: yes
12:47rhickeybasically calls the ctor
12:47chouserbut no assoc support with the same behavior?
12:48rhickeystuartsierra: yes, I'm tired of these impedance mismatches, this (attribute semantics) is a longstanding problem and RDF's solution is as good as any. Building it in is key, else you are constantly left with mappings
12:48danleihow about a deftype read/print syntax like this: #s{org.myns.foo :fred 1 :ethel 42 ...}
12:49danleis/#s/#t/
12:49rhickeychouser: that's there under Associative/expando
12:49chouseroh, yep. sorry.
12:51rhickeychouser: the only reason it's not in basics is I haven't thought through all the ramifications. As far as storage overhead, both meta and expando are one word each. For a 2-slot datatype that's a doubling, but the per-object overhead is like 6 words, so only 25% or less
12:51rhickeythe dissoc a field = non-type seems fair
12:52chouserthe URI field alias really is a lovely idea.
12:52rhickeythe only other thing is I don't want datatypes to show up as instanceof maps necessarily
12:52chouserdissoc on a struct field is currently an error, is it?
12:52rhickeyyes, an error
12:52rhickeybut a wart
12:53rhickeyshould just become non-struct
12:53cemerickIs there any other use case for the field IDs that isn't RDF-related?
12:54rhickeydanlei: very CL-like, but I'm not sure I like mixing the name with the key/val pairs
12:54chouserdissoc + assoc wouldn't take you back to a compatible object.
12:55danleirhickey: yes, I'm sceptical about that too, but I don't really like such a long prefix either ...
12:55cemerickI'd much rather have an error on dissoc of a field.
12:55chousercemerick: I can imagine using namespaced keyword aliases just for bookkeeping inside a large app
12:55rhickeycemerick: I think it is a general problem. Consider, you want to write some type-independent data processing code. Without uri aliases you are left with duck-types on local names, always a mess
12:56rhickeycemerick: but the (error on dissoc) precludes treating structs uniformly as associative things in the relational world, i.e. as information
12:57rhickeyuris are interfaces for fields/attributes/properties
12:57cemerickwell, to chouser's point, assoc and dissoc should be symmetrical w.r.t. types/structs/whatever.
12:57cemerick(IMO, of course)
12:59rhickeycemerick: I disagree about the symmetry - the whole point of the dominance of associative types in Clojure is to deemphasize type-specific information processing. So, while you might have a data structure for a specific purpose, when you start using assoc/dissoc/join etc with it you are using it (profitably) as a generic information source
13:00cemerickI guess the utility of URI naming is dependent on one's domain, and the complexity of the data modeling therein. I can't say I've had much trouble with name duck typing, although perhaps I don't know what I'm missing in some way.
13:01danleirhickey: how about this: |org.myns.foo {:foo 42 ...}| ?
13:01rhickeydanlei: I don't think I'm ready to use up || yet
13:01danleiok
13:02hiredmanwhat about host independent stuff? it seems like it would be nice to create a datatype constructor fn and have some generated clojure name for a datatype other than a java class name
13:02rhickeyhiredman: oh, yes, there will be a Foo fn, I forgot to include that
13:05rhickeyhiredman: fixed
13:05hiredman:)
13:06hiredmanif you do end up passing a map to the constructor, I think it would be nice to pass a map to deftype (deftype {:foo String :bar List})
13:14stuartsierrarhickey: I'm working on code generation from an RDF ontology: http://tinyurl.com/yhthzjj
13:28danleianother possibility would be plain: #t(my.ns.foo {:foo 42 ...}). just #my.ns.foo{:foo ...} feels to "unparenthesized" to me. Personally, I'd prefer #t{my.ns.foo :foo 42 ...}, or one of the other options to it.
13:31somniumdanlei: its the first time I've heard a complaint that lisp does not contain enough parentheses :)
13:31danlei:)
13:32danleiI actually liked them right from the start :)
13:39chouserthis is new. spam sent to the group apparently from the accounts of good members such as kotarak and rhickey.
13:39danleidesign question: for something like a telnet client, what would be an idiomatic clojure approach of handling the socket? atm, I just do like I would in an imperative language: A loop which reads available characters and operates on them. In general, is there a preferred way to do things like this in Clojure?
13:40danleiOr: Is there a "fp-idiom" to handle things like this?
13:41danlei(maybe a stupid question :)
13:42chouserno, it's a good question.
13:42chouserI've done it a couple times now and am not exceedingly pleased with any of the results.
13:42rhickeychouser: yes, I saw that - I moderated myself. If you see someone else being impersonated, please set moderation on for them
13:42rhickeystuartsierra: I saw that, but haven't looked too closely
13:43danleichouser: what were your approaches?
13:44chouserrhickey: I only saw it with kotarak a.k.a. Meikel Brandmeyer, but didn't notice until I had un-moderated him once. sorry about that.
13:44chouserdanlei: all I can suggest is do everything you can to contain the statefulness and mutation.
13:44rhickeychouser: np, this is very annoying. when I looked into it I found that it is common on ggroups, and we've just been lucy so far. The only surefire defense is full moderation
13:45rhickeylucky
13:45chouserdanlei: This amounts to studying each function you write to see if it is impure. If it is, try to make it pure or factor out as many pure parts as possible.
13:46danleichouser: I thought about having just the socket reads in the loop and putting read lines in a ref, than have a watcher on that
13:46chouserrhickey: that's quite frustrating. a quick look at the message suggests it's simple smtp envelope spoofing.
13:46danlei*then
13:46chouserdanlei: I'm not sure that's better than just calling a pure function directly from your loop.
13:47danleichouser: me too ... that's why I'm asking :)
13:47chouserdanlei: I don't have much for you. Maybe somebody else has better ideas.
13:47rhickeychouser: yes, just the from: field, but that's what ggroups keys moderation on
13:47danleichouser: thanks anyway
13:48chouserdanlei: another option would be to send to an agent from your loop -- that would let the work queue up and be handled in another thread, and help enforce purity.
13:48chouserrhickey: full moderation would be quite onerous.
13:48rhickeychouser: yeah
13:49danleiyes, that's something I considered, too
13:50danleichouser: maybe this would be a good use for monads, but I'm not really at home with them
13:51rhickeychouser: have to be careful when getting spam via a valid user to just remove and not flag as spam, else will ban user!
13:52Chousukedanlei: with the reader (which I still have to finish :() I had a similar problem... The input comes from a PushbackReader, which is stateful.
13:52chouserrhickey: bleh. ok.
13:54Chousukedanlei: I just converted the input to a seq of chars and made my reader work on that. probably not fast, but at least I didn't have to care about the statefulness :)
13:55danleiChousuke: : I'll take a look at it again. I took a similar approach for my little cl-like format implementation, before I knew about faulhaber's great work
13:56Chousukethe thing is not very well designed though (or designed at all, actually). It's basically the simplest possible approach :P
13:57danleiwell, I wouldn't have done better :)
13:57danleialso, the simplest approach isn't necessarily the worst one
13:57ChousukeI guess.
13:57Chousukeit'd be nice if the reader were restartable though.
13:58Chousukeas in, if it doesn't get the input it wants it just returns and you can feed it more stuff.
13:58danleimore like what you did with my ansi-sequence thingie?
13:58Chousukeyeah.
13:58ChousukeI used monads with that. I don't have monads available for the reader ;(
13:59danleiYes, but there was a nice stateless version before that, too
13:59danleiI still haven't grasped Monads yet, gotta take some time for it
14:01danleiI think the big picture is that they are a very general means for composition, but I didn't really understand how to use e.g. the state monad in real code. must have a look at your implementation of the ansi-thing again.
14:02ChousukeI guess if I make the reader restartable I'll end up writing a monad anyway
14:02Chousukeeven if I don't call it one :P
14:02danlei:)
14:04Chousukebut I should figure out how to integrate the reader with Clojure itself next. that would help with testing.
14:04danleigo for it, I'll be an early adopter :)
14:04Chousukeit's not complete but it'd be interesting to see what blows up.
14:06danleiI could even use it in my client, instead of parsing user input I could have something like ! dispatch for commands and so on
14:07danleibut atm it's all a horrible mess, I'm just rewriting the whole network stuff and have plowed through the protocol, implemented a little telneg DSL &c
14:09danleiand, to be honest: there still is the stateful ansi-sequence parser in it ;)
14:46avital/j shiftspace
14:47avital...strange
15:17rhickeyhttp://www.assembla.com/wiki/show/clojure/Protocols
15:30liebkerhickey: very interesting
15:35chouserSo... I could implement a protocol by providing a datatype instance? :-)
15:37hiredmanit seems like a mistake to rely on java classnames
15:38rhickeychouser: yes, (implement aprotocol adatatype ...) is the idea
15:39hiredmandatatypes would have a .getName method and protocals would prefer that to classes
15:39rhickeyhiredman: I'm on the fence about extending to dynamic type slot. It's a flexibility/speed tradeoff.
15:40chouserrhickey: oh, right. I meant the more subversive and less useful (implement AProtocol AClass (ADatatype. (fn ...) (fn ...)))
15:40hiredmanrhickey: I'm not saying it should be dynamic
15:40hiredmanjust a clojure name vs. a java name
15:40rhickeychouser: for what purpose?
15:41chouserI have no purpose, just noting how pervasive the core interfaces (map in this case) are.
15:41rhickeyhiredman: implement is evaluated, you can just put the class in a var
15:41rhickey(implement myprotocolvar myclassvar mymapvar)
15:42rhickeychouser: yes, that's still the plan, everything connects together
15:42hiredmanyeah, but if you move code to different host that doesn't have java names...
15:42hiredmanI guess that is just pie in the sky
15:44rhickeyhiredman: no, it's a good point. I'm not sure it's a serious problem as there will be several ways to encapsulate the name
15:44chouserhiredman: fwiw, ClojureScript used Java-like names for things, and I think the .Net port does too.
15:44chouseras in, it was still accurate and useful to say (instance? clojure.lang.IPersistentMap x)
15:45cemerickDoes anyone know what one would use under LLVM in that context? I presume that'd be the next likely target.
15:45hiredmanchouser: well, java like names just are names with dots in them, which I have no problem with, the issue is tieing this all to the existence of classes
15:45rhickeycemerick: that begs my question - where are the libs for LLVM?
15:45hiredmana jave name is a class
15:46rhickeyhiredman: on the CLR it's a CLR class and in ClojureScript an object I presume
15:46hiredmanhmmmm'
15:46cemerickrhickey: I've no idea -- I presume it'd be platform-bound. There was an Apple fellow here a while back talking about how dreamy clojure-on-LLVM would be. *shrug*
15:46chousera dotted name in clojure is a host class name -- exactly what that means can change as long as the required behaviors are supported.
15:47hiredmanok
15:47rhickeyI think the demands on the host from datatypes and protocols are minimal
15:48rhickeycemerick: Clojure on Obj-C is interesting, if only there was GC on iPhone
15:49chouserdatatypes will be implemented using asm calls like gen-class, right? Those parts will have to be hand-ported along with the gen part of the compiler.
15:49cemerickMy sense was that that was this guy's idea, but he was sorta cagey about the eventual runtime environment.
15:50chouserby protocols will require very little gen support I would guess.
15:50rhickeychouser: yes, datatypes are code gen, but protocols should only need datatypes and Clojure itself
15:51rhickeythe dispatch function needs to be as fast as possible
15:51gascon protocols, is it a performance reason or a design reason that motivates dispatching on only the first argument, rather than letting the designer of the protocol choose the dispatching argument for a given method? maybe i'm missing something as to why the latter wouldn't make sense...
15:53rhickeygasc: no, that's still a possibility. I have in my notes letting the protocol specify a name for the dispatch arg (defprotocol AProtocol [x] (foo [a x y]...))
15:54rhickeyit's more complexity and I'm not sure how often it would be used. I couldn't find one case in Clojure where the dispatch arg didn't end up being first in the resulting Clojure fn
15:55rhickeywher eClojure now uses - interface method + RT dispatch wrapper + Clojure fn
15:56chousercons narrowly escapes
15:56cemerickThe diff between protocols and multimethods narrows.
15:57rhickeyprotocols are like groups of multimethods with hardwired dispatch fn, and implement-as-a-set only
15:58rhickeyyou always end up wanting some abstraction for sets of generic functions anyway
15:59AWizzArdrhickey: the new Datatypes page in the assembla wiki looks very interesting *thumbs up*
15:59rhickeyI think much easier to manage a protocol than say, 5 independent multimethods
15:59cemerickso given arbitrary-argument dispatch, protocols would eventually overtake multimethods as the de facto polymorphism mechanism (assuming most multimethods have very simple dispatch fns)
15:59cemerick(or, type-of-argument dispatch fns, that is)
16:00rhickeycemerick: the numbers in any study of multiple dispatch point to vast majority being single dispatch on type
16:00rhickeyagain, I haven;t seen a lot of call for other-than-first arg, show your use cases now...
16:01rhickeyI think the ideal compliment to protocols is full predicate dispatch, something to which I'll eventually return
16:01rhickeybut multimethods still have great utility. I know I've used the non-type and multiple arg aspects and so have many others
16:02rhickeyI have some high-perf implementation ideas for protocols that may make it back into multimethods - e.g. perfect hashing based dispatch
16:02gascrhickey: got it. first-argument dispatch has a more java interop-y feel, like real methods, but as one gets away from thinking in terms of methods i can see it being pretty cool and useful, gives the author more syntactic freedom etc., cf str-utils2 (i think). but weighing the cost-benefit of that extra form in the definition will of course be up to you.
16:03cemerickrhickey: is there any sense in attempting to simplify the aggregate semantics -- e.g. make protocols a specialization of multimethods, where if no dispatch fn is provided, the type of the first arg is used, and dispatched on very efficiently.
16:03rhickeygasc: I would still need to analyze any perf aspects as well
16:05rhickeycemerick: simplify or generalize? i.e. generalize multimethod sets
16:05rhickeyprotocols are pretty simple
16:07cemerickGeneralize, I suppose. My point being, protocols and multimethods are very similar conceptually (at least as far as I know the former so far). If that's true, then avoiding having to make a choice between them for typical cases would be ideal.
16:09Chousukehmh
16:10rhickeycemerick: I don't know. Right now protocols centralize at the protocol, not method level. So multimethod sets would still be different from single multimethods
16:10ChousukeI can't quite figure out what I need to do to make clojure use my reader instead of LispReader ;/
16:10rhickeya set that included true multimethods would be associated with what at implementation time?
16:11rhickeyi.e. a protocol is a relationship between a class and a protocol, what is the correspondence for true multimethods?
16:12cemerickdispatch val and fn
16:12cemerickand protocols are just using the class of the first arg as the dispatch val, so...
16:12rhickeythat's one of the reasons why it is hard to group multimethods, when you implemented the group you've done so for what target? Each method could have a different dispatch val
16:12hiredmanChousuke: replace read with a call to your reader?
16:15rhickeyI guess you could just manually ensure a consistent dispatch value for a set of multimethods
16:16cemerickrhickey: my main concern is just that the introduction of protocols muddies the waters quite a bit vis a vis implementing polymorphism. Having two separate and very different mechanisms does not lead to clarity.
16:16hiredmanChousuke: stub out a clojure.lang.LispReaderII based on your reader, AOT it, and then replace all refs to clojure.lang.LispReader with LispReaderII
16:17Chousukehiredman: that's what I'm trying to do but so far I'm failing with all kinds of weird initializer errors
16:17hiredman:(
16:17hiredmancare to share?
16:17Chousukenot yet :P
16:18hiredmanI have spent some time with LispReader
16:19rhickeycemerick: protocols will handle the vast majority of use cases and multimethods will be for more advanced cases. But making protocols more complex in order to encompass the set notion, which will be used even less frequently there than the multi- aspect, seems somewhat to defeat the purpose of optimizing the common case
16:20rhickeyi.e. if only 5% are multi and only 25% of them are subject to grouping...
16:21rhickeyyou're down to a 1% case
16:21cemerickrhickey: yeah, I was actually suggesting that protocols be folded into multimethods as a fast-path implementation when, i.e. no dispatch fn is provided.
16:21rhickeybut I'm open to concrete examples of multimethod sets that could map to the same dispatch value
16:21rhickeycemerick: the perf is important, but the grouping is almost moreso
16:23rhickeypeople come from OO and say 'where do I put my abstractions?' while Clojure is full of abstractions, all as host interfaces. Those interfaces map perfectly well to protocols. So protocols are an in-language alternative to host interfaces
16:24rhickeyIt's a fair critique of Clojure that some of the things it needed in its implementation are not yet present in it
16:24rhickeybut multimethods can't compete with interfaces for perf
16:24rhickeyprotocols might
16:25hiredmanI wonder if defprotocols might be more clear then defprotocol
16:25rhickeyhiredman: a protocol is a collection of sorts
16:26spuzlpetit: you there?
16:27lpetitspuz: he? how's behind this nickname please ? :)
16:27lpetitstill reading the intensive chats on the irc logs, because there has been a lot of things exchanged today !
16:28hiredmansure, but hten you could call the fn stubs defined in a defprotocols a protocol
16:28spuzlpetit: heh, um behind this nickname is spuz :p
16:28gascwhat if, as cemerick suggests, you allow (defmulti ...) to define, with slightly different syntaxes, both dispatch function-based multimethods (slower) and type-based multimethods (faster). then you allow the grouping of multimethods with defprotocol or whatever. if all multimethods in a group are type-based then the group is optimized into a high-perf protocol, otherwise it's just a nice...
16:28gasc...grouping construct for multis. could be that this doesn't work for reasons i'm not appreciating.
16:28spuzlpetit: I was bugging you about debugging a while ago
16:28hiredmangasc: what is a multimethod group?
16:29lpetitspuz: oh I remember now. Debugging has been bogued by too much work at work and too less work at home :-p
16:29spuzlpetit: heh, I know exactly what you mean ;)
16:30spuzthe only solution is to convince work to move from java to Clojure :D
16:31rhickeygasc: I have a hard time seeing how multimethods + a grouping construct is going to be seen as anything other than a real pain for those coming from interfaces. And there are many subtle niceties to protocols, method maps, code reuse etc
16:32spuzanyway I was going to ask, do you know if it's possible to use the latest master versions of clojure and clojure-contrib with CCW? I've tried putting jars built from the latest check outs of those code branches but the plugin doesn't like them.
16:32gaschiredman: well, maybe i have a bunch of multimethods that dispatch on :type metadata (or some other dynamic tag). since we're concerned with performance we don't want protocols to be able to dispatch on dynamic stuff like this, but maybe i don't care about perf for my application and want the equivalent of a protocol for multimethods.
16:32rhickeyOf course I've just done a week of implementation design around method sets etc, so I'd have to reconsider grouping and where caches lived. But again, is this for a minority case? Right now protocols will be really simple for many
16:33spuzI get the error "java.lang.NoClassDefFoundError: clojure/contrib/repl_ln" I think because clojure-contrib.jar does not actually include an AOT compiled version of repl_ln...
16:34spuzlpetit: is there a special way you have to compile these jars in order for CCW to work with them?
16:34rhickey(defprotocol AProtocol existing-multimethod-a existing-multimethod-b)?
16:34rhickey(implement AProtocol adispatchvalue amethodmap)?
16:35rhickeyplus defmultis for the methods?
16:35lpetitspuz: which jars are you talking about ?
16:35spuzlpetit: the latest versions of clojure.jar and clojure-contrib.jar as build by doing a check out of the git master repos
16:36lpetitspuz: I just take care of making clojure-contrib use the AOT compiled version of clojure, so that clojure-contrib itself is AOT compiled (so I carefully set the ${clojure.jar} (or something like that) in the build.xml of clojure-contrib
16:37gascrhickey: are you saying that those usages are already possible under your current idea? or are you asking if that's what i'm thinking about?
16:37spuzlpetit: ok, perhaps the way the build works has been changed. I don't think the necessary .clj files are all AOT compiled
16:38lpetitspuz: if you want Eclipse to play well with debug on clojure.jar, you'll also have to place both src/clj/**/*.clj files and src/jvm/**/*.java files in a same clojure-src.zip and reference it as the source archive for clojure.jar
16:38rhickeygasc: I'm just stating it out loud so it is easier to see what the issues might be. Another set of issues is the relationship between multimethods and hierarchies. Right now protocols don't interact with hierarchies
16:38lpetitspuz: currently the clojure-src.jar file bundled by build.xml of clojure project doesn't do that, it just bundles the .java stuff, and does not include the .clj stuff
16:38spuzlpetit: I can try to tackle debugging later, first I need to actually run the code :0
16:39lpetitso just using the raw clojure.jar and clojure-contrib.jar should work, as far as I know
16:40lpetitspuz: can you pastebin/lisppaste your .project and .classpath files contents ?
16:40spuzlpetit: ah, I think I can see the problem. See the changes Mr Hollaway has done to the contrib build.xml: http://github.com/richhickey/clojure-contrib/commit/04a22729691863a5b7e7b1b3c6c1157a02aff3b2
16:41chouseroh, protocols use only host class inheritence? I assumed they used the heirarchy.
16:43lpetitspuz: no time to test it, but can help think about it. What problem do you see ?
16:44cemerickchouser: I presume type and isa? are what limit multimethod perf.
16:44hiredman:(
16:45spuzWhen trying to run a program with the plugin: "java.lang.NoClassDefFoundError: clojure/contrib/repl_ln" I guess because the repl_ln.class file is never generated
16:46hiredmanI know I said ok ealier, but hierarchies seem like another clojure name vs. java name issue
16:46ngocHi, if you know both Clojure and Scala, how do you "feel" about Scala? I have study a little Clojure and Scala, and I don't feel any happy with Scala. With Scala, I feel I'm talking some kind o primitive language. How about you?
16:46hiredman~tell me about scala
16:46clojurebot{((x: Any, y: Any) => (f: Function2[Any, Any, Any]) => f(x, y))(1, 2)((x: Any, y: Any) => x)}
16:46spuzlpetit: by the way, where are the logs for this channel?
16:46The-Kennyngoc: I listened to a small talk about scala at Froscon... the syntax just doesn't fit for a functional language.
16:47The-Kenny(My opinion)
16:47eevarstatic typing is kindof neat. i'm shooting for haskell rather than scala, tho
16:47eevars/is/looks
16:47lpetitspuz : n01se.net -> last item of the page
16:48hiredman~logs
16:48clojurebotlogs is http://clojure-log.n01se.net/
16:48spuzlpetit: thanks
16:49gascrhickey: got it. i'm sketching it out now and, yes, i'm confusing myself even trying to understand what it would mean in concrete terms for a class/type to implement a protocol based on multimethods.
16:50Chousukehm
16:50hiredman~scala {((x: Any, y: Any) => (f: Function2[Any, Any, Any]) => f(x, y))(1, 2)((x: Any, y: Any) => x)}
16:50clojurebotAny = 1
16:53ngocScala makes me feel I'm a slave to machine. How do you feel?
16:57chousershould into-array support chunked seqs?
17:02ChousukeI can't figure this out :/
17:02Chousukecurrently it explodes with "Var clojure.core/load is unbound"
17:03chousertrying to use clojure before there's enough clojure there to use?
17:03hiredmanclojure/src/clj/clojure/core.clj:3910:(def load)
17:03Chousukewhich presumably happens when I first try to use the reader class and it tries to init itself
17:04hiredmanoh
17:04hiredman:(
17:04Chousukechouser: this is not in core.clj so I *should* have all of core available. except I don't because apparently it hasn't been loaded
17:05hiredmanhmmmm
17:06ChousukeI managed to compile everything fine using a bootstrap jar but then recompilation attempts using the result from the bootstrap fails
17:07Chousukeattempt* :P
17:09spuzlpetit: Ah I've found I can disable the "Run in Repl" option and it works fine. Obviously this just requires clojure.main to run, not clojure.contrib.repl_ln.
17:10lpetitspuz: ok
17:13Chousukehm.
17:13lpetitchouser: if I understand well, protocols would only be explicitly defined per 'implementation call type, no use of any type of hierarchy/host inheritence at all ?
17:15serp_in the typical program written in clojure, is it possible to at any time pause the execution and be given a repl to inspect the program's state?
17:16chousersurely not. if I have a bundle of fns that will all work for anything that implements APersistentMap, I don't need do multiple 'implements' for all the concrete sub-types.
17:16chouserlpetit: I hope, anyway.
17:16lpetitchouser: you're certainly right, it's getting late here and I'm getting confused :)
17:17chouser"call the supplied methods when an AClass is provided as the first argument" suggests anything that "isa?" AClass, which is why I assumed heirarchies were involved.
17:17chouserlpetit: :-) np -- clearly there's something here I don't understand yet as well.
17:18rhickeychouser: only class hierarchies, i.e. instance? not isa?
17:18ChousukeI think Clojure would need quite a lot of restructuring to make it possible to use my reader :(
17:18chouserserp_: I've not seen that, no. Generally Java debuggers are used, in which case the whole JVM is stopped and examined via interop.
17:18ChousukeI really don't want to figure out how loading the stuff works...
17:18chouserrhickey: ah, of course 'instance?' not 'isa?'. Clearly I'm also confused. :-)
17:19rhickeybut there are significant complexities to multiple inheritance of implementation. I would completely avoid it if I could, but need to reach interfaces, which are multiply inheritable
17:19serp_chouser: ahh.. too bad
17:19rhickeyI thought about just attaching to the abstract bases of the collections (pretty universally dervied from) but Iterable is the kicker
17:19spuzserp_: as far as I understand there is a single thread for the repl, if you want to use the repl at the same time as your code is executing then you need to run your code in a separate thread. See the 'future' macro
17:19hiredmanChousuke: you might see if you can find all the places lispreader is used and abstract it out so you can specify a different reader, that implements IReadLisp
17:20somniumhiredman: how many languages does clojurebot speak?
17:20serp_spuz: I'd be happy to pause the program while playing in the repl
17:20hiredmansomnium: speak?
17:20hiredmanlike evaluate?
17:21rhickeychouser: The possibility exists to reach the hierarchy system, which also opens up multiple implementation, but also has cache invalidation issues and other perf costs. Each layer adds more complexity
17:21chouserserp_: I have hope that someday somebody will make a clojure-aware JVM debugger, but I'm not aware of such a beast yet, or exactly how useful it would be.
17:21spuzserp_: well in theory you can use a debugger to pause the thread you're interested in, and continue to run the repl in another thread. You don't have to stop the entire JVM when debugging
17:21Chousukehiredman: how would that help, though?
17:22hiredmanit is a stepping stone
17:22Chousukehiredman: how would it solve the loading problem?
17:22serp_spuz: mhm I see
17:22ChousukeI mean, there are only ~three places where Clojure calls LispReader
17:23hiredmanyou let clojure use LispReader until it gets to a certain point, then flip over
17:23lpetitrhickey: you asked earlier in the day for concrete examples for multiple arg dispatch for protocols
17:23Chousukeyeah but... the idea is to remove lispreader
17:23Chousukeat some point.
17:24Chousukethe problem is that when I load Compiler, it loads my ClojureReader (which has been properly compiled during the bootstrap process), which calls its load code... that explodes, because clojure.core is apparently not available :(
17:24hiredmanwell you can't completely remove it yet
17:24rhickeylpetit: yes, have you got some?
17:25lpetitrhickey: maybe close to :)
17:25Chousukeso I wonder, what do I need to do to make the ClojureReader load code use the clojure.core compiled during the bootstrap? :/
17:25somniumhiredman: yeah, evaluate
17:27hiredmansomnium: just clojure really, it sends scala off to the simplyscala online repl thing
17:28ChousukeI'm really out of ideas with this. I suspect I'd have to mess with Compiler.java a bit more to get further but I don't really want to touch that code.
17:29lpetitrhickey: to speak with the design pattern "GoF" book terminology, I guess the Bridge DP, the Mediator DP are close to be examples of sets of methods that must be defined for couples (or sets) of types as a whole, and not just for a single type.
17:30lpetitrhickey: to speak about what I know more, the Visitor Design Pattern, which requires just double dispatch on types (not open generalized multiple dispatch), could benefit from prototypes by grouping methods, too.
17:31lpetitrhickey: so I'm not at all advocating in favor of prototypes as super-sets of multimethods, since you demonstrated that in the general case the semantics are hard (if at all) to define :), but allowing protocols to be defined on the types of more than the first argument may help evolve a design without having to rewrite everything too early with multimethods
17:32rhickeysketch of multprotocols added: http://www.assembla.com/wiki/show/clojure/Protocols
17:32rhickeymultiprotocols
17:33Chousuke~def require
17:34gasccool.
17:35rhickeythe real weakness is the inability to confirm the dispatch fns all return the same dispatch value
17:35rhickeybut I'd rather move this way (from protocols towards multimethod capability) than to try to superimpose grouping over current multimethods
17:36gascindeed
17:36hiredmanI'd prefer for the distrinction between the two to remain clear
17:36hiredmanso it is easier to decide when to use each
17:36rhickeyhiredman: oh great :) now convince cemerick
17:37gaschaha.
17:37hiredman:(
17:37rhickeythe thing is, while these now look similar, under the hood they are very different
17:37hiredmanexactly
17:38rhickeyalthough still now have methodmaps, a useful capability vs multimethods
17:39lpetitthe question remains : when a design evolves, is there a way were at a given step it may "cry" for evolving from protocols to multimethods, or multimethods to protocol, and how easy the move can be made
17:39lpetitI don't have the answer :)
17:39rhickeyit is a weakness of current defmethod that you can't just say (defmethod amulti aval some-existing-fn)
17:40rhickeylpetit: I wonder what form that evolution might take? Maybe from class-dispatch to class-or-value, but I can't see from single to multi
17:41rhickeydispatch fns + dispatch vals, while powerful, are definitely glaze-over material for many, while single dispatch on type is so easy to explain and by far most common
17:42rhickeybut they could have the same shape and different names, although defmultiprotocol is a mouthful
17:42lpetitrhickey: not sure about that, but from single to multi: you have a first implementation where you focused on a protocol for a single type, and you don't care about providing variants for other arguments. In the long run you want to evolve your library to be smarter on the 2d argument ...
17:43rhickeyI understand the binary dispatch case well, but that was something I was considering giving special handling as well. Moving to arbitrary dispatch fn is the big (enabling and complicating) leap
17:44lpetitI just advocate for *considering* keeping the protocols as you defined them, with a clear meaning for the dispatch method being predefined (currently instance? is considered), but opening it to work on more than the first arg. Nothing more.
17:44lpetitSo we almost agree.
17:45rhickeylpetit: it is not just defaulted, it is hardwired and potentially removed internally
17:45rhickeyin other words, the protocols don't have a proper dispatch fn step
17:45rhickeyat present
17:46rhickeyunlikely to ever compete with interfaces if they did
17:46lpetitrhickey: Yes, when I wrote (currently), I was referring the the fact that you still are considering (or maybe not anymore ?) whether you add inheritence to types or hierarchies .. but I understand that the final version will hardwire the dispatch fn for protocols
17:48rhickeyright, a separate issue is how far to reach for 'type' is it just (class x), or possibly a broader (type x) thing, where type becomes a first-class slot of Clojure data structures (or at least maps), like meta
17:50lpetit(implement AProtocol AClassForA AClassForB
17:50lpetit {:foo an-existing-fn
17:50lpetit :bar (fn [a b] ...)
17:50lpetit :baz (fn ([a b]...) ([a b & c] ...)...)})
17:51gascthat seems like a toughy. on one hand it seems like capitulation to the world of hard-typing everything. on the other hand keeping it as (class x) intertwines it very tightly with java. i'll be interested to see where the decision goes.
17:51lpetitNot sure if the defprotocol itself should declare how many args the dispatch on 'type' would have to consider
17:53lpetit(defprotocol #^{:dispatch-on-first 2} AProtocol
17:53lpetit "A doc string for AProtocol abstraction"
17:53lpetit (bar [a b] "bar docs")
17:53lpetit (baz ([a b] [a b & c]) "baz docs"))
17:53lpetit?
17:55lpetitrhickey: you then will have to reconcile deftype and hierarchies in some way ? People will suppose that all the "accessor" keys of a deftyped instance will work on a "subtype" (as defined per the existing hierarchy stuff) :-$
17:56lpetitrhickey: that is they will consider that the set of "accessor" keys for a deftype define an implicit protocol for the type, hehe
18:01rhickeyI considered many things, including implementing protocols on protocols. I remain wary of implementation inheritance, and especially multiple inheritance of implementation. That is why protocols are relatively hierarchy free. The way the methodmaps work gives you an easy way to reuse implementations without derivation or composition/wrapping
18:02lpetitrhickey: concerning 'how far to reach for 'type'': what types would (with-type {:a :foo} ::some-type}) match ? ::some-type ? IPersistentMap as well ? Map ? ArrayPersistentMap ?
18:02rhickeyeven with 'prefer' at the protocol level, it can get unwieldy quickly
18:02lpetitrhickey: indeed
18:03rhickeylpetit: if type slot is set, then it and its supers only
18:03rhickeyif not set, then class and its supers
18:04rhickeybut even looking at type slot could blow perf vs interfaces
18:04lpetitrhickey: but still it seems a bit unfair to only provide the 'instance? facility for host defined classes/interfaces, and not plain clojure stuff ... argh
18:05rhickeylpetit: deftype will be plain clojure stuff
18:05lpetitrhickey: Oh yes I missed something important, protocol is the "interface", no implementation inheritence (as in java), you're right
18:07rhickeyreally, if you had never seen Clojure multimethods, and came to Clojure finding deftype and protocols, you be substantially better off than you had been in Java IMO, for no more complexity
18:09rhickeybut I will think more about multiprotocols and dispatching. I have another set of ideas based upon per-arg dispatch, where single dispatch, but on say, broader type, could still be much more efficient than true pass-all-args-to-dispatch-fn, which is really quite opaque to the implementation
18:10rhickeybut current protocols are in a great place power/complexity-wise
18:11lpetitrhickey: just to speak about something totally different, have you noticed the questions of mwoelker on the ml concerning "side-effect free compilation" ? He did not have (so far) any concrete arguments pros or cons his idea. And since he is willing to help (ah, youth ! :-) ), and is very sympathic (already provided code to clojure-dev), I wondered he you would please either encourage or...
18:11lpetit...discourage him in this way by adding solid pros/cons arguments to the table, so that he does not spend too much time in a dead-end alley :-)
18:12rhickeylpetit: yes, I saw that and need to respond. Unfortunately the answer is, this will have to wait for cinc! Right now compilation is bound to reflection and that will have to change
18:12rhickeyIt's part of a set of things I want to do to improve modularity and namespace issues
18:14lpetitrhickey: so maybe he is wasting his time right now. So bad, because he's really willing to help and has great understanding. And his questions are sometimes challenging to the clojure community, but always well asked, so he is an interesting specimen of people which may help improve to advocate clojure in some circles, if his questions are given argumented answers :)
18:19lpetitmaybe specimen was not the more appropriate term, no offense mwoelker if you're reading. I hope you get the idea :)
18:28lpetitrhickey: to rephrase as an hypothetical java user what you said above, and to play a little bit the devil's advocate: "really, if I had never seen Clojure multimethods, and came to Clojure finding deftype and protocols, I would have first though "well, they redefined java interfaces as an internal clojure construct, minus the possibility to extend interfaces. Now they just have to rediscover...
18:28lpetit...that they can make types derive from types and they will have the full power of java regarding code reuse possibilities". Ouch!
18:28lpetitI mean, they will come from an OO background, and it will not be evident *at all* for them that it is better to do it this way. *And* they will not see any immediate benefit from classic java interfaces (the power of being able to extend existing types with protocols will not occur to them immediately, after all well designed java code is coded towards interfaces, so it is in some way...
18:28lpetit...already possible to "extend" an existing java type with a new interface by making a decorator for it, as long as the rest of the code is coded towards the interface)
18:30lpetitSo this new functionality (deftype / defprotocol) may be a double-edged sword. From the outside, it may well resemble a : "look, they are rediscovering the basic java concepts in clojure. Soon they will reinvent java altogether". Sort of.
18:36lpetitok I will not spam the chat anymore, I'll go to bed, bye all :)
18:36gasctake care lpetit
18:42serp_,(car '())
18:42clojurebotjava.lang.Exception: Unable to resolve symbol: car in this context
18:42serp_,(first '())
18:42clojurebotnil
18:43serp_,(first (first '()))
18:43clojurebotnil
18:47serp_,(rest '())
18:47clojurebot()
18:55serp_how come first and rest on nil are valid operations?
18:57The-Kennyserp_: http://clojure.org/lisps "() is not the same as nil"
18:57serp_,(first nil)
18:57clojurebotnil
18:58serp_why can I do that then?
18:59The-Kennyserp_: I don't know. It's mentioned in the doc for the functions. I'm not a designer of the language.. sorry.
18:59somniumserp_: for seqs to work I think its necessary (loop ... (if (nil? (first res)) res recur...)
18:59somniumto work as they do, rather
19:00somnium,(rest nil)
19:00clojurebot()
19:00somniumthat does look a bit odd ;)
19:01technomancy,(next nil)
19:01clojurebotnil
19:01Chousukeserp_: I guess the idea is that the first of nothing is nothing :)
19:01serp_I think the first of nothing should throw an error
19:01serp_and the rest of nothing as well
19:02Chousukebut that would complicate things.
19:02danleivery much
19:02Chousukewhy throw errors when you can make it valid behaviour?
19:02serp_because the semantics are broken
19:02Chousukenot really.
19:03Chousukenil is nothing. most operations on nothing result in nothing.
19:03serp_I don't see why one would say "nil is not a list" and then keep treating it like that
19:03Chousukeit's not a list. it's nothing. :)
19:03Chousuke(rest nil) results in () because rest always returns a lazy sequence and a lazy sequence made of nothing is of course empty.
19:04danleinil is a spelling variation of nihil, which is latin for "nothing" btw.
19:04serp_,(nth 3 nil)
19:04clojurebotjava.lang.NullPointerException
19:05Chousukeit's got a lot to do with how seqs work
19:05serp_so why does that not work? surely one should be able to implement nth from a sequence of rest and first?
19:05somniumfirst or next on nil has to be falsey
19:05Chousuke,(seq '())
19:05clojurebotnil
19:05danleibtw. (rest ()) used to be nil, too, so did (filter even? [1 3 5])
19:06danleiand I, for one, liked that
19:06Chousukeyeah, but it made fully lazy sequences impossible.
19:06Chousukeso nil punning had to go :(
19:06danleithen next became (seq (rest ...)), after the change
19:06danleiyes, I know
19:06danleiIt's bearable to wrap in seq
19:07danleinot my first choice, but ok
19:11danleianyway, throwing an error would likely be the least thing I want it to do
19:32chouserI can understand being in favor of more compile-time errors, but I like to have as few runtime error conditions as possible.
19:36somniumhow do you type-hint (into-array Klass (set-of-klass-instances)) ?
19:37somnium,(class (into-array Integer [1 2 3]))
19:37clojurebot[Ljava.lang.Integer;
19:38AWizzArdyou could type-hint before doing a method call instead of hinting the array itself
19:38somniumAWizzArd: how do you mean?
19:38AWizzArd(.klassMethod #^Klass (nth 3 my-klaas-array))
19:39AWizzArdwhere that call sits in a tight loop
19:39somniumright now its (.method #^Hint obj (?hint?) (into-array ...))
19:40somniumand still getting reflection warning
19:40somniumthe whole array is an argument
19:41defnuser> (index (rand-int (count vowels)) vowels)
19:41defnHow do I do something like that?
19:41somniumbah, its not important, one reflection call doesn't mean much on array 10,000 documents, just wondering how to do it
19:41defnI'm trying to get it to take the count of the (set "aeiou"), and select a random entry from it
19:41serp_,(nth "abc" 1)
19:41clojurebot\b
19:42defnthanks serp_
19:42serp_np :>
19:44defnhmm, that doesnt work on something like: (def vowels (set "aeiou"))
19:44serp_a set is not ordererd
19:44defnoh duh, hence no indexes
19:45defnis there a way to take a random element of a set
19:46somniumdefn: sure, call seq on it
19:46defnthanks for your help :)
19:54defnI'm trying to make a word generator thingy
19:54defnhmmm - *thinks*
20:01defnhttp://pastie.org/661381
20:01defnCould someone take a look and try and figure out what I'm doing wrong :)
20:01defnI'm trying to make a function which takes a number as an arg which says how many words to generate
20:02defnand then it concats random letters we get from the two sets into 7 letter words
20:02rhickeyarbscht and hiredman added to contributors - welcome!
20:03arbschtrhickey: thanks!
20:04arbschtrhickey: a typo: Arbishek -> Abhishek :)
20:04hiredmanclojurebot: contrib
20:04clojurebotcontrib is http://github.com/richhickey/clojure-contrib/tree/master
20:05durka42defn: dotimes doesn't return anything
20:05rhickeyarbscht: sorry about that - fixed!
20:05hiredmanclojurebot: I'd rather you just gave me the git url
20:05clojurebotsomething
20:06durka42clojurebot: good answer
20:06clojurebotTitim gan éirí ort.
20:20hiredmanhttp://www.thelastcitadel.com/images/contrib.svg
20:20hiredmanwhat a beast
20:21hiredmancrap
20:24hiredmanI sat down in the library and there is a book right in front of my on the shelf "the power of protocols"
20:36Chousukedefn: generating words is a job made for lazy seqs http://gist.github.com/213879
20:42somniumwhat is the "big picture" objective of deftype and defprotocol? some sort of non-imperative duck-type(ish) inheritance system?
20:43somniumor more like missing-parts for cinc?
20:44somniumbeen browsing the assembla wiki but I just can't see the forest
20:45chousersomnium: the motivation in cinc-related I think. That is, there are parts of clojure that can only be efficiently written in .java
20:52somniumchouser: thanks, it makes a bit more sense now.
21:48sebaHi, I have a question abount clojure.contrib.graph. Is this the right place? anyone can help?
21:49chouseryou can ask
21:50chouserhere or on the google group are your best bets.
21:51sebaaccording to clojure.contrib.graph directed-graph is the basic representation, and is a NamedMap. :nodes is supposed to return a collection of the nodes
21:52sebawhat if calculating the nodes is a non-trivial task ..... should I put that in a lazy collection? no other way to easily have a function to return the nodes?
21:52sebaWhat am I missing here?
21:53sebafor instance, if I keep the nodes in a map .... I would like to do (keys my_map) to get the nodes
21:53sebahow do I do that, without breaking (:nodes graph) interface ?
21:59hiredmanthere is an implementation of a lazy map somewhere, but {} is not lazy
22:00sebadoesn't graph inferface place a hard constraint on implementations?
22:01hiredmanI haven't looked at contrib.graph
22:02sebait's just algorithms plus a namedmap with members :nodes (a collection) and :neighbors (a function from node to neighbors)
22:03hiredmanand what's the problem?
22:03sebaif the algorithms used (graph :nodes) ... a graph could be a function, but they do (:nodes graph)
22:04hiredmanhmmm
22:04sebaso I guess a graph must be a map and only a map ....
22:05hiredmanyou could proxy whatever the bare interface keywords need for lookups
22:06sebahow would you do that ? I'm new to clojure and don't see how
22:07hiredman,(import 'clojure.lang.ILookup)
22:07clojurebotclojure.lang.ILookup
22:08hiredman,(proxy [ILookup] (valAt [here] (name here)))
22:08clojurebotjava.lang.IllegalStateException: Var null/null is unbound.
22:08hiredman,(proxy [ILookup] [] (valAt [here] (name here)))
22:08clojurebotjava.lang.IllegalStateException: Var null/null is unbound.
22:08hiredmanbah
22:08hiredman,(:foo (proxy [ILookup] [] (valAt [here] (name here))))
22:08clojurebotjava.lang.IllegalStateException: Var null/null is unbound.
22:09hiredmanhuh
22:09hiredmanI wonder what it's problem is
22:11hiredman,(:foo (proxy [ILookup] [] (valAt ([k] k) ([k v] k))))
22:11clojurebotjava.lang.IllegalStateException: Var null/null is unbound.
22:11hiredman$%@#$%
22:11sebajeje
22:11hiredmanit works here
22:11sebabut I see ... I thinks thats exactly what I was looking for
22:12sebait solves my problem ....
22:12hiredmanalso works in clojurebot's repl, just not from irc
22:12hiredmanclojure++
22:12hiredman~problem
22:12clojurebotPeople have a problem and think "Hey! I'll use a regular expression!". Now they have two problems....
22:12hiredman~problem
22:12clojurebotPeople have a problem and think "Hey! I'll use a regular expression!". Now they have two problems....
22:12hiredmanforget it
22:12sebajejeje
22:13sebagreat, thanks ... will do that
22:13hiredmansomewhere in there is something about layers of indirection
22:13sebagood oportunity to learn proxy
22:13hiredmanproxy is pretty useful
22:14sebawhere can you learn thinks like "keywords use ILookup". I guess only the code right ?
22:19hiredmanyeah
22:19hiredmanwell, that is how I just learned it
22:20hiredmanI looked at Keyword.java, then RT.java
22:22hiredmanactually, there is a nice picture somewhere
22:23sebaI see
22:23hiredmanhttp://github.com/Chouser/clojure-classes/blob/032beae497fddc426db05c7c6367c625a2dad04f/graph-w-legend.png
22:23hiredmanout of date, but I guess you could run the code and get an updated version
22:25hiredmanILookup isn't even on there
22:26sebaIn fact, I was planning to use this to get pictures similar to that one
22:26hiredmanhah
22:26sebaI see a lot of people is doing this ... even you with your clojure-dependency-grapher
22:26hiredman:)
22:27sebaI thought it was a good way to learn clojure ... and it is in fact.... of course I'm over engeniering things a bit, to know more libraries and stuff
22:28sebagreat, thanks for your help
22:28hiredmanI wasn't aware of contrib.graph
22:28hiredmanno problem
22:29sebaI don't think graph has a good interface yet ... what I'll have to do seems a little smelly ....
22:29sebabut .. it will be good to use the algorithms to get cycle detection for instance
22:30hiredmanI just sort of dump all that stuff on graphviz
22:30sebaI do that too ... but I create an on memory graph first, to have the oportunity to apply the algorithms
22:31sebaof course, I'm seeing your code right now and is waaaaay cleaner than mine ....
22:31hiredman:P
22:31sebabut ... I guess I'll improve with a little practice
22:32sebaget to know the API takes some time
22:32hiredmanI would not recommend my code as a style guide
22:35eyerisI've installed the latest vimclojure. I've started ng-server. ng (the client) is in my path. Running :scriptnames in vim shows the vimclojure scripts loaded. However vimclojure still fails to bind any key sequences.
22:36eyeris:messages doesn't show any errors.
22:41chouserI'm also fighting vimclojure
22:43hiredman:|
22:43hiredmanvimclojure's syntax highlighting and static completion + slime.vim
22:58chouserdoes slime.vim give you completion with arglists and such?
22:59hiredmannope
23:00hiredmanjust sending code the repl
23:00chouserok
23:01eyerisWhat is this b:vimclojure_namespace?
23:02eyerisAll of the vimclojure binds are wrapped in a 'if exists("b:vimclojure_namespace")'
23:02eyerisBut I have no idea how to determine whether that is evaluating to true or false
23:03eyerisand no idea how to make that namespace exist
23:03hiredmanb is a buffer
23:04eyerisSo that is a buffer-local variable?
23:06hiredman.vim/autoload/vimclojure.vim:645:let b:vimclojure_namespace =
23:06hiredmanthat is where it is set
23:06eyerisI see that now.
23:14chouservimclojure is working!
23:17eyerisCongratulations
23:18chouserheh
23:18hiredmanyou say that now
23:18chouserexcept I thought it would omnicomplete arglists, and I don't see how to trigger it.
23:22steigernight everyone
23:29eyeriswtf
23:30eyerisOn ~/.vim/autoload/vimclojure.vim:652, b:vimclojure_namespace doesn't exist
23:30eyerisyet it was just set on :646
23:30eyerisor on :642
23:35steigeryou're the first lispers ever to use vim to develop in lisp, no?
23:39eyerissteiger: there's a reason that lisp hasn't become a real player in the industry. I'm not saying that it's because emacs sucks, but emacs sucks.
23:39eyeris:)
23:43danlarkinthat is as misinformed as it is rude to us emacs users!
23:43danlarkin:)
23:44steigervery true, danlarkin
23:44steigeri don't mean to disrespect vim users, but, well, emacs *is* the standard way of editing lisp code ;)
23:44eyeris"we emacs users", I think
23:45danlarkinnobody likes a pedant :-p
23:47technomancyso there are some particularly onerous JVM libs that require the presence of a property file on the classpath before they can be loaded
23:47technomancythis runs counter to the notion of runtime configuration
23:47technomancysince you can't plop a properties file in a directory and add it to the classpath at runtime
23:47hiredmanexcept for what is left of Chousuke's work, clojurebot is written in vim
23:48technomancyoddly enough, you *can* do this in JRuby; adding a directory to the load path is equivalent to adding it to the classpath, and loaded libraries respect it.
23:48technomancyso what is Clojure missing that makes JRuby work?
23:48technomancyI suspect JRuby uses a more heavily-modified classloader?
23:49hiredmanI'm not sure, it might be an easy vs. correct split
23:49hiredman(rhickey of course doing what is correct)
23:49hiredmanyou could as headius about it next time he pops in
23:49technomancyI just might.
23:50technomancyI suspect you could create a classloader that does the right thing and just use it to load a single class and its dependencies ... it wouldn't have to be used by clojure for loading all subsequent classes.
23:51hiredmanI think there are visibility issues for code that interacts with that class
23:52technomancyprobably JRuby can get away with it because it's much more insulated from raw java
23:53hiredmanadd-classpath actually works a significant amount of the time
23:54hiredmanbut, uh, it breaks sometimes, and I don't know why, so I don't use it
23:56technomancymostly I see breakage when interacting with JVM libs; it seems to work well for pure-clj stuff
23:57hiredmanI've never used it for clojure stuff