2010-04-27
| 00:02 | defn | write code first, optimize later |
| 00:07 | pdk | no defn we gotta keep up the proud legacy of C |
| 00:08 | pdk | planning in advance whether every integer variable will be int or short |
| 00:10 | slyphon | i really like the name 'throwf' it kind of sounds like an exception "barfing" |
| 00:33 | slyphon | man, the guys that write this Atomikos JTA lib are dicks |
| 00:33 | slyphon | from the javadocs: |
| 00:33 | slyphon | "All non-transient errors (i.e., those that happen each time a message is delivered) indicate problems at the application level and should be dealt with by writing better application code." |
| 00:33 | slyphon | gee |
| 00:33 | slyphon | thanks |
| 00:41 | remleduff_ | technomancy: Best commit ever ;) |
| 01:40 | slyphon | ARGH |
| 02:53 | vegai | are there any active projects for bringing clojure to The Shootout? |
| 03:39 | LauJensen | vegai: Not to my knowledge |
| 03:42 | hircus | when using Leiningen, is there a way to specify a version number once and avoid repeating oneself? |
| 03:44 | ordnungswidrig | hircus: repeat where? |
| 03:44 | vegai | I guess you mean that you wanna get the version number of your app in project.clj to your app code |
| 03:45 | hircus | ordnungswidrig, vegai : I'm using several Incanter modules and I don't want to keep saying "1.2.3-SNAPSHOT" |
| 03:46 | vegai | ohhh |
| 03:46 | irfn | hircus project.clj is plain clojure code |
| 03:46 | vegai | cannot you just (def ver "1.2.3-SHAPSHOT") |
| 03:46 | irfn | so you should be able to def it |
| 03:46 | hircus | I tried (def *ver* "1.2.3-SNAPSHOT") and then :dependencies [[incanter/incanter-core *ver*] ...] but it fails, saying symbols can't be cast into strings |
| 03:46 | irfn | yeah |
| 03:47 | hircus | haven't used Clojure macros for a while, an dI forget my macro expansions |
| 03:51 | hircus | vegai: so after defining ver, how do I use it within defproject, given the problem I stated? |
| 03:52 | Borkdude | technomancy|away: I got leiningen working on XP now, just to let you know |
| 03:53 | Borkdude | Clojure is a seqsy language |
| 03:54 | vegai | hircus: odd |
| 03:55 | hircus | vegai: yeah. looking at the Leiningen source right now to see what's going on |
| 03:56 | Raynes | Borkdude: That was clever. I think sexpy is more clever though, hence the name of my bot. |
| 04:04 | hircus | vegai: so I guess the problem is that the arguments have to be quoted, because org.clojure/clojure etc. do not refer to anything in the namespace, but if they are quoted then the version numbers cannot be macro-expanded |
| 04:04 | hircus | vegai: the other solution, the Polyglot Maven syntax, requires you to quote the namespaces instead. gah. |
| 05:24 | stilkov | what would be the idiomatic way to do map over something that can either be a list of strings or a single string? |
| 05:24 | stilkov | the 'if' I currently use somehow feels ugly |
| 05:26 | Borkdude | If you map over a single string, it maps the function over the characters of that string |
| 05:27 | Chousuke | stilkov: I don't think there's an idiomatic way to do that :P |
| 05:27 | Chousuke | stilkov: just use an if |
| 05:28 | stilkov | Borkdude: exactly my problem |
| 05:28 | Chousuke | but in general, why is your function accepting both a string and a list of strings? |
| 05:28 | stilkov | Chousuke: destructured command line args - can either be a single file or a list of files |
| 05:29 | Chousuke | usually in those cases you want a (fn foo [& strings] ...) so that you can call either (foo "string") or (apply foo list-of-strings) |
| 05:30 | Chousuke | try and see if you can change your code so that it always gives you a list of strings, even if there is only one |
| 05:30 | Chousuke | I think that would be the most idiomatic approach |
| 05:31 | Chousuke | in general if you have a function that works with sequences of something, special casing it for one of something is probably unidiomatic. |
| 05:32 | stilkov | Fair enough. Is there an idiomatic way to turn a single element into a list? Or can the let destructuring do this on its own? |
| 05:32 | Licenser | I'd go with (fn foo [string & strings] ...) so it forces at least one argument |
| 05:34 | stilkov | Licenser: and what would go in the body then? (map #() (conj string strings)) ? |
| 05:34 | Licenser | well that depends on what you want to do with it :P |
| 05:34 | Licenser | but you've a point there |
| 05:35 | Chousuke | stilkov: (list element) :P |
| 05:35 | stilkov | Chousuke: that will turn a list into a list with an element that's a list |
| 05:35 | Chousuke | but I could help you better if I knew how you're doing your destructuring |
| 05:36 | Chousuke | stilkov: sure. but then why is your data at one time a list and other times a single element? Is there no way to fix that? |
| 05:36 | stilkov | (defn -main [& args] |
| 05:36 | stilkov | (let [[pattern & files] args] |
| 05:36 | stilkov | (great-function pattern files))) |
| 05:37 | Licenser | why not go with defn -main [pattern & files] ? |
| 05:37 | Chousuke | and what part of that will sometimes be a list and sometimes a single string? |
| 05:38 | stilkov | Chousuke: the "files" part, depending on how many arguments are passed on the cmd line |
| 05:38 | Chousuke | no, it'll always be a list. |
| 05:38 | Chousuke | or nil |
| 05:38 | Chousuke | but still, always a list |
| 05:38 | stilkov | hm |
| 05:38 | stilkov | checking ... |
| 05:39 | Chousuke | right, you could just (apply great-function args) :P |
| 05:39 | stilkov | Licenser: you're right, left-over from some earlier iteration |
| 05:39 | Licenser | *nods* |
| 05:40 | stilkov | Licenser: Ah, I remember: I had a check as to the number of arguments; but I can obviously do this with a nil check as well |
| 05:40 | Chousuke | ,(count nil) |
| 05:40 | clojurebot | 0 |
| 05:40 | stilkov | Licenser, Chousuke: thanks for the help so far, I guess I'll play some more |
| 05:40 | Licenser | it gives the advantage (in my eyes) that the signature of -main already tells you what it wants (a pattern and files) and not just that it wasnts something :) |
| 05:41 | Licenser | stilkov: have fun and you're welcome |
| 06:21 | kzar | Supposing you have a map and either another map or a list of maps and in either situation you need to return a list of maps how would you do it? |
| 06:23 | rhudson | Depends on how you get "either another map or a list of maps" |
| 06:24 | kzar | so either (list map1 map2) or (cons map1 list-of-maps) but I thought there might be a better way to write it |
| 06:24 | LauJensen | Any Linux Firefox users here who can help me out for 10 secs? |
| 06:24 | kzar | rhudson: Well I'm writing a function recursively that has a past-result parameter, usually it's just one map but sometimes it might be a list of a few maps. |
| 06:25 | kzar | rhudson: I thought of always wrapping the past-result map in a list but I thought that's a bit ugly |
| 06:25 | LauJensen | ,(flatten (cons [1 2 3] [[4 5 6] [7 8 9]])) |
| 06:25 | clojurebot | (1 2 3 4 5 6 7 8 9) |
| 06:26 | rhudson | kzar: you could define your function (defn whatever [ & maps ] ...) |
| 06:27 | LauJensen | kzar: that flatten demo was for you :) |
| 06:28 | rhudson | LauJensen: I run Firefox on Linux at work |
| 06:28 | LauJensen | rhudson: Are you at work ? |
| 06:28 | rhudson | thankfully no |
| 06:29 | rhudson | not at this ET hour |
| 06:29 | Raynes | LauJensen: I run firefox on Linux. |
| 06:31 | kzar | Raynes: Cool idea, so maps would always be a list of the parameters given in that example? |
| 06:31 | kzar | oops sorry I meant rhudson |
| 06:31 | Raynes | It's okay. I love to hear my name. |
| 06:32 | rhudson | kzar: right |
| 06:32 | kzar | heh |
| 06:32 | rhudson | reins rains reigns |
| 06:35 | stilkov | I'm trying to turn this into idiomatic clojure, I'm sadly pretty sure it's not: http://gist.github.com/380602 |
| 06:35 | stilkov | any comments appreciated |
| 06:37 | arbscht | stilkov: I think you can replace numbered-lines with indexed in clojure contrib |
| 06:37 | arbscht | that will get rid of the atom too |
| 06:38 | LauJensen | Yea, zero need for mutability for that specific task |
| 06:40 | stilkov | thanks, neat use of map with two args |
| 06:40 | arbscht | stilkov: you can use destructuring inside print-matches to abbreviate binding stuff |
| 06:42 | Chousuke | stilkov: (if (or (nil? pattern) (empty? files)) ...) <- (if-not (and pattern files)) |
| 06:43 | stilkov | arbscht: you mean something like (let [[fname matches] matches] ?? |
| 06:43 | stilkov | Chousuke: thanks |
| 06:44 | arbscht | stilkov: you can destructure within doseq itself |
| 06:44 | Chousuke | (doseq [[fname submatches] matches, match submatches] ...) |
| 06:45 | stilkov | er ? chewing on that for a second |
| 06:45 | Chousuke | or even (doseq [[fname submatches] matches, [first-part, second-part] submatches] ...) |
| 06:46 | stilkov | ah ? beautiful |
| 06:47 | Chousuke | it's similar to (for [row (rows matrix), element row] ...) except it's doseq :P |
| 06:48 | Chousuke | also you might want to use format instead of manually constructing the string with str |
| 06:49 | Chousuke | either is fine, but I think format strings are easier to read and modify |
| 06:50 | kzar | rhudson: I had a question about your idea to define the function using "& maps"; it works fine until I need to recur but then instead of passing the new map and all the old maps I end up passing back a new map and a list of all the old maps |
| 06:51 | patrkris | rhickey: Hey. Did you ever experiment with other contention mangement strategies than the one Clojure's STM currently employs? |
| 06:51 | stilkov | Chousuke, arbscht: thanks a lot, that surely looks a lot better |
| 06:51 | rhickey | patrkris: not much |
| 06:52 | patrkris | rhickey: so you don't have any idea how implementing e.g. karma would affect it? |
| 06:53 | rhudson | kzar: yes, that's what's wrong with my suggestion. |
| 06:53 | rhickey | patrkris: my guess is, not a lot. Clojure's STM is coarse-grained, so it's not going to be used on the inner bits of a concurrent collection, e.g. as in a lot of the STM literature |
| 06:55 | kzar | rhudson: Hey well macros let you expand a list, I could create a macro that took a list and just expanded it and then use that on the list of old maps? |
| 06:55 | patrkris | rhickey: ok, I believe you are right - but we'll try out a few different strategies and see how they work out. We're doing it as part of our studies. |
| 06:57 | rhickey | patrkris: If you are interested in doing something cool and new with Clojure's STM, and leveraging it being MVCC, one thing I have been thinking about is visible transaction timestamps |
| 06:57 | patrkris | rhickey: nice - I'll note that |
| 06:57 | rhickey | patrkris: so, rather than returning a value d-timestamped-sync would return a token representing the world at a point in time |
| 06:58 | rhudson | kzar: (defn f [m old-ms] (let [ms (cons m old-ms)] ... ) |
| 06:58 | rhickey | the nyou could run a read transaction as of a point in time |
| 06:58 | patrkris | rhickey: you meant do-timestamped-sync? |
| 06:59 | rhickey | this matters when someone does something in a transaction and needs to communicate it to someone for use later. Given long enough histories, they can go back and see the same world |
| 06:59 | rhickey | patrkris: yes, do-timestamped-sync or something |
| 06:59 | patrkris | rhickey: thanks man, cool suggestion |
| 06:59 | rhickey | another thing I am interested in is independent ref worlds |
| 07:00 | rhudson | kzar: then ms is always a list -- (cons x nil) => '(x) |
| 07:00 | rhickey | for some apps you might have small independent ref worlds of critical data for which you'd keep very large histories |
| 07:00 | patrkris | rhickey: so you'd have the ability to rewind? |
| 07:01 | rhickey | patrkris: not so much rewind as see the past |
| 07:01 | patrkris | rhickey: e.g. for undo operations? |
| 07:01 | patrkris | rhickey: oh ok |
| 07:02 | rhickey | patrkris: consider event-driven systems where the event receiver adds the even to a collection transactionally, then notifies others. If they race to look at the collection something might have happened in the interim, wheras is the producer could communicate the world time, they could see his result |
| 07:03 | patrkris | rhickey: ok, got it |
| 07:04 | Licenser | ,(doc flatten) |
| 07:04 | clojurebot | "([x]); Takes any nested combination of sequential things (lists, vectors, etc.) and returns their contents as a single, flat sequence. (flatten nil) returns nil." |
| 07:05 | patrkris | rhickey: so your two suggestions are actually related somewhat, right? |
| 07:06 | rhickey | patrkris: not really, separate ref pools just let you get more concurrency when you have never-overlapping sets of data |
| 07:06 | Licenser | out of curiosity, why does flatten not take multiple lists, it is kind of what people use a lot |
| 07:07 | rhickey | patrkris: given that history length is per ref you don't need separate pools for that |
| 07:08 | patrkris | rhickey: Ok, I was just focusing on the history thing :) |
| 07:08 | rhickey | patrkris: timestamped transactions are something likely to make it into Clojure, ref pools probably not for a while |
| 07:08 | patrkris | ok |
| 07:08 | rhudson | ,(var flatten) |
| 07:08 | clojurebot | #'clojure.contrib.seq-utils/flatten |
| 07:11 | rhudson | ,*clojure-version* |
| 07:11 | clojurebot | {:interim true, :major 1, :minor 1, :incremental 0, :qualifier "master"} |
| 07:12 | patrkris | rhickey: so in independent ref worlds, you'd be able to see a consistent view of a pool of refs at a given point in the past, or am I misunderstanding? |
| 07:14 | rhickey | patrkris: sorry I confused you. Independent ref pools simply make it so one set of refs has no interaction at all with another, e.g. can't be part of the same transaction. At very high concurrency levels, that would ease the pressure on the single timestamp CAS inside the STM, since each pool would have its own |
| 07:14 | rhickey | patrkris: really nothing to do with timestamped transactions |
| 07:14 | patrkris | rhickey: oh ok, thanks :) |
| 07:15 | rhickey | as long as you have sufficient history for any refs you need to see in the past, you can do timestamped reads |
| 07:15 | patrkris | yes, but clojure doesn't allow to look in the past as of now, right? |
| 07:15 | rhickey | talking about one just made me think of the other |
| 07:16 | patrkris | yes |
| 07:16 | rhickey | patrkris: right, that would be the enhancement - runs this read-only transaction as of this point in the past |
| 07:16 | rhickey | as id |
| 07:16 | rhickey | as if |
| 07:16 | patrkris | :) |
| 07:16 | Raynes | rhickey: It's called too-early-in-the-morning syndrome. |
| 07:17 | rhickey | Raynes: it doesn't get better later :( |
| 07:17 | Raynes | It can't get any worse. |
| 07:17 | patrkris | start drinking coffee |
| 07:21 | Raynes | rhickey: What kind of tea? |
| 07:21 | Raynes | I love me some tea. |
| 07:22 | rhickey | Raynes: in the morning - an Assam, today it's Mangalam |
| 07:22 | Raynes | Never heard of either of those. My teafoo is weak, but I'm learning. |
| 07:22 | vu3rdd | rhickey: Indian Tea looks like? |
| 07:23 | Raynes | vu3rdd: You Indians sure are proud, aren't you? :p |
| 07:23 | rhickey | vu3rdd: right |
| 07:23 | Raynes | You should be, with such awesome teas. |
| 07:23 | vu3rdd | :) |
| 07:23 | vu3rdd | We don't get as good coffees here as you have in Europe and the US. |
| 07:24 | vu3rdd | I am sad that I am missing meeting all you great clojure hackers. You are all in the west. May be you can visit me and I will give you loads of Tea |
| 07:25 | Raynes | vu3rdd: I'd totally visit you. You're watching Irclj. One of the few. <3 |
| 07:25 | Licenser | heh |
| 07:26 | vu3rdd | Raynes: Sure. I am quite interested in both sexpbot as well as irclj. |
| 07:26 | Licenser | vu3rdd: a colegue of mine was supposed to go to India the other weak but that silly vulcano thing keeped him in germny |
| 07:26 | vu3rdd | Oh.. |
| 07:26 | Raynes | Volcanoes are so silly!!! |
| 07:26 | vu3rdd | I am in Bangalore. If any of you are coming this way, please ping me at this handle @ gmail |
| 07:26 | Licenser | SOmeone from kuwait here? |
| 07:31 | Raynes | vu3rdd: Sexpbot is actually my biggest project ever. It started out as a little toy script to connect to IRC. |
| 07:31 | Raynes | And then I got bored. |
| 07:31 | Raynes | That's how all good projects start. "I got bored." |
| 07:34 | Licenser | Which would explain why I never have good projects :P I can't remember when I was boored the last time |
| 07:34 | patrkris | rhickey: in the software engineering podcast you talked about how STM couldn't be made to work correctly in certain other languages. One of the reasons, aside from MVCC and the persistent datastructures, would also be because of the "coarse grainedness" of Clojure's transactions? In C and Java STM implementations, the STM *has* to work at a finer granularity. Am I right in my understanding? |
| 07:34 | Raynes | clj-sandbox is great. |
| 07:34 | Raynes | Licenser: Ever figure out what was up with StringWriter? |
| 07:35 | patrkris | rhickey: sorry, 'correctly' is not the word here |
| 07:36 | rhickey | patrkris: right, my comment was directed at efforts to make ordinary mutating Java/C code safe by wrapping in transactions. The granularity would have to be at the field level, and most important, you'd need to be in a transaction to read. Clojure emphasizes programming with values, such values perfectly valid outside a transaction. |
| 07:39 | patrkris | rhickey: so how about haskell for instance? Could you hope to get MVCC working well in that language? Clojure's force with regard to MVCC is structural sharing and thus efficient 'copying', right? (I'm just sorting out the arguments we'll use when we write our paper.) |
| 07:41 | rhickey | patrkris: Haskell's STM is somewhat like Clojure's, sans MVCC. It is ref+value oriented, and can be used coarse grained, and of course the language emphasizes values |
| 07:42 | rhickey | patrkris: and Haskell's data structures are similar. So, nothing to knock on Haskell here, we're on the same side of this I think |
| 07:43 | patrkris | rhickey: Ok, I better read up on Haskell :) |
| 07:43 | rhickey | Haskell has orElse (or something) which I considered but rejected |
| 07:43 | patrkris | yes orElse |
| 07:44 | rhickey | The big diff with Haskell's STM is that in order to do orElse you need to do read tracking. Clojure doesn't need to do that |
| 07:44 | rhickey | Clojure is I think still unique in having commute |
| 07:45 | patrkris | and MVCC? |
| 07:45 | rhickey | there are other MVCC STMs I think |
| 07:45 | rhickey | at least now there are |
| 07:46 | rhickey | http://multiverse.codehaus.org/overview.html |
| 07:46 | sexpbot | "Multiverse - Java based Software Transactional Memory implementation" |
| 07:46 | patrkris | yeah you are probably right, but I can't see how you can get that to work as efficient as in clojure's case, unless the data structures have the same characteristics |
| 07:46 | rhickey | patrkris: exactly, the whole design works together |
| 07:47 | patrkris | rhickey: yes, and when I finally saw that, I was pretty amazed, rich :) |
| 07:47 | patrkris | i've been wanting to ask you if these things was all one epiphany for you, or did things just follow each other naturally? :) |
| 07:47 | patrkris | *were |
| 07:48 | rhickey | patrkris: took too long to be an epiphany :) |
| 07:49 | rhickey | I do think it is a natural outcome of the reconciliation of a bunch of forces |
| 07:50 | rhickey | looking backwards of course |
| 07:50 | patrkris | yes |
| 07:50 | rhickey | nothing about Clojure is really new |
| 07:50 | patrkris | but probably the combo is |
| 07:51 | wlangstroth | patrkris: beat me to it. |
| 07:51 | wlangstroth | rhickey: first lisp I've liked, fwiw |
| 07:51 | patrkris | first lisp I did serious programming in :) |
| 07:52 | patrkris | (for some definition of serious) |
| 07:52 | patrkris | ^ that wasn't a lisp expression, in case you wondered |
| 08:04 | cemerick | rhickey: thank you for that last commit :-) |
| 08:04 | rhickey | cemerick: you're welcome! |
| 08:04 | rhickey | protocol variadics will be harder |
| 08:05 | Raynes | patrkris: Looked more like python without the parens. |
| 08:05 | cemerick | ...and I was just about to (jokingly) suggest auto-hinting of % in fn literals in protocol fn maps :-P |
| 08:07 | rhickey | cemerick: extend-type auto-hints |
| 08:07 | cemerick | rhickey: yeah, I know :-) |
| 08:07 | rhickey | but extend doesn't look at the map at all |
| 08:08 | cemerick | so I figured. That's why it would have been a joke. :-) |
| 08:08 | rhickey | cemerick: but is there some real need? |
| 08:08 | cemerick | heh, no |
| 08:21 | wlangstroth | rhickey: I'm still catching up on your design ideals - Bagwell and Huet were new to me - any more required reading? |
| 08:26 | stilkov | rhickey: can I use the Clojure logo in a public presentation about the language? |
| 08:27 | rhickey | wlangstroth: tough to say, you learn from everything, even those things you reject |
| 08:27 | rhickey | stilkov: sure |
| 08:27 | stilkov | rhickey: thanks |
| 08:27 | rhickey | stilkov: what are you talking about? |
| 08:29 | stilkov | rhickey: I'm doing an intro to Clojure's concurrency features at JAX 2010 in Germany |
| 08:29 | rhickey | stilkov: good luck! |
| 08:30 | stilkov | rhickey: thanks! |
| 08:30 | wlangstroth | rhickey: true enough - thanks |
| 09:02 | Licenser | hmm the protocll stuff is pretty neat |
| 09:05 | Raynes | technomancy|away: I need you. Wake up. |
| 09:05 | Licenser | So could the rule of thumb for when to use protocols and when to use multimethods be: If you don't need the crazy stuff you can do with multi methods you should do it in protocols? |
| 09:06 | Raynes | Deftypes can't implement a multimethod. |
| 09:06 | Chousuke | an easier way: try protocols first, if they don't work, use multimethods |
| 09:06 | Licenser | Chousuke: but that is so simple :P |
| 09:07 | Chousuke | ideally you'd keep the fact that there is a protocol or a multimethod an implementation detail |
| 09:08 | Chousuke | they're all functions, and if you don't advertise the protocol as part of your API, no-one's going to notice the difference :P |
| 09:08 | clojurebot | api examples is http://en.wikibooks.org/wiki/Clojure_Programming/Examples/API_Examples |
| 09:08 | Raynes | (start-repl 4005 :host "localhost") <-- Confusing. |
| 09:08 | Raynes | start-repl takes any number of optional arguments, but doing that tosses a "Wrong number of arguments" error. |
| 09:09 | Licenser | Chousuke: muahaha |
| 09:09 | Raynes | I can't win for losing it seems. |
| 09:11 | _ato | Raynes: older version of swank-clojure didn't accept options |
| 09:12 | _ato | 1.0 just takes a port, nothing else |
| 09:12 | _ato | looks like 1.1 is the same |
| 09:12 | _ato | http://github.com/technomancy/swank-clojure/blob/1.1.0/src/swank/swank.clj#L60 |
| 09:12 | Licenser | hmm question: is every namespace in clojure a class in java? |
| 09:13 | Raynes | Oh. |
| 09:13 | Raynes | That's the problem. |
| 09:13 | Raynes | _ato: Thanks. |
| 09:13 | Raynes | Didn't know my version was old. |
| 09:15 | _ato | Licenser: no, each namespace has many classes. Usually at least one for each function/lambda and one for __init |
| 09:15 | Licenser | ah sneaky |
| 09:40 | qbg | Did anyone come to Clojure without a Java background? |
| 09:40 | esj | me |
| 09:41 | qbg | Did Clojure's java based exceptions confuse you? |
| 09:43 | bytecoder | clojure's exception/error reporting is still evolving if i'm not wrong. not just exceptions; i've had difficulty comprehending other issues reported as well. it's not a turn off for me though. |
| 09:43 | Raynes | qbg: Yes. It irks everybody at first. |
| 09:44 | Raynes | Eventually you get used to shitty error messages and start paying attention to the stack traces. |
| 09:45 | Raynes | $sed #clojure i s/shitty/shoddy/ |
| 09:45 | sexpbot | Eventually you get used to shoddy error messages and start paying attention to the stack traces. |
| 10:07 | jwr7 | Anybody know if clojure-jna (and JNA in general) places any limitations on multithreading? I tried to use pmap with a piece of code that uses JNA and it looks like something gets synchronized. |
| 10:09 | chouser | jwr7: clojure-jna doesn't sync anything, but I don't know about JNA itself. |
| 10:11 | jwr7 | chouser: I searched the docs, but couldn't find anything. And yet YourKit clearly show me a checkerboard pattern — I get 16 threads or so, but only one seems to be running at a time. |
| 10:17 | chouser | jwr7: http://gist.github.com/380762 |
| 10:18 | chouser | could the native lib you're calling be locking? |
| 10:20 | jwr7 | chouser: it isn't — it's just one C function, reentrant and fairly simple. I'm looking at JNA source now, perhaps it's because I was using jna-invoke instead of deifning a jna-fn? (com.sun.jna.Function/getFunction might be blocking me) |
| 10:21 | chouser | you saw my gist? that uses jna-invoke without apparent blocking |
| 10:22 | jwr7 | chouser: Right. That proves it, I guess. So why do I get blocking with pmap — it's the same mechanism, after all… |
| 10:26 | chouser | well, there are a few more variables there... |
| 10:27 | chouser | pmap uses a different thread pool. Is your input seq chunked? How are you forcing the pmap output seq? |
| 10:28 | jwr7 | chouser: I forced the output with doall and the inputs were real lists by then. I'm trying to work out a test case right now. |
| 10:29 | chouser | ok |
| 10:54 | powr-toc | What's the best way of interacting with databases currently in clojure? |
| 10:54 | powr-toc | clojureql seems like it's a short way off being prime-time... |
| 10:55 | powr-toc | and c.c.sql has warts, but seems to be more stable... is this a fair assessment? |
| 11:01 | Raynes | Yeah, I have trouble writing small ones. |
| 11:01 | Raynes | Check out defrecord's docstring in Clojure. |
| 11:01 | Raynes | Oops. |
| 11:01 | Raynes | Wrong channel. |
| 11:10 | AWizzArd | à propos defrecord... they they now have a print-dup representation. But there is no constructor which could rebuild them. |
| 11:11 | chouser | ,(condp = 99, 1 :a, 2 :b, #_else :unknown) |
| 11:11 | clojurebot | :unknown |
| 11:11 | chouser | is #_else helpful or confusing? |
| 11:11 | AWizzArd | confusing |
| 11:12 | AWizzArd | Oh cool, defrecords are now serializable :) |
| 11:13 | rhickey | AWizzArd: it would be cooler if http://www.assembla.com/spaces/clojure/tickets/281-make-more-datastructures-serializable patch applied - I was al set to do this Serializable stuff this morning |
| 11:13 | stuartsierra | chouser: confusing |
| 11:13 | sexpbot | "#281 - Make more datastructures serializable (Test) | Clojure | Assembla" |
| 11:15 | fogus | chouser: confusing |
| 11:15 | chouser | wow |
| 11:15 | chouser | ok then |
| 11:15 | chouser | :-) |
| 11:16 | chouser | ,(condp = 99 1 :a 2 :b :unknown) ; it is then! |
| 11:16 | clojurebot | :unknown |
| 11:18 | stuartsierra | chouser: If your condp spans multiple lines, ";;else" before the last line would be helpful |
| 11:18 | rhickey | ick |
| 11:18 | chouser | hm. |
| 11:19 | rhickey | (if x |
| 11:19 | rhickey | ;;then |
| 11:19 | rhickey | y |
| 11:19 | rhickey | ;;else |
| 11:19 | rhickey | z |
| 11:19 | rhickey | ) ;;endif |
| 11:20 | hiredman | you could also include the docstring for condp in a comment :P |
| 11:25 | moshisushi | rhickey: :D |
| 11:25 | chouser | I'm having far too much fun with :inline |
| 11:25 | chouser | but I need a better macroexpand |
| 11:26 | hiredman | mexpand-all? |
| 11:26 | chouser | hm, I don't trust it. But it doesn't do :inline's anyway, does it? |
| 11:26 | hiredman | no idea |
| 11:26 | hiredman | ,mexpand-all |
| 11:26 | clojurebot | #<macro_utils$mexpand_all__4397 clojure.contrib.macro_utils$mexpand_all__4397@b0b955> |
| 11:26 | hiredman | ,(mexpand-all '(+ 1 2)) |
| 11:26 | clojurebot | (+ 1 2) |
| 11:26 | fogus | rhickey: What did "end." expand to? |
| 11:26 | The-Kenny | rhickey: There's a guy who wants to implement something very similar to lisp macros for c++. His syntax looks like @#wenn a ist 42 dann def b = a+@# ("wenn a ist 42 dann..." translates to "when a is 42 then ..." |
| 11:26 | hiredman | guess not |
| 11:27 | The-Kenny | He's writing a pre-processor for this |
| 11:28 | rhickey | fogus: nothing, it just made him happy to see it |
| 11:32 | stilkov | what's the point of most macros being defined with (defmacro [& body] ...) instead of (defmacro [body] ...) ? |
| 11:32 | LauJensen | powr-toc: correct assesment |
| 11:33 | bsteuber | stilkov: you can then offer implicit do for multiple statement (side effects) |
| 11:33 | chouser | if you want real macros on C++, this is interesting: http://voodoo-slide.blogspot.com/2010/01/amplifying-c.html |
| 11:33 | sexpbot | "voodoo slide: Amplifying C" |
| 11:33 | LauJensen | The problem with ClojureQL is, that at 0.9.7 we decided to rework the entire frontend. And when thats done it will be great, but we have to put in a lot of work and unfortunately we're all very busy atm |
| 11:34 | AWizzArd | When should I write a method for print-dup (vs. print-method)? |
| 11:34 | rhickey | stilkov: [body] can only take one form |
| 11:35 | rhickey | often macros need to manipulate a variable number of forms |
| 11:36 | stilkov | rhickey: the reason then would be the one pointed out by bsteuber. is it idiomatic to expect macros do wrap the body in an implicit (do ...)? |
| 11:36 | stilkov | s/do wrap/to wrap/ |
| 11:36 | stuartsierra | chouser: try "wtf" from Halloway's circumspec |
| 11:37 | stuartsierra | It's a macroexpansion, name is short for "what the form" |
| 11:37 | rhickey | stilkov: not necessarily, (defmacro add [& body] `(+ ~@body)) doesn't even emit a block |
| 11:38 | rhickey | stilkov: macros like defrecord take variable forms, not related to statements/do |
| 11:38 | AWizzArd | btw, with print-method go away in 1.2 and get replaced by Protocols? |
| 11:39 | stilkov | rhickey: I see; I may have been thinking of the wrong examples |
| 11:40 | rhickey | stilkov: there are plenty that just dump ~@body into something like a let or do as well |
| 11:41 | stilkov | rhickey: I was wondering about those that don't, yet use [& body] and ~@body anyway |
| 11:41 | rhickey | stilkov: searching for ~@ in core.clj can be instructive into the various uses |
| 11:43 | stilkov | rhickey: thanks |
| 11:43 | bsteuber | I've just been discussing the idea of having and/or being a function that just gets inlined to short-circuit evaluation |
| 11:43 | bsteuber | would that be a bad idea? |
| 11:44 | bsteuber | I'd love to write (map and boolean-seq1 boolean-seq2) |
| 11:44 | chouser | but it would *not* short circuit when used as a function |
| 11:44 | chouser | sounds confusing to me |
| 11:45 | bsteuber | chouser: I thought so, too, at first - but if you pass sth. as a function to apply etc., the arguments would get evaluated anyways |
| 11:45 | bsteuber | so you'd expect it to do so |
| 11:46 | chouser | (partial and foo) would be greedy on all args |
| 11:46 | stuartsierra | bsteuber: your example could be written (map #(and %1 %2) seq1 seq2) |
| 11:47 | bsteuber | stuartsierra: sure, the idea is just about simplifying this a little |
| 11:48 | AWizzArd | ,(every? boolean (concat [1 2 3] [4 5 6])) |
| 11:48 | clojurebot | true |
| 11:48 | joshua-choi | (doc boolean) |
| 11:48 | clojurebot | "([x]); Coerce to boolean" |
| 11:48 | joshua-choi | I did not know about that |
| 11:48 | stuartsierra | So (defn add* [& args] (every? identity args)) |
| 11:48 | chouser | (map and boolean-seq1 boolean-seq2) used to return something, once upon a time. |
| 11:48 | stuartsierra | I mean defn and |
| 11:49 | stuartsierra | and* |
| 11:49 | stuartsierra | whatever |
| 11:49 | chouser | but ... it returned code. |
| 11:49 | bsteuber | :) |
| 11:50 | bsteuber | at least after I thought of it I found the idea less confusing than in the beginning :) |
| 11:50 | bsteuber | because in function-land you expect anything to be eager |
| 11:51 | hiredman | (map (comp eval #'and) bseq bseq2) |
| 11:51 | chouser | I'm not sure the boundary between function-land and inline-land is very clear to a lot of people |
| 11:52 | bsteuber | hmm, maybe |
| 11:53 | chouser | hiredman: have you tried that in a recent version of clojure? |
| 11:53 | chouser | calling macros manually is more complicated than it used to be. |
| 11:53 | hiredman | nope |
| 11:53 | bsteuber | chouser: btw, do you think it's ok to use images (with citation, of course) from JoyOfClojure in a talk I give at my university? |
| 11:53 | hiredman | why would I try such a silly thing? |
| 11:54 | bsteuber | not familiar with copyright on images in books |
| 11:54 | chouser | bsteuber: I'd think normal fair-use rules apply. |
| 11:54 | stuartsierra | just ask the author |
| 11:54 | stuartsierra | who's not likely to sue you anyway |
| 11:55 | chouser | well, the publisher has a legal interest, for now anyway. |
| 11:55 | fogus | stuartsierra: Soeak for yourself! ;-) |
| 11:55 | fogus | Speak that is |
| 11:56 | stuartsierra | Seriously, no publisher is going to bother to sue you for using images in one talk. |
| 11:56 | bsteuber | ok, then I'll just do it :) |
| 11:56 | hiredman | it's a setup |
| 11:56 | stuartsierra | but it would be considerate to ask the author's permission |
| 11:57 | bsteuber | hm right, I just asked one of them so far :) |
| 11:57 | fogus | My plan is to make more money off of litigation than book sales. |
| 11:57 | hiredman | sierra talks you into giving the talk, and peddles his expert clojure legal opinions to the publishers law firm and you can turned into a smoking crater |
| 11:57 | bsteuber | chouser, fogus: so you personally wouldn't mind? |
| 11:57 | stuartsierra | hiredman: darn, you've figured out my secret plan! |
| 11:58 | bsteuber | haha |
| 11:58 | fogus | bsteuber: I do not. Which image(s)? |
| 11:58 | stuartsierra | IANALAIAPOTFETIWAALS |
| 11:59 | stuartsierra | I Am Not A Lawyer And I Am Proud Of That Fact Even Though I Work At A Law School |
| 11:59 | hiredman | * see back of card for consulting rates |
| 12:00 | bsteuber | fogus: at least the mutable runner for now |
| 12:01 | bsteuber | fogus: and maybe the three circles from the start |
| 12:01 | chouser | bsteuber: yeah, as long as you credit the book, I don't mind in the least. |
| 12:03 | bsteuber | chouser: I will for sure :) |
| 12:04 | Luyt | Hmmm, I think I found a typo in Stuarts book, on page 39 it says "syntax for shorter anonymous function: (#body)" but I think that should be "#(body)" |
| 12:04 | Luyt | ,(#(print "Yup")) |
| 12:04 | clojurebot | Yup |
| 12:05 | stuartsierra | Which Stuart? |
| 12:06 | bsteuber | stuartsierra: do you have a book, too? |
| 12:06 | stuartsierra | yes |
| 12:06 | stuartsierra | not published yet |
| 12:06 | stuartsierra | No one has ever heard of it. |
| 12:06 | stuartsierra | Not even me. |
| 12:06 | bsteuber | haha |
| 12:07 | bsteuber | but it's great there's already at least two very good clojure books out there |
| 12:07 | bsteuber | (can't talk about Clojure in Action, yet) |
| 12:07 | stuartsierra | yse |
| 12:07 | Luyt | Stuart Holloway, "Programming in Clojure" |
| 12:08 | stuartsierra | 2010 will be the year Clojure goes mainstream. |
| 12:08 | Luyt | eh, "Programming Clojure" |
| 12:08 | stuartsierra | We'll all have to shop for ties. |
| 12:08 | Luyt | ISBN 101934356336 |
| 12:08 | chouser | is clojureconj still on for this fall? |
| 12:09 | stuartsierra | chouser: what's this? |
| 12:09 | chouser | the conference |
| 12:09 | stuartsierra | I vaguely remember some talk about that |
| 12:09 | stuartsierra | Then I heard it wasn't in New York, and I stopped paying attention. :) |
| 12:09 | chouser | heh |
| 12:10 | chouser | If I only paid attention to things around here, I'd have a lot more free time... |
| 12:10 | stuartsierra | But who knows where I'll be in the Fall. |
| 12:10 | Luyt | If I kept myself to C++, I'd also have more free time. What makes me interested in Clojure? |
| 12:10 | technomancy | supposedly it's still on, but with no call for talk proposals yet I have my doubts |
| 12:15 | maravillas | I'm trying to work with the change in c.c.str-utils* => c.c.string from 1.1 to 1.2, as well as the changed signature for c.c.str-utils2/drop and c.c.string/drop. There's something happening here that I don't understand...any thoughts? http://gist.github.com/380924 |
| 12:16 | stuartsierra | don't do that |
| 12:16 | maravillas | Which part? :) |
| 12:16 | stuartsierra | the whole thing |
| 12:16 | stuartsierra | just copy the old namespaces from 1.1 |
| 12:17 | stuartsierra | I got to make a ticket for that |
| 12:17 | maravillas | sorry, I'm not sure what you're suggesting |
| 12:18 | stuartsierra | If you want to use the 1.1 contrib functions, use 1.1. I'm nudging people toward copying the old 1.1 namespaces into 1.2 master, with a deprecation warning. |
| 12:19 | stuartsierra | Don't try to support two different versions in one piece of code. That way lies madness. |
| 12:22 | maravillas | Hm, I see. Will 1.2 generally be considered a breaking upgrade? That is...should libraries not worry about supporting both? I'm not up to date on all the changes, but it seems silly for me to select one if this particular function is the only difference. |
| 12:22 | stuartsierra | Current trend is that 1.2 contrib will deprecate a bunch of namespaces, but will try not to break anything. |
| 12:23 | stuartsierra | Current master branch breaks a lot. |
| 12:23 | stuartsierra | That needs to change. |
| 12:24 | maravillas | Alright, fair enough. I'm still curious what's going on in that snippet, though...I can reference string/drop outside of the try, but I get the exception on the inside. |
| 12:25 | raek | maravillas: this might be useful: http://blog.licenser.net/2010/04/22/on-clojure-libs-and-versions |
| 12:25 | sexpbot | "lice! : On clojure libs and versions." |
| 12:26 | danlarkin | lol at contrib ticket #20 |
| 12:26 | maravillas | I saw that, but it doesn't deal with my second issue, where the signature for the respective drop functions changes |
| 12:28 | raek | ah, ok... |
| 12:29 | digash | ,(byte 255) |
| 12:29 | clojurebot | -1 |
| 12:29 | digash | ,(apply byte [255]) |
| 12:29 | clojurebot | -1 |
| 12:29 | digash | in the latest 1.2 |
| 12:29 | digash | user> (apply byte [255]) |
| 12:29 | digash | -1 |
| 12:29 | digash | user> (byte 255) |
| 12:29 | digash | ; Evaluation aborted. |
| 12:29 | digash | |
| 12:30 | digash | the second one throws an exception Value out of range for byte: 255 |
| 12:30 | stuartsierra | https://www.assembla.com/spaces/clojure-contrib/tickets/79-forward-port-deprecated-1-1-namespaces |
| 12:30 | sexpbot | "#79 - Forward-port deprecated 1.1 namespaces (New) | Clojure Contrib | Assembla" |
| 12:31 | chouser | ,(.byteValue 255) |
| 12:31 | clojurebot | -1 |
| 12:31 | digash | cool, but i am still confused why the apply works? |
| 12:32 | stuartsierra | byte is actually a type cast to primitive byte. |
| 12:32 | chouser | it's the difference between function-land and inline-land |
| 12:32 | stuartsierra | It also happens to work as a function, in which case it coerces to byte. But they're different operations. |
| 12:32 | digash | feels like a bug to me |
| 12:32 | chouser | when used as a function (as with apply), it just does .byteValue on a boxed Number |
| 12:33 | stuartsierra | I kinda wish the primitive coercions looked more like type hints. |
| 12:33 | stuartsierra | e.g. #^byte 127 |
| 12:33 | stuartsierra | only that wouldn't work in the current reader |
| 12:33 | chouser | when used inline-ably, it does a cast and thus works with primitives |
| 12:34 | stuartsierra | Could the reader support read-time metadata on non-Clojure types by wrapping them in a special "MetaFoo" object? |
| 12:34 | digash | maybe (^byte 127) vs (byte 127) |
| 12:35 | stuartsierra | ack no |
| 12:35 | stuartsierra | that would expand to (127) |
| 12:35 | rhickey | digash: that is a bug, I didn't realize the fn defs weren't calling through RT |
| 12:36 | stuartsierra | rhickey: what do you think of #^byte 127 ? |
| 12:37 | rhickey | stuartsierra: #^ is so day-before-yesterday |
| 12:37 | stuartsierra | ok, fine, ^byte 127 |
| 12:37 | stuartsierra | one innovation at a time |
| 12:37 | rhickey | are we talking for literals only? |
| 12:38 | stuartsierra | yse |
| 12:38 | stuartsierra | yes |
| 12:38 | chouser | oh, only literals? |
| 12:38 | rhickey | 127b ? |
| 12:38 | stuartsierra | hm, maybe |
| 12:38 | maravillas | Is there a set approach for dealing with deprecated symbols & namespaces? I appreciate that copying the old namespaces helps with 1.2, but when should we expect that we'll have to actually fix things to reference the new ones? |
| 12:38 | stuartsierra | actually, no, I was thinking for symbols too |
| 12:38 | stuartsierra | oh, never mind |
| 12:39 | stuartsierra | maravillas: what else could we expect? |
| 12:39 | chouser | I actually think it's pretty clever how primitive casts are built directly on interop support -- no explicit reader or compiler code needed. |
| 12:40 | maravillas | Of course they'll go away at some point, I'm just wondering if there's a guideline for how long deprecated stuff sticks around. |
| 12:41 | Licenser | maravillas: you can work around it with try catch |
| 12:42 | stuartsierra | Don't 'require' in try/catch! |
| 12:42 | stuartsierra | That will drive you maaaaad. |
| 12:42 | Licenser | stuartsierra: ma ma ma maaaad |
| 12:42 | stuartsierra | If you want to use the new stuff, you've got to abandon some old stuff. |
| 12:42 | stuartsierra | If you don't need the new stuff, you can stick around with an old version as long as you like. |
| 12:45 | rhickey | digash: fixed |
| 12:46 | dnolen | 127b and 1f would be cool for literals |
| 12:47 | rhickey | [b]yte, [s]hort, [i]nt, [l]ong, [f]loat [d]ouble ? |
| 12:48 | stuartsierra | l for long is hard to read, but it is consistent |
| 12:48 | chouser | that'll be the default eventually, right? |
| 12:48 | rhickey | BigDeci[M]al . BigInteger? |
| 12:48 | dnolen | rhickey: yes! graphics/audio code would benefit from less typing. |
| 12:48 | chouser | long will be the default eventually, right? |
| 12:49 | rhickey | chouser: I hope so |
| 12:49 | fogus | I think 131l will be tough to catch |
| 12:49 | digash | rhickey: so now it throw an exception always? |
| 12:49 | chouser | if the suffix letter is case-insensitive, 131L is a possible |
| 12:49 | rhickey | digash: yes |
| 12:50 | chouser | rhickey: If I understand your idea for default primitive literals, throwing on overflow, etc. I've grown to like it. |
| 12:50 | rhickey | digash: so now these are safe coercions. I'd take a patch for bit-casts |
| 12:50 | rhickey | chouser: I really wish now I had done that up front |
| 12:51 | rhickey | It's a big break with Lisp tradition, but much more practical |
| 12:51 | fogus | Why not make the suffix require caps? |
| 12:51 | rhickey | fogus: could do, but how would one as for Integer, Long etc? |
| 12:51 | rhickey | ask for |
| 12:51 | chouser | combined with a syntax for literal non-defaults types (50i, etc.) a bunch of tricky problems become easier to handle |
| 12:52 | fogus | rhickey: L131 is long, 131L is Long... :( I got nothing |
| 12:52 | rhickey | fogus: also I becomes a problem then |
| 12:53 | stuartsierra | if primitives are the default, then there would rarely be a reason to ask for boxed literals |
| 12:53 | digash | (.byteValue n) is the way to get unsigned byte value then? |
| 12:53 | stuartsierra | And you could write (Integer. 127) when you need to. |
| 12:53 | chouser | digash: no such thing as unsigned byte on the JVM. :-/ |
| 12:54 | somnium | maybe 123L <- primitive, 123<L> <- boxed ? |
| 12:54 | stuartsierra | ugh |
| 12:54 | fogus | 131L 131^L |
| 12:55 | stuartsierra | erg |
| 12:55 | fogus | Hmmm, nothing looks nice |
| 12:55 | stuartsierra | maybe we should stick with (long 131) |
| 12:55 | Licenser | stuartsierra: but not using require for namespaces would mean we can't make libraries and such that are version independant - that is kind of bad |
| 12:56 | stuartsierra | there is no such thing as a library that is version independent |
| 12:56 | Licenser | over certain version ranges, yes there is |
| 12:56 | stuartsierra | Then releases within those version ranges should aim for some backwards compatibility. |
| 12:56 | digash | chouser: i meant in java (byte)177, will "translate" int into byte |
| 12:56 | stuartsierra | In other words, the onus of library compatibility should never be on client code. |
| 12:57 | Licenser | and if I publish my lib for 1.1.0 and somene has a project in 1.2.0 he want's to use the lib for their thing they should be able to do so witout forking the project I think |
| 12:57 | stuartsierra | no |
| 12:57 | Licenser | yes |
| 12:57 | rhickey | stuartsierra: I agree (long 42) is both verbose and not really making it to the compiler |
| 12:57 | Licenser | not on client code stuartsierra but on library code |
| 12:57 | stuartsierra | If 1.2 contrib becomes supports backwards compatibility with 1.1, then that problem goes away. |
| 12:57 | Licenser | I would not make a app that uses require to work with 1.1 and 1.2. But I certenly made 2 libs arelday that do and they can nicely be included in any 1.1 or 1.2 project |
| 12:58 | stuartsierra | Then they should target 1.1. |
| 12:58 | rhickey | digash: wow, the spec for byteValue is really bad: http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Number.html#byteValue() |
| 12:58 | sexpbot | "Number (Java 2 Platform SE 5.0)" |
| 12:58 | Licenser | they should 'just work' for most of the people :P |
| 12:59 | Licenser | if 1.2 c.c becomes backwards compatible, yes the problem goes away but will it? |
| 12:59 | stuartsierra | If I get my way. |
| 12:59 | Licenser | :P |
| 12:59 | stuartsierra | And I have commit access, so who's going to stop me? |
| 12:59 | Licenser | rhickey might |
| 13:00 | dnolen | for those that will be casting literals to primitive long often, 131l is fine I say, also seems like something that's not hard to highlight with syntax highlighting |
| 13:00 | Licenser | if I support your effort will you make a clojure.controb.silly namespace for me? where can go funtions like (defn rand [& _] 4) ;from xcdk or (defn cokkies [] (println "*nom nom nom*"))? |
| 13:00 | rhickey | 1.2 cc becoming backwards compatible is me getting my way too |
| 13:01 | Licenser | shush rhickey I was about to con stuartsierra in making a silly namespace! |
| 13:01 | Licenser | don't backstab my efforts :P |
| 13:01 | digash | ,(.byteValue 1234) |
| 13:01 | clojurebot | -46 |
| 13:01 | slyphon | so, in the repl (and only in the repl), is it possible to say, add 'pp' and 'pprint' to clojure.core so that it's available everywhere? |
| 13:02 | stuartsierra | Licenser: there's some pretty silly stuff in there already |
| 13:02 | Licenser | stuartsierra: you know if you do that and make 1.2 cc backwards compatible my only usefull blog post in the last 2 years will become meaningless *shakes fist* |
| 13:02 | stuartsierra | heh |
| 13:02 | stuartsierra | The best code needs no blogs. |
| 13:03 | stuartsierra | You can quote me. |
| 13:03 | chouser | in your blog |
| 13:03 | slyphon | that's the main problem with ruby |
| 13:03 | Licenser | heh |
| 13:03 | slyphon | everyone confuses blogging-about-code with code quality |
| 13:03 | Licenser | stuartsierra: well you can still use a blog to tell people nice things? |
| 13:03 | stuartsierra | sure |
| 13:03 | livingston | what's the correct way to shutdown the repl / swank / etc. from emacs swank-clojure-project ? |
| 13:04 | stuartsierra | But blog posts are no substitute for good documentation. |
| 13:04 | dnolen | livingston: I use slime-quit |
| 13:04 | stuartsierra | Licenser: you want silly, check out c.c.apply-macro |
| 13:04 | tomoj | livingston: at the repl, type ',', then type 'sayoonara' |
| 13:04 | Licenser | slyphon: no I don't confuse that but when I started my blog I decided not to make a whine girl dairy but write about things that matter (for me) IT wise so if I don't blog aobut code I blog about hardware and my little cluster of atom boards seemed not to be of interest :P |
| 13:04 | slyphon | hahaha |
| 13:04 | slyphon | well, i salute your intentions |
| 13:05 | Licenser | thank you |
| 13:05 | Licenser | so the atom cluster was pretty cool even so noone liked it |
| 13:05 | stuartsierra | I have a blog too. I hate myself for it. |
| 13:05 | livingston | dnolen: I don't have that defined? there's a slime-quit-lisp |
| 13:05 | dnolen | livingston: that's the one |
| 13:06 | slyphon | stuartsierra: yeah, i do too, i just never really update it |
| 13:06 | Licenser | about 95% of all blogs go along the line 'oh my god a bird pooped on my shoe, my life is so horrible meh meh meh' |
| 13:06 | stuartsierra | livingston: ,quit at the REPL also works |
| 13:06 | slyphon | unless i *really* get annoyed at ubuntu |
| 13:06 | stuartsierra | Licenser: heh :) |
| 13:06 | livingston | dnolen: that'll tear everything down, right? |
| 13:06 | dnolen | livingston: yes |
| 13:06 | tomoj | for some reason I always use ,sayoonara |
| 13:06 | Licenser | I could blog about cooking too but then I never can write down my recepies |
| 13:06 | Licenser | ,sayoonara |
| 13:06 | clojurebot | java.lang.Exception: Unable to resolve symbol: sayoonara in this context |
| 13:07 | stuartsierra | It's a SLIME feature. |
| 13:07 | livingston | stuartsierra: I tried forms of that but you mean with the comma too? (I thought maybe (quit) or (exit) would be bound |
| 13:07 | stuartsierra | no |
| 13:07 | stuartsierra | comma+command is a SLIME feature, there are several commands |
| 13:07 | Licenser | ,cookies |
| 13:07 | clojurebot | java.lang.Exception: Unable to resolve symbol: cookies in this context |
| 13:07 | kzar | Is there an easy way to "map" a tree? |
| 13:08 | stuartsierra | To kill a standard REPL, Ctrl-C or Ctrl-D usually does the trick. |
| 13:08 | stuartsierra | kzar: (into {} (map (fn [key value] ...)) is the easy way |
| 13:08 | Licenser | kzar: I wrote some code for that |
| 13:08 | livingston | stuartsierra: yeah I'm in emacs - so that won't cut it |
| 13:09 | stuartsierra | kzar: (reduce (fn [result [key value]] (assoc result...)) {} ...) is the fun way |
| 13:09 | Licenser | http://github.com/Licenser/clj-sandbox/blob/master/src/net/licenser/sandbox.clj#L15 |
| 13:09 | livingston | kzar: look at the "zip" routines |
| 13:09 | tomoj | livingston: get at the repl. type ','. now type 'quit' or 'sayoonara', your choice. now hit RET. |
| 13:09 | Licenser | if yo actually mean what I ment by that |
| 13:09 | stuartsierra | livingston: killing the *inferior-lisp* buffer also does it |
| 13:10 | tomoj | similarly ,i will let you change the namespace |
| 13:10 | rhickey | seq-contains? for sequential equality lookup? |
| 13:11 | stuartsierra | linear, right? |
| 13:11 | rhickey | yes |
| 13:11 | tomoj | wonder what pushd and popd do, they seem to be undocumented |
| 13:11 | stuartsierra | adding contains-key? or has-key? for associative would be clearer, I think |
| 13:11 | rhickey | then at least find-doc "contains" will find it, vs includes? |
| 13:11 | rhickey | or apropos |
| 13:12 | stuartsierra | but can't break 'contains?' right now, so yeah |
| 13:12 | Licenser | well people I hop in the bath see you alter |
| 13:13 | kotarak | ,(doc tree-seq) |
| 13:13 | clojurebot | "([branch? children root]); Returns a lazy sequence of the nodes in a tree, via a depth-first walk. branch? must be a fn of one arg that returns true if passed a node that can have children (but may not). children must be a fn of one arg that returns a sequence of the children. Will only be called on nodes for which branch? returns true. Root is the root node of the tree." |
| 13:13 | kotarak | kzar: maybe that is what you need? |
| 13:14 | livingston | kzar: there is a set of stuff in clojure.walk that will help you |
| 13:14 | stuartsierra | clojure.walk must die |
| 13:14 | stuartsierra | I gave birth to a monster. |
| 13:15 | rhickey | technomancy: so the performant, often used one should get the long name and the inefficient use-at-your-own-risk one the short name? |
| 13:15 | chouser | has-key? is shorter than contains? |
| 13:15 | technomancy | rhickey: no, I think "contains?" should be dropped eventually |
| 13:16 | technomancy | not that it should become seq-contains? |
| 13:16 | rhickey | technomancy: but it should become contains-key? |
| 13:16 | technomancy | actually yeah, has-key? is probably better than contains-key? |
| 13:16 | powr-toc | will has-key return the key if present? |
| 13:17 | rhickey | powr-toc: you have the key in hand when you ask, and what about nil? |
| 13:17 | kotarak | powr-toc: kind of like not-empty ? |
| 13:17 | stuartsierra | powr-toc: no, 'get' does that |
| 13:17 | stuartsierra | no |
| 13:17 | stuartsierra | ignore that |
| 13:18 | rhickey | ,(doc find) |
| 13:18 | clojurebot | "([map key]); Returns the map entry for key, or nil if key not present." |
| 13:18 | stuartsierra | right |
| 13:18 | powr-toc | stuartsierra: yes, fair point |
| 13:19 | stuartsierra | ,(contains? #{1 2 3} 2) |
| 13:19 | clojurebot | true |
| 13:19 | rhickey | well, the only thing on the table right now is the name for what c.c.seq/includes? does right now, moving into core |
| 13:20 | rhickey | I don't like includes? |
| 13:21 | chouser | seq-contains? seems nice for that. |
| 13:21 | stuartsierra | yeah |
| 13:21 | chouser | can some remain idiomatic though? |
| 13:21 | rhickey | what about rand-nth for rand-elt? |
| 13:21 | rhickey | kotarak: the problem with some is that few will think of that before they've been shown it |
| 13:23 | kotarak | Maybe there should be a Cookbook. "How to do FOO in Clojure..." "Chapter 21: Linear search: (some #(= % x) ys)" |
| 13:23 | powr-toc | rhickey: that happened to me today... It's been a while since I've been coding clojure, and it took a few minutes digging before I found 'some' again. |
| 13:24 | stuartsierra | seq-contains? is good enough |
| 13:25 | technomancy | seq-contains? is nice in that it highlights the fact that it's slow/sequential |
| 13:25 | kotarak | linear-search-which-is-slow-use-at-own-risk, but jokes aside: seq-contains? sounds ok to me, too |
| 13:25 | rhickey | technomancy: great! that's what I was going for |
| 13:26 | rhickey | so, I have the same concern with readn-elt, thinking rand-nth. Then at least you know that if nth is fast, rand-nth is too |
| 13:26 | rhickey | rand-elt |
| 13:26 | stuartsierra | Imagine if all fns were annotated with metadata describing their big-O performance: could useful metrics be devised from that information? |
| 13:26 | rhickey | a;so, we don't use elt anywhere else |
| 13:27 | livingston | some has always gone nice with every, etc. |
| 13:27 | chouser | I don't like "elt" |
| 13:27 | rhickey | chouser: does that mean you like rand-nth? |
| 13:27 | chouser | rand-nth seems nice, yeah |
| 13:27 | livingston | by the way is there a parallel some? (I know there is a parallel map) I could see myself looking for that in the very near future |
| 13:27 | technomancy | how about rand-from ? |
| 13:27 | stuartsierra | "elt" is good for situations like (rand-elk herd-of-bison) |
| 13:28 | rhickey | ouch |
| 13:28 | stuartsierra | heh |
| 13:28 | kotarak | maybe choose |
| 13:28 | kotarak | no, rand-nth is better |
| 13:28 | stuartsierra | yes, joking aside |
| 13:29 | chouser | rand-nth will work on seqs, but force the whole thing and do O(n) lookup? |
| 13:29 | stuartsierra | that would be more or less consistent with nth |
| 13:30 | rhickey | chouser: whatever nth does, given some random n |
| 13:30 | rhickey | in range |
| 13:30 | stuartsierra | but it's got to count first, so that's going to force a lazy seq |
| 13:31 | rhickey | stuartsierra: that doesn't change the big-O |
| 13:31 | stuartsierra | true |
| 13:32 | rhickey | people that use these things on large seqs are asking for trouble. Just want to make that clear to them |
| 13:32 | stuartsierra | Right, (rand-nth (range 100000000)) will blow heap unpredictably! |
| 13:32 | stuartsierra | no, predictably |
| 13:32 | stuartsierra | never mind |
| 13:32 | rhickey | I can't help people that do that |
| 13:34 | chouser | well, ranges could be Indexed. :-) |
| 13:34 | stuartsierra | actually, having a real Range object might be useful someday |
| 13:35 | rhickey | we had one, and it implemented Counted |
| 13:35 | stuartsierra | oh, what happened? |
| 13:36 | rhickey | it became a testing ground for chunks |
| 13:36 | LauJensen | rhickey: chunks going away soon? :) |
| 13:37 | stuartsierra | oh, so it was cut up into chunks and sold? |
| 13:37 | rhickey | LauJensen: no |
| 13:37 | LauJensen | rhickey: Thats sad. I was hoping your new cell construct could eliminate the need for them |
| 13:38 | rhickey | LauJensen: only so many hours in a day here |
| 13:38 | stuartsierra | :) |
| 13:39 | LauJensen | rhickey: Yea we're all feeling it. My question didn't have an end-date, so I was just poking at whether or not it was in the pipe for 1.3 or 1.4 etc |
| 13:39 | rhickey | how much do people care about group-by returning a map that is sorted? |
| 13:39 | stuartsierra | never noticed it did |
| 13:39 | arohner | rhickey: I wrote my own unsorted group-by so I could use transients |
| 13:39 | rhickey | arohner: exactly |
| 13:39 | Licenser | well night people |
| 13:41 | kotarak | rhickey: never needed sorted group-by, got bitten by it once. |
| 13:42 | rhickey | kotarak: bitten how? |
| 13:42 | rhickey | non-comparables? |
| 13:42 | kotarak | rhickey: I think so. IIRC. Was a while back. |
| 14:06 | slyphon | you know, the java interop stuff would be a little easier to use if calling it could be more dynamic |
| 14:07 | mefesto | hey everyone, i have a newbie style question. with the names invoice-inc, invoice-str... am i not using namespaces the way i should be? should names that match core function names be avoided? http://pastie.org/937655 |
| 14:07 | slyphon | i.e. pulling the literal symbol as the method that . is going to call makes it kind of difficult for a non-lisp-master |
| 14:08 | mefesto | i guess i'm wondering if invoice/str is preferred to invoice-str ? |
| 14:09 | joshua-choi | mefesto: The answer is not clear-cut. |
| 14:09 | slyphon | well |
| 14:09 | slyphon | shadowing core function names is probably a bad idea |
| 14:09 | chouser | slyphon: I don't quite know what you mean yet |
| 14:09 | chouser | not necessarily. nothing wrong with invoice/str |
| 14:10 | chouser | not really much wrong with invoice-str either. :-) |
| 14:10 | joshua-choi | slyphon: Actually, shadowing core function names was actually preferred when possible, according to a draft of Clojure style people were making on clojure-dev. |
| 14:10 | slyphon | chouser: it's very difficult to do this: (. blah (some-method-name-that-i-constructed-elsewhere arg1 arg2)) |
| 14:10 | slyphon | joshua-choi: uh, wut? |
| 14:10 | chouser | mefesto: invoice-inc is (update-in inv [:num] inc) |
| 14:11 | slyphon | joshua-choi: seriously? |
| 14:11 | stuartsierra | slyphon: that's explicitly not allowed |
| 14:11 | slyphon | stuartsierra: but why? |
| 14:11 | joshua-choi | slyphon: Let me try to find it |
| 14:11 | stuartsierra | reflection |
| 14:11 | slyphon | i'm confused |
| 14:11 | slyphon | there are legitimate reasons for wanting to do stuff like that |
| 14:11 | stuartsierra | (. object (method ...)) can become a bytecode method call, with appropriate type hints. |
| 14:12 | slyphon | ok, but what if you're willing to take the performance hit? |
| 14:12 | stuartsierra | Then use reflection. |
| 14:12 | stuartsierra | RT/invokeMethod or something |
| 14:12 | slyphon | hrm |
| 14:12 | slyphon | is that documented? |
| 14:12 | stuartsierra | no |
| 14:12 | joshua-choi | slyphon: http://groups.google.com/group/clojure-dev/browse_frm/thread/d090b5599909497 |
| 14:12 | slyphon | ... |
| 14:12 | stuartsierra | but java.util.reflection is |
| 14:13 | slyphon | yeah, but that's a pain in the balls |
| 14:13 | joshua-choi | My language was too strong; it's not "preferred", but "don't be afraid to". |
| 14:13 | slyphon | stuartsierra: sorry, i know that's a poor argument |
| 14:13 | chouser | ,(clojure.lang.Reflector/invokeInstanceMethod 4 "toString" (to-array []))"4" |
| 14:13 | clojurebot | "4" |
| 14:13 | stuartsierra | sorry, that should be java.lang.reflect |
| 14:13 | slyphon | i don't mean to be a whiny bitch |
| 14:14 | chouser | slyphon: there are legitimate reasons to do that, but not as often as you might think, and doing it efficiently can be tricky |
| 14:14 | stuartsierra | The dot special form can't be dynamic and avoid the reflection at the same time. |
| 14:14 | chouser | it's a kind of meta-programming and should be approached with caution, or at least that appears to be Clojure's take. Other (slower) JVM languages may take other approaches. |
| 14:15 | chouser | on techinque I've used is to (eval `(fn ...)) and cache the resulting fn. |
| 14:15 | chouser | this is relatively succinct and quite fast after the initial eval |
| 14:15 | stuartsierra | huh |
| 14:16 | slyphon | so (eval `(fn [] (. ~thing ~@arglist))) |
| 14:16 | slyphon | ? |
| 14:16 | chouser | yeah |
| 14:16 | chouser | ,(let [s (eval `(fn [n#] (. n# ~(symbol "toString"))))] (map s (range 4))) |
| 14:16 | clojurebot | DENIED |
| 14:17 | chouser | :-( he hates my metaprogramming. |
| 14:17 | slyphon | hahaha |
| 14:17 | slyphon | i'll try that in my repl |
| 14:17 | stuartsierra | It makes a kind of sense: you're generating thunks that contain compiled method calls. |
| 14:17 | kotarak | The lesson for using eval... |
| 14:17 | chouser | stuartsierra: exactly |
| 14:17 | stuartsierra | Actually similar to what the compiler itself does, I think. |
| 14:17 | slyphon | ah |
| 14:18 | slyphon | ok, well, that makes sense |
| 14:18 | cgrand | rhickey: (joining the party late) on group-by, I'd like it to take 4 args: [key-fn f seed coll], the 2-args case would then call (group-by key-fn conj |] coll) |
| 14:18 | chouser | well, not a thunk exactly, but yeah -- implementing IFn via eval :-) |
| 14:18 | stuartsierra | right |
| 14:18 | slyphon | stuartsierra: and the argument for performance is a compelling one |
| 14:18 | slyphon | as long as there's "a way to do it" that doesn't require pulling out the "big gun" of Reflection |
| 14:19 | slyphon | well, it's kind of a big gun to me |
| 14:19 | chouser | slyphon: depending on the circumstances, a macro or :inline fn may work and be easier than caching eval results |
| 14:19 | slyphon | :inline ? |
| 14:19 | chouser | more undocumented compiler fun. :-) |
| 14:19 | slyphon | i've tried that above with a macro and didn't get far |
| 14:20 | cemerick | ouch; at some point Region lost its DEFAULT value, so the ebs wrapper is now broken; gotta get some AOT-compilation into the build process so that stuff gets caught... |
| 14:20 | kotarak | slyphon: macros only get you to compilation |
| 14:20 | cemerick | ugh, sorry, wrong channel |
| 14:20 | slyphon | mmarczyk and i tried that for a while |
| 14:20 | chouser | for both macros and :inline, it only works if you can compute the method name at compile-time. |
| 14:20 | slyphon | ahh |
| 14:20 | slyphon | yeah, that's probably not gonna work here |
| 14:20 | chouser | where are you getting your method name from? |
| 14:21 | slyphon | in this case it's pretty static, but the number of args changes |
| 14:21 | slyphon | in the case with mmarczyk, i was trying to write a complement to the 'bean' function that let you update a bean |
| 14:21 | slyphon | (i wound up using reflection) |
| 14:22 | chouser | I've been doing some crazy/fun stuff along these lines with Google protobufs. |
| 14:22 | slyphon | oh yeah? |
| 14:22 | chouser | But it's for work, so I'll have to jump through some hoops to get it open-sourced. |
| 14:22 | slyphon | i've been meaning to look at those |
| 14:23 | slyphon | it sounds really interesting |
| 14:23 | chouser | if you can get away with slinging clojure s-exprs around as text or something, I highly recommend that. |
| 14:23 | chouser | protobufs are all static and java-y |
| 14:23 | slyphon | i was gonna ask |
| 14:23 | stuartsierra | chouser: tried avro? |
| 14:24 | chouser | but if you need them (in my case for interop with other services that use protobufs) they can be made pretty fast and convenient in Clojure. |
| 14:24 | slyphon | if i wanted to serialize a clojure data structure and stick it in a javax.jms.TextMessage, how do i do that, then un-freeze-dry it |
| 14:24 | slyphon | ? |
| 14:24 | stuartsierra | slyphon: prn-str, then read-string |
| 14:25 | lancepantz | we use protobufs |
| 14:25 | slyphon | ok, i kinda thought that was it |
| 14:25 | chouser | stuartsierra: no, I haven't. I wasn't involved in choosing protobufs, just using them. |
| 14:25 | stuartsierra | prn/read only works for simple cases, though |
| 14:25 | stuartsierra | ah |
| 14:25 | lancepantz | they are really really fast, we use atomic appends as well |
| 14:26 | chouser | avro sounds interesting though |
| 14:26 | slyphon | oy, *another* apache project? |
| 14:26 | slyphon | ;) |
| 14:27 | slyphon | guys, give someone else a chance! |
| 14:27 | stuartsierra | I think Avro grew out of Hadoop, actually. |
| 14:27 | slyphon | yeah, looks like it |
| 14:27 | stuartsierra | Hadoop had its own binary serialization protocol that nobody used. |
| 14:27 | LauJensen | nobody used? |
| 14:28 | stuartsierra | Yeah, it was called Hadoop Records or something. |
| 14:28 | lancepantz | has hadoop switched to avro now? |
| 14:28 | stuartsierra | dunno |
| 14:28 | LauJensen | Oh that one. They had that Binary format where you could munge a bunch of files together which was quite useful |
| 14:29 | stuartsierra | no, that's still there |
| 14:30 | LauJensen | I should really blog more about Hadoop, so much cool data to be crunched |
| 14:37 | LauJensen | What is this ibm-jdk-clojure-build stuff on build.clojure.org? |
| 14:37 | dysinger | I added it |
| 14:37 | dysinger | for stuart holloway |
| 14:37 | dysinger | to test for bugs in clojure 1.2 |
| 14:37 | LauJensen | its a test suite of sorts? Or just targeting a different jvm ? |
| 14:38 | dysinger | diff vm |
| 14:38 | LauJensen | ah ok, thanks |
| 14:43 | livingston_afk | i messed with protobufs for a while in common lisp, mostly because I wanted to make it into a tutorial on how you could hack the reader to read the format file - it was panning out to be pretty straightforward (only a few files of code), but I let it die |
| 14:44 | livingston_afk | considering it was mostly thesis-avoidance it kinda had to go -- maybe I'll pick it up again someday |
| 14:47 | livingston | is there a convenient way to give struct-map a default map to extend? |
| 14:48 | livingston | i mean I can merge, I just thought there might be something else |
| 14:54 | stuartsierra | no |
| 14:55 | livingston | yeah now that I look at it, I kinda like the merge anyway |
| 15:07 | LauJensen | When you guys are running off the latest versions on github, which version of swank do you use with that ? |
| 15:07 | stuartsierra | 1.2.0-snapshot |
| 15:08 | LauJensen | stuartsierra: Do you pull everything via deps or build yourself? |
| 15:08 | stuartsierra | I use maven |
| 15:08 | LauJensen | How? |
| 15:08 | clojurebot | with style and grace |
| 15:08 | technomancy | LauJensen: you should be fine using the version on clojars |
| 15:09 | LauJensen | k |
| 15:09 | Chousuke | heh, sometimes clojurebot amuses me :P |
| 15:09 | technomancy | and there should be a new release soon |
| 15:09 | technomancy | fingers crossed. |
| 15:09 | LauJensen | new release as in ? |
| 15:09 | technomancy | 1.2.0 stable |
| 15:10 | LauJensen | ah ok. How often are the snapshots pushed to clojars? |
| 15:10 | technomancy | it's not automated, but it happens often enough |
| 15:11 | technomancy | the swank-break stuff is in there, but not a lot has been committed since then |
| 15:12 | LauJensen | If not I'll email your employer explaining why he must fire you so that the opensource community can live on :) |
| 15:12 | technomancy | moar free time! |
| 15:12 | technomancy | last time I lost my job I wrote the Clojure PeepCode screencast =) |
| 15:14 | technomancy | LauJensen: hugod is also a committer on swank now, so if I am a bottleneck there is a workaround =) |
| 15:14 | LauJensen | lein new produces a bad :dependencies (old version?) and searching clojars for the clojure line is impossible |
| 15:14 | LauJensen | hugod: Its a privilegde watching hugo go, man that guy works fast :) |
| 15:14 | LauJensen | privilige |
| 15:14 | LauJensen | privilege |
| 15:14 | LauJensen | hmm, thats looks right |
| 15:15 | hugod | LauJensen: :), I built a time machine in my free time |
| 15:15 | LauJensen | sensible place to start |
| 15:15 | technomancy | LauJensen: interesting; could you submit an issue for that? |
| 15:15 | LauJensen | I could... :) |
| 15:16 | LauJensen | technomancy: can you drop the lines for lein, for the latest and great clojure, contrib and swank ? |
| 15:17 | dakrone | what's the best way to expand something like (my-func '(2 3 4)) into (my-func 2 3 4) ? |
| 15:17 | technomancy | sure: [[org.clojure/clojure "1.2.0-master-SNAPSHOT"] [org.clojure/clojure-contrib "1.2.0-SNAPSHOT"] [leiningen/lein-swank "1.2.0-SNAPSHOT"]] |
| 15:17 | technomancy | though you want lein-swank in dev-dependencies actually |
| 15:17 | kotarak | dakrone: apply |
| 15:17 | LauJensen | thanks |
| 15:18 | dakrone | kotarak: cool, thanks |
| 15:19 | LauJensen | technomancy: issue reported |
| 15:19 | technomancy | thanks |
| 15:20 | LauJensen | technomancy: btw - Loved that post you did on your pedantic requirements for contribs |
| 15:25 | chouser | technomancy: looks like you're using c.c.condition -- how's that going? |
| 15:26 | technomancy | chouser: I like it quite a bit |
| 15:26 | dysinger | "LauJensen: If not I'll email your employer explaining why he must fire you so that the opensource community can live o" <- lol |
| 15:26 | dysinger | no emails needed |
| 15:26 | dysinger | :) |
| 15:26 | LauJensen | ok, phil is *poof* :) |
| 15:27 | dysinger | no we need phil |
| 15:27 | technomancy | oh noes! |
| 15:27 | chouser | technomancy: excellent. I've been hesitent to walk away from vanilla throw/catch |
| 15:27 | technomancy | chouser: with contrib ticket #80 you can catch vanilla Exceptions in handle-case forms |
| 15:28 | technomancy | which makes them mesh fairly naturally |
| 15:28 | chouser | yeah, I saw that. looks good. |
| 15:29 | hugod | what's the distinction between condition and error-kit? |
| 15:29 | chouser | condition is might lighter-weight |
| 15:29 | chouser | -might +much |
| 15:29 | LauJensen | and condition is might heavier-weight |
| 15:30 | LauJensen | (sorry couldnt resist =) |
| 15:30 | technomancy | I like the idea behind error-kit, but it seems like it would be more useful if everyone else used it. it seems like it's subject to more of a chicken/egg dilemma |
| 15:30 | LauJensen | what dilemma? chicken came first |
| 15:30 | stuartsierra | dinosaurs had eggs |
| 15:31 | chouser | error-kit provides rarely-used features around outer dynamic scopes controlling the behavior of inner 'raises' and handlers. |
| 15:31 | chouser | and for free you also get a clumsy undocumented object system |
| 15:32 | ordnungswidrig | re |
| 15:33 | hugod | I miss CL restarts, very useful in slime |
| 15:33 | LauJensen | hugod: go implement, chop chop |
| 15:34 | chouser | you might be able to do something interesting with debug-repl + error-kit |
| 15:34 | hugod | well, patching condition/raise to call swank-break would be easy |
| 15:34 | chouser | but you'd probably be better off just using a Java debugger |
| 15:34 | LauJensen | chouser: only problem is, that they're hard to fit into Emacs |
| 15:35 | chouser | Java debuggers? Someone did it already. |
| 15:35 | cemerick | is JDEE still unpleasant? |
| 15:35 | chouser | all java is more pleasant from Clojure, even JDEE. :-) |
| 15:36 | algoriffic | hi all, how do i print out all nodes at a certain depth of an arbitrary tree structure? |
| 15:36 | hugod | LauJensen: haven't had time to do that yet... |
| 15:37 | LauJensen | k |
| 15:40 | digash | hmm, interesting message from defprotocol: Warning: protocol #'bar.foo/PacketHeaderReader is overwriting method foo of protocol MessageHeaderReader |
| 15:40 | digash | |
| 15:40 | chouser | technomancy: would there be any value in the Condition instance printing its values? |
| 15:40 | stuartsierra | digash: that's a bug with AOT-compiled protocols |
| 15:41 | stuartsierra | I think |
| 15:41 | chouser | really? |
| 15:41 | stuartsierra | if the method names are the same |
| 15:41 | stuartsierra | but that's not what digash posted |
| 15:41 | chouser | you can't have two protocol methods with the same name for two different protocols in the same namespace |
| 15:41 | chouser | AOT or not |
| 15:42 | digash | why is that? |
| 15:42 | chouser | they're namespaced to the namespace, not to the protocol. |
| 15:42 | digash | hmm, i am generating protocols in the macro, need to figure out how to do it then. |
| 15:43 | chouser | just think about how you'd call the protocol method and it should make sense. |
| 15:44 | chouser | (defprotocol Foo (bar ...) (baz ...)) (my.ns/bar ...) ; note no Foo in the method call |
| 15:45 | digash | ah, i see, it is different from deftype fields |
| 15:46 | digash | i need to generate accessors to my generated deftypes |
| 15:46 | digash | fields |
| 15:48 | chouser | hm... or have them implement ILookup so you can do (:my-field obj) |
| 15:48 | fogus | So for type (deftype Foo [a b]) |
| 15:48 | fogus | and (def x (Foo. 1 2)) |
| 15:48 | fogus | we can currently do (.a x) |
| 15:49 | fogus | But maybe that is not going to be true tomorrow? |
| 15:51 | chouser | fogus: That's documented and pretty well guaranteed I think |
| 15:51 | chouser | "The class will have the immutable fields named" |
| 15:51 | fogus | So accessor problem solved then? |
| 15:53 | digash | what about definterface, are the names of methods also namespaced? |
| 15:53 | digash | also what is hms? hash-map-set? |
| 15:54 | chouser | definterface produces an interfaced ("namespaced" in a Java package) with Java methods ("namespaced" in the interface) |
| 15:56 | digash | maybe i need that, then the java api would make more sense |
| 16:04 | digash | ,(definterface Dig (foo-bar [])) |
| 16:04 | clojurebot | java.lang.Exception: Unable to resolve symbol: definterface in this context |
| 16:05 | digash | (show Dig) |
| 16:05 | digash | === public abstract interface user.Dig === |
| 16:05 | digash | [ 0] foo-bar : Object () |
| 16:05 | digash | shouldn't it put _ in the name? |
| 16:05 | chouser | I think there's a ticket for that |
| 16:06 | digash | chouser: cool, thanks, just making sure my expectation is correct |
| 16:07 | chouser | though I'm not finding it now |
| 16:08 | chouser | digash: https://www.assembla.com/spaces/clojure/tickets/306 |
| 16:08 | sexpbot | "#306 - definterface does not convert - to _ (Fixed) | Clojure | Assembla" |
| 16:09 | tcrayford | that's been fixed recently that one |
| 16:09 | tcrayford | just saw it when I was looking through the commit log for clojure |
| 16:11 | tcrayford | ,(doc group-by) |
| 16:11 | clojurebot | "([f coll]); Returns a sorted map of the elements of coll keyed by the result of f on each element. The value at each key will be a vector of the corresponding elements, in the order they appeared in coll." |
| 16:13 | digash | hmm, it is still broken in clojure-contrib-1.2.0-20100427.200505-82.jar |
| 16:15 | chouser | well, turns out that patch only munges package names, not method names. |
| 16:16 | rhickey | digash: might I ask why you would have an interface with an invalid Java name? |
| 16:16 | rhickey | do you really want to expose name munging to Java clients? |
| 16:17 | digash | i started with defprotocol but ran into issue of namespace methods |
| 16:17 | digash | they i thought let me use interface |
| 16:17 | rhickey | the only reason we are supporting -/_ in packages is because people are already in my-ns... |
| 16:17 | rhickey | digash: what was the namespace methods issue? |
| 16:18 | digash | and make it also available to java people |
| 16:18 | digash | yes |
| 16:19 | rhickey | digash: what was the namespace methods issue? |
| 16:19 | digash | sorry, i misread you question |
| 16:19 | digash | i would not call it an issue, more ignorance on my part of protocol |
| 16:20 | digash | i though protocols are like interfaces |
| 16:20 | digash | and will generate java interface classes |
| 16:20 | rhickey | they will |
| 16:21 | digash | then i am confused about the method names in the protocol being namespaced NOT including the protocol name |
| 16:22 | rhickey | my.ns/Protocol becomes my.ns.Protocol interface, protocol method foo becomes interface method foo |
| 16:23 | digash | my.ns/Protocol1, method foo gives me a warning |
| 16:23 | rhickey | you wanted my.ns.Protocol interface, Protocol_foo method? |
| 16:23 | rhickey | what warning? |
| 16:23 | digash | <digash> hmm, interesting message from defprotocol: Warning: protocol |
| 16:23 | digash | #'bar.foo/PacketHeaderReader is overwriting method foo of protocol |
| 16:23 | digash | MessageHeaderReader [15:39] |
| 16:23 | digash | |
| 16:24 | rhickey | right, protocols put fns in the current namespace, so two protocols that define the same-named fn must be in different namespaces |
| 16:25 | rhickey | you can think of protocols as a way to define a set of fns in your ns |
| 16:26 | rhickey | still subject to the one def of name per ns |
| 16:27 | digash | the interface = protocol thing confused me, since it is possible in java to do it with interfaces |
| 16:27 | rhickey | to do what? |
| 16:27 | rhickey | two interfaces in same package with same method name? |
| 16:28 | digash | my.ns/Interface1 (foo) and my.ns/Interface (foo) |
| 16:28 | digash | yes |
| 16:29 | chouser | digash: depending on what you're trying to do, you could have your macro generate a whole namespace for your protocol. |
| 16:30 | digash | yes i guess i can do it, but I prefer it to be javaish |
| 16:30 | digash | since people are going to use it from java |
| 16:31 | chouser | maybe you want to use definterface and munge the method names yourself. my-method -> myMethod |
| 16:31 | rhickey | chouser: this seems independent of the munging |
| 16:32 | rhickey | digash: how would you use it from Clojure? |
| 16:33 | chouser | I haven't seen much pushback on the inability to share proto-method names in multiple protos of the same ns. digash seems to be running into it because of generating the names in a macro |
| 16:34 | digash | I would generate deftype or defrecord and the implementation for them |
| 16:34 | digash | it is like a small compiler |
| 16:35 | digash | the methods are very repetitive, it is a parser for the byte array and each method have offset and length and datatype |
| 16:35 | rhickey | chouser: I could see it coming from requirements that the Java side look like a.b.C and a.b.D interfaces, both with method foo. Couldn't deliver with protocols as it stands |
| 16:36 | chouser | sure, I can see that. Though it's an interop concern that definterface deals with already. |
| 16:37 | digash | chouser: i am implementing munging with definterfaces as we chat... |
| 16:38 | chouser | digash: where are you getting these method names (with dashes in them) from? |
| 16:38 | digash | data dictionary based on the spec |
| 16:39 | chouser | is there a reason you don't want them to have javaCamelCase names in the spec? |
| 16:40 | digash | there are hundreds of them and i copied it from the spec with spaces and replaced spaces with - |
| 16:40 | digash | so now i need to do camel-case on them |
| 16:40 | rhickey | Java devs wouldn't expect _s usually |
| 16:41 | chouser | so even from the clojure code you'll be using camelCase and java interop syntax? |
| 16:43 | rhickey | yes, that's what I'm missing, how do you intend to implement and consume on the Clojure side? |
| 16:44 | digash | i made it a macro, so i can bounce off the client, the names of methods |
| 16:45 | digash | the consumption would be to call a constructor with byte buffer |
| 16:45 | rhickey | and the method calls via interop? |
| 16:45 | digash | and then call any accessor and get a field value back |
| 16:46 | digash | ah, i see, another ignorance on my part |
| 16:46 | rhickey | digash: not necessarily, it could be some missing feature |
| 16:47 | chouser | heh, I guess you could generate one protocol per namespace (with dashed-names), and extend it to all the generated interfaces (calling camelCase methods) |
| 16:47 | digash | the methods on the defrecord are not available in java ? |
| 16:47 | rhickey | e.g. it would be easy to let defprotocol specify the name of the interface type |
| 16:47 | rhickey | digash: the only methods you can have in defrecord are those in interfaces, and thus consumable in Java via those interfaces |
| 16:48 | digash | not the ones on the protocol |
| 16:48 | rhickey | digash: yes, those too via its interface |
| 16:49 | chouser | if it feels like magic, that's because it is. |
| 16:49 | rhickey | all methods of a deftype/record are available from Java |
| 16:50 | rhickey | not extends of course |
| 16:50 | digash | ok, let me restate my understanding of protocols |
| 16:51 | digash | defprotocol will give me java interface |
| 16:51 | chouser | digash: if I understand what you're implementing now, you'll have an interface with camelCase accessors, and you'll be able to call those on an record that implements it from both java and clojure |
| 16:51 | mtm | before I roll my own, does anyone know of a GML (Graph Modeling Language, not Geography Markup Language) parser for Clojure (or, barring that, one for java)? |
| 16:51 | chouser | but from clojure, it'll look like java interop: (.foo myrecord) |
| 16:51 | rhickey | digash: yes, with interface type name my.ns.Protocol |
| 16:52 | digash | defrecord "implments" that protocol and gives me class |
| 16:52 | digash | then i can call the methods on the class through the interface |
| 16:53 | rhickey | digash: when you implement the protocol inline, the resulting record isA my.ns.Protocol. You never leverage that from the Clojure side explicitly |
| 16:53 | rhickey | digash: you'd call them that way from Java, but use my.ns/foo from Clojure usually |
| 16:54 | rhickey | doing so does away with all of the interop cruft and need for type hints, (foo x) is the same as (.foo ^my.ns.Protocol x) |
| 16:56 | digash | now, i see where the requirement for the namespace coming from |
| 16:56 | clojurebot | namespaces are (more or less, Chouser) java packages. they look like foo.bar; and corresponde to a directory foo/ containg a file bar.clj in your classpath. the namespace declaration in bar.clj would like like (ns foo.bar). Do not try to use single segment namespaces. a single segment namespace is a namespace without a period in it |
| 16:58 | slyphon | with .. do you have to wrap thunks in () ? |
| 16:58 | chouser | we haven't deprecated .. yet? |
| 16:58 | slyphon | :( |
| 16:58 | slyphon | uh |
| 16:59 | slyphon | should i use -> then? |
| 16:59 | stuartsierra | slyphon: to answer your question, no |
| 16:59 | chouser | I always recommend it, but I've been shot down on that point by Important People, so take it for what it's worth. |
| 16:59 | digash | i think i am going to stick with interfaces for now, since one of my goals is a java api and create names to look like java accessors getField, etc. |
| 16:59 | slyphon | i like -> |
| 17:00 | digash | rhickey: thank you for clarifications |
| 17:00 | chouser | what do you mean by thunks in .. ? |
| 17:00 | digash | chouser: thank you for suggestion |
| 17:00 | slyphon | (.. thing getSomething (add blah)) |
| 17:00 | slyphon | being thing.getSomething.add(blah) |
| 17:01 | slyphon | er |
| 17:01 | slyphon | being thing.getSomething().add(blah) |
| 17:01 | chouser | ah. right, what stuartsierra said. no need for parens if you only have the method's name there |
| 17:01 | slyphon | kk |
| 17:01 | Borkdude | -> is like a spear which forces your objects to accumulate through functional spheres |
| 17:01 | slyphon | Borkdude: :D |
| 17:01 | slyphon | ->> is that but harder |
| 17:01 | slyphon | blasts them clear to the other side of the parens |
| 17:07 | ataggart | I liked the notion that -> is for banging on an object and ->> is for banging on a stream |
| 17:08 | ataggart | inferred from something Rich wrote once |
| 17:08 | Chousuke | hm, why does that sounds painful to me? |
| 17:08 | Chousuke | like, you're mutating an object by banging it with a hammer or something |
| 17:08 | Borkdude | slyphon, how does Clojure's -> behave in comparison with C's --> operator? http://www.guyrutenberg.com/2007/11/19/c-goes-to-operator/ ;-) |
| 17:08 | sexpbot | " C’s “Goes To” Operator by Guy Rutenberg" |
| 17:08 | chouser | I always thought it was about how many open-mouthed people were trying to eat the cookie on the left. |
| 17:09 | chouser | no, actually, I didn't. |
| 17:09 | slyphon | hahahhaa |
| 17:09 | slyphon | where is the -?> hiding? |
| 17:10 | slyphon | Borkdude: wow, nothing like that |
| 17:10 | slyphon | Borkdude: that's kind of cool, though |
| 17:10 | slyphon | Borkdude: in a "Oh my god C syntax is totally retarded" kind of way |
| 17:10 | Borkdude | haha |
| 17:10 | slyphon | "Please stop doing that, it's going to fall off eventually" |
| 17:16 | Borkdude | "Most programmers know Lisp for its parentheses. Few programmers know their power." |
| 17:18 | Borkdude | I was thinking, while reading The Joy of Clojure about vectors being so ubiquitous in Clojure, if Lists to present code is still the right choice? Probably, because you always start with the head of a program and then the rest? |
| 17:20 | stuartsierra | In general, Clojure uses lists for things that will get evaluated somehow. |
| 17:20 | stuartsierra | And vectors for things that won't. |
| 17:24 | Borkdude | stuartsierra: things that will get evaluated... I can think of one example: code |
| 17:24 | stuartsierra | yeah |
| 17:24 | stuartsierra | I think I misunderstood your question. |
| 17:25 | Borkdude | I'm just checking if you had other things than code in mind |
| 17:27 | Borkdude | putting code into vectors instead would be back to GW-Basic: goto 10 ;P |
| 17:29 | Borkdude | stuartsierra: it isn't entirely true btw, Clojure uses vectors for argument 'lists |
| 17:29 | Borkdude | ', those will get evaluated first |
| 17:30 | Borkdude | But I'm just thinking out loud while being very tired, I better not do that |
| 17:36 | rich_holygoat | hi folks |
| 17:36 | rich_holygoat | I just ran into an annoying impedance mismatch; thought I'd run it past the IRC brains before hitting the list |
| 17:37 | rich_holygoat | deftype generates final classes; JAX-WS mandates that its classes be non-final. Is there any way to force deftype's classes to be non-final? |
| 17:38 | chouser | and an interface won't do? |
| 17:39 | rich_holygoat | chouser: it's the implementing class that gets annotated as a WebService, not its interface |
| 17:39 | rich_holygoat | "implementing class must not be declared final and must not be abstract... must have a default public constructor... must not define a finalize method..." |
| 17:40 | rich_holygoat | I don't know why, but there it is |
| 17:44 | Borkdude | Cool, Clojure in Action MEAP update |
| 17:48 | rich_holygoat | ah, reading the compiler source it looks like individual fields can have final removed by marking them as mutable, but the class as a whole is always emitted as final (and public, for that matter) |
| 17:50 | chouser | rich_holygoat: you might have to use gen-class to meet such specific requirements. |
| 17:50 | rich_holygoat | falling between two stools -- gen-class doesn't yet have annotations (though I see the patch in Assembla) |
| 17:51 | rich_holygoat | I do wonder precisely why the generated class is final -- it might just be that all other classes generated by Clojure using this mechanism are final, so it's this way by default |
| 17:52 | rich_holygoat | perhaps I'll ping Rich and see if he has a reason; I'm not averse to doing the patch work. |
| 17:53 | chouser | Clojure doesn't like implementation inheritence. |
| 17:53 | chouser | pure virtual abstract interfaces or concrete final implementations -- take your pick. :-) |
| 17:54 | rich_holygoat | and neither do I -- but it does allow volatile and mutable fields in deftype to allow "rolling up the sleeves". In this case it wouldn't be used for inheritance; merely to satisfy JAX-WS's demands |
| 17:54 | rich_holygoat | it would be a shame to have to add another layer of passthrough |
| 18:05 | livingston | I'm assuming alter-var-root is thread safe and will alter for all threads like this: (def foo 5) (binding [foo 2] (pr foo)) ;some other thread alters foo with inc (pr foo) -- I expect to see 2 and 6 printed right? |
| 18:05 | rhickey | rich_holygoat: what are JAX-WS's demands? |
| 18:05 | livingston | as long as I'm not under the scope of a binding form I always get the current root value, right? |
| 18:05 | Borkdude | I made a foolish little program that runs things like this: (def ops ['(goto 2) '(goto 4) '(println "two") '(goto 1) '(println "end")]) |
| 18:05 | Borkdude | |
| 18:06 | rhickey | livingston: yes |
| 18:06 | technomancy | livingston: yes, but in general if you've already got multiple threads running I would say it's too late to be thinking about alter-var-root |
| 18:06 | technomancy | it's a matter of taste, but that's my take on it |
| 18:06 | rhickey | technomancy: not really, with no bindings it still makes sense |
| 18:07 | technomancy | rhickey: ok, maaaaybe, but it still needs big caution signs all over =) |
| 18:09 | livingston | I've got this problem where RDF databases can communicate with an abbreviated URI, using an identifier for the namespace instead... I can query the server for the current mappings - constantly. but since my code is creating them, it'd be nice instead to juse cache them as they are created |
| 18:09 | livingston | as long as the mapping is cached before it's used, that seems like it'll be ok |
| 18:12 | livingston | the problem I'm worried about is one thread stores with a piece of short-hand, and later another thread gets it back, either the mappings have to be cached somewhere, or the threads have to ask every time they talk for the mappings in case new ones were added -- I think |
| 18:12 | rich_holygoat | rhickey: just sending you an email; saves spamming the channel. In short: non-final classes and a bunch of other things. |
| 18:15 | livingston | I'm also assuming binding something to itself is relatively benign? |
| 18:49 | sattvik | rich_holygoat: I am guessing that once the gen-class annotation patch is in, that should solve your problems. It gen-class generates non-final, public classes. It should also allow you to have some state and a default constructor. |
| 18:50 | vin | How can I find out if "hell" is in "hello world" |
| 18:51 | dakrone | vin: (re-find #"hell" "hello world") |
| 18:51 | rich_holygoat | sattvik: yes, that's one option; but if non-final deftypes are simply an omission, I'll take that route. |
| 18:52 | wooby | Chousuke, thanks for the tip on that futures macro gist |
| 18:54 | sattvik | rich_holygoat: deftype certainly is nice. The other problem is that if you want to have fields with a deftype, you cannot have a no-arg constructor. |
| 18:55 | rich_holygoat | sattvik: yup. fortunately I don't need fields (servlets etc. typically use a session for that -- they're stateless). deftype is really nice by comparison to gen-class for my purposes. |
| 18:56 | sattvik | rich_holygoat: That's good. I ran into the no-arg issue when trying to extend my EJB example with a stateful EJB. |
| 18:58 | rich_holygoat | ah, tricky :) |
| 18:58 | slyphon | woah, it never occurred to me, you can put a start-fn in a struct |
| 18:58 | slyphon | ~ wacky! ~ |
| 18:58 | clojurebot | Excuse me? |
| 18:58 | slyphon | :) |
| 18:58 | slyphon | clojurebot: botsnack |
| 18:58 | clojurebot | thanks; that was delicious. (nom nom nom) |
| 19:07 | raek | vin: a non-regex version (not= (.indexOf "hello world" "hell") -1) |
| 19:36 | livingston | is there a reason this is giving me a NullPointerException? (def *kb* nil) (alter-var-root *kb* #(if *kb* *kb* a-kb)) |
| 19:37 | livingston | can I not refer to something in it's alter form? (I guess I could call defonce, but this may get called a lot, I thought the alter seemed "cleaner") |
| 19:47 | zakwilson_ | Is there a built-in (or in contrib) more performant way to persist built-in data-structures to disk than (spit (str foo))? |
| 19:47 | technomancy | livingston: your function needs accept one argument, the current root value of the var |
| 19:48 | technomancy | not sure if that would cause a NPE |
| 19:50 | livingston | technomancy: that just dawned on me but... there still seems to be an issue: |
| 19:50 | ataggart | (alter-var-root #'*kb* #(if-not % "something")) |
| 19:50 | livingston | oooooh I have to #' the var? |
| 19:50 | ataggart | ya |
| 19:51 | ataggart | cuz *kb* isn't a var |
| 19:51 | ataggart | or rather, it doesnt resolve to a var |
| 19:51 | ataggart | if I jave my lingo correct |
| 19:51 | rhudson | livingston: is there a reason you're not doing something like (def abbrevs (ref {})) -- I mean, using a ref or atom for your URI abbrev data? |
| 19:52 | livingston | there's no reason for it to be a ref, that I can tell |
| 19:52 | rhudson | atom then? |
| 19:52 | livingston | a var does the same thing, right? just no transaction support, right? |
| 19:53 | rhudson | Seems like atoms are designed for what you're trying to do. |
| 19:55 | livingston | I guess atoms would work, but if I wanted to cover the values up with a binding I would then need to bind over it with a new atom etc. I just don't see what it buys me? |
| 19:56 | livingston | an atom would allow the threads to stay in sync, but I don't think that's really needed in my case |
| 20:04 | _rata_ | how do I get the minibuffer information that clojure-swank gives while at the REPL buffer in the other buffers as well? |
| 20:05 | livingston | _rata_: you mean the function call signatures and things? |
| 20:07 | _rata_ | livingston: yes |
| 20:08 | livingston | my buffers are in mode: (Clojure Slime[clojure]) and seems to work fine for me (w/ AquaMax) it's autodetected on .clj files you might have to add hooks in your .emacs |
| 20:08 | livingston | (add-hook 'lisp-mode-hook (lambda () (slime-mode t))) (add-hook 'inferior-lisp-mode-hook (lambda () (inferior-slime-mode t))) |
| 20:09 | livingston | that's pretty standard though, nothing special |
| 20:15 | _rata_ | oh thanks, livingston :) |
| 20:16 | livingston | np, did that work? |
| 20:17 | _rata_ | I did work before, but I had to press the spacebar after defn for it to show the help... I was standing over a piece of code already written |
| 20:38 | livingston | if I have (defmulti clj-ify type) is there a way to then define a defmethod that will accept any of a list of types? or do I defmethod for each type? |
| 20:41 | mmarczyk | (map #(defmethod clj-ify % [_] :foo) [String Integer]) |
| 20:41 | mmarczyk | also, how about calling it clojurify? :-) |
| 20:42 | mmarczyk | (just checked that map at the repl -- seems to work; perhaps it would be best to wrap it in a dorun, though) |
| 20:42 | Blkt | sounds like a World of Warcraft spell |
| 20:43 | mmarczyk | it *is* a World of Warcraft spell! cast clojurify on your sword and it becomes imbued with a spirit, which you can programme in Clojure |
| 20:43 | Blkt | Perl monk style? |
| 20:43 | Blkt | casting spells with Clojure |
| 20:43 | Blkt | omg |
| 20:43 | mmarczyk | :-) |
| 20:44 | livingston | yeah, I'm not sure that's worth doing .. it's just one liners, I'll think about it though if I get annoyed with this though |
| 20:44 | Blkt | (is it forbidden here to to use acronyms?) |
| 20:44 | mmarczyk | livingston: the proper way would probably be to derive a new relationship |
| 20:44 | mmarczyk | from the types to, say, ::MyGroupOfTypes |
| 20:44 | mmarczyk | and than use that as the dispatch value |
| 20:46 | livingston | yes I could isa them together... might do that |
| 20:46 | mmarczyk | (Blkt: forbidding acronyms!? doesn't that get one lynched in the IT community?) |
| 20:47 | mmarczyk | livingston: that buys you one more thing, namely you only have the one implementation of the multimethod |
| 20:48 | mmarczyk | if you change that, the change will work for all the types involved |
| 20:48 | mmarczyk | and there's always underive to kick out a type from the club |
| 20:51 | livingston | yeah I think I will create a pseudo class for this |
| 20:52 | livingston | it's kinda cool, in java there are like 10 classes but they all implement the same 3 functions, and clojure doesn't care when it comes time to call those 3 functions what it's being passed, it'll find the right thing |
| 20:52 | livingston | so I can treat the 10 or whatever things as if they are the same |
| 20:56 | mmarczyk | :-) |
| 21:05 | slyphon | man, i just suck at recursion |
| 21:09 | livingston | where there are multiple java methods with call signatures that maybe could be ambiguous to clojure, how can I make sure the right one is being called |
| 21:10 | livingston | e.g. this method has signatures Object Object Object Object and boolean Object Object Object and I think it may be calling the first instead of the second is there anyway to verify / force it |
| 21:10 | slyphon | i would imagine reflection is one way |
| 21:10 | somnium | livingston: you can use type hints |
| 21:11 | slyphon | yeah, that'd probably be easier |
| 21:11 | slyphon | Boolean/TRUE |
| 21:11 | mmarczyk | (boolean first-argument) instead of first-argument |
| 21:12 | mmarczyk | ,(boolean 1) |
| 21:12 | clojurebot | true |
| 21:12 | mmarczyk | ,(boolean true) |
| 21:12 | clojurebot | true |
| 21:12 | slyphon | ,(boolean 0) |
| 21:12 | clojurebot | true |
| 21:12 | slyphon | hah! |
| 21:12 | slyphon | suck it, C! |
| 21:12 | livingston | somnium: could you give me an example I tried (.method obj #^boolean true ... and it says Metadata can only be applied to IMetas |
| 21:12 | mmarczyk | yeah |
| 21:12 | chouser | that's not a type hint, but might help at runtime |
| 21:12 | mmarczyk | livingston: use (boolean true) |
| 21:13 | slyphon | really? there's nothing built-in that converts an Enumeration to a seq? |
| 21:13 | chouser | (doc enumeration-seq) |
| 21:13 | clojurebot | "([e]); Returns a seq on a java.util.Enumeration" |
| 21:13 | slyphon | oh ffs |
| 21:13 | slyphon | really? |
| 21:13 | chouser | :-) |
| 21:13 | mmarczyk | also see |
| 21:13 | mmarczyk | (doc iterator-seq) |
| 21:13 | clojurebot | "([iter]); Returns a seq on a java.util.Iterator. Note that most collections providing iterators implement Iterable and thus support seq directly." |
| 21:15 | slyphon | ok, i need some functional-fu here, i want to walk a NamingContext and print out, recursively, the tree |
| 21:15 | livingston | hmmm... ok looks like I have yet more problems then oh but wait, (boolean true) gives me a big-B Boolean |
| 21:15 | slyphon | for some reason this is stumping the hell out of me |
| 21:15 | livingston | the call signature seems to want an little-b boolean |
| 21:15 | mmarczyk | (doc tree-seq |
| 21:15 | clojurebot | EOF while reading |
| 21:15 | mmarczyk | (doc tree-seq) |
| 21:15 | clojurebot | "([branch? children root]); Returns a lazy sequence of the nodes in a tree, via a depth-first walk. branch? must be a fn of one arg that returns true if passed a node that can have children (but may not). children must be a fn of one arg that returns a sequence of the children. Will only be called on nodes for which branch? returns true. Root is the root node of the tree." |
| 21:15 | livingston | (at least that's what show is telling me) |
| 21:15 | slyphon | hrm |
| 21:16 | mmarczyk | also see clojure.zip |
| 21:16 | slyphon | see, now you guys are just makin me feel dumb |
| 21:16 | slyphon | :) |
| 21:16 | mmarczyk | livingston: when you pass (boolean true) to a method which expects a primitive Boolean |
| 21:16 | mmarczyk | it gets a primitive Boolean |
| 21:16 | mmarczyk | but when you do (class (boolean true)) |
| 21:16 | slyphon | mmarczyk: thanks |
| 21:17 | mmarczyk | then that (boolean true) gets boxed before being passed to the class function |
| 21:17 | livingston | yeah but there is also a method signature for that slot being an Object |
| 21:17 | livingston | and I think that instance of the method then becomes preferred |
| 21:17 | mmarczyk | livingston: I don't think so |
| 21:17 | livingston | (or at least that's what I'm trying to figure out - not my library) |
| 21:18 | mmarczyk | in fact |
| 21:18 | mmarczyk | http://stackoverflow.com/questions/2722856/how-do-i-call-overloaded-java-methods-in-clojure |
| 21:18 | sexpbot | "How do I call overloaded Java methods in Clojure. - Stack Overflow" |
| 21:21 | anair_84 | how do i do an import * |
| 21:21 | anair_84 | in clojure |
| 21:22 | Raynes | You can't import all the classes from a package. |
| 21:22 | anair_84 | :( |
| 21:22 | livingston | I'm reasonably confident because it's producing a Boolean instead of a boolean it's calling the the method with the Object signature and not the one with the boolean (little b) signature |
| 21:22 | anair_84 | Raynes: any thing close ? |
| 21:22 | anair_84 | can i list all classes in package and then import those ? |
| 21:22 | Raynes | You can do (:import [java.package Class1 Class2 Class3]) |
| 21:24 | Raynes | It's better to be explicit, even if it does require quite a bit of typing. Others don't have to guess where a class that you use comes from, and you always know which classes you have imported. |
| 21:24 | Raynes | At least, I assume that's the rationale for not being able to do what you want. |
| 21:24 | Raynes | Anyone, correct me if I'm wrong. :) |
| 21:24 | anair_84 | Raynes: yeah i understad the reasoning but in the repl importing explictly can be painful |
| 21:25 | anair_84 | extremely painful |
| 21:25 | Raynes | :\ |
| 21:27 | mmarczyk | livingston: have you visited that SO link? |
| 21:27 | mmarczyk | there is an example of a method overloaded on int vs. Object being called with 10 first, then with (int 10) |
| 21:28 | livingston | yes I looked |
| 21:28 | mmarczyk | right |
| 21:28 | livingston | I don't know - I'm just saying what I think I'm seeing on my machine |
| 21:29 | mmarczyk | that's consistent with everything else I've read on the issue |
| 21:30 | livingston | it's not my library so I can't get in there and muck with it and know for sure, but it's giving me an error that's consistent with it trying to do some object like stuff to my poor Boolean |
| 21:30 | slyphon | get a Method object through reflection and call it explicitly? |
| 21:30 | livingston | I have some workarounds for now, I think |
| 21:30 | slyphon | i think wall-hack will let you list the explicit signature |
| 21:31 | mmarczyk | (inc slyphon) |
| 21:31 | slyphon | :) |
| 21:32 | mmarczyk | hope it feels good to be incremented ;-) |
| 21:32 | slyphon | indeed :D |
| 21:32 | slyphon | i'm one more now! |
| 21:32 | mmarczyk | yeah; in time, one can grow by a thousand! |
| 21:32 | slyphon | hahaha |
| 21:36 | livingston | if I have the instance of a java object how do I get the member field foo (not the method foo, but a member variable?) |
| 21:36 | chouser | (.foo obj), and hope there's not also a method of no args named foo |
| 21:37 | livingston | no... but that's just great, it's not set |
| 21:38 | livingston | thanks |
| 21:41 | chouser | livingston: http://gist.github.com/381625 |
| 21:42 | slyphon | when you call a variadic method in java, do you have to terminate the array you pass in with a nil? |
| 21:43 | livingston | chouser: cool thanks for checking that. just for the sake of argument can you change that to be 4 objects and 1 boolean and 3 objects. |
| 21:43 | livingston | I'm sure it won't matter but that's the situation I'm in |
| 21:44 | livingston | actually there's like 10 methods signatures with excruciatingly minor variations (I hate this api already) |
| 21:46 | rhudson | chouser: lines 11-16 in that gist disturb me. Do you know why it behaves that way? |
| 21:46 | hiredman | slyphon: uh, no |
| 21:47 | livingston | rhudson: why? those lines seem fine? |
| 21:48 | rhudson | line 13 in particular |
| 21:49 | livingston | 13 is output? 11 creates an instance and sets it to u and 12 calls a method on that instance |
| 21:50 | rhudson | Right. It seems like u being dynamically typed in 12 is losing the conversion of the argumen to a primitive type. |
| 21:50 | chouser | without a hint on the target, the clojure compiler can't generate a single method call and has to generate reflection code instead |
| 21:51 | chouser | rhudson: I think that's right. |
| 21:51 | rhudson | But in the process converting back to boolean |
| 21:51 | rhudson | i mean Boolean -- missed the shift key |
| 21:52 | livingston | OH wait I read that wrong 11-13 are *exactly* my problem |
| 21:53 | livingston | it didn't work in those lines |
| 21:53 | mmarczyk | ohhh |
| 21:53 | mmarczyk | that's good to know |
| 21:54 | mmarczyk | would (.foo (cast mypkg.Ugly u) (boolean true)) work? |
| 21:54 | chouser | mmarczyk: no |
| 21:55 | chouser | you need a type hint |
| 21:55 | livingston | and line 15 is the fix |
| 21:55 | livingston | wow that's ugly |
| 21:55 | mmarczyk | ok, thanks |
| 21:56 | chouser | you can hint u |
| 21:56 | livingston | that's really unfortuante, so it's because it's using reflection to figure it out? and it's doing so at compile time? |
| 21:56 | mmarczyk | chouser: would you care to add this to this SO question: http://stackoverflow.com/questions/2722856/how-do-i-call-overloaded-java-methods-in-clojure ? |
| 21:56 | sexpbot | "How do I call overloaded Java methods in Clojure. - Stack Overflow" |
| 21:56 | chouser | (def #^mypkg.Ugly u (mypkg.Ugly.)) |
| 21:57 | chouser | livingston: not quite |
| 21:58 | livingston | yeah I seem to be back to rhudson 's question because yeah, that certainly doesn't seem right |
| 21:58 | slyphon | wow, java, you complete me |
| 21:58 | livingston | or at least doesn't seem like something that should confuse clojure |
| 21:59 | chouser | at compile time when it can't figure out exactly one correct method to call, it generates code to do reflection at runtime, and by then it seems to have lost track of the fact that the arg is a primitive. |
| 22:00 | mmarczyk | chouser: that's if you do SO, of course, otherwise I could post a link to your gist myself -- seems directly relevant to that question |
| 22:02 | livingston | why doesn't it know that the arg is primitive? - i mean it makes sense that it didn't know, that was my problem BUT ... even with the type hint that only tells it the class the method is attached to not the method signature which still must wait until runtime I would think? |
| 22:03 | mmarczyk | that would make sense if you could compile the code without having the class on your classpath |
| 22:03 | slyphon | or, you could be explicit and use wall-hack-method...? |
| 22:03 | livingston | it seems like if it can compute any method signatures at all, it should be able to get past this particular problem without much trouble at all? |
| 22:03 | slyphon | and Boolean/TYPE |
| 22:04 | slyphon | wrapped in a parital...? |
| 22:04 | hiredman | livingston: the method signature definitely does not have to wait until runtime |
| 22:04 | mmarczyk | livingston: well actually this isn't at all different from what happens when you compile Java code |
| 22:04 | chouser | mmarczyk: eh, go ahead. |
| 22:05 | chouser | I started an answer, but I should be doing other things. |
| 22:06 | mmarczyk | chouser: if it's a certain book you have in mind, I'm definitely interested in removing any distractions you might face :-) |
| 22:07 | livingston | hiredman: it doesn't have to, but it sometimes it must right? if it doesn't know and and has to dispatch |
| 22:07 | rhudson | At this point I'd be tempted to wrap the pesky overloaded methods, in Java or Clojure, give them distinct names (f-yes-I-mean-the-one-with-little-b-boolean-first-arg-dammit) & use those |
| 22:08 | hiredman | livingston: what do you want? |
| 22:08 | livingston | mmarczyk: I suspect not, but one of the most unattractive things about java is how about 50% of your code is type information (hell even Ada wasn't that bad) |
| 22:09 | pdk | couldve been haskell :p |
| 22:09 | livingston | hiredman: I'm just confused as to how this is confusing to the compiler |
| 22:09 | mmarczyk | livingston: well that (.foo ^TypeHint stuff more-stuff) business hardly seems to suffer from this problem |
| 22:09 | mmarczyk | it's just one hint, you know :-) |
| 22:11 | livingston | if the compiler can't figure it out at compile time and has to generate some reflection code to dispatch at run time, and it gets the arguments bool I would expect it to quite easily call the bool one, I mean why should that change if it knows the base class or not? |
| 22:11 | livingston | that's what's weird about this |
| 22:12 | chouser | it's actually already some pretty gnarly code. dynamic method invocation on the jvm is a bit of a mess. |
| 22:13 | chouser | But I'm only suggesting why it doesn't, not that it couldn't or shouldn't handle this. |
| 22:15 | livingston | so is this just a limitation of the clj compiler? or of the jvm or something else in general? |
| 22:15 | mmarczyk | does the unhinted code generate a reflection warning? |
| 22:17 | livingston | mmarczyk: it just breaks at runtime (from what I can tell) at the repl - I didn't try compiling it any other way |
| 22:17 | rhudson | ,*warn-on-reflection* |
| 22:17 | clojurebot | false |
| 22:17 | rhudson | (doc *warn-on-reflection*) |
| 22:17 | clojurebot | "; When set to true, the compiler will emit warnings when reflection is needed to resolve Java method calls or field accesses. Defaults to false." |
| 22:17 | defn | for someone with very limited java experience is reading effective java worth the time, or should i start with a more introductory text first? |
| 22:17 | chouser | mmarczyk: yes, you get reflection warnings |
| 22:18 | defn | ,(set! *warn-on-reflection* true) |
| 22:18 | clojurebot | java.lang.IllegalStateException: Can't change/establish root binding of: *warn-on-reflection* with set |
| 22:20 | mmarczyk | ok, thanks |
| 22:20 | mmarczyk | in that case it's fairly easy to catch |
| 22:21 | mmarczyk | I'd expect the compiler to become more sophisticated when it transitions to Clojure, no? |
| 22:21 | chouser | it will certainly become less painful to change. |
| 22:21 | mmarczyk | should be more pleasant adding stuff in Clojure than in Java |
| 22:24 | mmarczyk | ok, posted that SO answer, hope it's accurate |
| 22:27 | rhudson | defn: I'd say start with something else besides Effective Java. (I think the best way to write effective Java is to write Clojure :) ) |
| 22:27 | chouser | ok, it looks like when it generates reflection code, it just stuffs the args into an array (Object[]), and that's all it uses to find the correct method at runtime. |
| 22:29 | livingston | this is the clojure compiler? so it just gets the class'es then and the big-B Boolean wins as an Object? |
| 22:30 | livingston | OH wait I see so it need to use reflection when it doesn't know the object's type, BUT when it does it just hands it off to the jvm for normal dispatch? |
| 22:31 | chouser | http://github.com/richhickey/clojure/blob/master/src/jvm/clojure/lang/Compiler.java#LID1278 |
| 22:32 | chouser | no, not quite. |
| 22:33 | chouser | if it knows the type of the target and the types of enough of the args *at compile time* (which it does by using reflection at compile time), then it generates a normal java method call which at runtime is handled by the normal jvm dispatch stuff. |
| 22:34 | defn | rhudson: any recommendations? |
| 22:34 | defn | rhudson: i dont wanna learn java so much as i want to learn enough java to use it properly in clojure |
| 22:35 | livingston | I hate the API that lead me to this even more now ... for one class they have .getNameSpace and another is .getNamespace - so I can't just use one simple clojure function that doesn't care which class it gets - blech |
| 22:35 | livingston | chouser: ok that's starting to make sense |
| 22:35 | chouser | if it doesn't know enough at compile time, it stuffs the args into an Object[] and generates code that at runtime will do reflection to find the right method and call it via refleciton |
| 22:35 | defn | livingston: i think you can do that with a multimethod |
| 22:36 | defn | livingston: are you talking about inheritance? |
| 22:36 | rhudson | The intro stuff in Java in a Nutshell is pretty good, then you have a good reference to the standard library as well |
| 22:36 | livingston | chouser: ok that also makes sense |
| 22:36 | defn | rhudson: cool! thanks |
| 22:36 | chouser | but since all its got is an Object[], primitives have gotten autoboxed and so the Object,Object,Object signature matches |
| 22:36 | livingston | defn: I know i can but it'd be nice not to have to |
| 22:37 | livingston | chouser: ok good, at least this is telling a sane story as to why this works this way |
| 22:38 | defn | livingston: idk, i think the control over polymorphism is pretty cool -- i like having that fine grain control |
| 22:38 | defn | id almost prefer clojure *not* do that for me |
| 22:40 | slyphon | defn: it's easy to make it do "dumb polymorphism" too, just dispatch off the class or (obj :type) of the first arg |
| 22:41 | livingston | chouser: this is odd though, because getParameterTypes must return something where primitives are discernible? because clojure.contrib.repl-utils/show knows the difference between big-B and little-b boolean |
| 22:41 | slyphon | i remember that kind of blew my mind the first time i played around with CLOS |
| 22:41 | livingston | (unless it's just calling toString or something) |
| 22:43 | mmarczyk | livingston: sure, but if the compiler postpones reflection until runtime and then at runtime all you've got is Object[], then the fact that reflection could find a (boolean, Object, Object) method is irrelevant by that point |
| 22:43 | mmarczyk | you'd have to not stuff everything into Object[], basically |
| 22:44 | mmarczyk | incidentally, the new ^foo syntax for reader meta data is Really Pretty :-) |
| 22:44 | chouser | right. or include flags indicating which args were primitives and should unboxed again. |
| 22:44 | livingston | or route it through the regular dispatch code? |
| 22:45 | livingston | couldn't you just scan for things that could be primitive? |
| 22:45 | chouser | livingston: The jvm doesn't have "regular dispatch code" that's dynamic |
| 22:45 | chouser | you have to name a specific method of a specific class or interface at compile time |
| 22:46 | livingston | although that presumes it's illegal to have a Boolean and a different little-b boolean - because you couldn't tell between those... |
| 22:46 | livingston | chouser: I meant the clojure dispatch code, basically dynamically build a multi-method |
| 22:46 | mmarczyk | http://blogs.sun.com/jrose/entry/dynamic_invocation_in_the_vm |
| 22:46 | sexpbot | "dynamic invocation in the VM - John Rose @ Sun" |
| 22:47 | mmarczyk | I am under the impression that invokedynamic will make all of this easier |
| 22:47 | mmarczyk | is this correct? |
| 22:47 | livingston | interesting |
| 22:48 | livingston | well there's still a problem though if you can have two signatures one with a little b and one big B because you won't know to unbox or not, right? |
| 22:49 | chouser | livingston: that's why I was suggesting a separate set of info about which args were primitives before being stuffing into the Objectp[ |
| 22:49 | chouser | Object[] |
| 22:49 | dnolen | is contrib being continuously rebuilt as well? |
| 22:49 | dnolen | that is, how can I get the latest in my lein project? |
| 22:50 | mmarczyk | clojure-contrib-1.2.0-SNAPSHOT |
| 22:50 | mmarczyk | I believe |
| 22:50 | livingston | chouser: yeah, I think that is the right thing. clojure could do that today and get around this problem |
| 22:50 | dnolen | mmarczyk: is that coming from hudson as well? |
| 22:50 | mmarczyk | it is, afaik |
| 22:50 | mmarczyk | I mean it must be, since there's no c-c in maven central or clojars to the best of my knowledge |
| 22:51 | dnolen | i see, somewhat confusing the lack of master in the name when clojure has it. |
| 22:51 | mmarczyk | true |
| 22:51 | chouser | livingston: I pasted a link to the code. feel free to write a patch and try to get it in. |
| 22:51 | chouser | :-) |
| 22:52 | mmarczyk | the last c-c build is from ~7 hrs ago |
| 22:52 | livingston | although I'm still a bit confused, why there isn't a simpler solution? since somewhere somehow with an array of objects show is able to show me the difference between a Boolean and a boolean |
| 22:52 | chouser | I suspect rhickey won't want this kind of change so close to 1.2 release, but I could be wrong. |
| 22:52 | mmarczyk | livingston: I'm not sure what you mean |
| 22:52 | livingston | http://github.com/richhickey/clojure-contrib/blob/4f9a78d13217a8de4c29221d74aca0a67cec8c1a/src/main/clojure/clojure/contrib/repl_utils.clj#L59 |
| 22:52 | mmarczyk | i.e. what use of show you have in mind |
| 22:52 | chouser | livingston: there's two different things that have to be matched up. Clojure's got to find the declared method that matches the actual args. |
| 22:53 | livingston | right |
| 22:53 | mmarczyk | yeah, I use show all the time, but that's at the REPL to find out what methods a class has |
| 22:53 | chouser | 'show' and the Clojure compiler and the Clojure runtime reflection code all have no problem finding which declared methods have primitive args. |
| 22:53 | mmarczyk | which has nothing to do with matching the correct method with a given set of arguments |
| 22:53 | chouser | the problem is knowning what the actual args being passed in are. |
| 22:54 | livingston | right and show can tell me the difference between little and big B, but I'm looking at the code and they seem to use an array of objects, which suggests there's a way to pass the little b boolean around without losing it's type... |
| 22:54 | chouser | Once the actual args have been put in an Object[], clojure.lang.Reflector/invokeInstanceMethod looks at the type of each actual object there to see if it can find a matching declared method |
| 22:55 | livingston | oh wait I see where I went wrong, the object coming out of getParameters aren't objects, duh |
| 22:55 | livingston | they're something else Parameters or something (probably) |
| 22:56 | livingston | no yeah I get it - I was just over generalizing or something about how show worked |
| 22:56 | livingston | blech |
| 22:57 | livingston | yeah your vector of what was / wasn't boxed is good, also meta type hints on the parameters themselves to suggest a call signature to force it would be fine too |
| 22:58 | livingston | I would have liked (.foo (mypkg.Ugly.) #^boolean true) |
| 22:58 | livingston | but your can't type hint there currently |
| 22:59 | livingston | although, the auto un/re boxing should really fix this up (that's something I like about lisps, is not having to crud up my code with types) |
| 23:01 | mmarczyk | livingston: actually (boolean true) does ensure that the true is unboxed -- and it will be used unboxed if non-reflective code can be generated |
| 23:02 | mmarczyk | so the key hint becomes the one on the object you're calling the method on |
| 23:03 | livingston | although one would think the literal true would be sufficient for that |
| 23:03 | mmarczyk | hm? why would you think that? |
| 23:03 | chouser | all literals in Clojure are currently boxed |
| 23:03 | slyphon | wah-wah |
| 23:03 | mmarczyk | with both little-b and Big-B Booleans around |
| 23:04 | mmarczyk | incidentally, having both little-b and Big-B Booleans seems crazy to me |
| 23:04 | livingston | well the first problem is that booleans and other types need two forms |
| 23:04 | mmarczyk | I'm not saying it doesn't make sense |
| 23:04 | chouser | ,(expression-info true) |
| 23:04 | clojurebot | {:class java.lang.Boolean, :primitive? false} |
| 23:04 | chouser | ,(expression-info 5) |
| 23:04 | clojurebot | {:class java.lang.Integer, :primitive? false} |
| 23:04 | chouser | ,(expression-info (long 5)) |
| 23:04 | clojurebot | {:class java.lang.Long, :primitive? false} |
| 23:04 | chouser | heh |
| 23:04 | mmarczyk | I'm perfectly prepared to believe that it makes sense in a very deep way due to performance considerations or whatever |
| 23:04 | mmarczyk | or just history |
| 23:04 | chouser | ,(expression-info '(long 5)) |
| 23:04 | clojurebot | {:class long, :primitive? true} |
| 23:04 | mmarczyk | but it makes it no less crazy |
| 23:04 | livingston | the second is even needing boolean at all, common lisp has gotten along just fine with nil being false and everything else is true |
| 23:05 | mmarczyk | why expect straightforward literal behaviour in this situation :-) |
| 23:05 | mmarczyk | livingston: the Java world is doing reasonably well despite the ridiculous decision to have a separate notion of Booleans ;-) |
| 23:05 | livingston | all this boxing only makes sense when you live in the Kingdom of Nouns |
| 23:05 | slyphon | hah |
| 23:06 | mmarczyk | incidentally, coming from Scheme, I still find it somewhat surprising that we have two false objects :-) |
| 23:06 | mmarczyk | or should I say falsey |
| 23:06 | slyphon | it makes sense when your design has made tradeoffs for performance reasons |
| 23:06 | slyphon | mmarczyk: coming from ruby it's very natural |
| 23:07 | slyphon | mmarczyk: although, i must say, i'm very happy that '{} and nil aren't equivalent |
| 23:07 | slyphon | er '() |
| 23:07 | mmarczyk | slyphon: I'm actually trying to learn a bit of Ruby now |
| 23:07 | slyphon | mmarczyk: ruby is fun |
| 23:07 | mmarczyk | slyphon: just because so many Clojurians seem to have strong Ruby backgrounds |
| 23:07 | slyphon | :) |
| 23:07 | livingston | the only reason there's a performance issue is that java decided that everything needed to be objects and that numbers et. al can't play where everything else is allowed to play without a big brother object to hold it's hand |
| 23:07 | mmarczyk | makes me curious :-) |
| 23:07 | slyphon | yeah, i've been a ruby developer for about 4 years |
| 23:07 | mmarczyk | but it does look *really weird* to me :-) |
| 23:07 | slyphon | (primarily) |
| 23:08 | slyphon | hahahaha |
| 23:08 | dnolen | livingston: that's not the problem at all, IMO. fns should accept and return anything, that means boxing. |
| 23:08 | dnolen | the only time you don't want that behavior is truly performance critical code. |
| 23:09 | mmarczyk | livingston: if you're proposing to have a Java-bashing session, I'm at one with that :-) |
| 23:09 | livingston | mmarczyk: no I do that enough at work (we're a java shop) |
| 23:10 | mmarczyk | livingston: yeah, I guess your Java must be thouroughly bashed then |
| 23:10 | mmarczyk | that must be some really atrocious api you're trying to use, btw |
| 23:10 | livingston | dnolen: only if you assume that an object is somehow different from a number - common lisp doesn't have this issue, it has a type hierarchy with numbers in it - things work just fine |
| 23:11 | mmarczyk | somehow the .getNamespace vs. .getNameSpace thing really gets to me |
| 23:11 | livingston | mmarczyk: it's Jena and AllegroGraph's bastardization of Jena |
| 23:11 | mmarczyk | filed under "try not to need to use" |
| 23:11 | slyphon | livingston: it's different when you're referring to an Object and when you're referring to a location in memory |
| 23:12 | livingston | it makes me want to gouge my eyeballs out that it takes about 4-9 method calls (and a lot of objects) to do the equivalent of '(ex/a rdf/type ex/b) |
| 23:12 | livingston | I'm working on that though |
| 23:14 | livingston_ | awesome - web client died |
| 23:15 | livingston_ | not sure what I missed but I was going to say: |
| 23:15 | slyphon | livingston_: what client are you using? |
| 23:15 | livingston_ | I don't have to worry about when I call this method I get Triples back but when I call that one I get Statements back they are exactly the same, except completely different |
| 23:15 | livingston_ | http://webchat.freenode.net/ |
| 23:15 | sexpbot | "freenode Web IRC (qwebirc)" |
| 23:15 | slyphon | oh, nice |
| 23:15 | livingston_ | port 6667 is blocked here |
| 23:15 | slyphon | my buddy has the same situation |
| 23:15 | slyphon | "hackers use irc" |
| 23:16 | slyphon | (schmucks) |
| 23:17 | livingston_ | I wonder if I'm still here |
| 23:17 | rhudson | yep |
| 23:17 | livingston | (it just told me I timed out so I was confused - that was the old client I guess) |
| 23:18 | defn | slyphon: are you ming slyphon? |
| 23:19 | slyphon | defn: hahahahaha |
| 23:19 | slyphon | defn: i haven't heard that in ages |
| 23:19 | mmarczyk | "hackers use irc and we *certainly don't* want to employ hackers, do we" |
| 23:19 | defn | slyphon: im not even sure why it's funny! i just realized i have you on my google talk contact list |
| 23:19 | mmarczyk | makes perfect sense for an it shop |
| 23:20 | slyphon | defn: orly!? |
| 23:20 | defn | slyphon: we talked in ruby-lang ages ago |
| 23:20 | slyphon | defn: ahhh |
| 23:20 | slyphon | defn: i used to go by mingus also |
| 23:20 | slyphon | in #twisted |
| 23:20 | defn | ahhh |
| 23:20 | defn | a fan of charles? |
| 23:20 | slyphon | indeed! |
| 23:21 | livingston | 99% of the people here don't program - so it doesn't kinda make sense and a good preventative measure against worms - I can't say I don't understand why |
| 23:21 | slyphon | unless someone decides to run their CNC server on port, say, 6668 |
| 23:21 | slyphon | or 80 |
| 23:21 | slyphon | or 53 :D |
| 23:22 | slyphon | EVIL |
| 23:22 | dnolen | livingston: I see, I suppose that's what rhickey means when he says breaking with Lisp tradition. I do note that that even Common Lisp requires you to declare types in fns that use them. Clojure's deftype does avoid that. always tradeoffs I suppose. |
| 23:22 | livingston | I haven't checked but my guess is that everything that isn't http or ssh related is blocked - even skype's blocked |
| 23:22 | slyphon | woah, skype is hard to block |
| 23:23 | slyphon | they go out port 80 if necessary |
| 23:23 | livingston | dnolen: you don't have to put types in function signatures in CL |
| 23:23 | slyphon | is deftype in 1.2? |
| 23:23 | livingston | you do if you want to dispatch but then... |
| 23:23 | dnolen | not in signatures, but inside the fn to hint the compiler no? |
| 23:24 | livingston | some CL compilers will generate unsafe code with type info and (speed 3) (safety 0) set |
| 23:24 | dnolen | like SBCL i imagine. |
| 23:25 | livingston | dnolen: no no types unless you need the compiler to be more efficient (rare) - in fact it's genearally advisable to avoid them - then you can reuse and maintain code easier |
| 23:25 | livingston | ditto with clojure |
| 23:28 | dnolen | livingston: but that's more of an issue with CL, with so many compilers with different capabilities. In Clojure I only ever want type hints on arithmetic. |
| 23:30 | livingston | dnolen: it's the same thing - only hint when a bottleneck is found otherwise don't worry about it and don't waste your time - that's what the profiler is for |
| 23:32 | dnolen | livingston: except un-type hinted arithmetic is dog slow. I've seen it enough times first hand (doing graphics stuff) that I never want to do arithmetic with boxed numbers. |
| 23:33 | dnolen | you also never want to add non-binary arithmetic. the slowness is horrifying |
| 23:33 | livingston | ,(+ 3 4 5 ) |
| 23:33 | clojurebot | 12 |
| 23:33 | dnolen | that won't be inlined |
| 23:34 | mmarczyk | ,(+ (+ (int 3) (int 4)) (int 5)) |
| 23:34 | clojurebot | 12 |
| 23:34 | mmarczyk | oh, but so ugly |
| 23:34 | mmarczyk | ,(unchecked-add (unchecked-add (int 3) (int 4)) (int 5)) |
| 23:34 | clojurebot | 12 |
| 23:34 | dnolen | that's what macros are for |
| 23:34 | livingston | How do you know what + creates? |
| 23:34 | mmarczyk | oh, but even more ugly |
| 23:34 | hiredman | there is some possibility that the reduce protocol stuff will make reducing over an array of ints the fastest way to add |
| 23:34 | mmarczyk | true |
| 23:35 | dnolen | (prim float (+ 1 2 3 4 5 6 7 8 9 10)) |
| 23:35 | dnolen | is one macro I wrote to do the right thing |
| 23:35 | mmarczyk | hiredman: oh, that's a cool idea |
| 23:35 | livingston | most functions like that have multiple dispatch for 1 2 3 and many parameters to optimize for the common cases |
| 23:35 | mikem | ~def int |
| 23:36 | slyphon | chouser: where do inline functions live? |
| 23:36 | hiredman | + has one inline, which calls the binary add in Numbers |
| 23:36 | hiredman | ,(:inline (meta #'+)) |
| 23:36 | clojurebot | #<core$_PLUS___4516 clojure.core$_PLUS___4516@183ccdb> |
| 23:36 | hiredman | ,(:inline-arities (meta #'+)) |
| 23:36 | clojurebot | #{2} |
| 23:36 | livingston | I don't do enough math in code where it's ever been the case that I could get significant speed by altering my numbers my run-time goes to other things |
| 23:37 | slyphon | wow, ok |
| 23:37 | dnolen | livingston: as rhickey has said, if Clojure get's unboxed arithmetic everybody's code is going to get way faster, not just math code. |
| 23:37 | dnolen | billions of operations per second, instead of tens of millions |
| 23:38 | slyphon | dnolen: pfft, how often do computers have to "add things"? |
| 23:38 | slyphon | c'mon |
| 23:38 | dnolen | slyphon: heh, a good joke if you meant it :D |
| 23:39 | slyphon | :D |
| 23:39 | slyphon | eyebrows, even |
| 23:39 | mmarczyk | well now |
| 23:39 | livingston | in my world not that often only for bookkeeping (like how long did this take) - I do symbolic AI - it's all lists and symbols |
| 23:40 | mmarczyk | chouser: livingston: it appears that locals don't need type hints |
| 23:40 | mmarczyk | http://gist.github.com/381686 |
| 23:41 | mmarczyk | when their type can be inferred, that is |
| 23:42 | mmarczyk | (let [t u] ...) would still use the Object method |
| 23:42 | livingston | mmarczyk: wait what how the hell is that possible? |
| 23:42 | livingston | right ok |
| 23:43 | livingston | presumably code that wasn't the constructor in that let would also wreck some havoc |
| 23:43 | mmarczyk | (.foo (foo.TestInterop2.) true) uses the bool method too |
| 23:43 | mmarczyk | so apparently the compiler checks whether it's actually just emitted the code to construct the object in question (in which case it knows all about it) |
| 23:43 | mmarczyk | in addition to using type hints |
| 23:48 | livingston | well this has been fun everyone |
| 23:48 | mmarczyk | right |
| 23:48 | mmarczyk | one more thing |
| 23:48 | mmarczyk | (see my gist) |
| 23:48 | livingston | I'm going to go get some food and cuss about Triples not be the same as Statements |
| 23:48 | mmarczyk | you can also type-hint a Var |
| 23:48 | mmarczyk | then wherever you use this Var |
| 23:48 | livingston | *looking |
| 23:48 | mmarczyk | the type hint will be taken into account |
| 23:49 | mmarczyk | from what I gathered from experimenting at the repl, anyway |
| 23:50 | livingston | oh huh |
| 23:50 | livingston | most of my things are coming out of maps, but there might be a way to hint those too |
| 23:51 | livingston | but like i said, things are a little fluid now so I'd like to avoid having to lock things down too soon |
| 23:51 | mmarczyk | sure |
| 23:51 | livingston | thanks again everyone |