2011-06-24
| 00:06 | gko | I don't use leiningen/cake, only REPL+files+ad hoc scripts: are they like ASDF/quicklisp of CL? |
| 00:08 | cemerick | gko: lein and cake both provide dependency management via the maven model; so yes, they're similar to quicklisp in that respect. |
| 00:09 | symbole | cemerick: Pretty much. It would be nice to be able to extend the editor based on interfaces, and not on assigning values to seemblingly random global variables. |
| 00:09 | cemerick | I agree. |
| 00:09 | cemerick | Tough road to tread, tho not because of the language. |
| 00:10 | gko | cemerick: lein vs cake: which one is better? |
| 00:11 | gko | got it :) |
| 00:12 | gko | are they both matures? |
| 00:12 | cemerick | gko: FWIW, AFAICT, lein drives the "standard" for project.clj files, and it's been around longer, and its more widely used. Cake provides some nifty bits that lein doesn't though. |
| 00:13 | cemerick | Both are used for real projects in real companies, if that is a reasonable barometer. |
| 00:13 | gko | do they download JARs for each project or they put them in a common pool? |
| 00:14 | cemerick | Both of them reuse maven's ~/.m2 repository structure IIRC. |
| 00:14 | cemerick | There was some talk of cake switching to use ivy, but I don't know how that settled out. |
| 00:14 | cemerick | gko: so, the latter, though each lib needs to be downloaded at least once of course. |
| 00:15 | gko | cemerick: OK... I intend to put all that stuff in my Dropbox directory... |
| 00:15 | cemerick | stuff? |
| 00:16 | gko | cemerick: all these JARs, etc... |
| 00:16 | cemerick | gko: yeah, don't do that. :-) Back up ~, but don't put any effort into curating your own store of jars. |
| 00:17 | gko | cemerick: well, If leiningen/cake does the work, for the better... |
| 00:18 | cemerick | exactly; dependency management means never touching jars directly |
| 00:47 | technomancy | gko: to be honest, it seems to me like most people who learn clojure aren't to keen on going back to CL |
| 00:47 | technomancy | it can be done, but I'm not sure how. wouldn't be surprised if you had to keep them in separate Emacs instances |
| 00:49 | technomancy | *too keen |
| 00:49 | technomancy | the fact that the slime devs say "just use CVS" with a straight face may have something to do with it |
| 00:51 | cemerick | keeps out the riff-raff |
| 01:02 | technomancy | anybody try that vagrant script? |
| 01:02 | tomoj | clojure-box? |
| 01:03 | tomoj | oh, found it |
| 01:22 | gko | technomancy: that's what I do now... Emacs 1: use CVS or ELPA version; if use other Lisp: open Emacs 2 and corresponding SLIME. |
| 01:24 | gko | technomancy: regarding not going back to CL: quicklisp happened and it's a whole new world :) |
| 01:24 | technomancy | gko: it's impossible to make stable releases that are compatible with a constantly-changing target like slime CVS |
| 01:24 | technomancy | their release management is simply irresponsible |
| 01:24 | technomancy | hopefully quicklisp puts some pressure on them to go out of cowboy mode; who knows |
| 01:25 | gko | technomancy: agreed. Another solution would be to change ELPA version so that CVS and ELPA versions don't collide and can be used on the same instance. |
| 01:26 | technomancy | key bindings would still conflict |
| 01:28 | gko | technomancy: in CL REPL/buffers, use CL semantics, in Clojure REPL/buffers, use Clojure semantics? |
| 01:30 | technomancy | it's not that simple; you'd have to have two copies of every single slime function, and you'd have to also have a third function for each binding that would detect the major mode and dispatch to the right version |
| 01:31 | technomancy | it would be easier to make swank-clojure work with current slime CVS, but then it would just break in another month or so, so it's hard to get the motivation |
| 01:40 | gko | technomancy: what I meant was to make the ELPA version totally separated from the CVS version, it would be called something like SCIME, so that there are no common names... SLIME (M-x slime) for CL, SCIME (M-x scime) for Clojure. |
| 01:41 | gko | Of course, it would a permanent temporary solution... |
| 01:41 | technomancy | could work. but I'm not gonna do it. =) |
| 01:42 | gko | technomancy: of course not, you focus on clojure & contribs :) |
| 01:42 | justinlilly | technomancy: it worked for me in the updated version, fwiw. |
| 01:42 | justinlilly | though I had trouble getting jack-in to work with the seajure website. |
| 01:42 | justinlilly | some large exception that I just ignored. |
| 01:43 | technomancy | justinlilly: hm; I actually only tested jark |
| 01:43 | technomancy | kind of attached to the idea of launching jark in ~/.profile though; I may add that to my host |
| 01:44 | justinlilly | do it. it already takes forever for the thing to come up from nothing. |
| 01:44 | technomancy | oh, the vagrant script already launches jark in .profile =) |
| 01:46 | technomancy | it's not much different from lein install swank-clojure 1.3.1 and ~/.lein/bin/swank-clojure though I guess |
| 01:48 | feng | help |
| 01:52 | feng | 13:49 -clojurebot- recently on clojars.org: #{"org.clojars.mschristiansen/lein-beanstalk"} |
| 07:47 | tsdh | Hi |
| 07:50 | tsdh | I have a function that produces a finite lazy seq + an alternative eager version. The eager version is about 6 times faster. However, if I replace calls to the lazy fn to calls to the eager version, performance doesn't increase too much, although in my tests, I nearly always realize the seqs completely. |
| 07:52 | tsdh | The only explanation that I can come up is that (map foo (lazy)) possibly applies foo even before lazy is completely calculated while (map foo (eager)) first computes the seq and then reiterates it mapping to foo. Is something like that correct? |
| 07:53 | manutter | tsdh: it certainly true that (map foo (lazy)) will start mapping before lazy finishes computing -- that's what "lazy" means |
| 07:54 | tsdh | manutter: Ok, then I'm happy my guess is correct. :-) |
| 07:55 | manutter | The lazy seq should come back much quicker than the eager one for the same reason. |
| 07:56 | manutter | You said it was generating the eager seq more quickly than the lazy seq, though? Is that right? |
| 07:56 | tsdh | manutter: Yes, that's the case. (eager) is 6 times faster than (doall (lazy)). |
| 07:56 | manutter | oh, faster than lazy inside a doall |
| 07:57 | manutter | that kinda makes sense though I'm surprised the lazy would be six times slower than the eager |
| 07:58 | manutter | but if the code to generate the seq is really small/fast, I suppose the lazy-seq overhead could be relatively large by comparison. |
| 07:59 | manutter | or there could be some inefficiencies in how you're generating the lazy version. |
| 07:59 | tsdh | manutter: Yeah, the seqs are generated using fast first/next java methods in some external lib. There's no expensive calculation involved. |
| 08:00 | manutter | ok, that makes sense |
| 08:00 | manutter | You know about the built-in iterators for Java objects? |
| 08:01 | manutter | (hmm, now I'm trying to look it up real quick on clojuredocs.org and *I'm* having trouble remembering) |
| 08:01 | tsdh | manutter: Yeah, but the lazy seq thing has the charme of not being fail-fast. For example, using them I can do (map delete! (vseq mygraph)) which modifies the seq while iteration. |
| 08:02 | manutter | ah, here we go |
| 08:02 | manutter | ,(doc iterator-seq) |
| 08:02 | clojurebot | "([iter]); Returns a seq on a java.util.Iterator. Note that most collections providing iterators implement Iterable and thus support seq directly." |
| 08:03 | manutter | I believe that is lazy out of the box, if your Java object supports Iterable |
| 08:03 | manutter | haven't played with it much tho |
| 08:03 | tsdh | manutter: My lazy seqs support some additional features over the java counterparts. |
| 08:03 | manutter | gotcha |
| 08:04 | tsdh | manutter: And what happens if the underlying iterator throws a ConcurrentModificationException? |
| 08:04 | manutter | well, ordinary exception handling (or lack thereof, if you're not using try/catch) |
| 08:05 | manutter | that would be my guess anyway--like I said, I don't have much experience with it |
| 08:06 | tsdh | manutter: No, what I wanted to say is that iterators throw while my lazy seqs allow for modification on iteration. I don't want to lose that feature. |
| 08:07 | manutter | yeah, gotcha |
| 08:07 | manutter | that is, "gotcha" as in "I see what you're saying" not as in "I see a problem" :) |
| 08:08 | manutter | irc is nice but it doesn't carry tone of voice too well... |
| 08:08 | tsdh | manutter: Ok, now I think you see what I'm saying. :-) |
| 08:08 | manutter | I do, and I see the advantages of your approach |
| 08:10 | tsdh | Ok, I'm digging a bit more in the code to see where I can boost performance... |
| 08:31 | clgv | I just wondered about 'type vs 'class: the difference according to doc is that type will return the value of metadata attribute :type if present and otherwise the class. when or by what is :type metadata set? |
| 08:40 | clgv | hmmm :type is apparently not used in clojure.core 1.2 |
| 08:43 | clgv | oh 1.3-beta1 was released :) |
| 09:28 | gfrlog | (defn identity [x] (type (with-meta {} {:type x}))) |
| 09:29 | clgv | gfrlog: not the straight forward use case for it that I would have thought of ;) |
| 09:30 | clgv | but since it is not used in core, I assume it's build for application specific use. |
| 10:00 | Scriptor | int |
| 10:04 | timvisher | hey all |
| 10:04 | timvisher | who wants to help explain this behavior? https://gist.github.com/1044816 |
| 10:04 | timvisher | I have a map with a key pointing to a long |
| 10:04 | timvisher | when I print that at the repl, everything's fine |
| 10:05 | timvisher | if i do anything at all with it, the number turns to 0 |
| 10:05 | timvisher | including (first ...) or (into #{} ...) |
| 10:05 | timvisher | and i haven't the foggiest why |
| 10:08 | pjstadig | not enough information to debug |
| 10:08 | pjstadig | what to from-long and to-long do |
| 10:09 | pjstadig | where is fs/mtime coming from? |
| 10:09 | timvisher | or (pr ...) for that matter |
| 10:09 | pjstadig | what is happening during the snip? is the filesystem changing? |
| 10:09 | timvisher | fs/mtime is from the fs library |
| 10:10 | timvisher | $google clojure fs |
| 10:10 | sexpbot | First out of 2760 results is: ClojureWise: fs - File system utilities for Clojure |
| 10:10 | sexpbot | http://clojurewise.blogspot.com/2011/01/fs-file-system-utilities-for-clojure.html |
| 10:10 | timvisher | time is clj-time |
| 10:10 | timvisher | $google clj-time |
| 10:10 | sexpbot | First out of 61800 results is: clj-time | Clojars |
| 10:10 | sexpbot | http://clojars.org/clj-time |
| 10:10 | timvisher | those |
| 10:10 | timvisher | the snip is me clipping another 678kb of data |
| 10:10 | timvisher | this is a 'large' seq (by my thought, at least) |
| 10:11 | timvisher | my point was that the first element can clearly be seen to have the long intact before i call first on it |
| 10:11 | timvisher | once i call first it turns to a 0 |
| 10:11 | pjstadig | http://download.oracle.com/javase/6/docs/api/java/io/File.html#lastModified() |
| 10:11 | timvisher | to-long turns a joba time DateTime into a long |
| 10:11 | timvisher | and then from-long converts a long to a DateTime |
| 10:12 | timvisher | I'm familiar with what mtime is doing under the covers |
| 10:12 | timvisher | that's the whole idea. i'm basically backporting an addition I just made to my app that includes dates |
| 10:12 | timvisher | I can't serialize the DateTime the way i've serialized stuff so far so i need to convert it to something read can deal with |
| 10:13 | timvisher | so that i can spit it out to a file and then read it back in |
| 10:13 | timvisher | but in memory i'd like it to be a DateTime |
| 10:13 | pjstadig | lastModified returns 0 if there's an i/o error or if the file does not exist |
| 10:13 | timvisher | sweet |
| 10:13 | timvisher | but that doesn't explain what i'm seeing |
| 10:14 | timvisher | if i don't do anything to the seq resulting from the map, it prints with the expected values |
| 10:14 | timvisher | it's only when i use the map that it turns to 0 |
| 10:14 | timvisher | that's the point of the first line |
| 10:14 | timvisher | the 2 :imported-ats |
| 10:14 | pjstadig | well you're doing a complex operation here |
| 10:14 | pjstadig | (ref (map #(assoc % :imported-at (time-coerce/from-long (fs/mtime (wallpaper->thumbnail-path %))) |
| 10:14 | pjstadig | and here (map #(assoc % :imported-at (time-coerce/to-long (:imported-at %))) @library)) |
| 10:15 | pjstadig | the best thing would be to break it apart piece by piece and see that the values are what you are expecting |
| 10:15 | timvisher | i've been at the repl for an hour over this, I could gist my whole log if that would help |
| 10:15 | timvisher | in general though, i've done that |
| 10:15 | timvisher | i've picked it apart piece by peace |
| 10:15 | timvisher | piece* |
| 10:15 | timvisher | everything returns what I want it to until i do something to the map |
| 10:15 | timvisher | and then the number turns to 0 |
| 10:16 | timvisher | could this have something to do with them being primitive longs? |
| 10:16 | pjstadig | what is preferences-home? |
| 10:16 | pjstadig | you're binding preferences to {:library-cache-path "/Users/tim/Desktop/library.clj"} |
| 10:16 | timvisher | it's a path-prefix string |
| 10:16 | pjstadig | do those comport with each other? |
| 10:17 | timvisher | yes |
| 10:17 | timvisher | preferences is a map that i load from a file |
| 10:17 | timvisher | preferences-home is another var that has the default prefix |
| 10:17 | timvisher | not terribly proud of that but haven't gotten around to doing something better yet |
| 10:18 | timvisher | essentially, in the main app I have a ref called library that stores a big 'ol hash-set |
| 10:18 | dpritchett` | speaking of which i have a tiny noir app and i need a place to store my mysql password |
| 10:19 | timvisher | i make edits to that and every once in a while a serialize the datastructure to disk |
| 10:19 | timvisher | in a format that can be read by read-string |
| 10:19 | dpritchett` | would a .clj file with a single def containing my secrets accessed via load-file at runtime be a good starting point? |
| 10:19 | timvisher | so far, this has worked beautifully |
| 10:19 | dpritchett` | or is there a standard config file pattern |
| 10:19 | timvisher | i've been trying since yesterday though to add a imported-at key to the structure |
| 10:19 | timvisher | and it's the first java object that i'm introducing, thus my need to serialize it with conversion and then read it with conversion |
| 10:19 | timvisher | and that's where i discovered this behavior |
| 10:20 | timvisher | dpritchett: that's what has worked for me up until now |
| 10:20 | timvisher | as long as your storing your password as a string it works great |
| 10:21 | timvisher | just make sure you don't add it source control! :) |
| 10:21 | timvisher | pjstadig: does that make any more sense? |
| 10:22 | clgv | dpritchett`: you could add the config-file in your home in a ".yourapplication/" folder |
| 10:22 | timvisher | dpritchett: what's also nice is that if you do testing, you can use binding forms to override the default value and point at a different db |
| 10:22 | dpritchett` | clgv how would i access it though |
| 10:23 | dpritchett` | (load-file ".myapp/dbsecrets.clj") ? |
| 10:23 | timvisher | different: no, you need a full path to it |
| 10:23 | timvisher | or make sure it's relative to launch point |
| 10:23 | pjstadig | timvisher: you're using a ref and the filesystem, assuming that the functions in your pipeline are pure, either some state is changing on you, or some of those functions in your pipeline are not producing the values you think they are |
| 10:24 | timvisher | so if you store it in ~/.myapp/foo.clj then you need to get the home location and str them together |
| 10:24 | timvisher | i'm a big fan of fs |
| 10:25 | clgv | dpritchett`: like timvisher said you would have to gain the full path. maybe there is some java.io that does resolution for you. would be great since "~" probably makes no sense on windows ;) |
| 10:25 | dpritchett` | so i can't just use ~ to refer to the home location, I have to figure ito ut myself? |
| 10:25 | timvisher | java doesn't understand ~ |
| 10:25 | dpritchett` | my app is mostly a toy and it's intended to be run serverside on linux fwiw |
| 10:25 | cemerick | ~ is a shell thing |
| 10:25 | clojurebot | @ has nothing to do with whether sth is evaluated or not |
| 10:25 | timvisher | fs has a home function |
| 10:26 | timvisher | you don't have to store it in ~ |
| 10:26 | timvisher | you could also just store it relative to the root of the war/jar/project folder |
| 10:26 | timvisher | then you wouldn't need a full path |
| 10:26 | timvisher | the point i was making was simply that you can't use ~ to refer to user home |
| 10:26 | dpritchett` | so we're talking http://clojars.org/fs ? |
| 10:27 | timvisher | dpritchett: that's what i use to interact with the filesystem |
| 10:27 | timvisher | it's a nice wrapper over File as well as some other nice functions for processing trees of files |
| 10:27 | timvisher | and you get to refer to files by there path, rather than as objects, which is nice |
| 10:27 | dpritchett` | i think i'll just use a relative path for now... I am not exactly concerned with a perfect solution i just want to get the password out of my code |
| 10:28 | dpritchett` | then i'll gitignore the config file and push it out |
| 10:28 | timvisher | pjstadig: if you're saying that state must be changing outside of the run-time and thus messing with my results, that's a good point, but it still doesn't seem to explain what I'm seeing |
| 10:28 | timvisher | i can run those 2 functions over and over again and they return the same results every time |
| 10:29 | timvisher | if they were changing the state i'm reading, i'd expect the results to change |
| 10:29 | pjstadig | map is lazy |
| 10:29 | pjstadig | so the time between when you call map and when you print or first the seq...things can happen |
| 10:29 | timvisher | again, i totally agree with you, but if that was happening, you'd expect the results to be different every time, wouldn't you? |
| 10:30 | timvisher | i suppose i could do-run on the map |
| 10:30 | pjstadig | maybe it's not the solution, but it's all i got |
| 10:30 | timvisher | but the repl forces lazy seqs anyway |
| 10:30 | timvisher | that's cool. thanks for your help. this behavior is just baffling to me |
| 10:30 | pjstadig | if i were you i'd break apart those complex pieces of code, and try to test things in isolation |
| 10:30 | timvisher | that's what i've been doing |
| 10:30 | pjstadig | right |
| 10:30 | timvisher | everything works exactly as expected until i use the map |
| 10:30 | pjstadig | so maybe i'm not helping :) :( |
| 10:30 | timvisher | seq |
| 10:31 | timvisher | you're at least providing an ear to rant to. :) |
| 10:31 | pjstadig | the fact that lastModified returns 0 on an i/o error or if the file is missing seems like a good lead to me |
| 10:31 | pjstadig | that would explain seeing 0 for imported-at |
| 10:32 | pjstadig | and the fact that lastModified is accessing the file system which can change while you're not looking also seems like a good lead |
| 10:32 | pjstadig | but i agree it's weird that it is reproducible |
| 10:33 | dpritchett` | so i am using clojure.contrib.sql/with-query-results to pull from mysql and i haven't yet figured out the proper way to e.g. post the results to an html template before the connection closes |
| 10:33 | dpritchett` | i have one function that gets me the recordset and can format/print it |
| 10:33 | dpritchett` | and i have another that responds to an http request using noir's defpage macro at the url "/posts" |
| 10:33 | dpritchett` | haven't figured out how to compose this exactly |
| 10:34 | dpritchett` | Does anyone know of a good example of a simple CMS app using contrib.sql ? |
| 10:35 | clgv | do I still have to use DateTime/now or is there something in clojure 1.2.1 or contrib? |
| 10:35 | clgv | I want to use the timestamp as ID |
| 10:36 | timvisher | clgv: could you be looking for clj-time? |
| 10:36 | clgv | since I dont need any real ID management but only a reference between datasets on disk |
| 10:36 | timvisher | $google clj-time |
| 10:36 | sexpbot | First out of 61800 results is: clj-time | Clojars |
| 10:36 | sexpbot | http://clojars.org/clj-time |
| 10:36 | pjstadig | ,(.getTime (Date.)) |
| 10:36 | clojurebot | java.lang.IllegalArgumentException: Unable to resolve classname: Date |
| 10:36 | pjstadig | ,(.getTime (java.util.Date.)) |
| 10:36 | clojurebot | 1308926197290 |
| 10:36 | pjstadig | can work as a timestamp |
| 10:36 | pjstadig | and can be compared easily |
| 10:38 | clgv | yep. I just dont want to build an own function if there is one already. |
| 10:38 | pjstadig | there is one though...it's the method on the Date class |
| 10:39 | clgv | I saw it ;) |
| 10:39 | pjstadig | suit yourself :) |
| 10:42 | cemerick | or ##(System/currentTimeMillis) |
| 10:42 | sexpbot | ⟹ 1308926534365 |
| 10:42 | pjstadig | ja, was just going to say that, too |
| 10:44 | clgv | cemerick: precise one :) |
| 10:44 | timvisher | so if i do the same operation without binding library, i'm golden. https://gist.github.com/1044912 |
| 10:44 | manutter | timvisher: Hey, I saw your questions about daylight time yesterday (it was in my scrollback) Did you ever get that figured out? |
| 10:44 | timvisher | with binding but with refs, still broken https://gist.github.com/1044918 |
| 10:45 | timvisher | manutter: yes and know |
| 10:45 | timvisher | no* |
| 10:45 | clgv | just checked: (-> (System/currentTimeMillis) (java.util.Date.)) to be sure that it isnt relative to system start ;) |
| 10:45 | timvisher | i figured out a way to do it |
| 10:46 | timvisher | what i didn't figure out is why (time-zone-for-id "US/Eastern") and (time-zone-for-offset -5) don't return the same thing |
| 10:46 | manutter | timvisher: that is odd, unless US/Eastern is auto-updating for DST |
| 10:47 | timvisher | that's what i mean |
| 10:47 | gfrlog | Us/Eastern should be an atom that gets swapped every 6 months |
| 10:47 | timvisher | any of the relevant string ids (i.e. "America/New_York") all auto update to DST |
| 10:47 | cemerick | gfrlog: The earth probably won't exist by the time the long overflows. |
| 10:47 | cemerick | ,(java.util.Date. Long/MAX_VALUE) |
| 10:47 | clojurebot | #<Date Sat Aug 16 23:12:55 PST 292278994> |
| 10:47 | cemerick | Or humanity will be extinct, whatever. |
| 10:48 | gfrlog | cemerick: you mean the earth probably won't exist BECAUSE the long overflows |
| 10:48 | timvisher | they return different types |
| 10:48 | manutter | cemerick: yeah, maybe if we were better prepared for Y2G it would be the end of everything |
| 10:49 | clgv | lol earth wont exist because of suns death by then ;) |
| 10:49 | timvisher | one is a CachedDateTimeZone and the other is a FixedDateTimeZone |
| 10:49 | manutter | yeah, but the sun uses an old MS timestamp... |
| 10:49 | timvisher | but the semantics of the functions then seem strange |
| 10:49 | timvisher | when i sign up for a site and they ask me for my GMT offset, i say 5 without thinking and they select US/Eastern |
| 10:49 | timvisher | -5* |
| 10:50 | gfrlog | what's 5? Israel? |
| 10:50 | timvisher | whereas it seems that if I want to use for-offset i'd have to keep track of whether that person is currently in DST |
| 10:50 | timvisher | to add or subtract an hour |
| 10:50 | timvisher | or whatever crazy thing that country is doing this year |
| 10:50 | manutter | timvisher: I haven't worked enough with Java dates to discuss the technical details beyond a certain rather shallow depth |
| 10:51 | timvisher | it's my first real forray as well so hurray to us! :) |
| 10:51 | clgv | timvisher: turkey switched DST later this year with an absurd reason^^ |
| 10:51 | manutter | I did see a link on joda.org about updating the timezones manually |
| 10:51 | manutter | apparently that's an issue for people stuck using older jvm version |
| 10:51 | manutter | *versions |
| 10:51 | timvisher | i just know that everything i've read about joda time up until now made me think that it did DST magically, which it _does_ so long as you don't get that FixedDateTimeZone back |
| 10:51 | timvisher | i just don't know why you'd ever want that. |
| 10:52 | timvisher | maybe if you wanted to stick it people dumb enough to live in countries with DST (like me! ;) |
| 10:52 | cemerick | clgv: The sun still has some billions of years to it yet, no? Or am I forgetting my local astrophysics timelines? |
| 10:52 | timvisher | cemerick: you're thinking of alpha centauri |
| 10:52 | timvisher | you have a suprisingly wide scope of local astrophysics ;) |
| 10:52 | timvisher | the sun's going in a few years |
| 10:53 | timvisher | don't worry though |
| 10:53 | clgv | cemerick: oh humm that number is only 292 million - well, guess I have to check ;) |
| 10:53 | timvisher | the government'll get us all relocated |
| 10:53 | gfrlog | hairdressers and marketing folks on the first ship |
| 10:53 | timvisher | anyone else had a chance to look at this seq problem i'm having? |
| 10:54 | manutter | Just put a dollar in the bank now, at 3% interest by the year 292M you'll be able to buy a whole solar system somewhere else. |
| 10:54 | cemerick | timvisher: A billion here, a billion there :-) http://en.wikipedia.org/wiki/Sun#Life_cycle |
| 10:54 | timvisher | manutter: that's why i don't invest in stocks |
| 10:54 | Scriptor | we're just about about halfway through the sun, I believe |
| 10:54 | tsdh | Is there a problem with generating and executing gazillions of identical anonymous functions (performance and maybe garbage collection wise)? |
| 10:54 | clgv | cemerick: damn. ok we need bigger integer types! ;) |
| 10:55 | Scriptor | manutter: or dine at a fabulously expensive restaurant and watch the universe end :) |
| 10:55 | Scriptor | tsdh: why are they identical? |
| 10:55 | Scriptor | or are you generating billions of closures? |
| 10:56 | tsdh | Scriptor: Well, not identical but equivalent. |
| 10:56 | gfrlog | can the number of functions generated be expressed by a Long? |
| 10:57 | tsdh | Scriptor: Basically, I have a type-matcher function that returns a function that accepts elements of some types. That is used in some lazy seq producing fn, and in each iteration step a new type-matcher for the *same* type is produced. |
| 10:57 | stuartsierra | tsdh: Every occurrence of `fn` in your code generates one Java class. Every time that fn expression is evaluated, it generates one instance of that class. |
| 10:58 | tsdh | Scriptor, stuartsierra: Now I wondered if it would improve performance if I refactored the code so that only one type-matcher instance is produced and passed along. |
| 10:58 | gfrlog | stuartsierra: the instance holds the closure information? |
| 10:58 | timvisher | anyone know why a long at the repl would suddenly turn to 0 upon looking at it putting it somewhere else? |
| 10:59 | timvisher | i.e. https://gist.github.com/1044816 |
| 10:59 | timvisher | /s/looking at it/ |
| 10:59 | timvisher | anyone know why a long at the repl would suddenly turn to 0 upon putting it somewhere else? |
| 10:59 | gfrlog | timvisher: is that the most minimal example you can get? |
| 10:59 | timvisher | hmm. was that /s supposed to work? |
| 10:59 | timvisher | no |
| 10:59 | timvisher | i'll work on getting it more minimal |
| 11:00 | timvisher | actually, is that minimal enough? |
| 11:00 | timvisher | https://gist.github.com/1044918 |
| 11:00 | timvisher | i removed the binding and all of that |
| 11:00 | timvisher | it's still fairly complex |
| 11:00 | timvisher | baha |
| 11:00 | timvisher | sorry, ignore that |
| 11:00 | gfrlog | there's all this stuff with these libraries I don't know anything about... |
| 11:00 | timvisher | have too many gists going |
| 11:00 | timvisher | i'll work on something new |
| 11:00 | gfrlog | usually if you try to strip out all the ancillary stuff at some step you'll figure out the real culprit |
| 11:01 | timvisher | how do i produce a primitive long on purpose? |
| 11:01 | gfrlog | do it by accident and then later claim you meant to |
| 11:01 | timvisher | lol |
| 11:01 | timvisher | that's what fs/mtime is doing so i want to remove that call |
| 11:01 | manutter | timvisher: I dunno, I looked at that code and I think you should call Schrodinger and tell him you found his cat. |
| 11:02 | clgv | roflmao! |
| 11:02 | Scriptor | tsdh: presumably it would be more performant, benchmarks would be pretty interesting to see just to get an idea of how all the class generation affects clojure performance |
| 11:02 | stuartsierra | gfrlog: yes |
| 11:03 | gfrlog | stuartsierra: cool. |
| 11:03 | stuartsierra | The instance holds the values of closed-over locals. |
| 11:03 | Scriptor | also, see if maybe you could refactor it into just one function and generate a ton of closures of it instead? |
| 11:03 | timvisher | manutter: that's what i've been looking to hear all morning! :) |
| 11:04 | stuartsierra | In general, you want to avoid generating hugh numbers classes (which can happen with `eval`). Generating huge numbers of instances (closures) should not be a problem. |
| 11:04 | timvisher | so, no one knows how to produce a long on purpose? |
| 11:04 | clgv | &(Long. 5) |
| 11:04 | sexpbot | java.lang.IllegalArgumentException: No matching ctor found for class java.lang.Long |
| 11:05 | timvisher | ,(long 5) |
| 11:05 | clojurebot | 5 |
| 11:05 | timvisher | that look about right? |
| 11:05 | gfrlog | ,(.longValue (long 3)) |
| 11:05 | clgv | &(type (long 5)) |
| 11:05 | clojurebot | 3 |
| 11:05 | sexpbot | ⟹ java.lang.Long |
| 11:05 | timvisher | god i've gotten lazy |
| 11:05 | gfrlog | docs say that Long#longValue returns a primitive |
| 11:05 | timvisher | does type do autoboxing? |
| 11:05 | gfrlog | don't know what clojure will do to it though |
| 11:05 | tsdh | Scriptor: Hm, now I refactored the function that way, and the performance is only very slightly increased. With ~1 million type-matcher each producing a new instance it takes 330ms, with one instance passed along it takes 270ms. So it seems it's not worth it. |
| 11:06 | clgv | the random version: ##(if (< (rand) 0.5) (long 5) (double 5)) |
| 11:06 | sexpbot | ⟹ 5 |
| 11:06 | stuartsierra | Starting in 1.3, all integer literals are longs. They will be primitive if used only in a primitive context. Anywhere else they will be boxed as java.lang.Long. |
| 11:06 | stuartsierra | Most Clojure functions, such as type, do not support primitives, so auto-boxing occurs. |
| 11:06 | cemerick | timvisher: All primitives are boxed at function boundaries, unless the function in question has primitive type decls. |
| 11:06 | Scriptor | tsdh: see if you can check memory consumption too, just in case the gc isn't able to keep up |
| 11:07 | Scriptor | otherwise, an 18% speedup isn't all that bad :) |
| 11:07 | timvisher | ,(doc long) |
| 11:07 | clojurebot | "([x]); Coerce to long" |
| 11:07 | timvisher | does that mean Coerce to Long? |
| 11:07 | Scriptor | ,(doc apply-macro) |
| 11:07 | clojurebot | No entiendo |
| 11:07 | timvisher | or is that really be a bonafide `long`? |
| 11:08 | gfrlog | timvisher: does your code not break if you substitute (long 5) for your function call? |
| 11:08 | tsdh | Scriptor: Memory is hard to measure. In any case, the requirements of these functions should be negligible in comparison to the data. |
| 11:08 | gfrlog | (or (long 6) if necessary) |
| 11:09 | timvisher | i'm working on making this simpler, i just want to know if I'm on the right track for replacing that call to fs |
| 11:09 | tsdh | Scriptor: Well, yes, the speedup is not that bad, but now the interface is 50% worse. Before users would call (vseq mygraph 'SomeType), now it's (vseq mygraph (type-matcher mygraph 'SomeType))... |
| 11:11 | Scriptor | ah, maybe not worth it then, though you maybe vseq could be implemented as a wrapper macro that rewrites it that way for you? |
| 11:11 | cemerick | timvisher: it returns a long, but will get boxed into a Long if you're just passing the result on to a fn that doesn't support primitives. |
| 11:11 | cemerick | Or, it yields a long, I should say. |
| 11:12 | Scriptor | how fast is java's instanceof? Asking because first/rest invoke it every call |
| 11:12 | timvisher | wow. i'm an idiot |
| 11:12 | timvisher | sorry everyone |
| 11:12 | tsdh | Scriptor: vseq is a protocol function that recursively calls itself in a lazy-cat. |
| 11:12 | timvisher | i wasn't binding one of the keys i needed in the function and so pjstadig was right all along! |
| 11:13 | timvisher | the path i was accessing didn't exist and thus mtime was returning 0 |
| 11:13 | timvisher | at binding time they existed because the preferences var hadn't been overwritten yet |
| 11:13 | timvisher | i hate state... |
| 11:13 | timvisher | should've been associng onto preferences rather than completely resetting it |
| 11:14 | Scriptor | tsdh: ah, you're right, sorry for the confusion |
| 11:14 | timvisher | thanks so much for everyones help |
| 11:15 | gfrlog | timvisher: did you figure it out while trying to minimize the example? |
| 11:16 | timvisher | yeah |
| 11:16 | gfrlog | :) |
| 11:16 | timvisher | which was also pjstadig advice |
| 11:16 | timvisher | which i'd been doing for an hour |
| 11:16 | timvisher | i just never though to not use mtime and instead insert a fixed long value |
| 11:16 | gfrlog | my strategy is to just delete random characters and see what happens |
| 11:17 | timvisher | have an emacs function that does that for you? :) |
| 11:17 | pjstadig | timvisher: glad you figured it out! |
| 11:18 | tsdh | Scriptor: Hm, but I could make a vseq function that creates a type-matcher and rename the protocol methods to vseq-1. Is there something like a private protocol? |
| 11:18 | timvisher | pjstadig: me too! |
| 11:18 | timvisher | as a meta question, why does the repls forced eval not exhibit the behavior that firsts eval does? |
| 11:20 | pjstadig | i'll tell you why |
| 11:20 | pjstadig | map is lazy |
| 11:21 | pjstadig | the seq escapes the binding form in one case |
| 11:21 | pjstadig | but not in another |
| 11:21 | timvisher | ah hah |
| 11:21 | pjstadig | stupid laziness :) |
| 11:22 | timvisher | so the seq comes out of the binding form having not been evaluated and then gets evaluated in the unbound context |
| 11:22 | timvisher | brilliant |
| 11:22 | timvisher | makes perfect sense |
| 11:22 | pjstadig | vars and binding are a form of state |
| 11:24 | tsdh | Hm, the docs specify (defprotocol name & opts+sigs) but don't mention what opts can be except the optional docscring... |
| 11:26 | gfrlog | ,(source defprotocol) |
| 11:26 | clojurebot | java.lang.Exception: Unable to resolve symbol: source in this context |
| 11:26 | pjstadig | ~source defprotocol |
| 11:28 | timvisher | anyone else using clojure-jack-in in emacs? |
| 11:31 | mattmitchell | is there a non-lazy concat? or, a recursive doall? |
| 11:32 | dnolen | mattmitchell: you can always make concat non-lazy by wrapping in doall. |
| 11:34 | mattmitchell | dnolen: ok that does work, however i am composing a data structure out of a hash-map and embedded laz seqs via concat. I would like to not have to worry about using doall all over my code, and instead use doall at the last minute. But it doesn't seem to eval the nested lazy seqs. Does that make sense? |
| 11:35 | dnolen | mattmitchell: you can use doall at the last minute, doall will only operate on the lazyseq it's applied to, not nested ones. |
| 11:35 | dnolen | s/can/can't |
| 11:35 | sexpbot | <dnolen> mattmitchell: you can't use doall at the last minute, doall will only operate on the lazyseq it's applied to, not nested ones. |
| 11:36 | mattmitchell | dnolen: ok good to know. I've been looking at this too... seem like a good/bad idea? http://stackoverflow.com/questions/1217131/recursive-doall-in-clojure |
| 11:37 | dnolen | mattmitchell: I'm curious as to why you need to force them. |
| 11:38 | mattmitchell | dnolen: yeah i'm still trying to figure this out. I might be doing something wrong here. |
| 11:38 | dnolen | mattmitchell: what about your problem requires you to force them? |
| 11:39 | pjstadig | i've run into the problem of doing concat of concats of concats to build up a structure, and once it gets forced at the end you get a stack overflow exception |
| 11:39 | pjstadig | and it was fixed but just doing (doall (concat ...)) |
| 11:39 | pjstadig | instead of waiting until the end |
| 11:40 | gfrlog | no matter how many times I encounter that issue I can never remember why it happens |
| 11:40 | dnolen | gfrlog: recursive applications of concat is almost always the culprit |
| 11:40 | pjstadig | there's also the issue of a lazy seq escaping a scope like with-open or something |
| 11:40 | gfrlog | dnolen: like (concat a (concat b (concat c (...))))? |
| 11:40 | pjstadig | but again you can doall at the appropriate levels to get around that |
| 11:41 | dnolen | gfrlog: if you have 5000 unrealized concats, you're gonna get stackoverflow when you try to pull out the first item. |
| 11:41 | gfrlog | dnolen: I guess I can't convince myself it's necessary, given the way laziness is handled elsewhere without stacking |
| 11:41 | mattmitchell | dnolen i think actually, i'm wrong. I need to dig a little bit more before I can explain what's happening here :) |
| 11:41 | gfrlog | dnolen: 5000 nested (lazy-seq)s generally would do the same thing? |
| 11:42 | dnolen | gfrlog: exactly. |
| 11:42 | gfrlog | dnolen: I wonder why everybody's so prone to do it with concat then... |
| 11:42 | gfrlog | could concat be rewritten to avoid that? |
| 11:43 | pjstadig | perhaps we should all make more use of into |
| 11:43 | pjstadig | and infact i guess into is really a "non-lazy" concat |
| 11:43 | dnolen | gfrlog: I don't see the point, since it applies to lazyseqs in general. |
| 11:43 | gfrlog | dnolen: but apparently concat is the only place it tends to pop up |
| 11:44 | dnolen | gfrlog: only because it's commonly used in recursive operations, special casing concat sounds meh. |
| 11:45 | __name__ | $source into |
| 11:45 | sexpbot | into is http://is.gd/uvV1dc |
| 11:46 | gfrlog | dnolen: well if it's meh then let's not do it |
| 11:50 | pjstadig | only problem with into vs. concat is |
| 11:50 | pjstadig | ,(into '(:d :e) [:a :b :c]) |
| 11:50 | clojurebot | (:c :b :a :d :e) |
| 11:50 | pjstadig | ,(concat '(:d :e) [:a :b :c]) |
| 11:50 | clojurebot | (:d :e :a :b :c) |
| 11:50 | dnolen | ,(into (vec '(:d :e)) [:a :b :c]) |
| 11:50 | clojurebot | [:d :e :a :b :c] |
| 11:50 | pjstadig | sure |
| 11:50 | pjstadig | but that's cheating |
| 11:51 | pjstadig | hehe |
| 11:51 | dnolen | :) |
| 11:51 | pjstadig | i'm just saying you have to be aware that into uses conj which is data structure specific in terms of where it stuffs new items |
| 11:51 | pjstadig | but concat is also ordered the way you'd "expect" |
| 11:52 | pjstadig | plus |
| 11:52 | pjstadig | ,(concat #{:a :b} #{:a :b}) |
| 11:52 | clojurebot | (:a :b :a :b) |
| 11:52 | pjstadig | ,(into #{:a :b} #{:a :b}) |
| 11:52 | clojurebot | #{:a :b} |
| 11:52 | pjstadig | assuming you'd want to do such a thing |
| 11:55 | Scriptor | anyone behind clojuredocs.org on here? |
| 11:55 | Scriptor | the sorting algorithm used in search is a bit off |
| 11:59 | gfrlog | Scriptor: I've seen it do weirder things |
| 12:01 | gfrlog | I forget what I was searching for, but when searching for the function "foo" by name, nothing would come up. When I searched for another function called "foo-bar", "foo" was the first result |
| 12:01 | mattmitchell | anyone know what the command is in emacs to show a list of search matches in a new buffer? |
| 12:02 | derp_ | hey, what is the != symbol in clojure? |
| 12:02 | dnolen | derp_: not= |
| 12:02 | mattmitchell | it'll show each match with a little context |
| 12:02 | derp_ | dnolen: thanks |
| 12:02 | dnolen | mattmitchell: are you talking about grep-find ? |
| 12:04 | mattmitchell | dnolen: no you can do C-s, then you can pull out the matches into a new buffer, and in that buffer you can see a little context around each match. If you select one of the items, you go to that place in your main buffer. Very handy, just can't remember what it's called! |
| 12:07 | mattmitchell | dnolen: can grep-find do that? |
| 12:07 | dnolen | mattmitchell: multi-occur ? |
| 12:07 | mattmitchell | dnolen: i'll try that |
| 12:07 | dnolen | M-x multi-occur |
| 12:07 | mattmitchell | oh that sounds right |
| 12:07 | dnolen | which is really cool, I never knew about that. |
| 12:07 | dnolen | http://www.emacswiki.org/emacs/SearchBuffers |
| 12:07 | mattmitchell | dnolen: yes! thank you. very helpful. |
| 12:09 | edwardg | hello, clojure noob here - trying to run clj-http tests, but `lein run -m clj-http.run-server` gives me a classpath error. is it implicit that i need to adjust the classpath, or am i missing something basic? |
| 12:09 | derp_ | I wrote this function to test for primality ( http://pastebin.com/fqL37JPN ) but for some reason it's not working, and I really can't guess why |
| 12:10 | edwardg | which tests are failing? |
| 12:10 | derp_ | the first if statement should return when checking against 1 or 2, but for some reason it's returning false, which doesn't make any sense to me |
| 12:12 | hiredman | derp_: you see to expect implicit return statements in non-tail positions? |
| 12:12 | hiredman | seem |
| 12:14 | hiredman | everything is an expression http://stackoverflow.com/questions/19132/expression-versus-statement |
| 12:15 | derp_ | so how do I make it explicit? |
| 12:17 | hiredman | derp_: there are no statements |
| 12:18 | derp_ | okay, but then how do I return the evaluated expression? |
| 12:27 | cemerick | derp_: use cond instead of a pile of `if`s |
| 12:29 | cemerick | There's also https://github.com/jpalmucci/clj-return-from, which I can see being handy for more complex situations |
| 12:33 | derp_ | okay, I tried using cond instead, here's my code now: http://pastebin.com/MHbx04dM |
| 12:33 | derp_ | but for some reason I still can't get it to work |
| 12:35 | hiredman | derp_: everything is an expression |
| 12:37 | manutter | ,(doc recur) |
| 12:37 | clojurebot | Huh? |
| 12:37 | manutter | ,(doc loop) |
| 12:37 | clojurebot | "([bindings & body]); Evaluates the exprs in a lexical context in which the symbols in the binding-forms are bound to their respective init-exprs or parts therein. Acts as a recur target." |
| 12:37 | dnolen | derp_: move your recur inside the cond expr as a :else clause |
| 12:39 | derp_ | dnolen: thanks! |
| 12:40 | derp_ | dnolen: why is it :else instead of else? |
| 12:41 | fliebel | ,(boolean :else) |
| 12:41 | clojurebot | true |
| 12:41 | gfrlog | is that why it works? |
| 12:41 | manutter | derp_: The :else isn't actually part of the cond syntax |
| 12:41 | fliebel | &(cond false 1 :blah 2) |
| 12:41 | sexpbot | ⟹ 2 |
| 12:41 | gfrlog | it hadn't occurred to me that it wasn't part of it |
| 12:42 | manutter | it's just a value that is truthy enough to serve the purpose of a "non of the above" clause |
| 12:42 | gfrlog | &(cond false 1 :never 4) |
| 12:42 | sexpbot | ⟹ 4 |
| 12:42 | dnolen | derp_: because it makes the cond macro simpler. |
| 12:43 | manutter | ,(code false 1 (= 1 0) 2 :none-of-the-above 3) |
| 12:43 | clojurebot | java.lang.Exception: Unable to resolve symbol: code in this context |
| 12:43 | manutter | doh, typo |
| 12:43 | manutter | (cond false 1, (= 1 0) 2, :none-of-the-above 3) |
| 12:43 | gfrlog | ah hah ha... |
| 12:43 | manutter | and he forgets the leading comma, doh again. |
| 12:43 | derp_ | okay, so it's just a random keyword that's evaluated after all other statements? |
| 12:44 | gfrlog | ,(cond :else 15 (= 1 1) "twelve") |
| 12:44 | clojurebot | 15 |
| 12:44 | gfrlog | only if you put it after all the other statements ;-) |
| 12:44 | manutter | Yeah, any keyword will evaluate to true, and thus satisfy cond, which looks for the first clause that returns a true value |
| 12:44 | derp_ | &(cond :blah 1 true 2 false 3) |
| 12:44 | sexpbot | ⟹ 1 |
| 12:44 | fliebel | gfrlog: That's a nasty trick to unsuspecting readers :) |
| 12:45 | gfrlog | ,(conf :if 1 :then 2 :else 3 :end 4) |
| 12:45 | clojurebot | java.lang.Exception: Unable to resolve symbol: conf in this context |
| 12:45 | gfrlog | bah |
| 12:45 | gfrlog | I'm not typing it again. |
| 12:45 | manutter | Yeah, the "magic" is that cond tries each pair until it finds one that evaluates to a true value, so if you have an always-true value, non of the other clauses will be tried. |
| 12:47 | halfprogrammer | I think even JoC talks about using any keyword in cond instead of :else thingy |
| 13:05 | choffstein | 1 |
| 13:06 | gfrlog | choffstein: 2 |
| 13:06 | choffstein | Has anyone successfully deployed a war file (generated from lein-ring) on tomcat? I am having some issues trying to figure out how to get the static files to serve (using ring / moustache / hiccup) and where they should be located in the war file for tomcat to serve them |
| 13:06 | gfrlog | choffstein: does the standard resources setup not work? |
| 13:06 | choffstein | yeah ... advice to IRC GUI programmers -- don't change window context when a user is typing in their password :-\ |
| 13:07 | gfrlog | your password is "1"? |
| 13:07 | choffstein | there is a 1 in it. |
| 13:07 | manutter | not any more ;) |
| 13:07 | choffstein | namely ... at the end |
| 13:07 | choffstein | hence the "enter" that quickly followed it. |
| 13:07 | manutter | That's amazing I have the same combination on my luggage. |
| 13:08 | gfrlog | Now I just gotta think of all the passwords that end in "1" and pick the most plausible |
| 13:08 | manutter | "we're-number-..." |
| 13:08 | gfrlog | "321"? |
| 13:08 | manutter | So, if I admit I successfully deployed a WAR file, you're going to ask me how I did it, and I don't remember :) |
| 13:08 | manutter | *:( |
| 13:08 | choffstein | lemme throw up a quick gist of my setup... |
| 13:09 | gfrlog | a quist |
| 13:10 | manutter | iirc, I ended up with a setup that would work for war files but not for lein/repl work, and one that would work with lein/repl but not war |
| 13:10 | choffstein | yeah. that is what I am finding in online resources manutter |
| 13:10 | manutter | and I could switch between the two with the right changes to my project.clj |
| 13:10 | manutter | but I'm at work now and don't have access to those files |
| 13:11 | choffstein | maybe something about changing the project environment settings? |
| 13:12 | manutter | I think I added a special plugin or something |
| 13:12 | choffstein | well ... that's an interesting idea. is it possible to get information from your leiningen project file from inside your project? |
| 13:13 | choffstein | my current issue is that my environment variables which I am trying to use to distinguish between production and development environments don't seem to be read from within tomcat... |
| 13:13 | manutter | On that question I'll defer to someone who actually knows what they're talking about |
| 13:15 | choffstein | yeah. let me get that gist up right quick |
| 13:16 | derp_ | I am still having a bit of trouble getting my euler #3 program to work http://pastebin.com/MHKSNz3A |
| 13:16 | derp_ | I keep getting an error about not recurring from the tail-position |
| 13:17 | derp_ | I'm not really sure how to get around that, so I think I must be making some fundamental mistake |
| 13:17 | sritchie | (reverse (rest (reverse lst))) can be (butlast lst), btw |
| 13:18 | manutter | derp_: the problem is in line 29 of your gist |
| 13:18 | manutter | if I'm parsing the nesting correctly anyway |
| 13:19 | tsdh | Can I have a protocol whose methods are not exposed? Something like defn-? |
| 13:19 | dnolen | tsdh: hiding fns of protocol doesn't make sense. |
| 13:20 | derp_ | so it's okay to have multiple recur statements within a function? |
| 13:20 | derp_ | the error was making me think I could not do that |
| 13:21 | tsdh | dnolen: why? I use protocols for fast dispatching in my own namespace but the functionality is exposed with some more convenient interface. |
| 13:21 | dnolen | derp_: you can, but you should probably stop solving your euler problem and take a moment to understand where recur has to go. make some small simple fns to test. |
| 13:22 | dnolen | tsdh: this isn't Java. imagine Clojure's core datastructures with hidden protocol fns. |
| 13:22 | choffstein | Okay, here is my project file / web.xml file / and server as well as the tomcat error I am getting (which is highly undescriptive): https://gist.github.com/1045242 |
| 13:22 | sdeobald | choffstein, can you use Jetty instead? We tried Tomcat for ages before finally switching. It's much... less awful. |
| 13:23 | tsdh | dnolen: Wouldn't make sense there, but here it does. |
| 13:23 | choffstein | sdeobald: Amazon's Elastic Beanstalk is on tomcat :-\ |
| 13:23 | choffstein | Which is what I am trying to deploy to... |
| 13:23 | sritchie | tsdh: can you just put the protocol in some other namespace, and :use it into the namespace with your convenient interfaces? |
| 13:23 | dnolen | tsdh: protocols produce fns, you could probably alter the vars if you really want to. or use definterface and don't involve fns at all. |
| 13:23 | derp_ | dnolen: I don't understand, what more do I need to know about recur except that it is an stack optimizing method for recursive calls? |
| 13:23 | derp_ | or is my understanding too fundamental? |
| 13:23 | rhdoenges | with clojure.string/replace, how do I access a matched group from the RE in my replacement? |
| 13:23 | dnolen | derp_: recur needs to be in the tail poisition, you need to figure out what that means. |
| 13:24 | sdeobald | choffstein, dang. Too bad. I remember having the same static resource issue on Tomcat. Let me see if I can find an old setup. |
| 13:24 | gfrlog | ,(doc clojure.string/replace) |
| 13:24 | clojurebot | I don't understand. |
| 13:24 | tsdh | sritchie: That's an idea... |
| 13:24 | gfrlog | rhdoenges: I believe you can pass a function that takes the match vector |
| 13:24 | rhdoenges | gfrlog: ohkay. so I would pass something like (fn [[group-one group-two]] ...) |
| 13:25 | gfrlog | rhdoenges: yeah. Test it out, it's probably the case that the 0th item in the vector is not one of the groups |
| 13:25 | choffstein | sdeobald: do you know a good jetty host? |
| 13:25 | tsdh | dnolen: What's definterface? |
| 13:25 | dnolen | tsdh: for defining a Java interface. |
| 13:26 | tsdh | dnolen: But I guess then I cannot use extend-protocol, right? |
| 13:26 | sdeobald | choffstein: Nope, sorry. We're just running it ourselves. |
| 13:27 | choffstein | okay, thanks anyway :) |
| 13:27 | sdeobald | And I guess the old tomcat setup is dead. So I'm just not any help at all. :) |
| 13:28 | choffstein | my biggest issue is getting static files to serve. ring's wrap-file seems to want the directory to exist, but to create a war, the directory needs to be in "resources." I just end up having a double copy of assets to make it work :-\ |
| 13:28 | rhdoenges | gfrlog: that's what was tripping me up, the first item is the whole matched part. thanks! |
| 13:28 | gfrlog | choffstein: I thought there was a handler that in the resources directory |
| 13:28 | gfrlog | rhdoenges: yessir |
| 13:29 | choffstein | gfrlog: eh? don't quite follow that |
| 13:29 | gfrlog | choffstein: okay lemme see what I have... |
| 13:29 | sritchie | derp_: your parens are off, on your cond statement |
| 13:30 | sritchie | derp_: you close off that cond block on line 27 |
| 13:30 | gfrlog | choffstein: I think it's a compojure thing. Are you using compojure? |
| 13:30 | dnolen | tsdh: yeah you can't. I guess I don't personally see much benefit in the convention ^:private when a) it can be circumvented, b) naked use is discouraged. |
| 13:30 | choffstein | nope. ring / moustache |
| 13:30 | gfrlog | choffstein: okay nevermind. I have (route/resourses "/") in my compojure routes and it finds everything in /resources/public |
| 13:31 | choffstein | well ... might be time to switch to compojure. I think moustache and compojure play nicely... |
| 13:31 | tsdh | dnolen: The obvious benefit is that you get less clutter when autocompleting. :-) |
| 13:31 | gfrlog | choffstein: I don't even know what the heck moustache is, so I can't comment on that |
| 13:32 | gfrlog | I thought it was this javascript templating thing but I think that's something else |
| 13:32 | sritchie | derp_: I fixed your formatting for you, and that cond error: https://gist.github.com/1045258 |
| 13:32 | sritchie | the code runs, now, though the answer's not correct |
| 13:32 | derp_ | sritchie: thank you very much! |
| 13:32 | dnolen | tsdh: heh, what are you using? I guess it doesn't process the ns declaration? |
| 13:33 | sritchie | I didn't change any functionality, but I tweaked your implementation of prime? to show you a different way of writing statements like that |
| 13:33 | tsdh | dnolen: I use slime/swank |
| 13:33 | sritchie | derp_: or goes through each of its forms and, if it hits one that's true, returns it, otherwise it moves on. If it gets to to end, it returns the value of the final form |
| 13:34 | sritchie | derp_: also, here's a nice style guide that should help you with formatting a bit: http://mumble.net/~campbell/scheme/style.txt. the key thing here is, don't treat the parens like curly braces and close them off on new lines |
| 13:34 | sritchie | let the reader use the indentation as a guide... you don't really count parens, once you've read enough of this code |
| 13:35 | derp_ | sritchie: thank you, I really appreciate your comments |
| 13:35 | hiredman | get paredit |
| 13:36 | derp_ | hiredman: already got, although I barely know how to use it |
| 13:36 | derp_ | *got it |
| 13:36 | sritchie | derp_: http://www.emacswiki.org/emacs/PareditCheatsheet |
| 13:42 | gfrlog | easiest way to make a black hole to bind *out* to? |
| 13:43 | drewr | (FileWriter. "/dev/null")? |
| 13:43 | gfrlog | drewr: okeedoke, thx |
| 13:44 | sdeobald | sritchie, that's a great sheet. derp_: you'll wind up using all of those all the time. paredit makes editing sexps a spiritual experience. |
| 13:45 | sritchie | derp_: try M-(, and go from there |
| 13:45 | sritchie | do that at the beginning of some symbol, and see what happens |
| 13:45 | rhdoenges | sritchie: that is what I have been looking for. I got one of those for vim and pinned it on my wall next to my monitor |
| 13:45 | rhdoenges | makes it a whole lot easier |
| 13:45 | sritchie | yup |
| 13:46 | sritchie | http://www.pchristensen.com/slimecommands.pdf |
| 13:46 | sritchie | good stuff there, too, for SLIME |
| 13:50 | rhdoenges | sritchie: it must be christmas or something |
| 13:55 | mattmitchell | anyone know of a way to remove double quotes from a word using paredit? for example, I want "test" to become test |
| 13:56 | mattmitchell | sorry, maybe i should go to #emacs :) |
| 13:57 | hugod | M-s |
| 13:58 | mattmitchell | hugod: awesome thank you |
| 14:03 | gfrlog | aw crap never use macros in (deftest) :( |
| 14:03 | matthias_ | im usign cantor. when i type (vec2 3 3) in the slime-repl, i get [x=3.0, y=3.0]. how does slime get that? when i try to turn a vec2 into a string in my program, i just get the type and the address |
| 14:04 | dnolen | matthias_: cantor probably doesn't define toString for vec2 |
| 14:05 | matthias_ | but then how does slime get that string? |
| 14:14 | aaelony | hi, I'm making a silly mistake somewhere. I have a map and I see the key exists, but can't access the value of the key... test=> (class (j 0)) |
| 14:14 | aaelony | clojure.lang.PersistentHashMap |
| 14:14 | aaelony | test=> (keys (j 0)) |
| 14:14 | aaelony | ("a" "b" "c" d" "e" ) |
| 14:14 | aaelony | test=> (:d (j 0)) |
| 14:14 | aaelony | nil |
| 14:16 | gfrlog | aaelony: your keys are strings but you're trying to access keywords |
| 14:16 | gfrlog | ({"a" 8 :a 3} :a) |
| 14:16 | gfrlog | ,(:a {"a" 8 :a 3}) |
| 14:16 | clojurebot | 3 |
| 14:17 | gfrlog | if you need to use strings for keys, you can access them like ((j 0) "d") or (get (j 0) "d") |
| 14:17 | aaelony | gfrlog: wow, thanks. |
| 14:17 | gfrlog | (strings and keywords are two different but similar things, and both can be used as keys in a map) |
| 14:17 | gfrlog | (in fact just about anything can be a key in a map) |
| 14:18 | aaelony | thx |
| 14:18 | gfrlog | yep |
| 14:19 | aaelony | that helps quite a lot :) |
| 14:20 | gfrlog | using keywords as keys is more common, but whether you should or not depends on what you're doing |
| 14:20 | aaelony | I'm just using what clj-json decided was best. I just couldn't access what I knew it read in. |
| 14:21 | gfrlog | ah, I see. I think clj-json has a config option that will convert the strings to keywords for you |
| 14:22 | gfrlog | (parse-string s true) |
| 14:22 | gfrlog | I'm mildly surprised it doesn't default to that |
| 14:22 | amalloy | gfrlog: string literals for unusual objects are easier to construct than keyword literals |
| 14:23 | amalloy | i mean, i think it should default to keywords too. but it's possible to see why they might not |
| 14:23 | gfrlog | amalloy: in the context of converting a JSON object to a map? |
| 14:23 | gfrlog | I mean...I guess |
| 14:24 | gfrlog | you're probably thinking the same thing I was and saying it differently |
| 14:24 | jcromartie | imagine if your JSON had spaces in the keys |
| 14:24 | jcromartie | keywords = fail |
| 14:24 | jcromartie | although |
| 14:25 | jcromartie | ,(keyword "this works") |
| 14:25 | clojurebot | :this works |
| 14:25 | jcromartie | :) |
| 14:25 | gfrlog | jcromartie: as does asking the parser to return strings |
| 14:25 | jcromartie | yes |
| 14:25 | gfrlog | I didn't say they should be incapable of returning strings :) |
| 14:26 | aaelony | well, I'm using the clj-json/parse-string s true option, but I have some nesting where I guess I didn't get keywords |
| 14:26 | gfrlog | augh |
| 14:26 | gfrlog | I've never used that library |
| 14:26 | jcromartie | this should just be a generic function |
| 14:27 | aaelony | or maybe I messed something else up... |
| 14:28 | gfrlog | I just successfully wrote some meta-testing helpers for clojure.test |
| 14:28 | jcromartie | (defn keywordify [m] (if (map? m) (into {} (map (fn [[k v]] [(keyword k) v]) m)) m)) |
| 14:29 | gfrlog | e.g., (should-fail (is (nil? 42))) |
| 14:29 | gfrlog | jcromartie: that misses the nested maps though, doesn't it? |
| 14:30 | gfrlog | maybe [(keyword k) (keywordify v)] |
| 14:34 | aaelony | in my case it seems I've got a mix of a vector then a nested map |
| 14:34 | aaelony | so, map, vector, map |
| 14:36 | gfrlog | fun! |
| 14:37 | jcromartie | gfrlog: no it doesn't |
| 14:37 | jcromartie | but it does miss maps in collections |
| 14:38 | jcromartie | like a vector of maps |
| 14:38 | gfrlog | jcromartie: how would it do {"foo" {"bar" 12}} then? |
| 14:46 | gfrlog | ,(let [keywordify (fn [m] (if (map? m) (into {} (map (fn [[k v]] [(keyword k) v] m)) m)))] (keywordify {"foo" {"bar" 12}})) |
| 14:46 | clojurebot | java.lang.IllegalArgumentException: Wrong number of args (1) passed to: core$map |
| 14:47 | jcromartie | gfrlog: it works in that case |
| 14:48 | gfrlog | ,(let [keywordify (fn [m] (if (map? m) (into {} (map (fn [[k v]] [(keyword k) v]) m)) m))] (keywordify {"foo" {"bar" 12}})) |
| 14:48 | clojurebot | {:foo {"bar" 12}} |
| 14:49 | gfrlog | maybe I'm misunderstanding what you were trying to do |
| 14:55 | mattmitchell | what's the easiest way to pull out values from a list, where the values returned must be present in another? |
| 14:56 | stuartsierra | (filter (set the-other-list) the-first-list) |
| 14:56 | scgilardi | certified easiest™ |
| 14:57 | gfrlog | ,(filter #{false nil true 17} [1 2 3 true false nil "whut"]) |
| 14:57 | clojurebot | (true) |
| 14:57 | gfrlog | sorry I couldn't stop myself :( |
| 14:57 | mattmitchell | nice thanks to you both! |
| 14:58 | amalloy | gfrlog: that always makes me cry |
| 14:58 | gfrlog | amalloy: that the code does that or that I wrote the code? |
| 14:58 | amalloy | both i guess |
| 14:58 | gfrlog | glad I could help |
| 14:59 | gfrlog | Clojure: because the easiest way to do something shouldn't have to work 100% of the time. |
| 14:59 | derp_ | is there an easy way to comment out highlighted text in emacs? |
| 14:59 | jcromartie | M-x comment-region |
| 15:00 | amalloy | derp_: M-; |
| 15:00 | jcromartie | or that |
| 15:00 | derp_ | thanks! |
| 15:00 | scgilardi | right, you need to be careful if nil and false are possible. or change to using keep and only special-case nil. |
| 15:01 | amalloy | or: commit it to git so you won't be afraid to just delete it instead of commenting it out |
| 15:01 | manutter | what if your afraid of git tho? |
| 15:01 | manutter | *you're |
| 15:01 | gfrlog | read about git |
| 15:02 | amalloy | manutter: there's always room in our nations jails for more dissidents |
| 15:02 | gfrlog | if you're afraid of reading, then watch a youtube video about reading |
| 15:02 | amalloy | *nation's |
| 15:02 | manutter | lol |
| 15:02 | rhdoenges | manutter: then use hg. or bzr. or svn. or cvs. anything is better than nothing |
| 15:02 | gfrlog | if you're afraid of youtube, then I'll tell amalloy that you're afraid of git and that'll be the end of you |
| 15:03 | jcromartie | amalloy: what nation is that? |
| 15:03 | jcromartie | not mine |
| 15:03 | amalloy | jcromartie: the us, alas |
| 15:03 | manutter | I think that would be consternation |
| 15:03 | jcromartie | hah hah... no more room |
| 15:03 | jcromartie | anyway |
| 15:03 | jcromartie | yes, source control is better that commented out code... |
| 15:03 | jcromartie | and also, (comment ...) is better than ;; |
| 15:03 | jcromartie | if you really want to be slick |
| 15:03 | gfrlog | git commit -a -m 'wut this commit is' |
| 15:04 | arohner | so I have a large set of strings (11 million). Is there a faster or more memory efficient way to determine if a string is in the set than a normal contains? |
| 15:04 | amalloy | jcromartie: ##((fn [x] (inc x) (comment "used to return 2x")) 3) |
| 15:04 | sexpbot | ⟹ nil |
| 15:04 | arohner | I can't just store the hash codes, because of collisions, right? |
| 15:04 | jcromartie | ah, (comment) returns nil? |
| 15:05 | amalloy | yes. that is why it is evil and shouldn't be encouraged |
| 15:05 | jcromartie | derp! |
| 15:05 | jcromartie | I always use it in the top level |
| 15:05 | jcromartie | that's why |
| 15:05 | amalloy | *nod* |
| 15:05 | gfrlog | arohner: contains should be looking up by hash code. I'd think the worst part is that the hash code of your test string has to be computed |
| 15:05 | amalloy | it's usually harmless of course |
| 15:05 | gfrlog | arohner: and I guess it'll compare them character-by-character as well |
| 15:06 | arohner | sounds like I need to read some source |
| 15:06 | scgilardi | arohner: a bloom filter could help |
| 15:06 | jcromartie | then there is #_ |
| 15:06 | amalloy | gfrlog: i imagine strings cache their hashes |
| 15:06 | jcromartie | scgilardi: the only problem there is that you need more hash functions |
| 15:06 | amalloy | since they're immutable |
| 15:06 | arohner | amalloy: yeah, I would assume that too |
| 15:06 | gfrlog | amalloy: yes |
| 15:06 | gfrlog | but there's no reason to assume his string has been cached before |
| 15:06 | gfrlog | hashed |
| 15:06 | gfrlog | hash-cached |
| 15:07 | gfrlog | hached |
| 15:07 | amalloy | gfrlog: as soon as it gets put into a hashmap, it has |
| 15:07 | gfrlog | amalloy: if he already put it into his set then he doesn't need to check if it's there |
| 15:07 | gfrlog | probably |
| 15:07 | amalloy | scgilardi: know of a good article on bloom filters? sounds interesting but i don't know anything about them |
| 15:07 | scgilardi | jcromartie: right, I was interpreting it as a problem to be solved with 11 million strings rather than specifically about set. |
| 15:07 | scgilardi | http://en.wikipedia.org/wiki/Bloom_filter |
| 15:07 | jcromartie | how about grep |
| 15:07 | mattmitchell | stuartsierra: how the heck does "(filter (set the-other-list) the-first-list)" work? |
| 15:08 | jcromartie | that would search 11M strings pretty fast |
| 15:08 | jcromartie | ;) |
| 15:08 | mattmitchell | ,(doc set) |
| 15:08 | clojurebot | "([coll]); Returns a set of the distinct elements of coll." |
| 15:08 | gfrlog | mattmitchell: it creates a set, which is a function that will return elements it contains |
| 15:08 | gfrlog | mattmitchell: for almost all elements, that corresponds to returning truthy, which is what filter looks for |
| 15:08 | mattmitchell | good grief that's slick |
| 15:09 | gfrlog | sounds like a bloom filter is like a hash-map that doesn't bother storing values |
| 15:10 | gfrlog | or hash-set rather |
| 15:10 | arohner | and requires multiple hash fns |
| 15:10 | gfrlog | haven't seen that part |
| 15:10 | amalloy | scgilardi: that's pretty neat |
| 15:11 | arohner | gfrlog: it's in the second sentence of the wiki article |
| 15:11 | arohner | requires k distinct hash fns |
| 15:11 | gfrlog | arohner: yep found it. Okay I take it back this is totally different and also clever. |
| 15:12 | gfrlog | I would join a band by that name. |
| 15:14 | gfrlog | "Unlike sets based on hash tables, any Bloom filter can represent the entire universe of elements." |
| 15:15 | amalloy | gfrlog: (constantly true) |
| 15:15 | gfrlog | okay fine |
| 15:17 | gfrlog | I guess you can represent cofinite sets as well... |
| 15:17 | mattmitchell | how can i extract the values from a hash-map, using a list of keys? For example, {:one 1 :two 2 :three} -- I want the values for :two and :three |
| 15:17 | jcromartie | I wonder... how big would your bloom filter have to be for an 11M item set |
| 15:17 | gfrlog | mattmitchell: (map m my-keys) |
| 15:17 | mattmitchell | i know this is gonna be simple |
| 15:17 | mattmitchell | there you go :) |
| 15:17 | mattmitchell | thanks |
| 15:17 | gfrlog | yessir |
| 15:18 | gfrlog | I would say for whathisface's application, if he can't tolerate false positives then the bloom filter won't do any good |
| 15:18 | gfrlog | since he'd have to compute a bunch of hashes instead of just one |
| 15:19 | gfrlog | save some space though I guess |
| 15:20 | arohner | gfrlog: saving space would be nice, right now the strings occupy 1.5GB. I'm more interested in speed than space though |
| 15:21 | gfrlog | arohner: I guess the bloom filter would help you filter out the negatives. Are your strings long? |
| 15:21 | arohner | gfrlog: not really. They're wikipedia article titles |
| 15:21 | amalloy | arohner: if you have them in a set already, looking them up will be fairly fast, i think |
| 15:21 | arohner | amalloy: but I want moar speed :-) |
| 15:21 | amalloy | the set will keep growing itself to limit collisions |
| 15:22 | amalloy | or at any rate, j.u.HashMap does. i haven't read the impl for clojure's, but i imagine it has similar guarantees about the load factor |
| 15:22 | gfrlog | get a real big CPU that has 2 GB of on-chip cache |
| 15:25 | edw | Anyone out there using aleph? I'm getting a hang when I wait on respons from my redis server. |
| 15:25 | amalloy | edw: (a) what version of aleph redis, (2) what commands are you sending? |
| 15:28 | jcromartie | arohner: maybe another option would be a tree |
| 15:29 | amalloy | jcromartie: that will be way slower than a hashset |
| 15:29 | gfrlog | a tree based on prefixes maybe? |
| 15:29 | jcromartie | right |
| 15:29 | derp_ | how does one append to a vector? |
| 15:29 | gfrlog | derp_: conj |
| 15:29 | arohner | clojure sets are already tries on the string's hashcode, right? |
| 15:29 | amalloy | &(conj [1 2] 3) |
| 15:29 | sexpbot | ⟹ [1 2 3] |
| 15:29 | gfrlog | amalloy: dang that was fast |
| 15:30 | gfrlog | arohner: probably so |
| 15:30 | amalloy | gfrlog: i have six fingers on my right hand |
| 15:30 | derp_ | why does conj prepend when used with lists? |
| 15:30 | sritchie | amalloy: I know a guy who's been looking for you |
| 15:30 | derp_ | &(conj [1 2] 3) |
| 15:30 | sexpbot | ⟹ [1 2 3] |
| 15:31 | amalloy | derp_: it adds in whatever manner is most efficient for the underlying type |
| 15:31 | gfrlog | amalloy: dang that was fast |
| 15:31 | gfrlog | I'm gonna stop reading questions |
| 15:31 | gfrlog | or at least wait 5 secondns |
| 15:31 | amalloy | *chuckle* |
| 15:32 | derp_ | okay, well I am using this function called 'butlast', but it returns the modified vector's contents as a list |
| 15:32 | derp_ | how do I change that behavior? |
| 15:32 | amalloy | derp_: no, it returns it as a lazy-seq |
| 15:33 | amalloy | (which happens to print the same as a list) |
| 15:33 | amalloy | derp_: use subvec instead if you want a vector |
| 15:33 | amalloy | &(doc subvec) |
| 15:33 | sexpbot | ⟹ "([v start] [v start end]); Returns a persistent vector of the items in vector from start (inclusive) to end (exclusive). If end is not supplied, defaults to (count vector). This operation is O(1) and very fast, as the resulting vector shares structure with the original and no trimming is done." |
| 15:33 | gfrlog | woah |
| 15:33 | gfrlog | I wonder how often I've missed that :/ |
| 15:34 | gfrlog | &(doc supervec) |
| 15:34 | sexpbot | java.lang.Exception: Unable to resolve var: supervec in this context |
| 15:36 | amalloy | gfrlog: i was sad to find out that subvec throws an exception on negative offsets |
| 15:36 | gfrlog | haha |
| 15:36 | derp_ | amalloy: thank you very much |
| 15:36 | amalloy | &(-> [1 2 3] (subvec 1 3) (subvec -1 3)) ; wish this returned [1 2 3] |
| 15:36 | sexpbot | java.lang.IndexOutOfBoundsException |
| 15:36 | edw | amalloy: redis 2.2.10 and I'm sending PING, AUTH, stuff like that. The basics... |
| 15:37 | gfrlog | oh that'd be terrible |
| 15:37 | derp_ | one last q, how would you have known that butlast returns a lazy-seq if you were unfamiliar with clojure? |
| 15:37 | gfrlog | ,(class (butlast (range 20))) |
| 15:37 | clojurebot | clojure.lang.PersistentVector$ChunkedSeq |
| 15:37 | amalloy | edw: i was terribly unclear. what version of aleph? |
| 15:38 | gfrlog | derp_: well maybe that didn't help, but most functions return lazy seqs if there's no particular reason to do anything else |
| 15:38 | edw | 0.2.0-alpha2 |
| 15:38 | amalloy | edw: he fixed a similar issue for me in 0.2.0-alpha3: http://groups.google.com/group/aleph-lib/browse_thread/thread/60e02641dbaa05fe |
| 15:38 | derp_ | so it's the default return type for most list/vector manipulation stuff? |
| 15:38 | amalloy | derp_: yes |
| 15:39 | edw | Ah, didn't know there was an alpha 3... |
| 15:39 | amalloy | edw: i think it's still a snapshot |
| 15:39 | amalloy | this was like a week ago |
| 15:39 | gfrlog | derp_: clojure's designed to encourage you to deal with lazy seqs whenever you can |
| 15:39 | edw | amalloy: Is it up on clojars? 0.2.0-alpha4-SNAPSHOT? |
| 15:39 | edw | Err, 3. |
| 15:39 | amalloy | yes |
| 15:40 | gfrlog | like ##(zipmap (range 5) (repeat 0)) |
| 15:40 | sexpbot | ⟹ {4 0, 3 0, 2 0, 1 0, 0 0} |
| 15:40 | edw | There we go! Thanks, amalloy. Let's see if this works... |
| 15:41 | jcromartie | trie functions yay |
| 15:41 | jcromartie | probably too slow for 11M strings |
| 15:41 | jcromartie | https://gist.github.com/1045515 |
| 15:41 | jcromartie | but too elegant to pass up :) |
| 15:42 | gfrlog | jcromartie: another way to make it go faster is to only use 11 strings instead of 11M |
| 15:42 | jcromartie | that's a great idea |
| 15:42 | jcromartie | why doesn't everybody just do that? |
| 15:42 | gfrlog | ,(let [str-set (set (map str (range 11)))] (time (contains? str-set "7"))) |
| 15:42 | clojurebot | "Elapsed time: 0.019 msecs" |
| 15:42 | clojurebot | true |
| 15:42 | gfrlog | can't beat that |
| 15:43 | gfrlog | jcromartie: now that I bring that up, what's the access time for your big set? |
| 15:43 | edw | amalloy: Still not working (on localhost with 2.2.10 and alpha3-SNAPSHOT). Durn. |
| 15:44 | jcromartie | my what? it was arohner's problem |
| 15:44 | gfrlog | jcromartie: ah whoops sorry :) |
| 15:45 | jcromartie | dammit rlwrap/REPL... why does C-y (yank) send it to the background? |
| 15:45 | arohner | gfrlog: I have a document, I want to find all wikipedia titles in the doc. It takes ~700ms right now |
| 15:45 | amalloy | jcromartie: O(log32(n)) is not much slower than O(1) - the size of the set isn't going to matter much |
| 15:45 | gfrlog | amalloy: the caching level will matter |
| 15:46 | gfrlog | L1 cache vs. swap matters :) |
| 15:46 | jcromartie | so then it's solved? (use a set) |
| 15:46 | edw | amalloy: There's some promising stuff in the new branch on github. Might try that. |
| 15:46 | amalloy | gfrlog: granted. but he shouldn't be going into swap, and fitting it into cpu cache is impossible regardless |
| 15:46 | gfrlog | unless he takes my suggestion of using 11 strings |
| 15:46 | gfrlog | or wait |
| 15:47 | gfrlog | O(1) was regarding the trie functions? |
| 15:47 | amalloy | yes |
| 15:47 | gfrlog | sorry, sometimes I get lost in my own stupid side comments |
| 15:48 | gfrlog | I'll go make an 11M string set and see how it performs |
| 15:48 | jcromartie | I can't even *make* an 11M string set |
| 15:49 | jcromartie | I gave up after letting it churn |
| 15:49 | jcromartie | for 2 minutes |
| 15:49 | gfrlog | jcromartie: how much memory? |
| 15:49 | jcromartie | 1024 |
| 15:49 | jcromartie | (def bigset (set (map str (range 11000000)))) |
| 15:49 | choffstein | Freaking tomcat. Doesn't play nice with compojure ... seems that when you do your routes in compojure, they are absolute and when you upload your application to tomcat, you get a context in your route (e.g. localhost:8080/myApp/) -- which means all my routes get prefixed with myApp and hence NOTHING MATCHES on compojure. Aaaarrrrrggghhhhh!!! *slams face against keyboard* |
| 15:49 | arohner | I have 4GB on this machine, and it takes 2.5GB to load the strings out of the DB, and 1.5GB steady state |
| 15:50 | arohner | takes about 10 minutes to load them all |
| 15:50 | dpritchett` | choffstein, your dev routes don't match your production routes? |
| 15:50 | jcromartie | choffstein: can you handle that with middleware? |
| 15:50 | jcromartie | arohner: yeah, not surprising I guess |
| 15:50 | gfrlog | jcromartie: that expression returned for me after about 15 sec |
| 15:51 | gfrlog | `top` puts the jvm at about 23.6% right now |
| 15:51 | gfrlog | I think I have 8G? |
| 15:51 | jcromartie | gfrlog: weird |
| 15:51 | choffstein | ...I can?! |
| 15:51 | jcromartie | hm |
| 15:51 | jcromartie | choffstein: routes are just functions |
| 15:51 | gfrlog | user=> (time (contains? bigset "48482")) |
| 15:51 | gfrlog | "Elapsed time: 0.036596 msecs" |
| 15:51 | jcromartie | you should be able to wrap them |
| 15:52 | jcromartie | not really "middleware" but something to "massage" the request URL |
| 15:52 | amalloy | jcromartie: that's middleware :P |
| 15:52 | choffstein | dprichett`: the issue is, I have my routes like "/portal", but when I deploy to tomcat, the routes are like "/myApp/portal" |
| 15:52 | jcromartie | yeah I was going to say |
| 15:52 | jcromartie | :) |
| 15:52 | choffstein | Yeah. It's a tomcat issue though. I'm trying to see if I can just deploy the application to / ... but tomcat doesn't seem to like me doing that at the moment :D |
| 15:53 | amalloy | (defn without-prefix [prefix handler] (fn [req] (handler (update-in req [:uri] #(s/replace % prefix ""))))) |
| 15:54 | amalloy | choffstein: just wrap your outer-level route in something like that, and it will strip the leading "/myApp" before giving it to the rest of your code |
| 15:54 | choffstein | amalloy: that is my last ditch idea. seems "hacky" to me. |
| 15:54 | gfrlog | amalloy: and then parse the html that comes out and add it back to all the <a>'s? |
| 15:54 | amalloy | gfrlog: ouch |
| 15:55 | gfrlog | I guess you can do relative paths that avoid that? |
| 15:55 | amalloy | gfrlog: yeah but not always |
| 15:55 | amalloy | choffstein: yes, you should probably be able to configure tomcat to do that for you, i guess |
| 15:55 | gfrlog | jcromartie: I made another set with longer strings (~25 chars) and it took a few minutes |
| 15:56 | gfrlog | choffstein: tomcat lets you deploy an app as the root app |
| 15:56 | jcromartie | I've got a lot of stuff going on with my 4G machine... VMWare, Chrome, iTunes |
| 15:56 | choffstein | gfrlog: I'm trying to figure that out :) |
| 15:56 | jcromartie | 4GB |
| 15:56 | gfrlog | choffstein: I think if you upload it as ROOT.war it'll do that automatically |
| 15:56 | choffstein | re-he-he-heaaalllyyy? |
| 15:56 | gfrlog | choffstein: ma-ha-ha-haaaaaby |
| 15:57 | choffstein | IT'S ALIIIVVVEEEE |
| 15:57 | choffstein | IITTTT'S ALLLIIIIVVVEEEEE |
| 15:57 | gfrlog | using 11M big strings wasn't much slower than 11M little strings |
| 15:58 | gfrlog | not only that, 11M big strings was only 1 or 2 times slower than 11 strings. |
| 15:58 | gfrlog | unless contains? is returning some kind of lazy boolean |
| 16:00 | choffstein | gfrlog: thank you so much. ROOT.war did the trick. |
| 16:00 | gfrlog | choffstein: no probalo |
| 16:00 | gfrlog | I hate trying to figure out how to make tomcat do stuff |
| 16:01 | edw | D'oh. Nothing's working here, amalloy. |
| 16:01 | arohner | gfrlog: I assume the big strings aren't much slower, because you only have to deal with the length when you get a hash collision |
| 16:02 | ibdknox | How many of you guys would be interested in a datastore backed by redis that mimicked clojure's datastructures: |
| 16:02 | arohner | and then you only need to compare strings until you find a mismatch |
| 16:02 | ibdknox | (def x (redis-atom {})) |
| 16:02 | ibdknox | (swap! x assoc :r 3) |
| 16:02 | amalloy | edw: sorry bro |
| 16:02 | jcromartie | ibdknox: sounds like the perfect interface to a data store if you ask me |
| 16:02 | jcromartie | especially if it works in a transaction |
| 16:02 | gfrlog | arohner: I'd think if the string is present you'd still have to compare |
| 16:02 | no_mind | I am writing a macro where I wanta function to be passed. This function should be called if certain conditions are met. My queries are a) should I go with a macro or a define a function b) Is it possible to pass the namespace and function name as a single argument ? |
| 16:02 | arohner | gfrlog: yes, but only after the hashes match |
| 16:02 | edw | What version of Redis are/were you using? |
| 16:03 | no_mind | *function to be passed as argument |
| 16:03 | amalloy | 2.0.1 |
| 16:03 | edw | Whoa, that was a while ago. |
| 16:03 | hiredman | I would hope a database would supply something higher level than datastructure operations |
| 16:03 | amalloy | no_mind: almost certainly this should be a function |
| 16:03 | amalloy | edw: so far i haven't had to deploy at all; it's just what apt-get put on my dev machine |
| 16:03 | ibdknox | hiredman: what do you mean? |
| 16:04 | ibdknox | hiredman: even a database has to have an add command ;) |
| 16:04 | hiredman | ibdknox: a distributed hash table is not a database |
| 16:04 | amalloy | hiredman: i think he only called it a datastore |
| 16:04 | no_mind | amalloy: ok, and how about passing function name and namespace as single argument ? |
| 16:04 | ibdknox | hiredman: that was one example, take this as another: |
| 16:04 | amalloy | no_mind: i don't understand the question. just pass the function itself, don't mess around with names |
| 16:05 | ibdknox | (def rlist (redis-atom [1 2 3])) |
| 16:05 | ibdknox | (nth @rlist 2) |
| 16:05 | ibdknox | basically it's a persistence mechanism for clojure collections |
| 16:06 | hiredman | *shrug* |
| 16:06 | ibdknox | using the wonderful datatypes in redis |
| 16:06 | ibdknox | the point was to judge interest more than anything :) |
| 16:06 | no_mind | amalloy: lets say I have a namespace abc and a function in abc xyz. I want to know if ther eis some way to just pass fully qulaified function name like abc.xyz assigle function and then have the function executed ? or should I pass ns and function name as two arguments |
| 16:07 | ibdknox | hiredman: I assume you use a SQL variant? |
| 16:07 | gfrlog | no_mind: you can pass the function itself without worrying about its name |
| 16:07 | gfrlog | |
| 16:07 | hiredman | ibdknox: use for what? |
| 16:07 | ibdknox | hiredman: persistence? lol |
| 16:08 | hiredman | depends |
| 16:08 | scgilardi | the fully qualified name would be abc/xyz |
| 16:09 | hiredman | persisting datastructures is neat for little apps, or when you are just starting, but not really useful for larger datasets |
| 16:09 | no_mind | gfrlog: the function will not be called under all conditions. Plus the arguments tot he function will be modified before function's execution |
| 16:09 | dpritchett` | oh hi ibdknox |
| 16:09 | gfrlog | no_mind: none of those things require knowing the function's name |
| 16:09 | dpritchett` | i have been enjoying noir this week, thank you |
| 16:10 | ibdknox | you're quite welcome :) |
| 16:10 | ibdknox | hiredman: so anyone using a key-value store is doing it wrong? |
| 16:10 | gfrlog | no_mind: if your function is receiving a function as its argument, it can refer to it by the argument name |
| 16:10 | dpritchett` | now i just need to figure out how to nest clojure.contrib.sql/with-query-results with your common/layout and defpage functions |
| 16:10 | amalloy | no_mind: look at the map function. it takes a function as argument, and applies it a number of times. or partial, which modifies the arguments to the underlying function. model your solution on those |
| 16:10 | dpritchett` | For some reason the correct ordering is eluding me |
| 16:10 | hiredman | ibdknox: please don't turn my dismissal of your idea into a debate about nosql |
| 16:11 | no_mind | gfrlog: yes it can. But what if the function received is in another namespace ? |
| 16:11 | gfrlog | no_mind: (fn [f a b] (if a (f b) "not calling that function")) for example |
| 16:11 | ibdknox | hiredman: hm |
| 16:11 | no_mind | amalloy: thanks |
| 16:11 | gfrlog | no_mind: functions don't belong to namespaces |
| 16:11 | derp_ | is there an easy way to turn a list of characters into a string? |
| 16:11 | gfrlog | no_mind: so it doesn't matter |
| 16:11 | scgilardi | derp_: use str |
| 16:11 | derp_ | I am stuck at (map str (rest "1001")) |
| 16:11 | amalloy | derp_: ##(apply str '(\a \b)) |
| 16:11 | sexpbot | ⟹ "ab" |
| 16:12 | no_mind | ok |
| 16:12 | ibdknox | hiredman: as you wish. |
| 16:12 | hiredman | if I want to persist a datastructure I will most likely pr-str it or serialize it and write it to disk |
| 16:12 | Raynes | no_mind: Functions are completely and utterly first class. They are just normal values in Clojure. As normal as a string or an integer. |
| 16:12 | jcromartie | relations and invariants FTW |
| 16:12 | ibdknox | I was thinking of this more as an interface to redis that looked just like any other clojure code |
| 16:13 | ibdknox | maybe that's a better way to think of it :) |
| 16:13 | hiredman | but redis is not a clojure datastructure |
| 16:13 | gfrlog | no_mind: Raynes makes a good point -- you wouldn't as what namespace your other arguments "belonged to" |
| 16:13 | gfrlog | s/as/ask |
| 16:13 | sexpbot | <gfrlog> no_mind: Raynes makes a good point -- you wouldn't ask what namespace your other arguments "belonged to" |
| 16:13 | ibdknox | there's basically a 1:1 mapping between redis datatypes and clojure's collections |
| 16:13 | no_mind | ok |
| 16:13 | jcromartie | ibdknox: unfortunately it is only 1:1 as long as the elements of those data structures are compatible |
| 16:14 | amalloy | ibdknox: that's rather an overstatement. redis's sorted-sets are a bizarre parody of sorted sets |
| 16:14 | hiredman | ibdknox: I doubt that |
| 16:14 | jcromartie | so, how would you store {:foo 'bar "bat" (java.util.Date.)} |
| 16:14 | jcromartie | pr-str? |
| 16:14 | gfrlog | no_mind: if that's not clear, then maybe try writing the code the way you think it should work and we can look at it |
| 16:14 | hiredman | jcromartie: are you asking me? |
| 16:14 | jcromartie | ibdknox: |
| 16:14 | amalloy | they're definitely a useful structure, but they don't really map onto anything in clojure |
| 16:14 | ibdknox | yes, the downside is that you can't store types |
| 16:15 | jcromartie | there is sorted-set in Clojure |
| 16:15 | jcromartie | not sure if that's the same thing |
| 16:15 | ibdknox | but that's true of any db |
| 16:15 | hiredman | hmmm? |
| 16:15 | no_mind | gfrlog: its clear andI am trying the ideassuggested |
| 16:15 | ibdknox | and that's fair, the semantics between the two are not identical |
| 16:15 | ibdknox | the point would be to make them seem that way, though, I feel the intent of my proposal is now lost and I'll drop the subject :) |
| 16:15 | amalloy | jcromartie: i know, but redis's are weird |
| 16:16 | ibdknox | amalloy: they really are |
| 16:16 | jcromartie | ibdknox: I wouldn't discourage you |
| 16:16 | hiredman | I would recommend grabbing an existing clojure redis client and making it nice to use and using it a lot to burn it in over this kind of thing |
| 16:16 | jcromartie | Redis is what it is, and that interface sounds good |
| 16:16 | jcromartie | at least to me |
| 16:17 | gfrlog | I kept wanting to say that vars belong to namespaces, but I don't think that's true. Is there anything that can be properly said to "belong to" a namespace? are they just maps from symbols to vars? |
| 16:17 | hiredman | "I like my kitchen, my kitchen has knives, this battle axe is kind of like knife, but awkward to use in my kitchen, so I'll pretend it is a knife" |
| 16:18 | hiredman | like a knife |
| 16:18 | ibdknox | lol |
| 16:19 | hiredman | next thing you know you don't have a leg to stand on |
| 16:19 | amalloy | hah |
| 16:22 | jcromartie | I am flabbergasted that every part of this trie implementation is basically a one-liner https://gist.github.com/1045515 |
| 16:22 | jcromartie | FP FTW |
| 16:23 | gfrlog | jcromartie: that is remarkable. therefore it is appropriate that you remarked. |
| 16:25 | jcromartie | vs. http://code.google.com/p/trie/source/browse/trunk/trie/src/net/bcharris/trie/TrieImpl.java |
| 16:25 | jcromartie | or http://code.google.com/p/typocalypse/source/browse/Trie/TrieNode.cs |
| 16:25 | jcromartie | or ... |
| 16:25 | jcromartie | you get the idea |
| 16:28 | gfrlog | jcromartie: you wrote that code just now? |
| 16:28 | bsteuber | come on, it's unfair to compare it to java or c# code :) |
| 16:28 | gfrlog | user=> (merge (trie/trie "abc") (trie/trie "abd")) |
| 16:28 | gfrlog | {\a {\b {\d {}}}} |
| 16:28 | dpritchett | this is by far my favorite part of noir so far ibdknox https://github.com/ibdknox/noir/blob/master/src/noir/server.clj#L8 |
| 16:29 | gfrlog | oh ha |
| 16:29 | gfrlog | I'm using clojure.core/merge :) |
| 16:29 | dpritchett | that is sweet behavior i had not expected |
| 16:29 | gfrlog | no wonder it don't work |
| 16:29 | ibdknox | gotta have a good development experience ;) |
| 16:29 | jcromartie | gfrlog: yeah |
| 16:29 | ibdknox | throw an exception on purpose some time |
| 16:30 | jcromartie | gfrlog: maybe I should use merge instead of merge+ |
| 16:30 | ibdknox | it highlights the parts of the stack that are in your code, if you have the :ns property set when you start the server |
| 16:30 | jcromartie | or merge-trie |
| 16:30 | gfrlog | jcromartie: I'm not familiar with the data structure -- if I merge "abc" and "abcd", should it contains? both of them? |
| 16:30 | jcromartie | yes |
| 16:30 | gfrlog | k, might wanna work on that then :) |
| 16:31 | gfrlog | user=> (trie/merge+ (trie/trie "abc") (trie/trie "abcd")) |
| 16:31 | gfrlog | {\a {\b {\c {\d {}}}}} |
| 16:32 | jcromartie | huh |
| 16:32 | jcromartie | works over here |
| 16:32 | gfrlog | I'm using https://gist.github.com/1045515 |
| 16:32 | jcromartie | ah ha |
| 16:32 | gfrlog | (search t "abc") => {\d {}} |
| 16:33 | jcromartie | yeah I see |
| 16:33 | jcromartie | because it's not accounting for the terminator in abc |
| 16:34 | aaelony | hi, I like the clj-json library in general, but (clj-json.core/parse-string json true) is returning strings instead of keywords for nestings of vectors and maps. |
| 16:34 | aaelony | The following (from earlier) helps a little bit: (defn keywordify [m] (if (map? m) (into {} (map (fn [[k v]] [(keyword k) (keywordify v)]) m)) m)) but not for vectors of maps. How would I locate all keywords and keywordify them even if they are buried in combinations of vectors and maps? |
| 16:35 | duck1123 | Has anyone here ever experienced an issue where they can upload a small file to their ring app, but a slightly larger file times out? |
| 16:35 | jcromartie | gfrlog: I don't think contains? should exist, or it should be (not (nil? (search t s))) |
| 16:35 | gfrlog | aaelony: you could add a second clause after (if (map? m)) that checks if it's a collection |
| 16:35 | gfrlog | aaelony: I guess it could only be a vector right? so check if it's a vector and if so map it over keywordify |
| 16:35 | gfrlog | jcromartie: I like the terminator idea |
| 16:35 | duck1123 | it gets a bit more complicated with my using aleph and 1.3 |
| 16:35 | aaelony | i think it will be a vector |
| 16:36 | aaelony | thanks, gfrlog |
| 16:36 | jcromartie | aaelony: actually let me rework that keywordify |
| 16:36 | gfrlog | jcromartie: so contains? would check if the resulting map has the terminator as an element |
| 16:37 | gfrlog | jcromartie: you could even make it all safe by using a unique (new Object) instead of nil or anything else |
| 16:37 | ibdknox | duck1123: servers often have upload memory limits |
| 16:37 | aaelony | thanks jcromartie |
| 16:37 | gfrlog | isn't there a keywordize-keys function somewhere? |
| 16:38 | gfrlog | maybe not... |
| 16:38 | ibdknox | gfrlog: I think ring actually has one |
| 16:38 | amalloy | gfrlog: clojure.walk, i think? |
| 16:38 | gfrlog | clojuredocs doesn't return one |
| 16:38 | gfrlog | oh but walk does have it |
| 16:39 | gfrlog | aaelony: try clojure.walk/keywordize-keys |
| 16:39 | aaelony | checking, thanks |
| 16:39 | duck1123 | wrap-keyword-params |
| 16:39 | gfrlog | (dec clojuredocs) |
| 16:39 | sexpbot | ⟹ -1 |
| 16:39 | ibdknox | https://github.com/mmcgrana/ring/blob/master/ring-core/src/ring/middleware/keyword_params.clj |
| 16:39 | jcromartie | like a boss, gfrlog |
| 16:39 | ibdknox | lol |
| 16:40 | aaelony | it says "Recursively transforms all map keys from strings to keywords." I wonder if it allows for nestings with vectors... |
| 16:40 | gfrlog | aaelony: try it :) |
| 16:40 | duck1123 | I don't believe it does |
| 16:40 | aaelony | looks great |
| 16:40 | aaelony | very nice |
| 16:40 | aaelony | at least for me mangy data structure :) |
| 16:41 | aaelony | s/me/my/ |
| 16:41 | sexpbot | <aaelony> at least for my mangy data structure :) |
| 16:41 | jcromartie | aaelony: it does |
| 16:43 | jcromartie | gfrlog: you'll be pleased to know that fixing trie/contains? involved changing two lines |
| 16:44 | gfrlog | jcromartie: you'd have to fix trie/trie as well, right? to add a terminator? |
| 16:45 | jcromartie | updated https://gist.github.com/gists/1045515/edit |
| 16:45 | ibdknox | that link redirects |
| 16:46 | ibdknox | we can't edit it ;) |
| 16:46 | jcromartie | oops |
| 16:46 | jcromartie | herp derp https://gist.github.com/1045515 |
| 16:46 | ibdknox | that really is impressive |
| 16:46 | ibdknox | tries are fun |
| 16:46 | gfrlog | jcromartie: ::terminator is gooder idea than (new Object) |
| 16:47 | jcromartie | and I even spelled it right (some blub implementation had "Terminater") |
| 16:48 | gfrlog | ha |
| 16:48 | jcromartie | makes me think of a cybernetic potato for some reason |
| 16:48 | jcromartie | is it idiomatic for predicates to return true or false, exactly? |
| 16:48 | jcromartie | or is true or nil good enough? |
| 16:49 | gfrlog | jcromartie: considering the sorts of things that people use for predicates, I'd say you can return any dang thing you want :) |
| 16:49 | jcromartie | hah |
| 16:49 | jcromartie | our database uses -1 for true |
| 16:49 | jcromartie | 0 or NULL for false |
| 16:49 | jcromartie | fun times |
| 16:49 | gfrlog | that's fantastic |
| 16:50 | gfrlog | if I want to restrict a predicate I just pass it through (boolean) at the end |
| 16:52 | jcromartie | ah |
| 16:52 | jcromartie | good idea |
| 16:53 | jcromartie | I was reading this today http://dev.clojure.org/display/design/Library+Coding+Standards |
| 16:53 | jcromartie | pretty good advice in general |
| 16:53 | dpritchett | is the @ dereference operator in clojureql standard clojure or specific to this library? |
| 16:53 | dpritchett | (clojureql.core/table :posts) gives me a sql statement, if i prepend a @ it gives me the results |
| 16:53 | Raynes | gfrlog: Or true? |
| 16:53 | Raynes | :D |
| 16:54 | gfrlog | Raynes: uhhh...huh? |
| 16:54 | Raynes | gfrlog: And then pretend that doesn't cause bugs. |
| 16:54 | dpritchett | nevermind, found it myself on the clojure docs |
| 16:54 | gfrlog | oh okay. I can pretend. |
| 16:55 | gfrlog | Raynes: may as well use (not) while we're at it |
| 16:55 | gfrlog | boolean is clojure for !! |
| 16:56 | amalloy | gfrlog, jcromartie: i prefer (Object.) to ::terminator, fwiw |
| 16:56 | jcromartie | amalloy: what's your reason why? |
| 16:56 | gfrlog | amalloy: whyso? Isn't it a perfect example of qualified keywords? |
| 16:56 | hugod | stuartsierra: I thought the new contribs were all 1.2 compatible - doesn't that imply that they should declare a 1.2 dependency, rather than whatever happens to be the latest release? |
| 16:56 | gfrlog | not to mention it's using clojure stuff instead of jvm stuff |
| 16:57 | amalloy | jcromartie: it's more general. yes, in practice people won't want to store :my-ns/terminator, but it's silly to make that illegal |
| 16:57 | amalloy | whereas if you use an (Object.) you can guarantee nobody will ever put it in there |
| 16:57 | jcromartie | amalloy: there's a problem with (Object.) |
| 16:57 | gfrlog | amalloy: when would you ever want to use a qualified keyword outside your own namespace? |
| 16:57 | amalloy | gfrlog: plenty of reasons |
| 16:57 | jcromartie | and you couldn't really serialize it |
| 16:58 | amalloy | jcromartie: that's a fair point |
| 16:58 | gfrlog | I say anybody who does such a thing deserves his fate |
| 16:58 | bsteuber | everything that's not a char and easy to compare is okey, isn't it? |
| 16:58 | gfrlog | also something something about plenty of room in the prisons |
| 16:58 | bsteuber | so my favorite would be nil as terminator |
| 16:58 | amalloy | bsteuber: ergh |
| 16:59 | jcromartie | nil might be a good idea |
| 16:59 | jcromartie | assuming you can use nil as a key? |
| 16:59 | amalloy | don't use nil as a map key. it's horrible |
| 16:59 | gfrlog | but wanting to store seqs with nil is much more plausible |
| 16:59 | amalloy | jcromartie: you can, but it's such a cause of problems that even j.u.Collection says it's an optional feature for maps to support, iirc |
| 16:59 | jcromartie | hah |
| 17:00 | stuartsierra | hugod: Perhaps. For now it's convenient on the build server, and your local dependency should override it. |
| 17:00 | bsteuber | ah true, you can use tries for any sequential data |
| 17:00 | amalloy | Some map implementations have restrictions on the keys and values they may contain. For example, some implementations prohibit null keys and values, and some have restrictions on the types of their keys. Attempting to insert an ineligible key or value throws an unchecked exception |
| 17:00 | bsteuber | so ::terminator or just ::end is best |
| 17:00 | gfrlog | or ::__TERMINATOR__ just to be safe |
| 17:01 | jcromartie | ::__PRIVATE__*TERMINATOR*__DO_NOT_USE |
| 17:01 | gfrlog | maybe with a guid at the end :) |
| 17:01 | hugod | stuartsierra: just worried about 1.2 compatability being tested/lost |
| 17:02 | stuartsierra | hugod: It's true we need more tests across versions. I have to figure out how best to do that on Hudson. |
| 17:02 | stuartsierra | But please file bugs if anything is not 1.2-compatible. |
| 17:02 | amalloy | jcromartie: and, since i'm on my mini-rant about null keys, clojure.lang.APersistentMap has a .valAt method that looks like: if (hasNullKey) return nullValue; else // do real lookup |
| 17:03 | gfrlog | jcromartie: time to box all your keys. 1 more line per function. |
| 17:04 | bsteuber | amalloy: good to know, always thought nil is as good as any other value |
| 17:04 | gfrlog | ,({nil "tom" :jill "bob"} nil) |
| 17:04 | clojurebot | "tom" |
| 17:05 | gfrlog | ,(let [m {nil "tom" :jill "bob"}] [(.get m nil) (.get m :jill)]) |
| 17:05 | clojurebot | ["tom" "bob"] |
| 17:06 | amalloy | &(clojure.string/replace-first "test" #"q" identity) |
| 17:06 | sexpbot | ⟹ nil |
| 17:07 | amalloy | does this seem crazy to anyone else? |
| 17:07 | gfrlog | hmmm....maybe not |
| 17:07 | gfrlog | since you want to replace exactly one thing, you might be interested to know that it wasn't there |
| 17:08 | jcromartie | gfrlog: is there a standard way to box values? |
| 17:08 | gfrlog | jcromartie: dunno. I'd stick'em in a vector maybe? |
| 17:08 | gfrlog | then use first to access |
| 17:08 | amalloy | wait why are we boxing things? |
| 17:08 | jcromartie | it looks like a box |
| 17:08 | gfrlog | amalloy: so he can have nil keys |
| 17:08 | jcromartie | (defn box [x] [x]) |
| 17:08 | gfrlog | ha |
| 17:09 | gfrlog | now make a macro to get rid of that redundancy |
| 17:09 | gfrlog | jcromartie: (def box vector) |
| 17:09 | gfrlog | (def unbox first) |
| 17:09 | amalloy | (defmacro identity-function [name args-and-body] `(defn ~name ~@(repeat 2 args-and-body))) |
| 17:10 | jcromartie | I was going to say |
| 17:10 | jcromartie | defredundant |
| 17:10 | jcromartie | totally worth it |
| 17:10 | gfrlog | (defmacro defaboxingfn ...) |
| 17:12 | gfrlog | amalloy: so you don't object to having [nil] as a key? |
| 17:12 | amalloy | gfrlog: in most circumstances i suspect it's silly, but there's nothing wrong with it |
| 17:12 | gfrlog | jcromartie: now that I think about it, list might be better than vector for performance |
| 17:13 | gfrlog | I don't know how much ceremony small vectors create. maybe it's nothing |
| 17:14 | jcromartie | BTW, there's no unboxing required |
| 17:14 | jcromartie | just (map box s) |
| 17:14 | jcromartie | for the lookups |
| 17:15 | gfrlog | jcromartie: oh right. I guess you never have to return actual values |
| 17:15 | edw | amalloy: ARGH! 9920 != 9220. Was tracing through the code looking to see if the port num was actually used by Aleph but after 30 min I noticed I'd continuously fat-fingered the port number. |
| 17:15 | gfrlog | edw: no problem, just (binding [9920 9220] ...) |
| 17:16 | edw | Doesn't that only work in Fortan? |
| 17:16 | gfrlog | :) |
| 17:16 | jcromartie | gfrlog: anyway the gist is updated... this was a distraction, even if it was a fun one! |
| 17:17 | gfrlog | jcromartie: w00p |
| 17:17 | gfrlog | I love how clojars keeps the pushing instructions front and center |
| 17:17 | jcromartie | real work is never so interesting |
| 17:17 | gfrlog | jcromartie: nope :( |
| 17:18 | jcromartie | now I'm off to manually download a file from an un-scriptable Classic ASP app, manually run it through an XSLT parser because the painfully outdated version of MSXML that we rely on is seriously broken, and then manually email it to a client |
| 17:18 | ibdknox | jcromartie: the pain. |
| 17:19 | ibdknox | it should be illegal really. |
| 17:19 | rbuchmann | (inc gfrlog) |
| 17:19 | sexpbot | ⟹ 3 |
| 17:19 | rbuchmann | :) |
| 17:19 | gfrlog | three! |
| 17:20 | gfrlog | that's my mostest ever |
| 17:20 | rbuchmann | quick, someone dec him :-p |
| 17:20 | edw | jcromartie: You just described about half of my job. If you get two spreadhseets too close together on any of my coworkers' monitors, they'll automatically start copying and pasting data to and fro. |
| 17:20 | amalloy | rbuchmann: the power...is yours! |
| 17:20 | jcromartie | hah hah |
| 17:21 | rbuchmann | ^^ |
| 17:21 | jcromartie | at least the conversion I have to do is scripted |
| 17:21 | dpritchett | jcromartie what are you scripting it with |
| 17:22 | jcromartie | just bash |
| 17:23 | jcromartie | later y'alls |
| 17:23 | gfrlog | bye |
| 17:23 | jcromartie | (but I do love me some Rake) |
| 17:23 | matthias_ | what;s an abstract method error? |
| 17:24 | hiredman | matthias_: often means you are calling an abstract method |
| 17:25 | clizzin | hey all, i haven't used clojure with mysql for a few months. last time i checked, clojureql was great for querying but not inserts/updates/connections, clojure.contrib.sql got the job done on those other fronts but wasn't too elegant, and there were some other little libs that aimed to cover both areas but weren't too mature. what's the state of the art now for clojure and mysql? |
| 17:26 | gfrlog | clizzin: those first two points are all I know of. |
| 17:31 | VT_entity | hey all, I was wondering if you could help me with a tricky error |
| 17:32 | gfrlog | VT_entity: continue |
| 17:32 | Raynes | ~anyone |
| 17:32 | clojurebot | Please do not ask if anyone uses, knows, is good with, can help you with <some program or library>. Instead, ask your real question and someone will answer if they can help. |
| 17:32 | VT_entity | (if (<= 0 (count examplelist)) |
| 17:32 | VT_entity | ;figure out a way to use let instead of an inline def here |
| 17:32 | VT_entity | ((conj newlist (+ 1 (peek examplelist))) (def examplelist (pop examplelist)))) |
| 17:32 | gfrlog | Raynes: I thought of that but he didn't use the word "anyone" :) |
| 17:32 | VT_entity | thanks clojurebot, that's not condescending at all. |
| 17:32 | Raynes | Still applies. :p |
| 17:32 | VT_entity | lol |
| 17:32 | gfrlog | VT_entity: he said please at least |
| 17:33 | gfrlog | VT_entity: that (<= 0 (count ...)) should always be true right? |
| 17:33 | VT_entity | it's giving me "clojure.lang.PersistentList cannot be cast to clojure.lang.IFn" |
| 17:33 | amalloy | yes, that's the (( construct |
| 17:34 | VT_entity | you mean I have too many parens? |
| 17:34 | gfrlog | VT_entity: yes |
| 17:34 | amalloy | no |
| 17:34 | gfrlog | maybe |
| 17:34 | Raynes | inpossible |
| 17:34 | gfrlog | always |
| 17:34 | VT_entity | hahahaha |
| 17:34 | Raynes | impossible, even. |
| 17:34 | amalloy | if you *wanted* to do it that way, you need (do (thing1) (thing2)), which is the same number of parens |
| 17:35 | amalloy | but the approach is evil and sinful anyway, as you noted since you came to ask for help |
| 17:35 | VT_entity | I thought the do was implied? if evaluates whichever predicate based on whether it's true or false |
| 17:35 | amalloy | no |
| 17:36 | VT_entity | so I need (if (foo?) (do (bar)) |
| 17:36 | dpritchett | Quick data manipulation question: How would I turn '({:id 1 :content "hey"} {:id 2 :content "there"}) to [:h1 1][:p "hey"][:h1 2][:p "there] ? |
| 17:36 | gfrlog | VT_entity: no (if (foo?) (bar)) |
| 17:36 | dpritchett | i'm messing with noir and hiccup, trying to turn my simple map into a series of vectors |
| 17:37 | VT_entity | that's what I figured, amalloy wants me to use do, but I wasn't sure if I needed it. |
| 17:38 | rbuchmann | if bar is several statements, you need do |
| 17:38 | gfrlog | dpritchett: ##(mapcat (fn [{:keys [id content]}] [[:h1 id] [:p content]]) '({:id 1 :content "hey"} {:id 2 :content "there"})) |
| 17:38 | sexpbot | ⟹ ([:h1 1] [:p "hey"] [:h1 2] [:p "there"]) |
| 17:38 | amalloy | &(mapcat (fn [{:keys [id content]}] [[:h1 id][:p content]]) '({:id 1 :content "hey"} {:id 2 :content "there"})) |
| 17:38 | sexpbot | ⟹ ([:h1 1] [:p "hey"] [:h1 2] [:p "there"]) |
| 17:38 | dpritchett | thanks |
| 17:38 | gfrlog | amalloy: are those completely identical? |
| 17:38 | amalloy | *nod* |
| 17:38 | gfrlog | what does this mean??? |
| 17:39 | amalloy | that i forgot to use juxt |
| 17:39 | gfrlog | :D |
| 17:39 | lancepantz | hahah |
| 17:39 | gfrlog | man we even put the keys in the same order |
| 17:40 | amalloy | gfrlog: it's the natural order |
| 17:41 | gfrlog | whyso? |
| 17:41 | amalloy | because id is first in his example map, and also used first in the desired result |
| 17:41 | gfrlog | I guess so |
| 17:41 | dpritchett | that function worked first try when i dropped it into my code, thanks again |
| 17:41 | gfrlog | and we both used parentheses |
| 17:41 | dpritchett | i feel a little dirty now |
| 17:41 | amalloy | gfrlog: ? |
| 17:42 | gfrlog | amalloy: nothing |
| 17:42 | gfrlog | amalloy: it made no more sense than it appeared to |
| 17:42 | VT_entity | oh, you're right, the do fixed the problem. weird. I'm not sure why... also, it only peeks and pops once, which is weird. Any ideas? |
| 17:42 | VT_entity | (def examplelist '(1 2 3 4 5)) |
| 17:42 | VT_entity | (def newlist ()) |
| 17:42 | dpritchett | i got my mobi/epub copies of Joy of Clojure via email yesterday. i'll dig up :keys again while i'm reading |
| 17:42 | VT_entity | |
| 17:42 | VT_entity | (if (<= 0 (count examplelist)) |
| 17:42 | VT_entity | ;figure out a way to use let instead of an inline def here |
| 17:42 | VT_entity | (do (conj newlist (+ 1 (peek examplelist))) (def examplelist (pop examplelist)))) |
| 17:42 | amalloy | VT_entity: https://gist.github.com |
| 17:43 | VT_entity | oh, interesting |
| 17:43 | gfrlog | amalloy: no way did you type out that entire url with the https before he finished pasting |
| 17:43 | amalloy | gfrlog: wtf, of course i did |
| 17:43 | gfrlog | gosh dammit |
| 17:43 | gfrlog | you've got a bunch of clever emacs doohickeys |
| 17:43 | amalloy | gfrlog: using pidgin |
| 17:43 | gfrlog | emacs has pidgin now? :P |
| 17:43 | amalloy | (i know, right? not hardcore enough at all) |
| 17:45 | VT_entity | ok, I just posted it: https://gist.github.com/1045758 |
| 17:45 | gfrlog | much nicer on the eyes |
| 17:45 | gfrlog | next time give it a name that ends in ".clj" and it'll color everything pretty |
| 17:45 | VT_entity | oooh |
| 17:46 | VT_entity | there we go |
| 17:46 | VT_entity | .clj |
| 17:46 | Raynes | I don't understand how amalloy can function with Pidgin as an IRC client. |
| 17:46 | rbuchmann | wow, what is that supposed to do? |
| 17:46 | gfrlog | VT_entity: anyhow, you're not looping at any point, so there's no reason for it to do anything more than once |
| 17:46 | hiredman | digusting |
| 17:46 | VT_entity | I figured the conditional statement would continue the loop as long as the count of the members of examplelist remains above 9 |
| 17:46 | rbuchmann | ah, reading descriptions helps :-/ Sorry about that |
| 17:46 | VT_entity | 0* |
| 17:47 | VT_entity | ah, i'll try to add in recure |
| 17:47 | VT_entity | recur* |
| 17:47 | gfrlog | VT_entity: look at (loop) also |
| 17:47 | rbuchmann | you'll need something to recur to |
| 17:47 | rbuchmann | (if ...) is not it |
| 17:48 | amalloy | Raynes: i know, i risk making myself an outcast just by mentioning it |
| 17:48 | VT_entity | aaah I understand |
| 17:48 | dpritchett | i'm using xchat on windows |
| 17:48 | VT_entity | what if I name the function and make if recur back to itself |
| 17:48 | dpritchett | i don't *love* it but it required a tad less manual reading than irssi |
| 17:48 | dpritchett | honestly i miss mirc from ten years ago |
| 17:48 | rbuchmann | that'd word |
| 17:48 | rbuchmann | *work |
| 17:48 | rbuchmann | what are you actually trying to do? |
| 17:48 | VT_entity | probably blow the stack, not optimized I guess |
| 17:49 | amalloy | i think he's just implementing ##(map inc '(1 2 3 4 5)) |
| 17:49 | sexpbot | ⟹ (2 3 4 5 6) |
| 17:49 | VT_entity | well, my friend and I were talking about whether it's possible to do something like FOR EACH in a purely functional way. |
| 17:49 | rbuchmann | ofcourse |
| 17:49 | VT_entity | so, we came up with the idea of incrementing each item in a list by one. |
| 17:49 | rbuchmann | either (map ... |
| 17:49 | rbuchmann | or doseq |
| 17:49 | amalloy | rbuchmann: doseq isn't very functional |
| 17:50 | hiredman | ~people |
| 17:50 | clojurebot | max people is 317 |
| 17:50 | amalloy | &(for [x [1 2 3 4 5]] (inc x)) |
| 17:50 | sexpbot | ⟹ (2 3 4 5 6) |
| 17:50 | rbuchmann | not much worse that recur though :) |
| 17:50 | VT_entity | @______@ |
| 17:50 | dpritchett | oh no, a noir patch? |
| 17:50 | VT_entity | oh damn amalloy |
| 17:50 | ibdknox | just pushing the latest unstable build |
| 17:50 | ibdknox | for those who wish to follow along |
| 17:51 | hiredman | ~#7 |
| 17:51 | clojurebot | 7. It is easier to write an incorrect program than understand a correct one. |
| 17:51 | VT_entity | wait, what's the ampersand? |
| 17:51 | hiredman | rbuchmann: how is recur not functional? |
| 17:51 | amalloy | tells sexpbot to start paying some damn attention |
| 17:51 | VT_entity | oooooh |
| 17:52 | rbuchmann | in a style kind of way :hiredman :) |
| 17:53 | VT_entity | ah, but the for is still kind of a FOR EACH isn't it. |
| 17:53 | hiredman | rbuchmann: what does that mean? |
| 17:53 | hiredman | loop/recur is a *functional* looping construct |
| 17:54 | rbuchmann | hiredman: of course |
| 17:54 | rbuchmann | nvm :) |
| 17:57 | ibdknox | I think it's more that one should favor higher order functions over loop/recur and so while that *is* functional it's not as steeped in the spirit of functional programming as another solution would be |
| 17:57 | ibdknox | *shrug* |
| 18:11 | gfrlog | ibdknox: loop/recur could be done as a higher-order function. I think it's just harder to reason about than other expressions |
| 18:11 | gfrlog | (map) is much easier to understand than the equivalent thing done with loop-recur |
| 18:11 | ibdknox | gfrlog: very true |
| 18:12 | gfrlog | I should say harder to reason about when there are simpler/other ways of expressing the thing |
| 18:12 | gfrlog | certainly sometimes loop is the simplest thing to do |
| 18:12 | gfrlog | maybe that was tautological... :( |
| 18:12 | ibdknox | haha |
| 18:13 | ibdknox | in general, it's true |
| 18:13 | ibdknox | that's good enough I think ;) |
| 19:16 | matthias_ | huh, i tried using swank.core/break, but i couldnt get it to work. got an error "no such namespace: <mynamespace>" when i tried to compile anything. i now reverted all those changes and i still get that error. with the same code that used to work... and it seems like i can compile it when i type (use '<mynamespace>) in the repl... |
| 19:16 | matthias_ | wtf |
| 19:30 | bsteuber | matthias_: "no such namespace" means you need to require/use the namespace, so this makes perfect sense to me |
| 19:31 | matthias_ | the namespace is created in the file i'm trying to compile |
| 19:31 | bsteuber | hmm ok, that makes less sense :) |
| 19:32 | hiredman | matthias_: what do you mean by compile? |
| 19:32 | matthias_ | C-c M-k |
| 19:32 | matthias_ | C-c C-c gives me the same error |
| 19:33 | hiredman | C-c C-k |
| 19:33 | matthias_ | ok, wtf |
| 19:33 | matthias_ | tried it again and it works |
| 19:34 | matthias_ | hmm, C-c C-k works too. |
| 19:34 | hiredman | C-c C-c will try to run the toplevel form under the cursor in the namespace of the file you are in |
| 19:34 | hiredman | it will fail if the namespace doesn't exist |
| 19:34 | matthias_ | the menu says that's Compile/Load file as opposed to compiel file |
| 19:34 | hiredman | (before compiling) |
| 19:34 | hiredman | use C-c C-k |
| 19:34 | matthias_ | oh |
| 19:35 | matthias_ | so it worked later because i had typed (use 'blabla) in the repl and that compiled it? |
| 19:35 | hiredman | most likely |
| 19:35 | matthias_ | so that actually makes sense |
| 19:36 | matthias_ | thanks :p |
| 19:36 | hiredman | I am not sure what the behavior of C-c M-k is with clojure, because you can't just compile, compiling in clojure is always compile and load |
| 19:37 | matthias_ | what does compile and load mean? |
| 19:37 | bsteuber | I expected the two to be synonymous, but maybe they're not |
| 19:37 | hiredman | they are for clojure |
| 19:38 | bsteuber | sure, for CL it's different |
| 19:38 | matthias_ | synonymous? so "compile" doesnt work, but "compile and compile" does? ;) |
| 19:38 | hiredman | compile is code generation, load is loading (and running) code |
| 19:38 | hiredman | so, like, for c compiling and loading are very different |
| 19:40 | matthias_ | so C-c C-k would run a c program after it's done compiling? |
| 19:41 | hiredman | C-c C-k is just compile, so it would just compile it to object code or an executable of some kind |
| 19:41 | hiredman | er |
| 19:41 | hiredman | C-c M-k |
| 19:41 | hiredman | C-c C-k would compile and then run it |
| 19:43 | jcromartie | so, has Hiccup won? or what? |
| 19:44 | jcromartie | I don't hear much about enlive, as powerful as it is |
| 19:44 | jcromartie | it seems like Hiccup is easier |
| 19:44 | amalloy | jcromartie: i like hiccup. real web developers like enlive |
| 19:44 | jcromartie | "Real web developers" huh? |
| 19:44 | jcromartie | I am tempted to go with StringTemplate |
| 19:44 | hiredman | depends if you are looking for templating or just something better then concating strings |
| 19:45 | scottj | jcromartie: ppl other than weavejester :) |
| 19:45 | gfrlog | I lost my ability to write <html> when the rails folk switched to haml; so I use hiccup. |
| 19:45 | jcromartie | hah, Haml is great |
| 19:45 | gfrlog | haml doesn't feel very much like clojure though |
| 19:45 | jcromartie | well, it was nice being here |
| 19:45 | jcromartie | bye |
| 19:45 | jcromartie | :) |
| 19:45 | amalloy | jcromartie: eg, brehaut hates hiccup because he can't just open up the html file in his html editor, or even see what the page looks like without starting a clojure webserver |
| 19:46 | jcromartie | scrabble |
| 19:46 | gfrlog | jcromartie: scrabble |
| 19:46 | gfrlog | oh I didn't see the typo; I thought "playing scrabble" had something to do with saying "scrabble" |
| 19:46 | gfrlog | so I was joining in |
| 20:28 | matthias_ | ,(update-in {:test "bla"} [:test] #(%)) |
| 20:28 | clojurebot | java.lang.ClassCastException: java.lang.String cannot be cast to clojure.lang.IFn |
| 20:28 | matthias_ | why is that? |
| 20:29 | matthias_ | oh it works if i use (fn [s] s). thought that would be the same |
| 20:29 | hiredman | ,(macroexpand '#(%)) |
| 20:29 | clojurebot | (fn* [p1__803#] (p1__803#)) |
| 20:30 | dnolen | ,(update-in {:test "bla"} [:test] identity) |
| 20:30 | clojurebot | {:test "bla"} |
| 20:34 | matthias_ | i dont understand why #(%) doesnt work |
| 20:34 | hiredman | ,(macroexpand '#(%)) |
| 20:34 | clojurebot | (fn* [p1__808#] (p1__808#)) |
| 20:34 | matthias_ | yeah i saw that |
| 20:35 | hiredman | well, there you go |
| 20:35 | matthias_ | doesnt tell me anything :p |
| 20:35 | hiredman | uh |
| 20:35 | hiredman | you can read the code right? |
| 20:36 | matthias_ | i dont know what fn* is. looks like its calling its argument though. which is strange. cause i dont think its supposed to |
| 20:36 | hiredman | ,(macroexpand '(fn [x] x)) |
| 20:36 | clojurebot | (fn* ([x] x)) |
| 20:36 | hiredman | that is exactly what #() is |
| 20:38 | matthias_ | i must have learned that wrong... but i've been using that # syntax for a while now... ;) (still a clojure newb though) |
| 20:38 | hiredman | if that is not what #() is, what would #(str %) expand to? |
| 20:39 | matthias_ | oh |
| 20:39 | dnolen | ,((fn [x] x) "foo") |
| 20:39 | clojurebot | "foo" |
| 20:39 | dnolen | ,((fn [x] (x)) "foo") |
| 20:39 | clojurebot | java.lang.ClassCastException: java.lang.String cannot be cast to clojure.lang.IFn |
| 20:39 | hiredman | if #(%) expanded to (fn [x] x) then #(str %) would be (fn [x] str x) |
| 20:40 | hiredman | hardly seems useful |
| 20:41 | amalloy | matthias_: fwiw, what you meant by #(%) is just identity |
| 20:50 | amalloy | seancorfield: interesting. what've you changed in congomongo? |
| 20:53 | seancorfield | added 1.3 support |
| 20:54 | seancorfield | the owner of the congomongo group on clojars seems to have gone awol and i need it in a repo since i'm starting to share it with my team |
| 20:55 | seancorfield | every other library we depend on is already in a public repo... except congomongo 0.1.5-SNAPSHOT :( |
| 20:56 | seancorfield | ideally, i'd have update permissions on the existing congomongo group on clojars but... |
| 21:00 | matthias_ | shouldnt lisps have some kind of "close all open parentheses" thing? i mean you often end up with ))))))) at the end of a function... |
| 21:01 | dnolen | matthias_: that sort of thing is why people use paredit, or a Lisp-aware text editor. |
| 21:01 | seancorfield | most of us use an edit mode that balances parens automatically |
| 21:01 | seancorfield | i use eclipse + ccw |
| 21:02 | matthias_ | yeah i use one too. still dont like it. |
| 21:03 | seancorfield | oh, so you mean some magical syntax that means "close all open parentheses"? |
| 21:03 | matthias_ | yeah |
| 21:03 | seancorfield | like... #) ...? |
| 21:03 | seancorfield | as an example |
| 21:03 | matthias_ | yeah |
| 21:04 | matthias_ | i'm sure its a bad idea for some reason... ;) |
| 21:04 | amalloy | seancorfield: i've heard of some lisps that use ] for that |
| 21:04 | amalloy | but yes, it's a bad idea |
| 21:04 | matthias_ | why? |
| 21:04 | clojurebot | why not? |
| 21:04 | seancorfield | amalloy: i had some vague recollection of reading something about that once... |
| 21:04 | amalloy | matthias_: it would be so easy to make mistakes when editing the code |
| 21:05 | seancorfield | well, for a start () is a form but ((] looks... wrong... and doesn't balance |
| 21:05 | amalloy | eg, (defun do-stuff (x) (whatever x] |
| 21:05 | amalloy | then later you decide this should be placed inside a closure, or a CLOS class |
| 21:05 | seancorfield | yeah, then you need to balance the parens anyway |
| 21:06 | seancorfield | to be honest, i really don't notice the parens these days |
| 21:06 | amalloy | seancorfield: and if you forgot, the error messages would likely be pretty bad |
| 21:06 | seancorfield | :) yup |
| 21:07 | seancorfield | and it's not like lisp / clojure has the best error messages in the first place |
| 21:07 | clizzin | what's the best way to deal with configuration information that you want read into the project but don't want in the source code, e.g. database hosts/user/pw? |
| 21:07 | clizzin | for clojure projects |
| 21:07 | seancorfield | where would you prefer to keep it? |
| 21:07 | matthias_ | really? if you had something like ] bla bla), it should be able to tell you exactly what's wrong i think |
| 21:07 | clizzin | seancorfield: in something like a yml file |
| 21:07 | clizzin | in project root |
| 21:07 | amalloy | matthias_: not so! bla and bla would have compile errors before it got to ) |
| 21:07 | amalloy | matthias_: anyway the main thing i'd dislike is the way it makes later editing a landmine in all kinds of ways |
| 21:07 | seancorfield | so you'd need to read the file at startup... |
| 21:07 | clizzin | it would live only on the app server and in dev environment but not in the repo |
| 21:07 | clizzin | yup |
| 21:08 | clizzin | i feel like leiningen supports this somehow, but i don't remember how it's done anymore |
| 21:08 | amalloy | but really, what is the *gain* of having ] anyway? you'd still need to stack up ))))) quite often |
| 21:09 | seancorfield | we use a clojure map for our configuration ... and so it is in our source code |
| 21:09 | amalloy | $google clj-config |
| 21:09 | sexpbot | First out of 8100 results is: marklazz/clj-record-blog - GitHub |
| 21:09 | sexpbot | https://github.com/marklazz/clj-record-blog |
| 21:10 | amalloy | hrm |
| 21:10 | amalloy | well, Raynes wrote a super-lightweight config library. it basically just reads from ./config.clj |
| 21:11 | Raynes | It reads from whatever file you want it to. It's just a wrapper around slurping/spitting etc with some convenience functions. |
| 21:11 | seancorfield | https://github.com/Raynes/clj-config |
| 21:11 | Raynes | I wrote it 100 years ago. |
| 21:11 | clizzin | haha |
| 21:11 | amalloy | Raynes: "basically", in context meaning "whatever i want it to mean" |
| 21:11 | seancorfield | may 3rd 2010 was the first commit :D |
| 21:12 | clizzin | sounds like i should just do my own thing |
| 21:12 | seancorfield | we have all the system configs in one environments.clj file and automatically select the appropriate one, based on hostname, at startup |
| 22:02 | dnolen | interesting, parsing with monads can be slow, http://carlo-hamalainen.net/blog/2011/02/11/parsing-with-monads-can-be-slow/ |
| 22:04 | dnolen | I'm assuming Parsec has optimizations to get around this, wonder what similarities they have to optimizing DCGs if any. |
| 22:06 | Scriptor | reading about the difference between next/more here |
| 22:06 | clojurebot | Cool story bro. |
| 22:07 | Scriptor | so basically, calling seq() on a sequence forces the evaluation of the first element of that sequence? |
| 22:07 | dnolen | Scriptor: yes |
| 22:11 | Scriptor | aha |
| 22:24 | amalloy | Scriptor: the ISeq interface has methods first() and rest(). because nil can be stored in a sequence, first() can't return nil to indicate "no elements" |
| 22:24 | amalloy | so instead, functions that return an ISeq (such as clojure.core/seq) must force the first element *just to see if it exists* in order to decide whether to return an ISeq or nil |
| 22:25 | amalloy | there would be other problems, like even-harder nil-punning, if ISeq objects could say "nope! no elements here!" but that strikes me as the main one |
| 22:31 | amalloy | gfrlog: in common lisp: (defun count (seq) (if seq (1+ (count (cdr seq))) 0)) |
| 22:31 | amalloy | gfrlog: doesn't work in clojure, because empty seqs evaluate to true |
| 22:32 | amalloy | the "pun" is treating an empty sequence as false |
| 22:33 | gfrlog | I guess I cdr get it... |