2010-11-19
| 00:00 | technomancy | rata_: the example on that page actually is a leiningen plugin; you just have to add it to :hooks in project.clj to activate it |
| 00:00 | technomancy | I've been thinking about a function that would abstract away the messiness of being able to add-hook inside eval-in-project, but haven't written anything yet |
| 00:00 | rata_ | yes, I got that part |
| 00:02 | rata_ | the part I don't imagine how to implement is how to show the return value of a function call and all its locals |
| 00:02 | rata_ | I thought that had to be implemented in swank-clojure |
| 00:05 | technomancy | hmm... lemme think |
| 00:07 | technomancy | if you don't mind args being a single vector instead of being named, this would do it: http://p.hagelb.org/break.clj.html |
| 00:07 | technomancy | it would be possible to make break-hook's args match those of the target function with a severe macro, but I don't think I'm up for the task right now |
| 00:10 | rata_ | yes, that's close to what I want, but I'd like to see the locals, not just the args |
| 00:10 | rata_ | that's the most complicated part probably |
| 00:11 | technomancy | the macro would have to construct the hook function based on the :arglists in the metadata of the target function |
| 00:12 | rata_ | it'd have to insert the body of target there to have all the locals |
| 00:13 | rata_ | but the hook can't be a macro |
| 00:13 | technomancy | no, not necessarily. you could construct a wrapper function which has the same argument list as the target function and simply pass the arguments on to the target function |
| 00:13 | technomancy | right, the hook can't be a macro, but the hook function could be generated by a macro |
| 00:14 | rata_ | yes... but the locals... even if you has the same argument list, you can't see the locals of target |
| 00:14 | technomancy | well, the way hooke works is that the target function is replaced by the wrapper function |
| 00:15 | technomancy | so as long as the wrapper function passes the same args into the target, a break point in the wrapper will be equivalent to a break point inside the target |
| 00:15 | technomancy | as long as the wrapper has the same names for all its arguments |
| 00:15 | technomancy | the only difference is the first argument of the wrapper *is* the target |
| 00:16 | technomancy | it's a juicy problem... if you don't do it then maybe we can tackle it at the next Seajure meeting |
| 00:16 | rata_ | so, you are saying that with that break.clj, if you have a (let [x ...] ...) inside target, you could see the value of x? |
| 00:17 | technomancy | oh no not like that; just the function parameters |
| 00:17 | technomancy | I see what you mean |
| 00:17 | rata_ | =) |
| 00:18 | rata_ | that's the difficult part I think |
| 00:18 | technomancy | I thought you meant you'd rather see (defn my-target [a b c]) as a b c rather than & args |
| 00:18 | rata_ | no... I mean all the locals of the function |
| 00:18 | rata_ | not the args |
| 00:18 | technomancy | I don't know if it's possible to get even the let-bound stuff |
| 00:19 | technomancy | on a regular defn anyway, you could do it with a defn-debug... which is what you suggested in the first place. =) |
| 00:20 | technomancy | it still might be tricky to traverse the body find all the tail positions in order to insert breakpoints |
| 00:20 | rata_ | if you just want to see the locals, it's easy, you put a (swank.core/break) just before the expression that returns the value of the function, in the most nested let (don't care about let "branches") |
| 00:20 | rata_ | yes, it might be tricky |
| 00:22 | rata_ | but in addition to have the value of all the locals, it'd be great if you could see along them the return value of the fn |
| 00:23 | technomancy | that shouldn't be too hard; just replace the final value with (let [return-value# ~v] (swank.core/break) return-value#) |
| 00:23 | rata_ | because it happens to me all the time that to see just the return value of one fn is difficult, because I normally put it inside a form, so I don't bound it directly to a local |
| 00:23 | technomancy | of course with pure functions once you have the locals it's easy to calculate the return value =) |
| 00:24 | rata_ | it involves to write (or copy-paste) a lot of code to the repl |
| 00:24 | rata_ | and it's annoying when you have to do it for many fns |
| 00:24 | rata_ | to find where the bug is |
| 00:25 | KirinDave | Is there a clever way of invoking protected methods on instances from clojure? |
| 00:26 | rata_ | that's why I suggested something like defn-debug that puts a (let [return-value# ~v] (swank.core/break) return-value#) at the right place |
| 00:26 | rata_ | =) |
| 00:27 | technomancy | rata_: yeah, I think you have the right idea. |
| 00:28 | rata_ | I find (swank.core/break) immensely useful when debugging, so I'm sure having something like defn-debug would be very useful as well =) |
| 00:28 | rata_ | the first name I thought about was defn*, but then remembered that the asterisk is mainly used by the compiler |
| 00:29 | rata_ | *thought of |
| 00:31 | technomancy | not just used by the compiler, but it does indicate an internal function |
| 00:31 | technomancy | defn-debug is better |
| 00:34 | hiredman | KirinDave: clojure.contrib.reflect I believe |
| 01:10 | rata_ | if "lein compile" with :warn-on-reflection true doesn't warn about anything, does it mean that type hints wouldn't help the performance? |
| 01:12 | tomoj | need to actually run the program, no? |
| 01:13 | KirinDave | hiredman: Thank you, btw |
| 01:13 | amalloy | tomoj: i don't think so. the reflection warnings are only at compile time |
| 01:19 | tomoj | how can clojure know at compile time whether there's reflection? |
| 01:20 | amalloy | tomoj: um, because if it can't resolve the method calls at compile time, it has to generate code that uses reflection to resolve them at runtime |
| 01:21 | rata_ | so what about my question? |
| 01:21 | amalloy | rata_: i don't know. i don't use lein compile or warn-on-reflection |
| 01:21 | rata_ | ok |
| 01:23 | rata_ | methods are compiled as anon fns right? that is, they are compiled as fn__xyz? |
| 01:23 | amalloy | you mean, anon fns are compiled as methods? |
| 01:24 | amalloy | either way it's not correct. functions, anonymous or not, are compiled as classes with an invoke(args) method |
| 01:26 | rata_ | yes... I mean that methods are compiled to classes like fn__148 |
| 01:27 | rata_ | is there a way to give names to methods, like (fn name [...] ...)? |
| 01:29 | dnolen | (letn [f (fn foo [])] f) |
| 01:29 | dnolen | ,(letn [f (fn foo [])] f) |
| 01:29 | dnolen | erg |
| 01:29 | dnolen | ,(let [f (fn foo [])] f) |
| 01:29 | amalloy | &(fn name [] 1) |
| 01:29 | sexpbot | ⟹ #<sandbox8506$eval10166$name__10167 sandbox8506$eval10166$name__10167@184dc98> |
| 01:29 | amalloy | ,(fn name [] 1) |
| 01:29 | clojurebot | #<sandbox$eval104$name__105 sandbox$eval104$name__105@de04cd> |
| 01:29 | amalloy | sexpbot: kill |
| 01:29 | sexpbot | KILL IT WITH FIRE! |
| 01:29 | amalloy | huh. sexpbot is dead. Raynes, you around? |
| 01:29 | amalloy | anyway rata, that's exactly how you do it |
| 01:30 | clojurebot | java.lang.Exception: Unable to resolve symbol: letn in this context |
| 01:30 | clojurebot | #<sandbox$eval109$foo__110 sandbox$eval109$foo__110@260829> |
| 01:30 | amalloy | ah, good morning sexpbot |
| 01:31 | amalloy | &(fn quetzacoatl [x] (+ 10 x)) |
| 01:31 | sexpbot | ⟹ #<sandbox8506$eval10175$quetzacoatl__10176 sandbox8506$eval10175$quetzacoatl__10176@11a7733> |
| 01:39 | trybeingarun | Hey guys |
| 01:39 | trybeingarun | how do you write a recursive function when you use #(function) format? |
| 01:40 | trybeingarun | letfn here also? |
| 01:40 | amalloy | trybeingarun: you could do it with recur. but usually, "don't do it" is a good answer |
| 01:40 | trybeingarun | you do you recommend against doing it? Readability issues or anything else specific? |
| 01:41 | amalloy | well, rolling your own recursion is usually unnecessary - you get better and more readable code by using HOFs like reduce, iterate, map, etc |
| 01:41 | amalloy | and if you want to, it's usually complicated enough to merit a (defn) or at least a (fn) |
| 01:42 | trybeingarun | hm |
| 01:42 | trybeingarun | Am currently trying to write all the code in "The Little Schemer" in clojure |
| 01:42 | _ato | you can't do non tail recursion with #(...) |
| 01:42 | _ato | you can with fn though |
| 01:42 | _ato | (fn foo [x] (when (pos? x) (foo (dec x)))) |
| 01:42 | trybeingarun | There is a specific chapter on lambda functions |
| 01:43 | dnolen | trybeingarun: #(f ..) is for simple stuff, easy abused, I avoid it now mostly. |
| 01:43 | trybeingarun | so I was wondering how to write recursion in such scenarios |
| 01:43 | amalloy | trybeingarun: (fn) is lambda |
| 01:43 | dnolen | trybeingarun: use fn |
| 01:43 | amalloy | #() is shorthand |
| 01:43 | trybeingarun | _ato: u mean 'recur' can't be used?? |
| 01:43 | mister_roboto | dnolen: how is #() easily abused? curious what kind of scenario you're thinking of |
| 01:43 | _ato | recur can't be used to solve all problems |
| 01:43 | amalloy | &(macroexpand '#(inc %)) |
| 01:43 | sexpbot | ⟹ (fn* [p1__10198#] (inc p1__10198#)) |
| 01:44 | dnolen | mister_roboto: any scenario where the inside is complex, %1 %2 etc carries little meaning. |
| 01:44 | trybeingarun | amalloy & dnolen: currently I am using (fn ...). Just wanted to find out if the same can be done with %() |
| 01:44 | mister_roboto | dnolen: so when it's complicated enough that you want the args to have real names |
| 01:44 | amalloy | &'#(inc %) |
| 01:44 | sexpbot | ⟹ (fn* [p1__10206#] (inc p1__10206#)) |
| 01:45 | _ato | ,(#(when (pos? %1) (recur (dec %1))) 10) |
| 01:45 | clojurebot | nil |
| 01:45 | amalloy | trybeingarun: not always |
| 01:45 | dnolen | mister_roboto: I do, plus #() is just weak, no destructuring arguments |
| 01:45 | dnolen | &(map #(* % 2) [1 2 3 4]) |
| 01:45 | sexpbot | ⟹ (2 4 6 8) |
| 01:45 | trybeingarun | hm |
| 01:45 | amalloy | #() really is shorthand for simple cases of (fn) |
| 01:46 | _ato | ,(#(when (pos? %1) (2 + (recur (dec %1)))) 10) |
| 01:46 | clojurebot | java.lang.UnsupportedOperationException: Can only recur from tail position |
| 01:46 | mister_roboto | dnolen: I use it all the time to map or apply something relatively small. normally don't care about destructuring in such cases. |
| 01:46 | pppaul | &(#(% %) #(% %)) |
| 01:46 | sexpbot | java.lang.StackOverflowError |
| 01:46 | amalloy | for complicated cases, there's a reason you can't use #() :P |
| 01:46 | _ato | ,(#(fn foo [x] (pos? x) (2 + (foo (dec x)))) 10) |
| 01:46 | clojurebot | java.lang.IllegalArgumentException: Wrong number of args (1) passed to: sandbox$eval121$fn |
| 01:46 | _ato | ,((fn foo [x] (pos? x) (2 + (foo (dec x)))) 10) |
| 01:46 | clojurebot | java.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn |
| 01:46 | trybeingarun | amalloy: :P |
| 01:46 | _ato | ,((fn foo [x] (pos? x) (+ 2 (foo (dec x)))) 10) |
| 01:46 | clojurebot | java.lang.StackOverflowError |
| 01:46 | _ato | heh |
| 01:46 | _ato | brain not working well today |
| 01:47 | _ato | nevermind |
| 01:47 | _ato | ;-) |
| 01:47 | pppaul | my code is better for stack overflows |
| 01:47 | dnolen | &(map (fn [[k v]] (* k v)) {1 2 3 4}) |
| 01:47 | sexpbot | ⟹ (2 12) |
| 01:48 | amalloy | &(map #(apply * %) {1 2 3 4}) |
| 01:48 | sexpbot | ⟹ (2 12) |
| 01:48 | pppaul | dnolen, that's the sexy destructuring i like |
| 01:48 | amalloy | definitely less efficient, though arguably more readable for such a simple case |
| 01:49 | dnolen | &(map (fn [[k v]] (* k (/ v 2))) {1 2 3 4}) |
| 01:49 | sexpbot | ⟹ (1 6) |
| 01:49 | LauJensen | dnolen: Thanks for fighting the good fight on HN, I just read the comments :) |
| 01:49 | dnolen | LauJensen: ugh |
| 01:49 | amalloy | dnolen: there you go, that's one that cries out for (fn) |
| 01:49 | dnolen | amalloy: ;) |
| 01:50 | dnolen | LauJensen: sometimes HN really lets you down. BTW, I'm really blown away by ClojureQL! |
| 01:50 | dnolen | LauJensen: just add multi table joins :D |
| 01:50 | LauJensen | dnolen: I was quite happy to see that the majority of comments were positive actually, but its super sweet that you like it :) |
| 01:50 | amalloy | &(map #(/ (apply * %) 2) {1 2 3 4}) ; i guess? |
| 01:50 | sexpbot | ⟹ (1 6) |
| 01:50 | LauJensen | dnolen: multi table joins will be in 1.0.0 final, I just didnt have time before now |
| 01:50 | dnolen | LauJensen: also, do you do any SQL sanitizing? |
| 01:51 | LauJensen | dnolen: like what? |
| 01:51 | pppaul | mapping over hashmaps is ugly |
| 01:52 | dnolen | LauJensen: does ClojureQL ever take raw strings for substition into the final query? |
| 01:53 | LauJensen | dnolen: You can supply raw strings as column specs if you need. We also have an option to append a string to the final query |
| 01:54 | dnolen | LauJensen: so don't those need to be sanitized for SQL injection? |
| 01:54 | LauJensen | dnolen: You mean parameterized? |
| 01:54 | dnolen | LauJensen: sure, I'm no SQL expert. |
| 01:55 | LauJensen | Ah ok. Paramterization is on the chart for 1.0.0 final, its an important feature in guarding against injection attacks |
| 01:56 | pppaul | but i love injection attacks |
| 01:56 | dnolen | LauJensen: nice. As an aside I love how little code it ended up being. 700 LOC, less than Enlive ;) |
| 01:56 | LauJensen | dnolen: I was quite blown away by it myself. The old ClojureQL was thousands and thousands of lines in 10 different files. Arel is 4600+ lines in 30 something files. Also doing this in about 2 weeks was quite an experience |
| 01:56 | LauJensen | Shred + Rewrite FTW :) |
| 01:59 | dnolen | LauJensen: I have strong disgust for SQL syntax, not the tech. Like Clojure, ClojureQL puts a better interface on great technology. |
| 01:59 | LauJensen | dnolen: True. And I think Relational Algebra has always been the right way to do it. I dont know who dreamed up SQL92 instead :) |
| 02:03 | LauJensen | But its great to see how much elegance you get for free from Clojure, if you comepare Arels syntax to sexps there's quite a difference |
| 02:06 | dnolen | LauJensen: so is the idea to have ClojureQL be very focused on querying? leave transactions to clojure.contrib.sql and modeling to libraries like carte ? |
| 02:07 | LauJensen | dnolen: I would say that querying is such a huge part of our interactions with databases that it was just the natural place to start, however I will definitely introduce a (dosync) like semantic into it. Right now it automatically promotes inserts/updates to transactions when there are multiple rows involved |
| 03:00 | harishtella | anyway to import everything from a java package (like processing.core.*) ? |
| 03:00 | LauJensen | nope |
| 03:01 | harishtella | aww, why not? |
| 03:05 | _ato | possibly because it's not possible to get a list of all classes in a package, due to custom class loaders |
| 03:06 | _ato | my guess would be that javac's import foo.* doesn't actually search out all classes in the foo package, it instead just sets a search path for unqualified class names |
| 03:07 | _ato | Clojure's namespaces work differently to Java's, when you import something in Clojure it actually creates an entry in the namespaces |
| 03:07 | harishtella | ah, I see, thanks |
| 03:41 | cphang_ | /join #clojure |
| 03:41 | auscompgeek | cphang_: You are already here. |
| 03:41 | cphang_ | yap :) |
| 03:41 | cphang_ | didn't realized it |
| 09:04 | fliebel | morning |
| 09:04 | tonyl | morning |
| 09:08 | fliebel | There is a neat Twitter lib in Python that generates urls from method calls dynamically so that it requires little maintenance and supports all Twitter methods. How would I do such magic in Clojure? I'm talking about the second point: http://mike.verdone.ca/twitter/#why |
| 09:12 | fliebel | I could do a macro that just converts function calls to strings, but I'm not sure that's the cleanest way to do it. |
| 09:12 | Chousuke | I don't think you can do that directly, since clojure doesn't have methods that you can create on the fly :P |
| 09:13 | Chousuke | but you could always have some function that takes a bunch of keywords and returns a function that fetches the url |
| 09:13 | Chousuke | or a macro |
| 09:14 | fliebel | like (twitter :statuses :user-timeline)? |
| 09:14 | Chousuke | fliebel: something like that |
| 09:15 | Tordmor | "you won't have to update your version of the API (though you may have to update your code" WTF? |
| 09:15 | Chousuke | or if you want to be fancy, (twitter :statuses.user-timeline) |
| 09:15 | Tordmor | As if that were something good. |
| 09:16 | fliebel | Tordmor: Kind of. Twitter wont just remove an url, but they might add one. |
| 09:49 | piva | hey there! |
| 09:51 | piva | could someone please clarify a newbie mind towards this problem: I need to count words found in a given string, I thought that I could do that by splitting the string by whitespace and iterating over the resulting vector, create a map with the word as key and increase the value... I researched it vastly for over 4 hours yesterday and as a good newbie I stil don't have a clue to how to do it properly :// |
| 09:53 | chouser | piva: consider 'reduce' |
| 09:53 | tonyl | or split and count |
| 09:54 | cemerick | chouser: I see shades of Rich in you as time goes on ;-) |
| 09:54 | piva | chouser: I started to consider it only today, haha |
| 09:54 | tonyl | (count (clojure.string/split "my string of words" #"[:whitespace:]")) |
| 09:54 | Raynes | cemerick: He *is* rich. Just wearing a mask. |
| 09:55 | piva | tonyl: ah, I need to count every different word that appears |
| 09:55 | Raynes | cemerick: When they have to appear in public together, Rich get's Tom to wear the mask. |
| 09:55 | tonyl | oh so unique words? |
| 09:55 | piva | tonyl: that's why I thought in creating a map where each unique word is the key and increase the counting for each occurrence |
| 09:55 | Chousuke | piva: when you "increase the value" you actually need to create a whole new map :) |
| 09:55 | Raynes | forces* |
| 09:55 | tonyl | ok |
| 09:55 | tonyl | yeah |
| 09:56 | piva | Chousuke: yeah, that's what is forcing my mind, ahha, coming from non-functional programming is a big step to think in immutability and etc |
| 09:57 | Raynes | cemerick: Did you see my indirect getting started post? I only mentioned maven in passing so as to make the hair on the back of your neck stand on end. |
| 09:57 | piva | I really started to play a little with functional about 3 days ago, before that I'd only heard about... so it's been a challenge |
| 10:00 | tonyl | piva: I am starting too |
| 10:00 | tonyl | you are going to need reducing |
| 10:00 | piva | uhmm, great, I will get to study it so, thanks again :D |
| 10:01 | cemerick | Raynes: I looked at it briefly :-) |
| 10:02 | cemerick | Despite popular opinion, I actually don't care about maven one way or the other. It's just the only thing that does all of what I need. |
| 10:02 | cemerick | piva: would you like a working solution, or are you content to pick at the problem? |
| 10:03 | piva | cemerick: I think that would be better as a learning experience to pick at the problem, my real problem is to redefine my way of thinking |
| 10:04 | piva | cemerick: as such, looking at reduce I see a light, but it still I think about mapping and increasing values and etc :/ |
| 10:04 | cemerick | yeah, you still need to keep counts |
| 10:04 | tonyl | piva think of associating the values to the map |
| 10:04 | cemerick | that doesn't impact the utility of reduce, etc |
| 10:04 | Raynes | cemerick: I just like toying with you. <3 |
| 10:06 | cemerick | piva: In any case, don't kill yourself trying to derive idioms on your own. :-) |
| 10:06 | piva | tonyl: I'm at that, but I'm thinking something like this: "ok, I've got to count every word occurrence and when each one is done then I associate it to the map" but that would need many lookups over the vector |
| 10:06 | cemerick | A naive impl is here for when you want to peek. https://gist.github.com/706621 |
| 10:06 | cemerick | Raynes: It's appreciated. :-) |
| 10:07 | cemerick | it's just such a boring topic to me at this point (build-y things, that is) |
| 10:07 | piva | cemerick: thank you! I will pick at it some more and (as nothing is really gonna roll, lol) I'll look it |
| 10:07 | Raynes | Understandable. I have some vested interests in cake and the like though. I occasionally contribute things and write plugins. |
| 10:09 | cemerick | Sure. We all have our investments. |
| 10:09 | tonyl | piva: yeah you have to instert into map and update every time in the function that map is using |
| 10:09 | Raynes | Plus, ninjudd is just so darn awesome in person. <3 |
| 10:09 | tonyl | it is hard to come around, at least was for me. and it still is sometimes |
| 10:11 | stuartsierra | ,(frequencies (seq (.split "The quick brown fox jumped over the lazy dog." " "))) |
| 10:11 | clojurebot | {"jumped" 1, "quick" 1, "fox" 1, "The" 1, "the" 1, "dog." 1, "over" 1, "lazy" 1, "brown" 1} |
| 10:12 | cemerick | dammit, frequencies! |
| 10:12 | cemerick | :-P |
| 10:12 | piva | lol! |
| 10:12 | tonyl | *facepalm* I need to learn my functions |
| 10:13 | cemerick | tonyl: don't we all |
| 10:13 | cemerick | There goes stuartsierra, makin' me look like a dope again ;-) |
| 10:13 | stuartsierra | It's nice no feel needed. :) |
| 10:13 | stuartsierra | *to |
| 10:14 | tonyl | well, it was an exercise of the mind :P |
| 10:14 | piva | haha, thank you all very much, now I can see some light in how functional can be great :DD |
| 10:14 | piva | and well, I'll try to continue my lil program, haha |
| 10:14 | tonyl | $source frequencies |
| 10:14 | sexpbot | frequencies is http://is.gd/hqiDv |
| 10:18 | fliebel | sexpbot at least gets the https thing right, line number are gone from core docs :( |
| 10:20 | fliebel | cemerick: Your implementation could use fnil ;) Man, I read the whole core doc yesterday :) |
| 10:21 | cemerick | fliebel: heh -- see, I'm stuck with a 1.1 mindset still. fnil has always only ever been in contrib.core… |
| 10:22 | fliebel | cemerick: me, to. I'd still be using defstruct if it wasn't for chouser ;) |
| 10:22 | Raynes | fliebel: sexpbot is always right. |
| 11:23 | mjg123 | Hi - how do I prevent this kind of thing: java.lang.IllegalArgumentException: Value out of range for int: 10315434503 |
| 11:24 | tonyl | try bigInt |
| 11:24 | tonyl | maybe |
| 11:24 | raek | mjg123: which version of clojure? |
| 11:24 | mjg123 | 1.2.0 |
| 11:24 | mjg123 | I found it though, my mistake |
| 11:24 | raek | how do you construct it? |
| 11:24 | tonyl | what was it? |
| 11:25 | mjg123 | I was calling (int x) with x as a very large number |
| 11:25 | mjg123 | changed it to (num x) |
| 11:25 | raek | if you parse a number from a string, you might want to use long in this case |
| 11:25 | raek | ah |
| 11:26 | jkndrkn | hey folks. i've defined a protocol using defprotocol and two types that use that protocol in the namespace foo.bar |
| 11:26 | jkndrkn | how do i then use those types elsewhere? |
| 11:26 | chouser | deftype produces a class, so to use it directly you need to 'import' it |
| 11:26 | jkndrkn | i've tried using (:use [foo.bar]), (:import [foo.bar type1 type2]), and neither work |
| 11:27 | raek | jkndrkn: very often, you make a constructor function to create instances |
| 11:27 | raek | you should be able to import them, though |
| 11:27 | jkndrkn | yes, i do have a constructor function. however, said function is not located in the namespace foo.bar and needs to be able to make use of it. |
| 11:27 | jkndrkn | hm. |
| 11:28 | raek | by constructor function, I meant something like (defn make-foo [x] (Foo. x)) |
| 11:28 | chouser | you probably need to require and then import |
| 11:28 | jkndrkn | ok, i'll try requiring too. |
| 11:29 | raek | if you expose the type directly, you will have to change all callers if you add a field |
| 11:29 | raek | or rearrange them |
| 11:30 | raek | I think types and records are often regarded as low-level and are kept as an implementation detail |
| 11:30 | samx | is there some simple way through the Java API to determine is a specific Var has been defined ? I'm currently using the following, but just thinking there might be a simple way: return clojure.lang.Compiler.eval(RT.readString("(true? (some (fn [x] (= (key x) '" + varName + ")) (ns-publics '" + namespace + ")))")); |
| 11:31 | jkndrkn | i've tried requiring as well, and that does not work either |
| 11:32 | jkndrkn | is this import form correct? (:import [foo.bar Type1 Type2]) |
| 11:32 | cemerick | samx: look at Var.find(Symbol). |
| 11:32 | tonyl | jkndrkn: i think you need to actually use the import form instead of the ns form |
| 11:32 | jkndrkn | i'm getting "error: java.lang.ClassNotFoundException: foo.bar.Type" |
| 11:33 | jkndrkn | ah, i siee |
| 11:33 | samx | cemerick, thx |
| 11:33 | tonyl | i've had problems like that and using import worked for me before |
| 11:34 | raek | jkndrkn: the docs says you should write (:import (foo.bar Type1 Type2)), but sometimes vecors instead of lists happens to work |
| 11:35 | raek | well, lists for prefix lists is the only documented way... |
| 11:35 | raek | hrm, ok. looks like vectors worked in that case. |
| 11:37 | cemerick | was there a create-temp-directory fn floating around somewhere? |
| 11:39 | jkndrkn | ok, so i added an "(import [foo.bar.Type1])" under my ns form |
| 11:40 | tonyl | cemerick: not as far as I know, maybe sh (shell fn) |
| 11:40 | tonyl | jkndrdkn: did that work for you? |
| 11:40 | jkndrkn | now i'm getting java.lang.IllegalArgumentException: Unable to resolve classname: Type1 |
| 11:40 | jkndrkn | both the ns form and the import form compile fine |
| 11:41 | jkndrkn | the form that actually creates an instance of the type fails |
| 11:41 | mjg123 | cemerick: you can use java.io.File#createTempFile() then delete the file & create a dir with the same name |
| 11:41 | cemerick | yeah |
| 11:42 | tonyl | once you imported can you create a Type1 object |
| 11:42 | cemerick | I wonder how many times I've written that in my life |
| 11:42 | jkndrkn | tony1: nope |
| 11:42 | tonyl | then it is the importing |
| 11:43 | tonyl | that is weird, let me test it |
| 11:43 | jkndrkn | i'm using (:require foo.bar) in my ns form, and (import [foo.bar.Type1]) and then trying to compile a defn that creates an instance of Type1 using (Type1.) |
| 11:44 | jkndrkn | the import form is free-standing and outside of the ns form |
| 11:45 | tonyl | ok, i'll test for both |
| 11:50 | KirinDave | jkndrkn: So you made a deftype in another file an you're trying to use it in this file? |
| 11:51 | mjg123 | cemerick: (str (System/getProperty "java.io.tmpdir") (System/getProperty "file.separator") (.toString (java.util.UUID/randomUUID))) |
| 11:53 | cemerick | mjg123: heh, sure. I can never remember which one is which between file and path.separator. :-P |
| 11:53 | mjg123 | No, I had to look it up, too. If that clashes with something you ought to buy some lottery tickets. |
| 11:53 | jkndrkn | KirinDave: that's right |
| 11:54 | KirinDave | jkndrkn: So one of two things needs to happen |
| 11:55 | KirinDave | jkndrkn: You either need to explicitly make sure the file saying deftype is loaded into the vm. (Alternatively, you need to :use or :require a symbol from the namespace that includes the deftype) |
| 11:55 | cemerick | mjg123: Yeah, I'd never dispute UUID. (doto (File/createTempFile …) .delete .mkdir) is a little more readable though :-) |
| 11:55 | KirinDave | jkndrkn: Or, you need to lein compile and make sure :aot includes that namespace |
| 11:55 | jkndrkn | k, i'll try that |
| 11:55 | KirinDave | jkndrkn: When you go for the final jar, it won't matter. |
| 11:56 | KirinDave | But during dev, I usual use slime and C-c C-l to load the module again. |
| 11:56 | tonyl | so for importing types they have to be compiled? |
| 11:58 | KirinDave | tonyl: for using import, I think they either have to be loaded or compiled. Things like gen-interface and deftype will doing the loading at the time of their evaluation |
| 11:58 | KirinDave | tonyl: But you have to make that evaluation happen |
| 12:00 | tonyl | ok |
| 12:00 | cemerick | KirinDave: I've suggested doing an implicit require on import before, but that's not gone very far. |
| 12:00 | tonyl | that is good to know |
| 12:00 | KirinDave | cemerick: I think the safest way is to compile. it's what I have to do for scala interop. |
| 12:00 | KirinDave | It's onerous, but... |
| 12:01 | KirinDave | cemerick: One of the nice parts of having a make-* function is that you can :use :only [make-*] and be pretty sure your class gets loaded. |
| 12:01 | cemerick | Agreed. |
| 12:01 | cemerick | Re AOT compilation, there are maintenance downsides, e.g. binary compatibility between different revs of clojure. |
| 12:02 | tonyl | so if you do a make-mytype fn for the type in the same ns the type was declared then you can just require that make-mytype fn and use it to make the type? |
| 12:03 | KirinDave | tonyl: That's how it's explained to me. |
| 12:03 | tonyl | ok, if I don't want to go the compilation route, i'll try this. |
| 12:06 | tufflax | I'm trying out Vim for clojure, but one feature I miss from Emacs is the indentation; that I can just select a whole function and press tab and every row gets indented correctly, and that if I'm on a row and press tab that row get indented correctly even if that means moving backwards. Does anyone know if I can get something similar to work with Vim? |
| 12:06 | dakrone | tufflax: use = when selecting a visual block, or == to indent the current line |
| 12:07 | dakrone | gg=G to indent the entire file |
| 12:07 | tufflax | Ok, thanks I'll try |
| 12:10 | tufflax | Hm, I'm very new to vim, when you say "use =", what do you mean? Cause when I select the text and type = in normal mode I just replace the text :P |
| 12:11 | tufflax | Or, I was in select mode |
| 12:11 | dakrone | are you using v or V to select things in visual mode? |
| 12:12 | tufflax | visual mode? :P I'm in select mode :P maybe I should study vim some more first :P |
| 12:13 | dakrone | so, from normal mode, hit V to enter visual line mode, move up and down to select some lines, then press = to indent them |
| 12:13 | tonyl | tufflax: have you try the vimtutor? |
| 12:13 | tufflax | I did some of it :P gonna continue soon :P |
| 12:14 | tufflax | But I was very eager to see what vimclojure had to offer |
| 12:15 | tufflax | Ah, now it works, very nice. Thanks! |
| 12:32 | amalloy | anyone know of a good intro to fnparse? |
| 12:37 | aoeu256 | i saw a youtube video and clojure looks like a fun language (i program a little python). Im starting out, whats a good way to figure out which methods belong to a (Java) object. right now I am using clojure's lispbox |
| 12:38 | amalloy | aoeu256: there are a few ways. are you familiar with java, or is clojure your first java? |
| 12:38 | tonyl | aoeu256: you can use the class function |
| 12:41 | amalloy | aoeu256: https://gist.github.com/b12371be35213c7ff4a9 |
| 12:42 | amalloy | tonyl: this seems more friendly than (.getMethods (class x)) |
| 12:43 | mroessler | if we partition on a pattern and emit like : (let [pairs (partition 2 1 tuples)] (for [[today todays_value] [yesterday yesterdays_value]] pairs] [today (- todays_value yesterdays_value)])) we necessarily have dropped the first tuple [today todays_value]. Is there a common method to add it back in? Like [today nil]? |
| 12:43 | tonyl | yeah true, i assumed he new java |
| 12:44 | aoeu256 | i know a little java |
| 12:44 | amalloy | there's a (show) function somewhere that's supposed to do this in the repl, but since 1.2 i haven't been able to find it |
| 12:44 | tonyl | amalloy's would be more helpful though, class you just give you the full class name only |
| 12:45 | chouser | clojure.contrib.repl/show |
| 12:45 | chouser | clojure.contrib.repl-utils/show |
| 12:45 | chouser | I think |
| 12:45 | chouser | it will be replaced by something better in 1.3 |
| 12:45 | amalloy | chouser: damn you. i looked in repl-utils, and it wasn't there until you told me to look again |
| 12:46 | tonyl | mroessler: what do you mean dropped the first tupple (vector) isn't [today todays_value] still there? |
| 12:47 | tonyl | c.c bows to chouser |
| 12:47 | chouser | amalloy: heisenfunction |
| 12:48 | mroessler | tonyl: Thanks. I don't think it is, because my for is [today todays_value] [yesterday yesterdays_value], so the output is only emitted once there is a yesterday. |
| 12:50 | amalloy | mroessler: is that real code you pasted? i don't think that's a legal binding-form you used in your for |
| 12:51 | amalloy | &(for [[[a a1] [b b1]] (partition 2 1 [1 2 3 4])] [(- a b) (-a1 b1)]) |
| 12:51 | sexpbot | java.lang.Exception: Unable to resolve symbol: -a1 in this context |
| 12:51 | tonyl | you are missing a bracket |
| 12:51 | amalloy | &(for [[[a a1] [b b1]] (partition 2 1 [1 2 3 4])] [(- a b) (- a1 b1)]) |
| 12:51 | sexpbot | java.lang.UnsupportedOperationException: nth not supported on this type: Integer |
| 12:51 | amalloy | mutter |
| 12:52 | tonyl | &(for [[[a a1] [b b1]] (partition 2 1 [[1 2] [3 4]])] [(- a b) (- a1 b1)]) |
| 12:52 | sexpbot | ⟹ ([-2 -2]) |
| 12:52 | amalloy | thanks tonyl |
| 12:52 | tonyl | np |
| 12:52 | tonyl | he was missing a third bracket |
| 12:53 | mroessler | amalloy: well surely I'm inhibited by this being my third day with Clojure, but yes that code is running for me. This is a common issue when dealing with things such as moving averages. If we compute a 30 period moving average, the first 29 are nil, but we don't really want to drop them from the data. |
| 12:53 | tonyl | for never drops data as far as i know |
| 12:54 | mroessler | amalloy: the code I pasted is inside a let |
| 12:54 | amalloy | mroessler: you're missing a [ in your for |
| 12:54 | amalloy | but whatever |
| 12:54 | amalloy | tonyl: right, it never drops data, but if you have 30 data points there are only 29 pairs |
| 12:55 | amalloy | i'm not really clear on what mroessler wants to do to invent the first pair |
| 12:55 | tonyl | oh i see |
| 12:55 | amalloy | mroessler: it seems to me that your issue is with partition, not for |
| 12:55 | mroessler | I want [today nil] |
| 12:56 | amalloy | &(partition 1 2 [[1 2] [3 4] [5 6]]) |
| 12:56 | sexpbot | ⟹ (([1 2]) ([5 6])) |
| 12:56 | amalloy | er |
| 12:56 | amalloy | &(partition 2 1 [[1 2] [3 4] [5 6]]) |
| 12:56 | sexpbot | ⟹ (([1 2] [3 4]) ([3 4] [5 6])) |
| 12:57 | amalloy | &(partition 2 1 (repeat [nil nil]) [[1 2] [3 4] [5 6]]) |
| 12:57 | sexpbot | ⟹ (([1 2] [3 4]) ([3 4] [5 6]) ([5 6] [nil nil])) |
| 12:57 | amalloy | mroessler: ^^? |
| 12:58 | mroessler | Likely I'm insufficiently clear: I'm emitting a date: today, matched by (- todays_value yesterday's value). Clearly I can't emit (- today_value yesterdays_value) until there is a yesterday, which drop the first [today todays_value]. |
| 13:01 | amalloy | mroessler: what about computing the diff with tomorrow instead of with yesterday? |
| 13:01 | amalloy | then you can use the little padding scheme i show above |
| 13:04 | mroessler | amalloy: I'll look into that, thanks. |
| 13:14 | orphe | Hi, i'm beginning with clojure and trying to find the best way to set it up. Should i get the downloads the site or take the source from github |
| 13:14 | technomancy | ~getting started |
| 13:14 | clojurebot | getting started is http://www.assembla.com/wiki/show/clojure/Getting_Started |
| 13:15 | amalloy | orphe: Raynes made a blog post about this just yesterday: http://blog.raynes.me/?p=48 |
| 13:15 | orphe | technomancy, amalloy : thanks |
| 13:19 | dnolen | so what are people using for string templating again? |
| 13:26 | orphe | amalloy: wow that cljr installer does everything |
| 13:27 | amalloy | orphe: heh. i haven't used cljr myself, but i imagine it's using maven to download the required packages, just like cake or lein |
| 13:27 | hugod | dnolen: recently came across this http://alliance.seas.upenn.edu/~harmony/ which looks like it could be turned into an enlive type approach for general text |
| 13:28 | hugod | probably overkill as string templating though |
| 13:28 | orphe | amalloy: yeah its using maven, i had tough already compiled clojure ,and was wondering how to set it up correctly , but if that does everything ... its looks like gems for ruby or npm for node |
| 13:29 | dnolen | hugod: interesting, saved for later reading :) |
| 13:30 | amalloy | orphe: yeah, i compiled clojure myself too, the first time. it turns out to not really be worth the bother, especially as all the tools fetch their own copy of clojure anyway (you can point them at your local copy if you want, i guess) |
| 13:30 | jjido | freemarker is good for templating on the jvm |
| 13:31 | dnolen | jjido: I really want something idiomatic |
| 13:32 | dnolen | ((tmpl "Foo ~{keya} bar ~[keyb}') {:keya "blah" :keyb "argh"}) |
| 13:32 | orphe | dnolen: i used in js and ruby http://mustache.github.com/ , maybe the clojure port is good too |
| 13:33 | dnolen | orphe: ah seems close to what I want, will check it out. |
| 13:34 | orphe | dnolen: don't know how it works in clojure since im starting but in js/ruby you can pass lambda functions , direct values... |
| 13:37 | hugod | dnolen: https://github.com/hugoduncan/pallet/blob/master/src/pallet/strint.clj does this based on c.c.strint |
| 13:38 | tomoj | hmm |
| 13:38 | dnolen | hugod: tried it, seems I cannot use strings in first class manner w/ it (please correct me if I'm wrong) |
| 13:38 | fliebel | hugod: That boomerang thing is very interesting! Would be awesome the have a Clojure DSL to do that kind of stuff. |
| 13:38 | dnolen | (let [s some-str m some-map] (<< s m)) ; FAIL |
| 13:40 | hugod | fliebel: I have a good use case for it in pallet, but no time to implement at the moment :( |
| 13:41 | fliebel | So many cool stuff to build… :( |
| 13:41 | amalloy | $sed -fliebel s/\(/) |
| 13:41 | sexpbot | <fliebel> So many cool stuff to build… :) |
| 13:42 | amalloy | no being sad about having cool stuff |
| 13:42 | fliebel | Okay, "So much cool stuff to build… :) but only one lifetime :(" |
| 13:43 | amalloy | fliebel: that's better |
| 13:50 | amalloy | re-ping: anyone know of a decent intro to fnparse? |
| 14:08 | dnolen | amalloy: you might have to write one, eh ? ;) |
| 14:08 | amalloy | dnolen: oh noes |
| 14:09 | edw | Hey guys, I was wondering how one should approach transforming a hash like this {0 :a 2 :b 3 :c 8 :d} into an array like this [:a 0 :b :c 0 0 0 0 :d 0 0]. |
| 14:09 | dnolen | ,(flatten {0 :a 2 :b 3 :c 8 :d}) |
| 14:09 | clojurebot | () |
| 14:09 | mrBliss | ,(apply concat {0 :a 2 :b 3 :c 8 :d}) |
| 14:09 | clojurebot | (0 :a 2 :b 3 :c 8 :d) |
| 14:10 | dnolen | ,(into [] (apply concat {0 :a 2 :b 3 :c 8 :d})) |
| 14:10 | clojurebot | [0 :a 2 :b 3 :c 8 :d] |
| 14:10 | amalloy | edw: what do you mean with all your zeros? you don't seem to want just flip_map |
| 14:11 | amalloy | dnolen: (into [] foo)? i would think (vec foo) makes more sense |
| 14:11 | chouser | & (reduce (fn [v [x y]] (assoc v x y)) (vec (repeat 10 0)) {0 :a 2 :b 3 :c 8 :d}) |
| 14:11 | sexpbot | ⟹ [:a 0 :b :c 0 0 0 0 :d 0] |
| 14:11 | edw | My Q was about a 1-dimensional output structure, but I want to convert a list of triples into a matrix, with the un-specified elements set to a default value. |
| 14:12 | edw | I'm using Incanter. |
| 14:12 | chouser | edw: I think mine solves it for you |
| 14:12 | chouser | edw: though you left out the "length of the vector" parameter. I used 10 |
| 14:12 | chouser | But I don't know anything about Incanter. Maybe it has a better way. |
| 14:12 | edw | chouser: 1) Thanks, 2) you are correct, and 3) thanks again. |
| 14:13 | chouser | yw |
| 14:13 | amalloy | chouser: wut. i don't even understand the problem, how can you have solved it already |
| 14:13 | mjg123 | wtf? |
| 14:13 | chouser | amalloy: the map keys were to be used as indexes into the output vector |
| 14:13 | edw | I've looked around Incanter's docs, and I don't think there is. |
| 14:13 | amalloy | oh i see |
| 14:13 | chouser | the map values are the vector values at those indexes |
| 14:14 | chouser | heh, not sure that helps |
| 14:14 | amalloy | yeah, actually it totally explains it. wild |
| 14:14 | tonyl | oh i see |
| 14:14 | KirinDave | Sometimes clojure is so ugly it pisses me off |
| 14:14 | KirinDave | Still love it but... an unruly child |
| 14:14 | amalloy | KirinDave: you can't blame evolution just because you made an ugly baby |
| 14:15 | KirinDave | amalloy: Oh I _can_. |
| 14:15 | KirinDave | I am just unreasonable enough to. |
| 14:15 | tonyl | lol yeah |
| 14:15 | chouser | KirinDave: which bit is ugly today? |
| 14:15 | fliebel | KirinDave: That's explicit complexity, rather than accidental ;) |
| 14:15 | KirinDave | chouser: All this fucking date handling I am doing. |
| 14:15 | chouser | oh |
| 14:15 | chouser | yeah |
| 14:15 | KirinDave | chouser: e.g., https://gist.github.com/706981 |
| 14:16 | chouser | dates are deeply unhappy to work with |
| 14:16 | edw | Thanks everyone. The only place forgoing mutation in moving from Scheme to Clojure is in this sort of data structure initializion code. |
| 14:16 | amalloy | KirinDave: fun fact: java's DateFormat objects aren't threadsafe either |
| 14:16 | KirinDave | amalloy: I'm using joda |
| 14:16 | amalloy | are those threadsafe? |
| 14:16 | KirinDave | amalloy: Well, the immutable ones are. |
| 14:16 | KirinDave | THey have immutable versions of all their time stuff. |
| 14:17 | amalloy | KirinDave: sure? i never mutate my DateFormats and i still ran into problems because the parse() methods aren't threadsafe |
| 14:17 | KirinDave | amalloy: Please tell me that's not true |
| 14:17 | amalloy | KirinDave: scout's honor. took me a day and a half to discover |
| 14:17 | KirinDave | If JodaTime's parse isn't thread safe I'm going to sprout horns and a tail |
| 14:17 | amalloy | even though it's right in the javadoc |
| 14:18 | KirinDave | amalloy: "DateTimeFormat is thread-safe and immutable, and the formatters it returns are as well." |
| 14:18 | KirinDave | Whew |
| 14:18 | KirinDave | http://joda-time.sourceforge.net/apidocs/org/joda/time/format/DateTimeFormat.html |
| 14:18 | amalloy | hurrah |
| 14:18 | KirinDave | Yeah |
| 14:18 | dnolen | KirinDave: can date handling be made pretty? That code is at least clear. |
| 14:19 | fliebel | Can anyone name me a core function I might not know about? |
| 14:19 | amalloy | fliebel: fnil |
| 14:19 | amalloy | incidentally, writing memoize in java looks disgusting |
| 14:20 | amalloy | even with apache commons to help out |
| 14:20 | fliebel | amalloy: Know that one, replaces nil with a given value for fn. |
| 14:20 | chouser | fliebel: var-set |
| 14:20 | fliebel | chouser: Now you got me :( |
| 14:20 | chouser | fliebel: underive, |
| 14:20 | fliebel | &(doc var-set) |
| 14:20 | sexpbot | ⟹ "([x val]); Sets the value in the var object to val. The var must be thread-locally bound." |
| 14:20 | amalloy | fliebel: reductions. group-by |
| 14:20 | chouser | update-proxy |
| 14:21 | fliebel | chouser: I know that one, but the derive tree stuff is still magic to me. |
| 14:21 | chouser | probably know trampoline. If not, worth looking at. |
| 14:21 | fliebel | yea |
| 14:21 | KirinDave | Woah didn't know fnil |
| 14:22 | fliebel | update-proxy is some sort of java interop helper, right? |
| 14:22 | chouser | fliebel: allows you to change on the fly the implementation of an object created via proxy |
| 14:22 | chouser | so, yes |
| 14:23 | chouser | restart-agent is newish |
| 14:23 | chouser | ooh, rsubseq |
| 14:23 | fliebel | Oh, I am so going to make myself a Clojure quiz... |
| 14:23 | chouser | seque |
| 14:23 | tonyl | i would take that quiz! good learning tool i quess |
| 14:23 | tonyl | *quess |
| 14:23 | amalloy | KirinDave: fnil works together especially well with update-in |
| 14:23 | chouser | release-pending-sends |
| 14:23 | fliebel | I know all of those, though I can;t remember what rsubseq is for. |
| 14:24 | fliebel | is there deseque as well? I guess not :( |
| 14:24 | mjg123 | &(doc rsubseq) |
| 14:24 | sexpbot | ⟹ "([sc test key] [sc start-test start-key end-test end-key]); sc must be a sorted collection, test(s) one of <, <=, > or >=. Returns a reverse seq of those entries with keys ek for which (test (.. sc comparator (compare ek key)) 0) is true" |
| 14:24 | KirinDave | amalloy: Can I see an example? |
| 14:24 | chouser | pvalues |
| 14:24 | amalloy | &(update-in {} [:a :b] (fnil inc 0)) |
| 14:24 | sexpbot | ⟹ {:a {:b 1}} |
| 14:24 | fogus` | Are we playing the "name the obscure Clojure function game"? |
| 14:24 | chouser | fogus`: yup! |
| 14:24 | amalloy | &(update-in {:a {:b 2}} [:a :b] (fnil inc 0)) |
| 14:24 | sexpbot | ⟹ {:a {:b 3}} |
| 14:24 | KirinDave | amalloy: Damn that's fantastic |
| 14:25 | KirinDave | amalloy: I can change code _right now_ :) |
| 14:25 | fliebel | pvalues gets you a vector of values computed in paralel. |
| 14:25 | amalloy | KirinDave: i forget if i got that trick from chouser or raek, but it's magic |
| 14:25 | KirinDave | Yeah that's quality. |
| 14:25 | KirinDave | Actually fnil seems like a pretty nice tool in general |
| 14:26 | chouser | ,(rationalize 4.234) |
| 14:26 | clojurebot | 2117/500 |
| 14:26 | fliebel | chouser: Now in reverse, what's the name of the function that behaves like seq but gives an empy seq instead of nil? |
| 14:27 | chouser | fliebel: sequence |
| 14:27 | fogus` | ,(syntax-symbol-anchor '&) |
| 14:27 | clojurebot | fn |
| 14:27 | fliebel | whoo |
| 14:27 | amalloy | fliebel: not-empty |
| 14:27 | ossareh | "Caused by: java.lang.RuntimeException: java.lang.IllegalArgumentException: "Unparsable namespace form:" :reload" <- I get that when I run lazytest in watch mode on a brand new project - any thoughts on why this might be? (perhaps because I have 0 tests?) |
| 14:27 | chouser | fogus`: I have a patch in to make that go away |
| 14:27 | ossareh | clj 1.2 fwiw |
| 14:27 | fliebel | I'm leaving now, I'll show you guys the quiz later :) |
| 14:27 | amalloy | &(map not-empty [{} [:a]]) |
| 14:27 | sexpbot | ⟹ (nil [:a]) |
| 14:29 | Raynes | orphe: Was my post helpful? Just curious, as AFAIK, you're the first actual new person who might have read it. :> |
| 14:30 | fogus` | ,(namespace-munge 'foo.bar-baz) |
| 14:30 | clojurebot | "foo.bar_baz" |
| 14:30 | orphe | Raynes: lol, Yeah pretty helpful , tough i just used the cljr part! Would be nice to have a followup to what cljr does... (clojars and things like that) |
| 14:31 | Raynes | orphe: Yeah, that post wasn't meant to go into serious depth on any of them. A series of introductions to the various tools might be a nice series of articles to write sometime. |
| 14:32 | ossareh | Raynes: and critically required for the community to grow ihmo |
| 14:32 | ossareh | *imho |
| 14:32 | amalloy | ossareh: I Hate My Opinions |
| 14:32 | ossareh | ;) |
| 14:33 | Raynes | (; |
| 14:34 | orphe | Raynes: I'm gettin myself a blog in a week or two , just finishing writing the engine , maybe if i like really much clojure i will write about it |
| 14:34 | Raynes | You're writing your own blogging engine? |
| 14:35 | orphe | Raynes: yeah , static site generator , like Jekyll |
| 14:35 | Raynes | Neat. |
| 14:36 | orphe | i'm trying to write usefull things, tired of only doing school labs and doing nothing with it |
| 14:36 | orphe | solution : write open-source |
| 14:37 | ossareh | orphe: or better still, once again imho, help other projects |
| 14:37 | ossareh | damn.. I'm just all opinionated today |
| 14:37 | orphe | ossareh: yeah, that was included in "write open-source" |
| 14:38 | rata_ | hi |
| 14:38 | rata_ | what's the most convenient (and hopefully fastest) way to get something like rand-nth in a set? |
| 14:40 | mjg123 | Raynes: good blog post, I'm pretty new so it's good to read about the various tools & such as well as the language |
| 14:41 | tonyl | rata_: with rand-int maybe |
| 14:41 | Raynes | Thanks! Glad you enjoyed it. |
| 14:41 | amalloy | rata_: (comp rand-nth seq) is the best i can think of |
| 14:42 | rata_ | tonyl: but sets doesn't support nth |
| 14:42 | rata_ | amalloy: does seq copy the set? |
| 14:42 | tonyl | they support get |
| 14:42 | amalloy | rata_: not exactly. i don't understand seq, but i believe it returns an iterator-type thing that uses the set as its backing collection |
| 14:42 | tonyl | &(get u (rand-int (count (apply sorted-set (range 17)))) |
| 14:43 | sexpbot | java.lang.Exception: EOF while reading |
| 14:43 | tonyl | &(get u (rand-int (count (apply sorted-set (range 17))))) |
| 14:43 | sexpbot | java.lang.Exception: Unable to resolve symbol: u in this context |
| 14:43 | tonyl | &(get u (rand-int (count (apply sorted-set (range 17))))) |
| 14:43 | sexpbot | java.lang.Exception: Unable to resolve symbol: u in this context |
| 14:43 | tonyl | &(let [u (apply sorted-set (range 17))] (get u (rand-int (count u)))) |
| 14:43 | sexpbot | ⟹ 12 |
| 14:43 | tonyl | there it is |
| 14:43 | amalloy | rata_: it won't be very fast, because it will be traversing the whole set. but anything else would be biased in some way |
| 14:45 | rata_ | amalloy: why would it be traversing the whole set? once you apply seq to a set, isn't it randomly accessible? |
| 14:46 | amalloy | rata_: seq will have to traverse the set once to make that happen |
| 14:46 | rata_ | ah ok |
| 14:46 | amalloy | eg, suppose you knew the set were stored as a hash-table. you could use a random number as the hash key, then randomly select from the list of things that hash into that bucket. but some buckets will be larger than others, and some may be empty, so the results you get back won't be uniformly distributed |
| 14:47 | amalloy | so i think the best you can do is convert the set to a seq, and use rand-nth, which will be uniform |
| 14:48 | rata_ | in that case, it's better to store the thing as a vector, not a set |
| 14:48 | amalloy | &(counted? (seq (set (range 1000)))) |
| 14:48 | sexpbot | ⟹ false |
| 14:48 | rata_ | sets are implemented in clojure usign hash-tables then? |
| 14:49 | jarpiain | &(class #{1 2 3}) |
| 14:49 | sexpbot | ⟹ clojure.lang.PersistentHashSet |
| 14:49 | amalloy | &(map (comp class set range) [1 10 1000]) |
| 14:49 | sexpbot | ⟹ (clojure.lang.PersistentHashSet clojure.lang.PersistentHashSet clojure.lang.PersistentHashSet) |
| 14:49 | technomancy | yeah, sets are maps where the keys point to themselves. |
| 14:50 | amalloy | i thought the small one would be an array-set. or does that only exist for maps? |
| 14:50 | amalloy | rata_: yeah, sets and maps are implemented as hash tables (trees, if sorted) in both java.util and clojure.lang |
| 14:51 | rata_ | if they'd implemented as trees, I think it would be easy to make an analogous of rand-nth for them |
| 14:51 | rata_ | aha... trees if sorted |
| 14:51 | rata_ | maybe that's what I need |
| 14:52 | amalloy | rata_: no, rand-nth will be biased for trees too |
| 14:52 | chouser | I suppose counted-sorted-set might do it |
| 14:52 | amalloy | eg, suppose your tree is poorly balanced: one element in the left subtree of the root, and four in the right sub-tree |
| 14:52 | amalloy | if you randomly choose a direction to go from each node, you'll return the left element four times as often as any other |
| 14:53 | rata_ | counted-sorted-set? is that in clojure.core? |
| 14:53 | amalloy | which is why you'll have to seq it first |
| 14:53 | rata_ | amalloy: and what about balanced trees? |
| 14:53 | rata_ | well, it can't be perfectly balanced all the time |
| 14:54 | amalloy | rata_: well, of course clojure uses self-balancing trees. but they're very rarely 100% perfectly balanced, just balanced "enough" |
| 14:54 | rata_ | yes |
| 14:54 | rata_ | I just realized that after I asked you |
| 14:54 | amalloy | if you want uniformly random selection you'll have to traverse the whole set to get something you can random-access |
| 14:54 | amalloy | no matter how the underlying set is stored |
| 14:56 | rata_ | well... what I really need is a vector, but with less than O(n) for removal of an item |
| 14:56 | ossareh | rata_: more on the data structures: http://clojure.blip.tv/file/707974/ |
| 15:00 | fogus` | ,(let [p (-> (get-proxy-class Object) (construct-proxy))] (init-proxy p {}) (update-proxy p {"toString" (fn [this] "blah")}) (str p)) |
| 15:00 | clojurebot | "blah" |
| 15:00 | rata_ | http://www.innoq.com/blog/st/2010/04/clojure_performance_guarantees.html |
| 15:01 | rata_ | incredible... vector supports disj and is O(log n)! |
| 15:01 | rata_ | I didn't know about that |
| 15:01 | rata_ | &(disj [1 2 3] 2) |
| 15:01 | sexpbot | java.lang.ClassCastException: clojure.lang.PersistentVector cannot be cast to clojure.lang.IPersistentSet |
| 15:02 | rata_ | mmmm... I think that site is wrong |
| 15:03 | KirinDave | rata_: Um |
| 15:03 | KirinDave | rata_: http://idisk.me.com/dfayram/Public/Pictures/Skitch/Clojure_Performance_Guarantees_-_Stefan_Tilkov_s_Random_Stuff-20101119-120625.jpg |
| 15:03 | rata_ | it's also wrong in that lazy-seqs are O(n) for count |
| 15:03 | KirinDave | rata_: I don't see vector having disj |
| 15:03 | rata_ | KirinDave: did you see the link I wrote? |
| 15:03 | KirinDave | rata_: I clicked the last link you posted |
| 15:04 | rata_ | yes, that link |
| 15:04 | KirinDave | And screenshotted the table contained within |
| 15:04 | KirinDave | And between vector and disj, there is a - |
| 15:04 | fogus` | rata_: the columns are shifted in Chrome |
| 15:04 | tonyl | i think the header row in the table is shifted |
| 15:04 | tonyl | what fogus said |
| 15:04 | KirinDave | Haha. Womp womp. |
| 15:04 | KirinDave | Chrome: wins again |
| 15:04 | rata_ | yes, that was |
| 15:04 | rata_ | it |
| 15:05 | fogus` | I mean it's is a very complicated table. so it makes sense that Chrome might choke |
| 15:06 | KirinDave | fogus`: Ha |
| 15:10 | rata_ | mmm... so the best way to do it is probably to just (remove ...) from the vector and use (rand-nth ...) |
| 15:11 | rata_ | or would it be better to (disj ...) the set and then use (rand-nth (seq ...))? |
| 15:14 | devinus | anybody know of SQL databases writtein in Java? |
| 15:14 | mister_roboto | If I want to write some clojure to plug into a spring app as an interface impl, do I just use defprotocol to create an interface usable by java? |
| 15:14 | devinus | *slightly off-topic question, but im curious about connecting to clojure* |
| 15:15 | mister_roboto | Devinus, hsqldb |
| 15:16 | tonyl | mister_roboto: I would do that and compile the protocol so that java can use it |
| 15:18 | mister_roboto | Thanks! I haven't yet played with the deftype family |
| 15:18 | tonyl | I am starting too |
| 15:20 | rickmode | What's the best way to test if a map is empty? (empty? m) vs (= 0 (count m)) vs (zero? (count m)) |
| 15:20 | tonyl | I would go for (zero? (count m)) |
| 15:20 | rickmode | I don't trust timing in the REPL, but empty? appears to be faster |
| 15:21 | rickmode | tonyl: thanks |
| 15:21 | tonyl | I don't know what would be faster, though |
| 15:25 | rickmode | tonyl: the docs doesn't give speed guarantees for seq on a map, though I suspect it isn't O(1). Seems like empty? should be implemented by map directly, which would be O(1). count is supposed be O(1), so I guess (zero? (count m)) will be good. |
| 15:25 | chouser | seq, count, and empty? are all O(1) on a clojure map. |
| 15:26 | chouser | (if (seq m) ...) is most idiomatic, or if you need the inverse (if (empty? m) ...) |
| 15:27 | rickmode | chouser: i this case I wouldn't use the result of seq, however I am testing in an if and using the else clause |
| 15:27 | mjg123 | for speed of comprehension, (empty? m) has it, imho |
| 15:27 | rickmode | (empty? m) would be the clearest ... I agree with mjg123 |
| 15:28 | chouser | yes, it is normal, even preferred, to use 'seq' to test that there is something in the collection. |
| 15:28 | chouser | empty? is fine, but please avoid (if (not (empty? m)) ...) |
| 15:29 | rickmode | in this case it's something like (if (empty? error-map) (do-success) (do-failure error-map)) |
| 15:29 | chouser | sounds good to me |
| 15:30 | mjg123 | because (empty? m) just calls (not (seq m)) , so you don't want to waste time with (not(not(seq m))) - is that why, or is there another reason? |
| 15:31 | chouser | mjg123: HotSpot will likely make all that 'not'ing free anyway. It's more about clarity. |
| 15:31 | mister_roboto | Negative logic is harder to read too |
| 15:31 | chouser | right, why use "if not empty" when you can use "if something's here" |
| 15:32 | chouser | the way to say "if something's here" in Clojure is (if (seq m) ...) |
| 15:32 | rickmode | indeed: (if (not (empty? error-map)) (do-failure error-map) (do-success)) %( |
| 15:32 | mister_roboto | Even rickmode's formulation is irritating to me . Why not just do the failure if something in the map? |
| 15:32 | mister_roboto | Rather than do success if failure map is empty |
| 15:33 | mjg123 | as a beginner, I'd go to the doc to check what (if (seq m)) is trying to say. (if (not (empty? m))) is self-evident. |
| 15:33 | chouser | you still need both cases, and there are valid stylistic reasons for doing the success branch first. |
| 15:33 | rickmode | To my eye, this obfuscates the meaning a bit. But at this become a minor style issue. (if (seq error-map) (do-failure error-map) (do-success)) |
| 15:33 | chouser | mjg123: the standard response to that is, do you want all your code written for beginners in the language? |
| 15:34 | mjg123 | chouser: no :) |
| 15:34 | mjg123 | but I can totally see why someone might write it like that. |
| 15:34 | chouser | sure |
| 15:34 | mister_roboto | It doesn't obfuscate anything if u understand what seq does |
| 15:34 | chouser | until you talk him out of it |
| 15:35 | rickmode | Whereas this is more clearly good style: (when (seq error-map) (do-failure error-map)) |
| 15:35 | Chousuke | the seq idiom will be confusing the first time you see it |
| 15:35 | Chousuke | then you learn it and it becomes non-confusing :P |
| 15:36 | dnolen | mjg123: heh wait till you learn about contains? |
| 15:36 | rickmode | Chousuke / chouser: it does give me the ick creating a seq on a map then tossing away the result, even if it's O(1). But I'll get over it. |
| 15:36 | mister_roboto | U could just throw an exception ;) (kidding!) |
| 15:36 | dnolen | it actually drives me insane now that other langs don't have it. |
| 15:39 | chouser | rickmode: don't worry about it. if it actually becomes the performance bottleneck in your app, bring it up with rhickey and he may just solve it for you |
| 15:39 | ossareh | if (:use some-ns) from some-other-ns are defrecords in some-ns visible ? it seems like they're not, but I didn't see anything in the docs that says that is the case. |
| 15:39 | amalloy | ossareh: no |
| 15:39 | chouser | you have to keep in mind the difference between the current implementation of Clojure, and the fullness of the language that is promised. |
| 15:39 | amalloy | they're classes: you have to (:import) them |
| 15:39 | ossareh | ahh |
| 15:40 | ossareh | amalloy: thx |
| 15:40 | chouser | 'seq' is the primitive for testing if a collection has contents. Use it. :-) |
| 15:41 | ossareh | amalloy: and I assume that they are some-ns.RecordName ? |
| 15:41 | amalloy | ossareh: indeed |
| 15:42 | amalloy | (ns myproj.stuff) (defrecord Things [data])...(import myproj.stuff.Things) |
| 15:42 | fogus` | Does anyone see a reason why this patch would be problematic? https://gist.github.com/707137 |
| 15:43 | rickmode | I'm getting used the idea that seq means "give me a sequence on this collection if possible". It feels unlikely that (seq [1]) yields (1) (a chunked seq on the vector) and yet that's O(1). I guess the point is that this chunked seq is trivial to create. |
| 15:43 | tonyl | returning the proxy |
| 15:44 | chouser | fogus`: do they currently return nil? |
| 15:44 | fogus` | tnoyl: ? |
| 15:44 | fogus` | chouser: yes |
| 15:44 | amalloy | rickmode: the chunked seq doesn't traverse the whole vector all at once |
| 15:44 | tonyl | I don't see a problem, but then again, I don't know what that method from proxy returns |
| 15:44 | chouser | fogus`: looks good to me |
| 15:44 | Chousuke | rickmode: the sequences are also lazy |
| 15:44 | Chousuke | rickmode: so they're pretty easy to create in constant time .P |
| 15:44 | ossareh | amalloy: cheers, worked a charm. |
| 15:45 | rickmode | Chousake / amalloy: and thus having a dedicated empty? implementation would be minor optimization at best |
| 15:46 | ossareh | wow, lazytest's watching is very very nice |
| 15:47 | chouser | can I point a pom.xml at a lein-generated jar in clojars? |
| 15:47 | stuartsierra | chouser: sure |
| 15:48 | stuartsierra | add clojars.org/repo as a repository |
| 15:48 | chouser | I want [congomongo "0.1.3-SNAPSHOT"] ...what's the groupId? |
| 15:49 | stuartsierra | groupId and artifactId are the same when lein has a symbol with no / in it |
| 15:49 | chouser | ok, thanks. |
| 15:49 | stuartsierra | np |
| 15:50 | chouser | works. it's like magic. |
| 15:50 | stuartsierra | chouser: XML Magic (™) |
| 15:50 | chouser | nobody complains about the ugliness of the toad warts and bat ears required to make fantasy magic |
| 15:50 | stuartsierra | It's Mavelicious |
| 15:50 | chouser | so who am I to complain about XML? |
| 16:00 | fogus` | ,(doc get-proxy-class) |
| 16:00 | clojurebot | "([& bases]); Takes an optional single class followed by zero or more interfaces. If not supplied class defaults to Object. Creates an returns an instance of a proxy class derived from the supplied c... |
| 16:00 | fogus` | Lies! :p |
| 16:00 | fogus` | ,(get-proxy-class) |
| 16:00 | clojurebot | java.lang.NullPointerException |
| 16:02 | tonyl | another fn that is not returning the proxy it creates? |
| 16:03 | tonyl | looking at the source code I am guessing it returns a boolean |
| 16:04 | chouser | I think it returns the class ok, but the docstring is wrong about the args |
| 16:04 | chouser | ,(get-proxy-class java.util.Map) |
| 16:04 | clojurebot | sandbox.proxy$java.lang.Object$Map$ad8bc39c |
| 16:05 | fogus` | chouser: So the behavior is right, but not the doc? |
| 16:06 | dnolen | fogus: have you used your unifier much in macros? curious where you're putting it to work. |
| 16:07 | fogus` | dnolen: sorry, I need to run. drop me an email if you please |
| 16:35 | rata_ | it seems something like this is what I need: http://sourceforge.net/projects/avl-array/ |
| 16:36 | rata_ | I'll need to learn how to write clojure types =) |
| 17:05 | mjg123 | Is there a fn which counts the number of operations performed by a function call? |
| 17:05 | mjg123 | like (time (...)) but for complexity |
| 17:08 | tonyl | uff that is a tough one |
| 17:10 | mjg123 | for comparing two different implementations of a function |
| 17:11 | tonyl | comparing results and time performance is not enough |
| 17:11 | mjg123 | yes - probably |
| 17:11 | tonyl | this reminds me of php declare construct and ticks |
| 17:11 | mjg123 | I'm just curious |
| 17:11 | mjg123 | looking at P38 from here http://www.ic.unicamp.br/~meidanis/courses/mc336/2006s2/funcional/L-99_Ninety-Nine_Lisp_Problems.html |
| 17:12 | mjg123 | that "logical inferences" business is a Prolog thing, I suppose |
| 17:12 | tonyl | yeah... read about prolog, but never used it |
| 17:13 | mjg123 | OK I'll just time it & see what I get |
| 17:13 | tonyl | maybe posting it in the group, more people would help that are more knowladgeable |
| 17:13 | rata_ | amalloy: is it possible to know how many elements there are in each bucket? |
| 17:24 | amalloy | rata_: externally? not as far as i know |
| 17:25 | dnolen | how can I get core.unify? do I need run mvn package from inside a clone of the repo? |
| 17:25 | rata_ | there are so many containers out there, how isn't there at least one that is optimized for those three operations (remove by value, insertion and random-access)? |
| 17:25 | amalloy | dnolen: cake install? |
| 17:26 | amalloy | if it's a clojure project |
| 17:26 | tonyl | rata_: you can make your own if you want |
| 17:27 | amalloy | rata_: because it's not really possible? you can't optimize for everything all at once; each goal has different kinds of bookkeeping to do, and sometimes they conflict |
| 17:28 | rata_ | amalloy: I just think I don't know enough about different containers and their trade-offs, not that it isn't possible |
| 17:28 | dnolen | amalloy: will cake use a pom.xml ? |
| 17:28 | amalloy | rata_: could you expand on what you mean by "remove by value, insertion, and random access"? |
| 17:29 | dnolen | amalloy: yeah that doesn't work |
| 17:29 | dnolen | amalloy: mvn package does build the 4k jar that I can copy into my project lib directories tho |
| 17:29 | amalloy | dnolen: mvn install |
| 17:30 | amalloy | i think |
| 17:30 | amalloy | puts it in your local repo, and maven/ivy look there before looking externally if you specify it as a dependency in project.clj/pom.xml |
| 17:30 | rata_ | amalloy: fast random-access is that it can access an element by index in O(1), remove by value is like (disj set key) and insertion is just that (no constrains for that operation) |
| 17:31 | rata_ | I must read more... but I'll do that at another time |
| 17:31 | dnolen | amalloy: yeah that seems to work, thx |
| 17:32 | amalloy | rata_: it can't be done. fast lookup by index, fast lookup by value, and fast insertion at an arbitrary point? |
| 17:32 | rata_ | the last one isn't mandatory |
| 17:33 | amalloy | okay. then it's no problem. you can build as many indexes as you want, and update them every time you insert |
| 17:33 | amalloy | (or remove) |
| 17:34 | rata_ | I don't get it |
| 17:35 | amalloy | rata_: use an array as the backing store (fast lookup by index). keep a hashmap of {data, index-in-array} pairs. on every insert or delete, modify the backing array and adjust all of the keys in the hashmap |
| 17:36 | amalloy | it makes insertion and deletion O(N), but access very fast, whether by index or by value |
| 17:37 | rata_ | good idea =) |
| 17:38 | amalloy | rata_: but don't write it yourself :P. someone's done this already, probably even in clojure |
| 17:39 | rata_ | don't worry, it's a good idea but not what I need |
| 17:58 | pppaul | amalloy, got a link for the object you are talking about? |
| 17:58 | pppaul | i want my bloated collection object |
| 18:00 | pppaul | sounds like a sorted hash-map |
| 18:00 | pppaul | or double hashmap? |
| 18:02 | amalloy | pppaul: no, i've no idea where you can find one |
| 18:03 | amalloy | but eg sql does basically this |
| 18:04 | pppaul | so, make a database |
| 18:04 | amalloy | sure. use Lau's clojureql, even |
| 18:04 | amalloy | he'll love you forever |
| 18:04 | pppaul | a simple variation being a set of hashmaps |
| 18:04 | amalloy | pppaul: if your needs are modest, clojure.set/index might be good enough |
| 18:05 | pppaul | sets are sorted hashmaps? |
| 18:05 | pppaul | or regular hashmaps? |
| 18:05 | amalloy | pppaul: sorted [set/map] is a tree, unsorted [set/map] is a hashmap |
| 18:07 | pppaul | i think databases has a lot of overhead |
| 18:07 | pppaul | but, i could probably do an in-memory DB using clojureQL |
| 18:08 | pppaul | guess it wouldn't be much of a DB |
| 18:08 | pppaul | will lau still love me forever? |
| 18:12 | LaPingvino | use SQLite :) |
| 18:12 | LaPingvino | or fake SQLite ;) |
| 18:14 | pppaul | i'm thinking of doing everything with tuples and sets. tutorialD still |
| 18:15 | pppaul | style* |
| 18:15 | pppaul | but, if lau will love me for using clojureQL, then that is a big motivation to use clojureQL |
| 20:01 | Lajla | &(symbol? (first '#(+ % 1))) |
| 20:01 | sexpbot | ⟹ true |
| 20:02 | Lajla | &(first '#(+ % 1)) |
| 20:02 | sexpbot | ⟹ fn* |
| 20:02 | Lajla | &(string (first '#(+ % 1))) |
| 20:02 | sexpbot | java.lang.Exception: Unable to resolve symbol: string in this context |
| 20:02 | Lajla | &(set 'a-random-symbol) |
| 20:02 | sexpbot | java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Symbol |
| 22:26 | cemerick | chouser: FYI, I've got a patch in for CLJ-432. |
| 22:45 | chouser | cemerick: nice. |
| 22:45 | cemerick | chouser: I hope :-) |
| 22:45 | rathwell | is there an easy way to create a stub java class? looks like there used to be gen-and-load-class, any way to do something like that? |
| 22:47 | cemerick | chouser: I suspect there's still a bug lingering with the generated classname given to reify classes; according to laurent's original writeup, the IBM JDK doesn't allow dashes in package names when loading classes from byte[]s either. |
| 22:47 | cemerick | But then, I don't have an IBM JDK. :-P |
| 22:47 | chouser | rathwell: gen-class is still there, but you must use AOT compilation. |
| 22:48 | hiredman | you can use ASM... |
| 22:48 | rathwell | chouser: no way to do it dynamically though? |
| 22:51 | hiredman | there is always a way |
| 22:51 | cemerick | rathwell: is this class going to be used from Java, by name? |
| 22:54 | rathwell | cemerick: yes, it is referenced as a return type in a third party lib i'm using, but that class is no longer there, causing exception. i can just create the class in java and get it on the classpath, but would be easier if i could do it in clojure. |
| 22:54 | cemerick | so you need to match an existing API's package, name, signatures, etc? |
| 22:54 | rathwell | yes |
| 22:56 | cemerick | If it fits into deftype or defrecord's constraints, then one of it plus a definterface will work. |
| 22:56 | cemerick | Otherwise, gen-class is the most swiss-army-knife-esque thing Clojure has to interop'ing with the java object model, etc. |
| 22:56 | cemerick | one of them* |
| 22:57 | cemerick | hiredman's ASM approach is generally a little to 133t for most. ;-) |
| 22:58 | rathwell | cemerick: I will try defrecord first then, if not, then have to figure out which of gen-class or just doing it in java will work best with deployment, thanks |
| 22:59 | rathwell | yeah, dont think i'm there ;) (ASM) |
| 22:59 | hiredman | cemerick: it's only 133t the first time, the second time you can just copy and paste |
| 23:00 | cemerick | hiredman: True enough. Probably not very kind to the next fellow to look at the code though… |
| 23:01 | danlarkin | nice unicode ellipsis |
| 23:02 | hiredman | they sure are |
| 23:02 | technomancy | surely ellipsis isn't plural? |
| 23:02 | cemerick | danlarkin: no excuse for plebian typography – even in irc ;-) |
| 23:03 | danlarkin | technomancy: it's not, "ellipses" is the plural |
| 23:03 | danlarkin | <3 em dash |
| 23:03 | pppaul | - |
| 23:03 | technomancy | IIRC em dashes are supposed to be surrounded by narrow spaces; is that right? |
| 23:03 | pppaul | – |
| 23:03 | technomancy | I guess monospaced fonts kinda make that a non-starter |
| 23:04 | cemerick | what do the linuxes use for inputting extended characters like these? |
| 23:04 | danlarkin | M-x ucs-insert :) |
| 23:04 | cemerick | uh-huh :-O |
| 23:04 | technomancy | back when I was doing a lot of web work I avoided learning about typography because you end up just agonizing over how limited you are, but I guess things are improving |
| 23:05 | technomancy | cemerick: the right alt is usually mapped to "compose", which is a bit like option on Macs, I think |
| 23:05 | cemerick | typography geeks are always pissed at the web |
| 23:05 | cemerick | technomancy: Right -- but is there a defined extended keymap for these things? |
| 23:06 | cemerick | (I assume by "compose", you mean diacriticals: é, û, à, etc) |
| 23:06 | technomancy | cemerick: it might be locale-dependent... I mostly stick with Emacs input modes myself |
| 23:06 | hiredman | compose takes multiple characters and turns it into a single character |
| 23:07 | technomancy | having tab completion with M-x ucs-insert really helps for things like KANNADA LETTER TTHA ಠ_ಠ |
| 23:07 | cemerick | Apparently, there's a bit of OS X lockin that'll keep me there for a looong time. |
| 23:07 | hiredman | so it's not just diacriticals |
| 23:08 | technomancy | not to mention MUSICAL SYMBOL SIXTEENTH NOTE 𝅘𝅥𝅯 and HEXAGRAM FOR DARKENING OF THE LIGHT ䷣ |
| 23:08 | krumholt | hi. i want my datastructures to implement some clojure interfaces like IFn and ISeq can i do that? |
| 23:08 | hiredman | yes |
| 23:09 | cemerick | technomancy: still keeping your catalog of unicode death metal names? ;-) |
| 23:09 | technomancy | cemerick: always on the lookout; let me know if you spot any good ones. |
| 23:10 | cemerick | krumholt: They're just like any other interfaces: implement the semantics, and you're in. |
| 23:10 | Raynes | technomancy: I've been thinking, and I think we should rewrite Leiningen in Scala for shock value. Any objections? |
| 23:11 | technomancy | Raynes: the hardest part would be coming up with a good name. |
| 23:11 | technomancy | ports are always tricky like that |
| 23:11 | technomancy | unless you're porting the Kelley project to Ruby; in that case the name kinda falls into your lap. |
| 23:12 | danlarkin | my suggestion: wasteOfTime |
| 23:12 | Raynes | Now there is a fine name to be had. |
| 23:12 | cemerick | technomancy: You could probably get a decent side biz going doing product positioning consulting. Firms score 7 figures to come up with a product name and a logo. |
| 23:13 | technomancy | http://tenderlovemaking.com/category/rkelly/ |
| 23:13 | technomancy | I didn't name that one. |
| 23:13 | technomancy | cemerick: the public domain is a rich, rich resource. |
| 23:13 | cemerick | technomancy: OK, but jeez, don't tell the clients that! :-P |
| 23:15 | cemerick | 1. Consume Project Gutenberg. 2. ??? 3. PROFIT! |
| 23:15 | technomancy | wasn't one of the characters in Mona Lisa Overdrive employed checking names of potential projects for obscenity overlap in various languages? |
| 23:15 | hiredman | fun cooker! |
| 23:16 | cemerick | mmm, Gutenberg has a slick mobile app-ish site. |