#clojure logs

2011-06-24

00:06gkoI don't use leiningen/cake, only REPL+files+ad hoc scripts: are they like ASDF/quicklisp of CL?
00:08cemerickgko: lein and cake both provide dependency management via the maven model; so yes, they're similar to quicklisp in that respect.
00:09symbolecemerick: 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:09cemerickI agree.
00:09cemerickTough road to tread, tho not because of the language.
00:10gkocemerick: lein vs cake: which one is better?
00:11gkogot it :)
00:12gkoare they both matures?
00:12cemerickgko: 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:13cemerickBoth are used for real projects in real companies, if that is a reasonable barometer.
00:13gkodo they download JARs for each project or they put them in a common pool?
00:14cemerickBoth of them reuse maven's ~/.m2 repository structure IIRC.
00:14cemerickThere was some talk of cake switching to use ivy, but I don't know how that settled out.
00:14cemerickgko: so, the latter, though each lib needs to be downloaded at least once of course.
00:15gkocemerick: OK... I intend to put all that stuff in my Dropbox directory...
00:15cemerickstuff?
00:16gkocemerick: all these JARs, etc...
00:16cemerickgko: yeah, don't do that. :-) Back up ~, but don't put any effort into curating your own store of jars.
00:17gkocemerick: well, If leiningen/cake does the work, for the better...
00:18cemerickexactly; dependency management means never touching jars directly
00:47technomancygko: to be honest, it seems to me like most people who learn clojure aren't to keen on going back to CL
00:47technomancyit can be done, but I'm not sure how. wouldn't be surprised if you had to keep them in separate Emacs instances
00:49technomancy*too keen
00:49technomancythe fact that the slime devs say "just use CVS" with a straight face may have something to do with it
00:51cemerickkeeps out the riff-raff
01:02technomancyanybody try that vagrant script?
01:02tomojclojure-box?
01:03tomojoh, found it
01:22gkotechnomancy: that's what I do now... Emacs 1: use CVS or ELPA version; if use other Lisp: open Emacs 2 and corresponding SLIME.
01:24gkotechnomancy: regarding not going back to CL: quicklisp happened and it's a whole new world :)
01:24technomancygko: it's impossible to make stable releases that are compatible with a constantly-changing target like slime CVS
01:24technomancytheir release management is simply irresponsible
01:24technomancyhopefully quicklisp puts some pressure on them to go out of cowboy mode; who knows
01:25gkotechnomancy: 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:26technomancykey bindings would still conflict
01:28gkotechnomancy: in CL REPL/buffers, use CL semantics, in Clojure REPL/buffers, use Clojure semantics?
01:30technomancyit'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:31technomancyit 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:40gkotechnomancy: 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:41gkoOf course, it would a permanent temporary solution...
01:41technomancycould work. but I'm not gonna do it. =)
01:42gkotechnomancy: of course not, you focus on clojure & contribs :)
01:42justinlillytechnomancy: it worked for me in the updated version, fwiw.
01:42justinlillythough I had trouble getting jack-in to work with the seajure website.
01:42justinlillysome large exception that I just ignored.
01:43technomancyjustinlilly: hm; I actually only tested jark
01:43technomancykind of attached to the idea of launching jark in ~/.profile though; I may add that to my host
01:44justinlillydo it. it already takes forever for the thing to come up from nothing.
01:44technomancyoh, the vagrant script already launches jark in .profile =)
01:46technomancyit's not much different from lein install swank-clojure 1.3.1 and ~/.lein/bin/swank-clojure though I guess
01:48fenghelp
01:52feng13:49 -clojurebot- recently on clojars.org: #{"org.clojars.mschristiansen/lein-beanstalk"}
07:47tsdhHi
07:50tsdhI 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:52tsdhThe 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:53manuttertsdh: it certainly true that (map foo (lazy)) will start mapping before lazy finishes computing -- that's what "lazy" means
07:54tsdhmanutter: Ok, then I'm happy my guess is correct. :-)
07:55manutterThe lazy seq should come back much quicker than the eager one for the same reason.
07:56manutterYou said it was generating the eager seq more quickly than the lazy seq, though? Is that right?
07:56tsdhmanutter: Yes, that's the case. (eager) is 6 times faster than (doall (lazy)).
07:56manutteroh, faster than lazy inside a doall
07:57manutterthat kinda makes sense though I'm surprised the lazy would be six times slower than the eager
07:58manutterbut if the code to generate the seq is really small/fast, I suppose the lazy-seq overhead could be relatively large by comparison.
07:59manutteror there could be some inefficiencies in how you're generating the lazy version.
07:59tsdhmanutter: Yeah, the seqs are generated using fast first/next java methods in some external lib. There's no expensive calculation involved.
08:00manutterok, that makes sense
08:00manutterYou know about the built-in iterators for Java objects?
08:01manutter(hmm, now I'm trying to look it up real quick on clojuredocs.org and *I'm* having trouble remembering)
08:01tsdhmanutter: 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:02manutterah, here we go
08:02manutter,(doc iterator-seq)
08:02clojurebot"([iter]); Returns a seq on a java.util.Iterator. Note that most collections providing iterators implement Iterable and thus support seq directly."
08:03manutterI believe that is lazy out of the box, if your Java object supports Iterable
08:03manutterhaven't played with it much tho
08:03tsdhmanutter: My lazy seqs support some additional features over the java counterparts.
08:03manuttergotcha
08:04tsdhmanutter: And what happens if the underlying iterator throws a ConcurrentModificationException?
08:04manutterwell, ordinary exception handling (or lack thereof, if you're not using try/catch)
08:05manutterthat would be my guess anyway--like I said, I don't have much experience with it
08:06tsdhmanutter: 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:07manutteryeah, gotcha
08:07manutterthat is, "gotcha" as in "I see what you're saying" not as in "I see a problem" :)
08:08manutterirc is nice but it doesn't carry tone of voice too well...
08:08tsdhmanutter: Ok, now I think you see what I'm saying. :-)
08:08manutterI do, and I see the advantages of your approach
08:10tsdhOk, I'm digging a bit more in the code to see where I can boost performance...
08:31clgvI 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:40clgvhmmm :type is apparently not used in clojure.core 1.2
08:43clgvoh 1.3-beta1 was released :)
09:28gfrlog(defn identity [x] (type (with-meta {} {:type x})))
09:29clgvgfrlog: not the straight forward use case for it that I would have thought of ;)
09:30clgvbut since it is not used in core, I assume it's build for application specific use.
10:00Scriptorint
10:04timvisherhey all
10:04timvisherwho wants to help explain this behavior? https://gist.github.com/1044816
10:04timvisherI have a map with a key pointing to a long
10:04timvisherwhen I print that at the repl, everything's fine
10:05timvisherif i do anything at all with it, the number turns to 0
10:05timvisherincluding (first ...) or (into #{} ...)
10:05timvisherand i haven't the foggiest why
10:08pjstadignot enough information to debug
10:08pjstadigwhat to from-long and to-long do
10:09pjstadigwhere is fs/mtime coming from?
10:09timvisheror (pr ...) for that matter
10:09pjstadigwhat is happening during the snip? is the filesystem changing?
10:09timvisherfs/mtime is from the fs library
10:10timvisher$google clojure fs
10:10sexpbotFirst out of 2760 results is: ClojureWise: fs - File system utilities for Clojure
10:10sexpbothttp://clojurewise.blogspot.com/2011/01/fs-file-system-utilities-for-clojure.html
10:10timvishertime is clj-time
10:10timvisher$google clj-time
10:10sexpbotFirst out of 61800 results is: clj-time | Clojars
10:10sexpbothttp://clojars.org/clj-time
10:10timvisherthose
10:10timvisherthe snip is me clipping another 678kb of data
10:10timvisherthis is a 'large' seq (by my thought, at least)
10:11timvishermy point was that the first element can clearly be seen to have the long intact before i call first on it
10:11timvisheronce i call first it turns to a 0
10:11pjstadighttp://download.oracle.com/javase/6/docs/api/java/io/File.html#lastModified()
10:11timvisherto-long turns a joba time DateTime into a long
10:11timvisherand then from-long converts a long to a DateTime
10:12timvisherI'm familiar with what mtime is doing under the covers
10:12timvisherthat's the whole idea. i'm basically backporting an addition I just made to my app that includes dates
10:12timvisherI 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:13timvisherso that i can spit it out to a file and then read it back in
10:13timvisherbut in memory i'd like it to be a DateTime
10:13pjstadiglastModified returns 0 if there's an i/o error or if the file does not exist
10:13timvishersweet
10:13timvisherbut that doesn't explain what i'm seeing
10:14timvisherif i don't do anything to the seq resulting from the map, it prints with the expected values
10:14timvisherit's only when i use the map that it turns to 0
10:14timvisherthat's the point of the first line
10:14timvisherthe 2 :imported-ats
10:14pjstadigwell you're doing a complex operation here
10:14pjstadig(ref (map #(assoc % :imported-at (time-coerce/from-long (fs/mtime (wallpaper->thumbnail-path %)))
10:14pjstadigand here (map #(assoc % :imported-at (time-coerce/to-long (:imported-at %))) @library))
10:15pjstadigthe best thing would be to break it apart piece by piece and see that the values are what you are expecting
10:15timvisheri've been at the repl for an hour over this, I could gist my whole log if that would help
10:15timvisherin general though, i've done that
10:15timvisheri've picked it apart piece by peace
10:15timvisherpiece*
10:15timvishereverything returns what I want it to until i do something to the map
10:15timvisherand then the number turns to 0
10:16timvishercould this have something to do with them being primitive longs?
10:16pjstadigwhat is preferences-home?
10:16pjstadigyou're binding preferences to {:library-cache-path "/Users/tim/Desktop/library.clj"}
10:16timvisherit's a path-prefix string
10:16pjstadigdo those comport with each other?
10:17timvisheryes
10:17timvisherpreferences is a map that i load from a file
10:17timvisherpreferences-home is another var that has the default prefix
10:17timvishernot terribly proud of that but haven't gotten around to doing something better yet
10:18timvisheressentially, in the main app I have a ref called library that stores a big 'ol hash-set
10:18dpritchett`speaking of which i have a tiny noir app and i need a place to store my mysql password
10:19timvisheri make edits to that and every once in a while a serialize the datastructure to disk
10:19timvisherin a format that can be read by read-string
10:19dpritchett`would a .clj file with a single def containing my secrets accessed via load-file at runtime be a good starting point?
10:19timvisherso far, this has worked beautifully
10:19dpritchett`or is there a standard config file pattern
10:19timvisheri've been trying since yesterday though to add a imported-at key to the structure
10:19timvisherand 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:19timvisherand that's where i discovered this behavior
10:20timvisherdpritchett: that's what has worked for me up until now
10:20timvisheras long as your storing your password as a string it works great
10:21timvisherjust make sure you don't add it source control! :)
10:21timvisherpjstadig: does that make any more sense?
10:22clgvdpritchett`: you could add the config-file in your home in a ".yourapplication/" folder
10:22timvisherdpritchett: 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:22dpritchett`clgv how would i access it though
10:23dpritchett`(load-file ".myapp/dbsecrets.clj") ?
10:23timvisherdifferent: no, you need a full path to it
10:23timvisheror make sure it's relative to launch point
10:23pjstadigtimvisher: 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:24timvisherso if you store it in ~/.myapp/foo.clj then you need to get the home location and str them together
10:24timvisheri'm a big fan of fs
10:25clgvdpritchett`: 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:25dpritchett`so i can't just use ~ to refer to the home location, I have to figure ito ut myself?
10:25timvisherjava doesn't understand ~
10:25dpritchett`my app is mostly a toy and it's intended to be run serverside on linux fwiw
10:25cemerick~ is a shell thing
10:25clojurebot@ has nothing to do with whether sth is evaluated or not
10:25timvisherfs has a home function
10:26timvisheryou don't have to store it in ~
10:26timvisheryou could also just store it relative to the root of the war/jar/project folder
10:26timvisherthen you wouldn't need a full path
10:26timvisherthe point i was making was simply that you can't use ~ to refer to user home
10:26dpritchett`so we're talking http://clojars.org/fs ?
10:27timvisherdpritchett: that's what i use to interact with the filesystem
10:27timvisherit's a nice wrapper over File as well as some other nice functions for processing trees of files
10:27timvisherand you get to refer to files by there path, rather than as objects, which is nice
10:27dpritchett`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:28dpritchett`then i'll gitignore the config file and push it out
10:28timvisherpjstadig: 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:28timvisheri can run those 2 functions over and over again and they return the same results every time
10:29timvisherif they were changing the state i'm reading, i'd expect the results to change
10:29pjstadigmap is lazy
10:29pjstadigso the time between when you call map and when you print or first the seq...things can happen
10:29timvisheragain, i totally agree with you, but if that was happening, you'd expect the results to be different every time, wouldn't you?
10:30timvisheri suppose i could do-run on the map
10:30pjstadigmaybe it's not the solution, but it's all i got
10:30timvisherbut the repl forces lazy seqs anyway
10:30timvisherthat's cool. thanks for your help. this behavior is just baffling to me
10:30pjstadigif i were you i'd break apart those complex pieces of code, and try to test things in isolation
10:30timvisherthat's what i've been doing
10:30pjstadigright
10:30timvishereverything works exactly as expected until i use the map
10:30pjstadigso maybe i'm not helping :) :(
10:30timvisherseq
10:31timvisheryou're at least providing an ear to rant to. :)
10:31pjstadigthe fact that lastModified returns 0 on an i/o error or if the file is missing seems like a good lead to me
10:31pjstadigthat would explain seeing 0 for imported-at
10:32pjstadigand the fact that lastModified is accessing the file system which can change while you're not looking also seems like a good lead
10:32pjstadigbut i agree it's weird that it is reproducible
10:33dpritchett`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:33dpritchett`i have one function that gets me the recordset and can format/print it
10:33dpritchett`and i have another that responds to an http request using noir's defpage macro at the url "/posts"
10:33dpritchett`haven't figured out how to compose this exactly
10:34dpritchett`Does anyone know of a good example of a simple CMS app using contrib.sql ?
10:35clgvdo I still have to use DateTime/now or is there something in clojure 1.2.1 or contrib?
10:35clgvI want to use the timestamp as ID
10:36timvisherclgv: could you be looking for clj-time?
10:36clgvsince I dont need any real ID management but only a reference between datasets on disk
10:36timvisher$google clj-time
10:36sexpbotFirst out of 61800 results is: clj-time | Clojars
10:36sexpbothttp://clojars.org/clj-time
10:36pjstadig,(.getTime (Date.))
10:36clojurebotjava.lang.IllegalArgumentException: Unable to resolve classname: Date
10:36pjstadig,(.getTime (java.util.Date.))
10:36clojurebot1308926197290
10:36pjstadigcan work as a timestamp
10:36pjstadigand can be compared easily
10:38clgvyep. I just dont want to build an own function if there is one already.
10:38pjstadigthere is one though...it's the method on the Date class
10:39clgvI saw it ;)
10:39pjstadigsuit yourself :)
10:42cemerickor ##(System/currentTimeMillis)
10:42sexpbot⟹ 1308926534365
10:42pjstadigja, was just going to say that, too
10:44clgvcemerick: precise one :)
10:44timvisherso if i do the same operation without binding library, i'm golden. https://gist.github.com/1044912
10:44manuttertimvisher: Hey, I saw your questions about daylight time yesterday (it was in my scrollback) Did you ever get that figured out?
10:44timvisherwith binding but with refs, still broken https://gist.github.com/1044918
10:45timvishermanutter: yes and know
10:45timvisherno*
10:45clgvjust checked: (-> (System/currentTimeMillis) (java.util.Date.)) to be sure that it isnt relative to system start ;)
10:45timvisheri figured out a way to do it
10:46timvisherwhat 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:46manuttertimvisher: that is odd, unless US/Eastern is auto-updating for DST
10:47timvisherthat's what i mean
10:47gfrlogUs/Eastern should be an atom that gets swapped every 6 months
10:47timvisherany of the relevant string ids (i.e. "America/New_York") all auto update to DST
10:47cemerickgfrlog: The earth probably won't exist by the time the long overflows.
10:47cemerick,(java.util.Date. Long/MAX_VALUE)
10:47clojurebot#<Date Sat Aug 16 23:12:55 PST 292278994>
10:47cemerickOr humanity will be extinct, whatever.
10:48gfrlogcemerick: you mean the earth probably won't exist BECAUSE the long overflows
10:48timvisherthey return different types
10:48manuttercemerick: yeah, maybe if we were better prepared for Y2G it would be the end of everything
10:49clgvlol earth wont exist because of suns death by then ;)
10:49timvisherone is a CachedDateTimeZone and the other is a FixedDateTimeZone
10:49manutteryeah, but the sun uses an old MS timestamp...
10:49timvisherbut the semantics of the functions then seem strange
10:49timvisherwhen 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:49timvisher-5*
10:50gfrlogwhat's 5? Israel?
10:50timvisherwhereas 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:50timvisherto add or subtract an hour
10:50timvisheror whatever crazy thing that country is doing this year
10:50manuttertimvisher: I haven't worked enough with Java dates to discuss the technical details beyond a certain rather shallow depth
10:51timvisherit's my first real forray as well so hurray to us! :)
10:51clgvtimvisher: turkey switched DST later this year with an absurd reason^^
10:51manutterI did see a link on joda.org about updating the timezones manually
10:51manutterapparently that's an issue for people stuck using older jvm version
10:51manutter*versions
10:51timvisheri 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:51timvisheri just don't know why you'd ever want that.
10:52timvishermaybe if you wanted to stick it people dumb enough to live in countries with DST (like me! ;)
10:52cemerickclgv: The sun still has some billions of years to it yet, no? Or am I forgetting my local astrophysics timelines?
10:52timvishercemerick: you're thinking of alpha centauri
10:52timvisheryou have a suprisingly wide scope of local astrophysics ;)
10:52timvisherthe sun's going in a few years
10:53timvisherdon't worry though
10:53clgvcemerick: oh humm that number is only 292 million - well, guess I have to check ;)
10:53timvisherthe government'll get us all relocated
10:53gfrloghairdressers and marketing folks on the first ship
10:53timvisheranyone else had a chance to look at this seq problem i'm having?
10:54manutterJust 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:54cemericktimvisher: A billion here, a billion there :-) http://en.wikipedia.org/wiki/Sun#Life_cycle
10:54timvishermanutter: that's why i don't invest in stocks
10:54Scriptorwe're just about about halfway through the sun, I believe
10:54tsdhIs there a problem with generating and executing gazillions of identical anonymous functions (performance and maybe garbage collection wise)?
10:54clgvcemerick: damn. ok we need bigger integer types! ;)
10:55Scriptormanutter: or dine at a fabulously expensive restaurant and watch the universe end :)
10:55Scriptortsdh: why are they identical?
10:55Scriptoror are you generating billions of closures?
10:56tsdhScriptor: Well, not identical but equivalent.
10:56gfrlogcan the number of functions generated be expressed by a Long?
10:57tsdhScriptor: 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:57stuartsierratsdh: 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:58tsdhScriptor, 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:58gfrlogstuartsierra: the instance holds the closure information?
10:58timvisheranyone know why a long at the repl would suddenly turn to 0 upon looking at it putting it somewhere else?
10:59timvisheri.e. https://gist.github.com/1044816
10:59timvisher/s/looking at it/
10:59timvisheranyone know why a long at the repl would suddenly turn to 0 upon putting it somewhere else?
10:59gfrlogtimvisher: is that the most minimal example you can get?
10:59timvisherhmm. was that /s supposed to work?
10:59timvisherno
10:59timvisheri'll work on getting it more minimal
11:00timvisheractually, is that minimal enough?
11:00timvisherhttps://gist.github.com/1044918
11:00timvisheri removed the binding and all of that
11:00timvisherit's still fairly complex
11:00timvisherbaha
11:00timvishersorry, ignore that
11:00gfrlogthere's all this stuff with these libraries I don't know anything about...
11:00timvisherhave too many gists going
11:00timvisheri'll work on something new
11:00gfrlogusually if you try to strip out all the ancillary stuff at some step you'll figure out the real culprit
11:01timvisherhow do i produce a primitive long on purpose?
11:01gfrlogdo it by accident and then later claim you meant to
11:01timvisherlol
11:01timvisherthat's what fs/mtime is doing so i want to remove that call
11:01manuttertimvisher: I dunno, I looked at that code and I think you should call Schrodinger and tell him you found his cat.
11:02clgvroflmao!
11:02Scriptortsdh: 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:02stuartsierragfrlog: yes
11:03gfrlogstuartsierra: cool.
11:03stuartsierraThe instance holds the values of closed-over locals.
11:03Scriptoralso, see if maybe you could refactor it into just one function and generate a ton of closures of it instead?
11:03timvishermanutter: that's what i've been looking to hear all morning! :)
11:04stuartsierraIn 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:04timvisherso, no one knows how to produce a long on purpose?
11:04clgv&(Long. 5)
11:04sexpbotjava.lang.IllegalArgumentException: No matching ctor found for class java.lang.Long
11:05timvisher,(long 5)
11:05clojurebot5
11:05timvisherthat look about right?
11:05gfrlog,(.longValue (long 3))
11:05clgv&(type (long 5))
11:05clojurebot3
11:05sexpbot⟹ java.lang.Long
11:05timvishergod i've gotten lazy
11:05gfrlogdocs say that Long#longValue returns a primitive
11:05timvisherdoes type do autoboxing?
11:05gfrlogdon't know what clojure will do to it though
11:05tsdhScriptor: 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:06clgvthe random version: ##(if (< (rand) 0.5) (long 5) (double 5))
11:06sexpbot⟹ 5
11:06stuartsierraStarting 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:06stuartsierraMost Clojure functions, such as type, do not support primitives, so auto-boxing occurs.
11:06cemericktimvisher: All primitives are boxed at function boundaries, unless the function in question has primitive type decls.
11:06Scriptortsdh: see if you can check memory consumption too, just in case the gc isn't able to keep up
11:07Scriptorotherwise, an 18% speedup isn't all that bad :)
11:07timvisher,(doc long)
11:07clojurebot"([x]); Coerce to long"
11:07timvisherdoes that mean Coerce to Long?
11:07Scriptor,(doc apply-macro)
11:07clojurebotNo entiendo
11:07timvisheror is that really be a bonafide `long`?
11:08gfrlogtimvisher: does your code not break if you substitute (long 5) for your function call?
11:08tsdhScriptor: Memory is hard to measure. In any case, the requirements of these functions should be negligible in comparison to the data.
11:08gfrlog(or (long 6) if necessary)
11:09timvisheri'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:09tsdhScriptor: 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:11Scriptorah, maybe not worth it then, though you maybe vseq could be implemented as a wrapper macro that rewrites it that way for you?
11:11cemericktimvisher: 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:11cemerickOr, it yields a long, I should say.
11:12Scriptorhow fast is java's instanceof? Asking because first/rest invoke it every call
11:12timvisherwow. i'm an idiot
11:12timvishersorry everyone
11:12tsdhScriptor: vseq is a protocol function that recursively calls itself in a lazy-cat.
11:12timvisheri wasn't binding one of the keys i needed in the function and so pjstadig was right all along!
11:13timvisherthe path i was accessing didn't exist and thus mtime was returning 0
11:13timvisherat binding time they existed because the preferences var hadn't been overwritten yet
11:13timvisheri hate state...
11:13timvishershould've been associng onto preferences rather than completely resetting it
11:14Scriptortsdh: ah, you're right, sorry for the confusion
11:14timvisherthanks so much for everyones help
11:15gfrlogtimvisher: did you figure it out while trying to minimize the example?
11:16timvisheryeah
11:16gfrlog:)
11:16timvisherwhich was also pjstadig advice
11:16timvisherwhich i'd been doing for an hour
11:16timvisheri just never though to not use mtime and instead insert a fixed long value
11:16gfrlogmy strategy is to just delete random characters and see what happens
11:17timvisherhave an emacs function that does that for you? :)
11:17pjstadigtimvisher: glad you figured it out!
11:18tsdhScriptor: 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:18timvisherpjstadig: me too!
11:18timvisheras a meta question, why does the repls forced eval not exhibit the behavior that firsts eval does?
11:20pjstadigi'll tell you why
11:20pjstadigmap is lazy
11:21pjstadigthe seq escapes the binding form in one case
11:21pjstadigbut not in another
11:21timvisherah hah
11:21pjstadigstupid laziness :)
11:22timvisherso the seq comes out of the binding form having not been evaluated and then gets evaluated in the unbound context
11:22timvisherbrilliant
11:22timvishermakes perfect sense
11:22pjstadigvars and binding are a form of state
11:24tsdhHm, the docs specify (defprotocol name & opts+sigs) but don't mention what opts can be except the optional docscring...
11:26gfrlog,(source defprotocol)
11:26clojurebotjava.lang.Exception: Unable to resolve symbol: source in this context
11:26pjstadig~source defprotocol
11:28timvisheranyone else using clojure-jack-in in emacs?
11:31mattmitchellis there a non-lazy concat? or, a recursive doall?
11:32dnolenmattmitchell: you can always make concat non-lazy by wrapping in doall.
11:34mattmitchelldnolen: 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:35dnolenmattmitchell: you can use doall at the last minute, doall will only operate on the lazyseq it's applied to, not nested ones.
11:35dnolens/can/can't
11:35sexpbot<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:36mattmitchelldnolen: 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:37dnolenmattmitchell: I'm curious as to why you need to force them.
11:38mattmitchelldnolen: yeah i'm still trying to figure this out. I might be doing something wrong here.
11:38dnolenmattmitchell: what about your problem requires you to force them?
11:39pjstadigi'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:39pjstadigand it was fixed but just doing (doall (concat ...))
11:39pjstadiginstead of waiting until the end
11:40gfrlogno matter how many times I encounter that issue I can never remember why it happens
11:40dnolengfrlog: recursive applications of concat is almost always the culprit
11:40pjstadigthere's also the issue of a lazy seq escaping a scope like with-open or something
11:40gfrlogdnolen: like (concat a (concat b (concat c (...))))?
11:40pjstadigbut again you can doall at the appropriate levels to get around that
11:41dnolengfrlog: if you have 5000 unrealized concats, you're gonna get stackoverflow when you try to pull out the first item.
11:41gfrlogdnolen: I guess I can't convince myself it's necessary, given the way laziness is handled elsewhere without stacking
11:41mattmitchelldnolen i think actually, i'm wrong. I need to dig a little bit more before I can explain what's happening here :)
11:41gfrlogdnolen: 5000 nested (lazy-seq)s generally would do the same thing?
11:42dnolengfrlog: exactly.
11:42gfrlogdnolen: I wonder why everybody's so prone to do it with concat then...
11:42gfrlogcould concat be rewritten to avoid that?
11:43pjstadigperhaps we should all make more use of into
11:43pjstadigand infact i guess into is really a "non-lazy" concat
11:43dnolengfrlog: I don't see the point, since it applies to lazyseqs in general.
11:43gfrlogdnolen: but apparently concat is the only place it tends to pop up
11:44dnolengfrlog: only because it's commonly used in recursive operations, special casing concat sounds meh.
11:45__name__$source into
11:45sexpbotinto is http://is.gd/uvV1dc
11:46gfrlogdnolen: well if it's meh then let's not do it
11:50pjstadigonly problem with into vs. concat is
11:50pjstadig,(into '(:d :e) [:a :b :c])
11:50clojurebot(:c :b :a :d :e)
11:50pjstadig,(concat '(:d :e) [:a :b :c])
11:50clojurebot(:d :e :a :b :c)
11:50dnolen,(into (vec '(:d :e)) [:a :b :c])
11:50clojurebot[:d :e :a :b :c]
11:50pjstadigsure
11:50pjstadigbut that's cheating
11:51pjstadighehe
11:51dnolen:)
11:51pjstadigi'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:51pjstadigbut concat is also ordered the way you'd "expect"
11:52pjstadigplus
11:52pjstadig,(concat #{:a :b} #{:a :b})
11:52clojurebot(:a :b :a :b)
11:52pjstadig,(into #{:a :b} #{:a :b})
11:52clojurebot#{:a :b}
11:52pjstadigassuming you'd want to do such a thing
11:55Scriptoranyone behind clojuredocs.org on here?
11:55Scriptorthe sorting algorithm used in search is a bit off
11:59gfrlogScriptor: I've seen it do weirder things
12:01gfrlogI 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:01mattmitchellanyone know what the command is in emacs to show a list of search matches in a new buffer?
12:02derp_hey, what is the != symbol in clojure?
12:02dnolenderp_: not=
12:02mattmitchellit'll show each match with a little context
12:02derp_dnolen: thanks
12:02dnolenmattmitchell: are you talking about grep-find ?
12:04mattmitchelldnolen: 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:07mattmitchelldnolen: can grep-find do that?
12:07dnolenmattmitchell: multi-occur ?
12:07mattmitchelldnolen: i'll try that
12:07dnolenM-x multi-occur
12:07mattmitchelloh that sounds right
12:07dnolenwhich is really cool, I never knew about that.
12:07dnolenhttp://www.emacswiki.org/emacs/SearchBuffers
12:07mattmitchelldnolen: yes! thank you. very helpful.
12:09edwardghello, 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:09derp_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:10edwardgwhich tests are failing?
12:10derp_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:12hiredmanderp_: you see to expect implicit return statements in non-tail positions?
12:12hiredmanseem
12:14hiredmaneverything is an expression http://stackoverflow.com/questions/19132/expression-versus-statement
12:15derp_so how do I make it explicit?
12:17hiredmanderp_: there are no statements
12:18derp_okay, but then how do I return the evaluated expression?
12:27cemerickderp_: use cond instead of a pile of `if`s
12:29cemerickThere's also https://github.com/jpalmucci/clj-return-from, which I can see being handy for more complex situations
12:33derp_okay, I tried using cond instead, here's my code now: http://pastebin.com/MHbx04dM
12:33derp_but for some reason I still can't get it to work
12:35hiredmanderp_: everything is an expression
12:37manutter,(doc recur)
12:37clojurebotHuh?
12:37manutter,(doc loop)
12:37clojurebot"([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:37dnolenderp_: move your recur inside the cond expr as a :else clause
12:39derp_dnolen: thanks!
12:40derp_dnolen: why is it :else instead of else?
12:41fliebel,(boolean :else)
12:41clojurebottrue
12:41gfrlogis that why it works?
12:41manutterderp_: The :else isn't actually part of the cond syntax
12:41fliebel&(cond false 1 :blah 2)
12:41sexpbot⟹ 2
12:41gfrlogit hadn't occurred to me that it wasn't part of it
12:42manutterit's just a value that is truthy enough to serve the purpose of a "non of the above" clause
12:42gfrlog&(cond false 1 :never 4)
12:42sexpbot⟹ 4
12:42dnolenderp_: because it makes the cond macro simpler.
12:43manutter,(code false 1 (= 1 0) 2 :none-of-the-above 3)
12:43clojurebotjava.lang.Exception: Unable to resolve symbol: code in this context
12:43manutterdoh, typo
12:43manutter(cond false 1, (= 1 0) 2, :none-of-the-above 3)
12:43gfrlogah hah ha...
12:43manutterand he forgets the leading comma, doh again.
12:43derp_okay, so it's just a random keyword that's evaluated after all other statements?
12:44gfrlog,(cond :else 15 (= 1 1) "twelve")
12:44clojurebot15
12:44gfrlogonly if you put it after all the other statements ;-)
12:44manutterYeah, any keyword will evaluate to true, and thus satisfy cond, which looks for the first clause that returns a true value
12:44derp_&(cond :blah 1 true 2 false 3)
12:44sexpbot⟹ 1
12:44fliebelgfrlog: That's a nasty trick to unsuspecting readers :)
12:45gfrlog,(conf :if 1 :then 2 :else 3 :end 4)
12:45clojurebotjava.lang.Exception: Unable to resolve symbol: conf in this context
12:45gfrlogbah
12:45gfrlogI'm not typing it again.
12:45manutterYeah, 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:47halfprogrammerI think even JoC talks about using any keyword in cond instead of :else thingy
13:05choffstein1
13:06gfrlogchoffstein: 2
13:06choffsteinHas 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:06gfrlogchoffstein: does the standard resources setup not work?
13:06choffsteinyeah ... advice to IRC GUI programmers -- don't change window context when a user is typing in their password :-\
13:07gfrlogyour password is "1"?
13:07choffsteinthere is a 1 in it.
13:07manutternot any more ;)
13:07choffsteinnamely ... at the end
13:07choffsteinhence the "enter" that quickly followed it.
13:07manutterThat's amazing I have the same combination on my luggage.
13:08gfrlogNow I just gotta think of all the passwords that end in "1" and pick the most plausible
13:08manutter"we're-number-..."
13:08gfrlog"321"?
13:08manutterSo, 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:08manutter*:(
13:08choffsteinlemme throw up a quick gist of my setup...
13:09gfrloga quist
13:10manutteriirc, 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:10choffsteinyeah. that is what I am finding in online resources manutter
13:10manutterand I could switch between the two with the right changes to my project.clj
13:10manutterbut I'm at work now and don't have access to those files
13:11choffsteinmaybe something about changing the project environment settings?
13:12manutterI think I added a special plugin or something
13:12choffsteinwell ... that's an interesting idea. is it possible to get information from your leiningen project file from inside your project?
13:13choffsteinmy 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:13manutterOn that question I'll defer to someone who actually knows what they're talking about
13:15choffsteinyeah. let me get that gist up right quick
13:16derp_I am still having a bit of trouble getting my euler #3 program to work http://pastebin.com/MHKSNz3A
13:16derp_I keep getting an error about not recurring from the tail-position
13:17derp_I'm not really sure how to get around that, so I think I must be making some fundamental mistake
13:17sritchie(reverse (rest (reverse lst))) can be (butlast lst), btw
13:18manutterderp_: the problem is in line 29 of your gist
13:18manutterif I'm parsing the nesting correctly anyway
13:19tsdhCan I have a protocol whose methods are not exposed? Something like defn-?
13:19dnolentsdh: hiding fns of protocol doesn't make sense.
13:20derp_so it's okay to have multiple recur statements within a function?
13:20derp_the error was making me think I could not do that
13:21tsdhdnolen: why? I use protocols for fast dispatching in my own namespace but the functionality is exposed with some more convenient interface.
13:21dnolenderp_: 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:22dnolentsdh: this isn't Java. imagine Clojure's core datastructures with hidden protocol fns.
13:22choffsteinOkay, 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:22sdeobaldchoffstein, can you use Jetty instead? We tried Tomcat for ages before finally switching. It's much... less awful.
13:23tsdhdnolen: Wouldn't make sense there, but here it does.
13:23choffsteinsdeobald: Amazon's Elastic Beanstalk is on tomcat :-\
13:23choffsteinWhich is what I am trying to deploy to...
13:23sritchietsdh: can you just put the protocol in some other namespace, and :use it into the namespace with your convenient interfaces?
13:23dnolentsdh: 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:23derp_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:23derp_or is my understanding too fundamental?
13:23rhdoenges with clojure.string/replace, how do I access a matched group from the RE in my replacement?
13:23dnolenderp_: recur needs to be in the tail poisition, you need to figure out what that means.
13:24sdeobaldchoffstein, dang. Too bad. I remember having the same static resource issue on Tomcat. Let me see if I can find an old setup.
13:24gfrlog,(doc clojure.string/replace)
13:24clojurebotI don't understand.
13:24tsdhsritchie: That's an idea...
13:24gfrlogrhdoenges: I believe you can pass a function that takes the match vector
13:24rhdoengesgfrlog: ohkay. so I would pass something like (fn [[group-one group-two]] ...)
13:25gfrlogrhdoenges: yeah. Test it out, it's probably the case that the 0th item in the vector is not one of the groups
13:25choffsteinsdeobald: do you know a good jetty host?
13:25tsdhdnolen: What's definterface?
13:25dnolentsdh: for defining a Java interface.
13:26tsdhdnolen: But I guess then I cannot use extend-protocol, right?
13:26sdeobaldchoffstein: Nope, sorry. We're just running it ourselves.
13:27choffsteinokay, thanks anyway :)
13:27sdeobaldAnd I guess the old tomcat setup is dead. So I'm just not any help at all. :)
13:28choffsteinmy 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:28rhdoengesgfrlog: that's what was tripping me up, the first item is the whole matched part. thanks!
13:28gfrlogchoffstein: I thought there was a handler that in the resources directory
13:28gfrlogrhdoenges: yessir
13:29choffsteingfrlog: eh? don't quite follow that
13:29gfrlogchoffstein: okay lemme see what I have...
13:29sritchiederp_: your parens are off, on your cond statement
13:30sritchiederp_: you close off that cond block on line 27
13:30gfrlogchoffstein: I think it's a compojure thing. Are you using compojure?
13:30dnolentsdh: 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:30choffsteinnope. ring / moustache
13:30gfrlogchoffstein: okay nevermind. I have (route/resourses "/") in my compojure routes and it finds everything in /resources/public
13:31choffsteinwell ... might be time to switch to compojure. I think moustache and compojure play nicely...
13:31tsdhdnolen: The obvious benefit is that you get less clutter when autocompleting. :-)
13:31gfrlogchoffstein: I don't even know what the heck moustache is, so I can't comment on that
13:32gfrlogI thought it was this javascript templating thing but I think that's something else
13:32sritchiederp_: I fixed your formatting for you, and that cond error: https://gist.github.com/1045258
13:32sritchiethe code runs, now, though the answer's not correct
13:32derp_sritchie: thank you very much!
13:32dnolentsdh: heh, what are you using? I guess it doesn't process the ns declaration?
13:33sritchieI didn't change any functionality, but I tweaked your implementation of prime? to show you a different way of writing statements like that
13:33tsdhdnolen: I use slime/swank
13:33sritchiederp_: 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:34sritchiederp_: 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:34sritchielet the reader use the indentation as a guide... you don't really count parens, once you've read enough of this code
13:35derp_sritchie: thank you, I really appreciate your comments
13:35hiredmanget paredit
13:36derp_hiredman: already got, although I barely know how to use it
13:36derp_*got it
13:36sritchiederp_: http://www.emacswiki.org/emacs/PareditCheatsheet
13:42gfrlogeasiest way to make a black hole to bind *out* to?
13:43drewr(FileWriter. "/dev/null")?
13:43gfrlogdrewr: okeedoke, thx
13:44sdeobaldsritchie, 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:45sritchiederp_: try M-(, and go from there
13:45sritchiedo that at the beginning of some symbol, and see what happens
13:45rhdoengessritchie: 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:45rhdoengesmakes it a whole lot easier
13:45sritchieyup
13:46sritchiehttp://www.pchristensen.com/slimecommands.pdf
13:46sritchiegood stuff there, too, for SLIME
13:50rhdoengessritchie: it must be christmas or something
13:55mattmitchellanyone know of a way to remove double quotes from a word using paredit? for example, I want "test" to become test
13:56mattmitchellsorry, maybe i should go to #emacs :)
13:57hugodM-s
13:58mattmitchellhugod: awesome thank you
14:03gfrlogaw crap never use macros in (deftest) :(
14:03matthias_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:04dnolenmatthias_: cantor probably doesn't define toString for vec2
14:05matthias_but then how does slime get that string?
14:14aaelonyhi, 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:14aaelonyclojure.lang.PersistentHashMap
14:14aaelonytest=> (keys (j 0))
14:14aaelony("a" "b" "c" d" "e" )
14:14aaelonytest=> (:d (j 0))
14:14aaelonynil
14:16gfrlogaaelony: your keys are strings but you're trying to access keywords
14:16gfrlog({"a" 8 :a 3} :a)
14:16gfrlog,(:a {"a" 8 :a 3})
14:16clojurebot3
14:17gfrlogif you need to use strings for keys, you can access them like ((j 0) "d") or (get (j 0) "d")
14:17aaelonygfrlog: wow, thanks.
14:17gfrlog(strings and keywords are two different but similar things, and both can be used as keys in a map)
14:17gfrlog(in fact just about anything can be a key in a map)
14:18aaelonythx
14:18gfrlogyep
14:19aaelonythat helps quite a lot :)
14:20gfrlogusing keywords as keys is more common, but whether you should or not depends on what you're doing
14:20aaelonyI'm just using what clj-json decided was best. I just couldn't access what I knew it read in.
14:21gfrlogah, I see. I think clj-json has a config option that will convert the strings to keywords for you
14:22gfrlog(parse-string s true)
14:22gfrlogI'm mildly surprised it doesn't default to that
14:22amalloygfrlog: string literals for unusual objects are easier to construct than keyword literals
14:23amalloyi mean, i think it should default to keywords too. but it's possible to see why they might not
14:23gfrlogamalloy: in the context of converting a JSON object to a map?
14:23gfrlogI mean...I guess
14:24gfrlogyou're probably thinking the same thing I was and saying it differently
14:24jcromartieimagine if your JSON had spaces in the keys
14:24jcromartiekeywords = fail
14:24jcromartiealthough
14:25jcromartie,(keyword "this works")
14:25clojurebot:this works
14:25jcromartie:)
14:25gfrlogjcromartie: as does asking the parser to return strings
14:25jcromartieyes
14:25gfrlogI didn't say they should be incapable of returning strings :)
14:26aaelonywell, 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:26gfrlogaugh
14:26gfrlogI've never used that library
14:26jcromartiethis should just be a generic function
14:27aaelonyor maybe I messed something else up...
14:28gfrlogI just successfully wrote some meta-testing helpers for clojure.test
14:28jcromartie(defn keywordify [m] (if (map? m) (into {} (map (fn [[k v]] [(keyword k) v]) m)) m))
14:29gfrloge.g., (should-fail (is (nil? 42)))
14:29gfrlogjcromartie: that misses the nested maps though, doesn't it?
14:30gfrlogmaybe [(keyword k) (keywordify v)]
14:34aaelonyin my case it seems I've got a mix of a vector then a nested map
14:34aaelonyso, map, vector, map
14:36gfrlogfun!
14:37jcromartiegfrlog: no it doesn't
14:37jcromartiebut it does miss maps in collections
14:38jcromartielike a vector of maps
14:38gfrlogjcromartie: how would it do {"foo" {"bar" 12}} then?
14:46gfrlog,(let [keywordify (fn [m] (if (map? m) (into {} (map (fn [[k v]] [(keyword k) v] m)) m)))] (keywordify {"foo" {"bar" 12}}))
14:46clojurebotjava.lang.IllegalArgumentException: Wrong number of args (1) passed to: core$map
14:47jcromartiegfrlog: it works in that case
14:48gfrlog,(let [keywordify (fn [m] (if (map? m) (into {} (map (fn [[k v]] [(keyword k) v]) m)) m))] (keywordify {"foo" {"bar" 12}}))
14:48clojurebot{:foo {"bar" 12}}
14:49gfrlogmaybe I'm misunderstanding what you were trying to do
14:55mattmitchellwhat's the easiest way to pull out values from a list, where the values returned must be present in another?
14:56stuartsierra(filter (set the-other-list) the-first-list)
14:56scgilardicertified easiest™
14:57gfrlog,(filter #{false nil true 17} [1 2 3 true false nil "whut"])
14:57clojurebot(true)
14:57gfrlogsorry I couldn't stop myself :(
14:57mattmitchellnice thanks to you both!
14:58amalloygfrlog: that always makes me cry
14:58gfrlogamalloy: that the code does that or that I wrote the code?
14:58amalloyboth i guess
14:58gfrlogglad I could help
14:59gfrlogClojure: because the easiest way to do something shouldn't have to work 100% of the time.
14:59derp_is there an easy way to comment out highlighted text in emacs?
14:59jcromartieM-x comment-region
15:00amalloyderp_: M-;
15:00jcromartieor that
15:00derp_thanks!
15:00scgilardiright, you need to be careful if nil and false are possible. or change to using keep and only special-case nil.
15:01amalloyor: commit it to git so you won't be afraid to just delete it instead of commenting it out
15:01manutterwhat if your afraid of git tho?
15:01manutter*you're
15:01gfrlogread about git
15:02amalloymanutter: there's always room in our nations jails for more dissidents
15:02gfrlogif you're afraid of reading, then watch a youtube video about reading
15:02amalloy*nation's
15:02manutterlol
15:02rhdoengesmanutter: then use hg. or bzr. or svn. or cvs. anything is better than nothing
15:02gfrlogif 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:03jcromartieamalloy: what nation is that?
15:03jcromartienot mine
15:03amalloyjcromartie: the us, alas
15:03manutterI think that would be consternation
15:03jcromartiehah hah... no more room
15:03jcromartieanyway
15:03jcromartieyes, source control is better that commented out code...
15:03jcromartieand also, (comment ...) is better than ;;
15:03jcromartieif you really want to be slick
15:03gfrloggit commit -a -m 'wut this commit is'
15:04arohnerso 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:04amalloyjcromartie: ##((fn [x] (inc x) (comment "used to return 2x")) 3)
15:04sexpbot⟹ nil
15:04arohnerI can't just store the hash codes, because of collisions, right?
15:04jcromartieah, (comment) returns nil?
15:05amalloyyes. that is why it is evil and shouldn't be encouraged
15:05jcromartiederp!
15:05jcromartieI always use it in the top level
15:05jcromartiethat's why
15:05amalloy*nod*
15:05gfrlogarohner: 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:05amalloyit's usually harmless of course
15:05gfrlogarohner: and I guess it'll compare them character-by-character as well
15:06arohnersounds like I need to read some source
15:06scgilardiarohner: a bloom filter could help
15:06jcromartiethen there is #_
15:06amalloygfrlog: i imagine strings cache their hashes
15:06jcromartiescgilardi: the only problem there is that you need more hash functions
15:06amalloysince they're immutable
15:06arohneramalloy: yeah, I would assume that too
15:06gfrlogamalloy: yes
15:06gfrlogbut there's no reason to assume his string has been cached before
15:06gfrloghashed
15:06gfrloghash-cached
15:07gfrloghached
15:07amalloygfrlog: as soon as it gets put into a hashmap, it has
15:07gfrlogamalloy: if he already put it into his set then he doesn't need to check if it's there
15:07gfrlogprobably
15:07amalloyscgilardi: know of a good article on bloom filters? sounds interesting but i don't know anything about them
15:07scgilardijcromartie: right, I was interpreting it as a problem to be solved with 11 million strings rather than specifically about set.
15:07scgilardihttp://en.wikipedia.org/wiki/Bloom_filter
15:07jcromartiehow about grep
15:07mattmitchellstuartsierra: how the heck does "(filter (set the-other-list) the-first-list)" work?
15:08jcromartiethat would search 11M strings pretty fast
15:08jcromartie;)
15:08mattmitchell,(doc set)
15:08clojurebot"([coll]); Returns a set of the distinct elements of coll."
15:08gfrlogmattmitchell: it creates a set, which is a function that will return elements it contains
15:08gfrlogmattmitchell: for almost all elements, that corresponds to returning truthy, which is what filter looks for
15:08mattmitchellgood grief that's slick
15:09gfrlogsounds like a bloom filter is like a hash-map that doesn't bother storing values
15:10gfrlogor hash-set rather
15:10arohnerand requires multiple hash fns
15:10gfrloghaven't seen that part
15:10amalloyscgilardi: that's pretty neat
15:11arohnergfrlog: it's in the second sentence of the wiki article
15:11arohnerrequires k distinct hash fns
15:11gfrlogarohner: yep found it. Okay I take it back this is totally different and also clever.
15:12gfrlogI would join a band by that name.
15:14gfrlog"Unlike sets based on hash tables, any Bloom filter can represent the entire universe of elements."
15:15amalloygfrlog: (constantly true)
15:15gfrlogokay fine
15:17gfrlogI guess you can represent cofinite sets as well...
15:17mattmitchellhow 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:17jcromartieI wonder... how big would your bloom filter have to be for an 11M item set
15:17gfrlogmattmitchell: (map m my-keys)
15:17mattmitchelli know this is gonna be simple
15:17mattmitchellthere you go :)
15:17mattmitchellthanks
15:17gfrlogyessir
15:18gfrlogI would say for whathisface's application, if he can't tolerate false positives then the bloom filter won't do any good
15:18gfrlogsince he'd have to compute a bunch of hashes instead of just one
15:19gfrlogsave some space though I guess
15:20arohnergfrlog: saving space would be nice, right now the strings occupy 1.5GB. I'm more interested in speed than space though
15:21gfrlogarohner: I guess the bloom filter would help you filter out the negatives. Are your strings long?
15:21arohnergfrlog: not really. They're wikipedia article titles
15:21amalloyarohner: if you have them in a set already, looking them up will be fairly fast, i think
15:21arohneramalloy: but I want moar speed :-)
15:21amalloythe set will keep growing itself to limit collisions
15:22amalloyor 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:22gfrlogget a real big CPU that has 2 GB of on-chip cache
15:25edwAnyone out there using aleph? I'm getting a hang when I wait on respons from my redis server.
15:25amalloyedw: (a) what version of aleph redis, (2) what commands are you sending?
15:28jcromartiearohner: maybe another option would be a tree
15:29amalloyjcromartie: that will be way slower than a hashset
15:29gfrloga tree based on prefixes maybe?
15:29jcromartieright
15:29derp_how does one append to a vector?
15:29gfrlogderp_: conj
15:29arohnerclojure sets are already tries on the string's hashcode, right?
15:29amalloy&(conj [1 2] 3)
15:29sexpbot⟹ [1 2 3]
15:29gfrlogamalloy: dang that was fast
15:30gfrlogarohner: probably so
15:30amalloygfrlog: i have six fingers on my right hand
15:30derp_why does conj prepend when used with lists?
15:30sritchieamalloy: I know a guy who's been looking for you
15:30derp_&(conj [1 2] 3)
15:30sexpbot⟹ [1 2 3]
15:31amalloyderp_: it adds in whatever manner is most efficient for the underlying type
15:31gfrlogamalloy: dang that was fast
15:31gfrlogI'm gonna stop reading questions
15:31gfrlogor at least wait 5 secondns
15:31amalloy*chuckle*
15:32derp_okay, well I am using this function called 'butlast', but it returns the modified vector's contents as a list
15:32derp_how do I change that behavior?
15:32amalloyderp_: no, it returns it as a lazy-seq
15:33amalloy(which happens to print the same as a list)
15:33amalloyderp_: use subvec instead if you want a vector
15:33amalloy&(doc subvec)
15:33sexpbot⟹ "([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:33gfrlogwoah
15:33gfrlogI wonder how often I've missed that :/
15:34gfrlog&(doc supervec)
15:34sexpbotjava.lang.Exception: Unable to resolve var: supervec in this context
15:36amalloygfrlog: i was sad to find out that subvec throws an exception on negative offsets
15:36gfrloghaha
15:36derp_amalloy: thank you very much
15:36amalloy&(-> [1 2 3] (subvec 1 3) (subvec -1 3)) ; wish this returned [1 2 3]
15:36sexpbotjava.lang.IndexOutOfBoundsException
15:36edwamalloy: redis 2.2.10 and I'm sending PING, AUTH, stuff like that. The basics...
15:37gfrlogoh that'd be terrible
15:37derp_one last q, how would you have known that butlast returns a lazy-seq if you were unfamiliar with clojure?
15:37gfrlog,(class (butlast (range 20)))
15:37clojurebotclojure.lang.PersistentVector$ChunkedSeq
15:37amalloyedw: i was terribly unclear. what version of aleph?
15:38gfrlogderp_: well maybe that didn't help, but most functions return lazy seqs if there's no particular reason to do anything else
15:38edw0.2.0-alpha2
15:38amalloyedw: he fixed a similar issue for me in 0.2.0-alpha3: http://groups.google.com/group/aleph-lib/browse_thread/thread/60e02641dbaa05fe
15:38derp_so it's the default return type for most list/vector manipulation stuff?
15:38amalloyderp_: yes
15:39edwAh, didn't know there was an alpha 3...
15:39amalloyedw: i think it's still a snapshot
15:39amalloythis was like a week ago
15:39gfrlogderp_: clojure's designed to encourage you to deal with lazy seqs whenever you can
15:39edwamalloy: Is it up on clojars? 0.2.0-alpha4-SNAPSHOT?
15:39edwErr, 3.
15:39amalloyyes
15:40gfrloglike ##(zipmap (range 5) (repeat 0))
15:40sexpbot⟹ {4 0, 3 0, 2 0, 1 0, 0 0}
15:40edwThere we go! Thanks, amalloy. Let's see if this works...
15:41jcromartietrie functions yay
15:41jcromartieprobably too slow for 11M strings
15:41jcromartiehttps://gist.github.com/1045515
15:41jcromartiebut too elegant to pass up :)
15:42gfrlogjcromartie: another way to make it go faster is to only use 11 strings instead of 11M
15:42jcromartiethat's a great idea
15:42jcromartiewhy doesn't everybody just do that?
15:42gfrlog,(let [str-set (set (map str (range 11)))] (time (contains? str-set "7")))
15:42clojurebot"Elapsed time: 0.019 msecs"
15:42clojurebottrue
15:42gfrlogcan't beat that
15:43gfrlogjcromartie: now that I bring that up, what's the access time for your big set?
15:43edwamalloy: Still not working (on localhost with 2.2.10 and alpha3-SNAPSHOT). Durn.
15:44jcromartiemy what? it was arohner's problem
15:44gfrlogjcromartie: ah whoops sorry :)
15:45jcromartiedammit rlwrap/REPL... why does C-y (yank) send it to the background?
15:45arohnergfrlog: I have a document, I want to find all wikipedia titles in the doc. It takes ~700ms right now
15:45amalloyjcromartie: O(log32(n)) is not much slower than O(1) - the size of the set isn't going to matter much
15:45gfrlogamalloy: the caching level will matter
15:46gfrlogL1 cache vs. swap matters :)
15:46jcromartieso then it's solved? (use a set)
15:46edwamalloy: There's some promising stuff in the new branch on github. Might try that.
15:46amalloygfrlog: granted. but he shouldn't be going into swap, and fitting it into cpu cache is impossible regardless
15:46gfrlogunless he takes my suggestion of using 11 strings
15:46gfrlogor wait
15:47gfrlogO(1) was regarding the trie functions?
15:47amalloyyes
15:47gfrlogsorry, sometimes I get lost in my own stupid side comments
15:48gfrlogI'll go make an 11M string set and see how it performs
15:48jcromartieI can't even *make* an 11M string set
15:49jcromartieI gave up after letting it churn
15:49jcromartiefor 2 minutes
15:49gfrlogjcromartie: how much memory?
15:49jcromartie1024
15:49jcromartie(def bigset (set (map str (range 11000000))))
15:49choffsteinFreaking 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:49arohnerI have 4GB on this machine, and it takes 2.5GB to load the strings out of the DB, and 1.5GB steady state
15:50arohnertakes about 10 minutes to load them all
15:50dpritchett`choffstein, your dev routes don't match your production routes?
15:50jcromartiechoffstein: can you handle that with middleware?
15:50jcromartiearohner: yeah, not surprising I guess
15:50gfrlogjcromartie: that expression returned for me after about 15 sec
15:51gfrlog`top` puts the jvm at about 23.6% right now
15:51gfrlogI think I have 8G?
15:51jcromartiegfrlog: weird
15:51choffstein...I can?!
15:51jcromartiehm
15:51jcromartiechoffstein: routes are just functions
15:51gfrloguser=> (time (contains? bigset "48482"))
15:51gfrlog"Elapsed time: 0.036596 msecs"
15:51jcromartieyou should be able to wrap them
15:52jcromartienot really "middleware" but something to "massage" the request URL
15:52amalloyjcromartie: that's middleware :P
15:52choffsteindprichett`: the issue is, I have my routes like "/portal", but when I deploy to tomcat, the routes are like "/myApp/portal"
15:52jcromartieyeah I was going to say
15:52jcromartie:)
15:52choffsteinYeah. 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:53amalloy(defn without-prefix [prefix handler] (fn [req] (handler (update-in req [:uri] #(s/replace % prefix "")))))
15:54amalloychoffstein: 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:54choffsteinamalloy: that is my last ditch idea. seems "hacky" to me.
15:54gfrlogamalloy: and then parse the html that comes out and add it back to all the <a>'s?
15:54amalloygfrlog: ouch
15:55gfrlogI guess you can do relative paths that avoid that?
15:55amalloygfrlog: yeah but not always
15:55amalloychoffstein: yes, you should probably be able to configure tomcat to do that for you, i guess
15:55gfrlogjcromartie: I made another set with longer strings (~25 chars) and it took a few minutes
15:56gfrlogchoffstein: tomcat lets you deploy an app as the root app
15:56jcromartieI've got a lot of stuff going on with my 4G machine... VMWare, Chrome, iTunes
15:56choffsteingfrlog: I'm trying to figure that out :)
15:56jcromartie4GB
15:56gfrlogchoffstein: I think if you upload it as ROOT.war it'll do that automatically
15:56choffsteinre-he-he-heaaalllyyy?
15:56gfrlogchoffstein: ma-ha-ha-haaaaaby
15:57choffsteinIT'S ALIIIVVVEEEE
15:57choffsteinIITTTT'S ALLLIIIIVVVEEEEE
15:57gfrlogusing 11M big strings wasn't much slower than 11M little strings
15:58gfrlognot only that, 11M big strings was only 1 or 2 times slower than 11 strings.
15:58gfrlogunless contains? is returning some kind of lazy boolean
16:00choffsteingfrlog: thank you so much. ROOT.war did the trick.
16:00gfrlogchoffstein: no probalo
16:00gfrlogI hate trying to figure out how to make tomcat do stuff
16:01edwD'oh. Nothing's working here, amalloy.
16:01arohnergfrlog: 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:02ibdknoxHow many of you guys would be interested in a datastore backed by redis that mimicked clojure's datastructures:
16:02arohnerand then you only need to compare strings until you find a mismatch
16:02ibdknox(def x (redis-atom {}))
16:02ibdknox(swap! x assoc :r 3)
16:02amalloyedw: sorry bro
16:02jcromartieibdknox: sounds like the perfect interface to a data store if you ask me
16:02jcromartieespecially if it works in a transaction
16:02gfrlogarohner: I'd think if the string is present you'd still have to compare
16:02no_mindI 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:02arohnergfrlog: yes, but only after the hashes match
16:02edwWhat version of Redis are/were you using?
16:03no_mind*function to be passed as argument
16:03amalloy2.0.1
16:03edwWhoa, that was a while ago.
16:03hiredmanI would hope a database would supply something higher level than datastructure operations
16:03amalloyno_mind: almost certainly this should be a function
16:03amalloyedw: so far i haven't had to deploy at all; it's just what apt-get put on my dev machine
16:03ibdknoxhiredman: what do you mean?
16:04ibdknoxhiredman: even a database has to have an add command ;)
16:04hiredmanibdknox: a distributed hash table is not a database
16:04amalloyhiredman: i think he only called it a datastore
16:04no_mindamalloy: ok, and how about passing function name and namespace as single argument ?
16:04ibdknoxhiredman: that was one example, take this as another:
16:04amalloyno_mind: i don't understand the question. just pass the function itself, don't mess around with names
16:05ibdknox(def rlist (redis-atom [1 2 3]))
16:05ibdknox(nth @rlist 2)
16:05ibdknoxbasically it's a persistence mechanism for clojure collections
16:06hiredman*shrug*
16:06ibdknoxusing the wonderful datatypes in redis
16:06ibdknoxthe point was to judge interest more than anything :)
16:06no_mindamalloy: 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:07ibdknoxhiredman: I assume you use a SQL variant?
16:07gfrlogno_mind: you can pass the function itself without worrying about its name
16:07gfrlog
16:07hiredmanibdknox: use for what?
16:07ibdknoxhiredman: persistence? lol
16:08hiredmandepends
16:08scgilardithe fully qualified name would be abc/xyz
16:09hiredmanpersisting datastructures is neat for little apps, or when you are just starting, but not really useful for larger datasets
16:09no_mindgfrlog: the function will not be called under all conditions. Plus the arguments tot he function will be modified before function's execution
16:09dpritchett`oh hi ibdknox
16:09gfrlogno_mind: none of those things require knowing the function's name
16:09dpritchett`i have been enjoying noir this week, thank you
16:10ibdknoxyou're quite welcome :)
16:10ibdknoxhiredman: so anyone using a key-value store is doing it wrong?
16:10gfrlogno_mind: if your function is receiving a function as its argument, it can refer to it by the argument name
16:10dpritchett`now i just need to figure out how to nest clojure.contrib.sql/with-query-results with your common/layout and defpage functions
16:10amalloyno_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:10dpritchett`For some reason the correct ordering is eluding me
16:10hiredmanibdknox: please don't turn my dismissal of your idea into a debate about nosql
16:11no_mindgfrlog: yes it can. But what if the function received is in another namespace ?
16:11gfrlogno_mind: (fn [f a b] (if a (f b) "not calling that function")) for example
16:11ibdknoxhiredman: hm
16:11no_mindamalloy: thanks
16:11gfrlogno_mind: functions don't belong to namespaces
16:11derp_is there an easy way to turn a list of characters into a string?
16:11gfrlogno_mind: so it doesn't matter
16:11scgilardiderp_: use str
16:11derp_I am stuck at (map str (rest "1001"))
16:11amalloyderp_: ##(apply str '(\a \b))
16:11sexpbot⟹ "ab"
16:12no_mindok
16:12ibdknoxhiredman: as you wish.
16:12hiredmanif I want to persist a datastructure I will most likely pr-str it or serialize it and write it to disk
16:12Raynesno_mind: Functions are completely and utterly first class. They are just normal values in Clojure. As normal as a string or an integer.
16:12jcromartierelations and invariants FTW
16:12ibdknoxI was thinking of this more as an interface to redis that looked just like any other clojure code
16:13ibdknoxmaybe that's a better way to think of it :)
16:13hiredmanbut redis is not a clojure datastructure
16:13gfrlogno_mind: Raynes makes a good point -- you wouldn't as what namespace your other arguments "belonged to"
16:13gfrlogs/as/ask
16:13sexpbot<gfrlog> no_mind: Raynes makes a good point -- you wouldn't ask what namespace your other arguments "belonged to"
16:13ibdknoxthere's basically a 1:1 mapping between redis datatypes and clojure's collections
16:13no_mindok
16:13jcromartieibdknox: unfortunately it is only 1:1 as long as the elements of those data structures are compatible
16:14amalloyibdknox: that's rather an overstatement. redis's sorted-sets are a bizarre parody of sorted sets
16:14hiredmanibdknox: I doubt that
16:14jcromartieso, how would you store {:foo 'bar "bat" (java.util.Date.)}
16:14jcromartiepr-str?
16:14gfrlogno_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:14hiredmanjcromartie: are you asking me?
16:14jcromartieibdknox:
16:14amalloythey're definitely a useful structure, but they don't really map onto anything in clojure
16:14ibdknoxyes, the downside is that you can't store types
16:15jcromartiethere is sorted-set in Clojure
16:15jcromartienot sure if that's the same thing
16:15ibdknoxbut that's true of any db
16:15hiredmanhmmm?
16:15no_mindgfrlog: its clear andI am trying the ideassuggested
16:15ibdknoxand that's fair, the semantics between the two are not identical
16:15ibdknoxthe 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:15amalloyjcromartie: i know, but redis's are weird
16:16ibdknoxamalloy: they really are
16:16jcromartieibdknox: I wouldn't discourage you
16:16hiredmanI 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:16jcromartieRedis is what it is, and that interface sounds good
16:16jcromartieat least to me
16:17gfrlogI 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:17hiredman"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:18hiredmanlike a knife
16:18ibdknoxlol
16:19hiredmannext thing you know you don't have a leg to stand on
16:19amalloyhah
16:22jcromartieI am flabbergasted that every part of this trie implementation is basically a one-liner https://gist.github.com/1045515
16:22jcromartieFP FTW
16:23gfrlogjcromartie: that is remarkable. therefore it is appropriate that you remarked.
16:25jcromartievs. http://code.google.com/p/trie/source/browse/trunk/trie/src/net/bcharris/trie/TrieImpl.java
16:25jcromartieor http://code.google.com/p/typocalypse/source/browse/Trie/TrieNode.cs
16:25jcromartieor ...
16:25jcromartieyou get the idea
16:28gfrlogjcromartie: you wrote that code just now?
16:28bsteubercome on, it's unfair to compare it to java or c# code :)
16:28gfrloguser=> (merge (trie/trie "abc") (trie/trie "abd"))
16:28gfrlog{\a {\b {\d {}}}}
16:28dpritchettthis is by far my favorite part of noir so far ibdknox https://github.com/ibdknox/noir/blob/master/src/noir/server.clj#L8
16:29gfrlogoh ha
16:29gfrlogI'm using clojure.core/merge :)
16:29dpritchettthat is sweet behavior i had not expected
16:29gfrlogno wonder it don't work
16:29ibdknoxgotta have a good development experience ;)
16:29jcromartiegfrlog: yeah
16:29ibdknoxthrow an exception on purpose some time
16:30jcromartiegfrlog: maybe I should use merge instead of merge+
16:30ibdknoxit highlights the parts of the stack that are in your code, if you have the :ns property set when you start the server
16:30jcromartieor merge-trie
16:30gfrlogjcromartie: I'm not familiar with the data structure -- if I merge "abc" and "abcd", should it contains? both of them?
16:30jcromartieyes
16:30gfrlogk, might wanna work on that then :)
16:31gfrloguser=> (trie/merge+ (trie/trie "abc") (trie/trie "abcd"))
16:31gfrlog{\a {\b {\c {\d {}}}}}
16:32jcromartiehuh
16:32jcromartieworks over here
16:32gfrlogI'm using https://gist.github.com/1045515
16:32jcromartieah ha
16:32gfrlog(search t "abc") => {\d {}}
16:33jcromartieyeah I see
16:33jcromartiebecause it's not accounting for the terminator in abc
16:34aaelonyhi, 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:34aaelonyThe 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:35duck1123Has 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:35jcromartiegfrlog: I don't think contains? should exist, or it should be (not (nil? (search t s)))
16:35gfrlogaaelony: you could add a second clause after (if (map? m)) that checks if it's a collection
16:35gfrlogaaelony: I guess it could only be a vector right? so check if it's a vector and if so map it over keywordify
16:35gfrlogjcromartie: I like the terminator idea
16:35duck1123it gets a bit more complicated with my using aleph and 1.3
16:35aaelonyi think it will be a vector
16:36aaelonythanks, gfrlog
16:36jcromartieaaelony: actually let me rework that keywordify
16:36gfrlogjcromartie: so contains? would check if the resulting map has the terminator as an element
16:37gfrlogjcromartie: you could even make it all safe by using a unique (new Object) instead of nil or anything else
16:37ibdknoxduck1123: servers often have upload memory limits
16:37aaelonythanks jcromartie
16:37gfrlogisn't there a keywordize-keys function somewhere?
16:38gfrlogmaybe not...
16:38ibdknoxgfrlog: I think ring actually has one
16:38amalloygfrlog: clojure.walk, i think?
16:38gfrlogclojuredocs doesn't return one
16:38gfrlogoh but walk does have it
16:39gfrlogaaelony: try clojure.walk/keywordize-keys
16:39aaelonychecking, thanks
16:39duck1123wrap-keyword-params
16:39gfrlog(dec clojuredocs)
16:39sexpbot⟹ -1
16:39ibdknoxhttps://github.com/mmcgrana/ring/blob/master/ring-core/src/ring/middleware/keyword_params.clj
16:39jcromartielike a boss, gfrlog
16:39ibdknoxlol
16:40aaelonyit says "Recursively transforms all map keys from strings to keywords." I wonder if it allows for nestings with vectors...
16:40gfrlogaaelony: try it :)
16:40duck1123I don't believe it does
16:40aaelonylooks great
16:40aaelonyvery nice
16:40aaelonyat least for me mangy data structure :)
16:41aaelonys/me/my/
16:41sexpbot<aaelony> at least for my mangy data structure :)
16:41jcromartieaaelony: it does
16:43jcromartiegfrlog: you'll be pleased to know that fixing trie/contains? involved changing two lines
16:44gfrlogjcromartie: you'd have to fix trie/trie as well, right? to add a terminator?
16:45jcromartieupdated https://gist.github.com/gists/1045515/edit
16:45ibdknoxthat link redirects
16:46ibdknoxwe can't edit it ;)
16:46jcromartieoops
16:46jcromartieherp derp https://gist.github.com/1045515
16:46ibdknoxthat really is impressive
16:46ibdknoxtries are fun
16:46gfrlogjcromartie: ::terminator is gooder idea than (new Object)
16:47jcromartieand I even spelled it right (some blub implementation had "Terminater")
16:48gfrlogha
16:48jcromartiemakes me think of a cybernetic potato for some reason
16:48jcromartieis it idiomatic for predicates to return true or false, exactly?
16:48jcromartieor is true or nil good enough?
16:49gfrlogjcromartie: considering the sorts of things that people use for predicates, I'd say you can return any dang thing you want :)
16:49jcromartiehah
16:49jcromartieour database uses -1 for true
16:49jcromartie0 or NULL for false
16:49jcromartiefun times
16:49gfrlogthat's fantastic
16:50gfrlogif I want to restrict a predicate I just pass it through (boolean) at the end
16:52jcromartieah
16:52jcromartiegood idea
16:53jcromartieI was reading this today http://dev.clojure.org/display/design/Library+Coding+Standards
16:53jcromartiepretty good advice in general
16:53dpritchettis the @ dereference operator in clojureql standard clojure or specific to this library?
16:53dpritchett(clojureql.core/table :posts) gives me a sql statement, if i prepend a @ it gives me the results
16:53Raynesgfrlog: Or true?
16:53Raynes:D
16:54gfrlogRaynes: uhhh...huh?
16:54Raynesgfrlog: And then pretend that doesn't cause bugs.
16:54dpritchettnevermind, found it myself on the clojure docs
16:54gfrlogoh okay. I can pretend.
16:55gfrlogRaynes: may as well use (not) while we're at it
16:55gfrlogboolean is clojure for !!
16:56amalloygfrlog, jcromartie: i prefer (Object.) to ::terminator, fwiw
16:56jcromartieamalloy: what's your reason why?
16:56gfrlogamalloy: whyso? Isn't it a perfect example of qualified keywords?
16:56hugodstuartsierra: 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:56gfrlognot to mention it's using clojure stuff instead of jvm stuff
16:57amalloyjcromartie: 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:57amalloywhereas if you use an (Object.) you can guarantee nobody will ever put it in there
16:57jcromartieamalloy: there's a problem with (Object.)
16:57gfrlogamalloy: when would you ever want to use a qualified keyword outside your own namespace?
16:57amalloygfrlog: plenty of reasons
16:57jcromartieand you couldn't really serialize it
16:58amalloyjcromartie: that's a fair point
16:58gfrlogI say anybody who does such a thing deserves his fate
16:58bsteubereverything that's not a char and easy to compare is okey, isn't it?
16:58gfrlogalso something something about plenty of room in the prisons
16:58bsteuberso my favorite would be nil as terminator
16:58amalloybsteuber: ergh
16:59jcromartienil might be a good idea
16:59jcromartieassuming you can use nil as a key?
16:59amalloydon't use nil as a map key. it's horrible
16:59gfrlogbut wanting to store seqs with nil is much more plausible
16:59amalloyjcromartie: 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:59jcromartiehah
17:00stuartsierrahugod: Perhaps. For now it's convenient on the build server, and your local dependency should override it.
17:00bsteuberah true, you can use tries for any sequential data
17:00amalloySome 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:00bsteuberso ::terminator or just ::end is best
17:00gfrlogor ::__TERMINATOR__ just to be safe
17:01jcromartie::__PRIVATE__*TERMINATOR*__DO_NOT_USE
17:01gfrlogmaybe with a guid at the end :)
17:01hugodstuartsierra: just worried about 1.2 compatability being tested/lost
17:02stuartsierrahugod: It's true we need more tests across versions. I have to figure out how best to do that on Hudson.
17:02stuartsierraBut please file bugs if anything is not 1.2-compatible.
17:02amalloyjcromartie: 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:03gfrlogjcromartie: time to box all your keys. 1 more line per function.
17:04bsteuberamalloy: good to know, always thought nil is as good as any other value
17:04gfrlog,({nil "tom" :jill "bob"} nil)
17:04clojurebot"tom"
17:05gfrlog,(let [m {nil "tom" :jill "bob"}] [(.get m nil) (.get m :jill)])
17:05clojurebot["tom" "bob"]
17:06amalloy&(clojure.string/replace-first "test" #"q" identity)
17:06sexpbot⟹ nil
17:07amalloydoes this seem crazy to anyone else?
17:07gfrloghmmm....maybe not
17:07gfrlogsince you want to replace exactly one thing, you might be interested to know that it wasn't there
17:08jcromartiegfrlog: is there a standard way to box values?
17:08gfrlogjcromartie: dunno. I'd stick'em in a vector maybe?
17:08gfrlogthen use first to access
17:08amalloywait why are we boxing things?
17:08jcromartieit looks like a box
17:08gfrlogamalloy: so he can have nil keys
17:08jcromartie(defn box [x] [x])
17:08gfrlogha
17:09gfrlognow make a macro to get rid of that redundancy
17:09gfrlogjcromartie: (def box vector)
17:09gfrlog(def unbox first)
17:09amalloy(defmacro identity-function [name args-and-body] `(defn ~name ~@(repeat 2 args-and-body)))
17:10jcromartieI was going to say
17:10jcromartiedefredundant
17:10jcromartietotally worth it
17:10gfrlog(defmacro defaboxingfn ...)
17:12gfrlogamalloy: so you don't object to having [nil] as a key?
17:12amalloygfrlog: in most circumstances i suspect it's silly, but there's nothing wrong with it
17:12gfrlogjcromartie: now that I think about it, list might be better than vector for performance
17:13gfrlogI don't know how much ceremony small vectors create. maybe it's nothing
17:14jcromartieBTW, there's no unboxing required
17:14jcromartiejust (map box s)
17:14jcromartiefor the lookups
17:15gfrlogjcromartie: oh right. I guess you never have to return actual values
17:15edwamalloy: 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:15gfrlogedw: no problem, just (binding [9920 9220] ...)
17:16edwDoesn't that only work in Fortan?
17:16gfrlog:)
17:16jcromartiegfrlog: anyway the gist is updated... this was a distraction, even if it was a fun one!
17:17gfrlogjcromartie: w00p
17:17gfrlogI love how clojars keeps the pushing instructions front and center
17:17jcromartiereal work is never so interesting
17:17gfrlogjcromartie: nope :(
17:18jcromartienow 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:18ibdknoxjcromartie: the pain.
17:19ibdknoxit should be illegal really.
17:19rbuchmann(inc gfrlog)
17:19sexpbot⟹ 3
17:19rbuchmann:)
17:19gfrlogthree!
17:20gfrlogthat's my mostest ever
17:20rbuchmannquick, someone dec him :-p
17:20edwjcromartie: 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:20amalloyrbuchmann: the power...is yours!
17:20jcromartiehah hah
17:21rbuchmann^^
17:21jcromartieat least the conversion I have to do is scripted
17:21dpritchettjcromartie what are you scripting it with
17:22jcromartiejust bash
17:23jcromartielater y'alls
17:23gfrlogbye
17:23jcromartie(but I do love me some Rake)
17:23matthias_what;s an abstract method error?
17:24hiredmanmatthias_: often means you are calling an abstract method
17:25clizzinhey 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:26gfrlogclizzin: those first two points are all I know of.
17:31VT_entityhey all, I was wondering if you could help me with a tricky error
17:32gfrlogVT_entity: continue
17:32Raynes~anyone
17:32clojurebotPlease 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:32VT_entity(if (<= 0 (count examplelist))
17:32VT_entity ;figure out a way to use let instead of an inline def here
17:32VT_entity ((conj newlist (+ 1 (peek examplelist))) (def examplelist (pop examplelist))))
17:32gfrlogRaynes: I thought of that but he didn't use the word "anyone" :)
17:32VT_entitythanks clojurebot, that's not condescending at all.
17:32RaynesStill applies. :p
17:32VT_entitylol
17:32gfrlogVT_entity: he said please at least
17:33gfrlogVT_entity: that (<= 0 (count ...)) should always be true right?
17:33VT_entityit's giving me "clojure.lang.PersistentList cannot be cast to clojure.lang.IFn"
17:33amalloyyes, that's the (( construct
17:34VT_entityyou mean I have too many parens?
17:34gfrlogVT_entity: yes
17:34amalloyno
17:34gfrlogmaybe
17:34Raynesinpossible
17:34gfrlogalways
17:34VT_entityhahahaha
17:34Raynesimpossible, even.
17:34amalloyif you *wanted* to do it that way, you need (do (thing1) (thing2)), which is the same number of parens
17:35amalloybut the approach is evil and sinful anyway, as you noted since you came to ask for help
17:35VT_entityI thought the do was implied? if evaluates whichever predicate based on whether it's true or false
17:35amalloyno
17:36VT_entityso I need (if (foo?) (do (bar))
17:36dpritchettQuick 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:36gfrlogVT_entity: no (if (foo?) (bar))
17:36dpritchetti'm messing with noir and hiccup, trying to turn my simple map into a series of vectors
17:37VT_entitythat's what I figured, amalloy wants me to use do, but I wasn't sure if I needed it.
17:38rbuchmannif bar is several statements, you need do
17:38gfrlogdpritchett: ##(mapcat (fn [{:keys [id content]}] [[:h1 id] [:p content]]) '({:id 1 :content "hey"} {:id 2 :content "there"}))
17:38sexpbot⟹ ([:h1 1] [:p "hey"] [:h1 2] [:p "there"])
17:38amalloy&(mapcat (fn [{:keys [id content]}] [[:h1 id][:p content]]) '({:id 1 :content "hey"} {:id 2 :content "there"}))
17:38sexpbot⟹ ([:h1 1] [:p "hey"] [:h1 2] [:p "there"])
17:38dpritchettthanks
17:38gfrlogamalloy: are those completely identical?
17:38amalloy*nod*
17:38gfrlogwhat does this mean???
17:39amalloythat i forgot to use juxt
17:39gfrlog:D
17:39lancepantzhahah
17:39gfrlogman we even put the keys in the same order
17:40amalloygfrlog: it's the natural order
17:41gfrlogwhyso?
17:41amalloybecause id is first in his example map, and also used first in the desired result
17:41gfrlogI guess so
17:41dpritchettthat function worked first try when i dropped it into my code, thanks again
17:41gfrlogand we both used parentheses
17:41dpritchetti feel a little dirty now
17:41amalloygfrlog: ?
17:42gfrlogamalloy: nothing
17:42gfrlogamalloy: it made no more sense than it appeared to
17:42VT_entityoh, 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:42VT_entity(def examplelist '(1 2 3 4 5))
17:42VT_entity(def newlist ())
17:42dpritchetti got my mobi/epub copies of Joy of Clojure via email yesterday. i'll dig up :keys again while i'm reading
17:42VT_entity
17:42VT_entity(if (<= 0 (count examplelist))
17:42VT_entity ;figure out a way to use let instead of an inline def here
17:42VT_entity (do (conj newlist (+ 1 (peek examplelist))) (def examplelist (pop examplelist))))
17:42amalloyVT_entity: https://gist.github.com
17:43VT_entityoh, interesting
17:43gfrlogamalloy: no way did you type out that entire url with the https before he finished pasting
17:43amalloygfrlog: wtf, of course i did
17:43gfrloggosh dammit
17:43gfrlogyou've got a bunch of clever emacs doohickeys
17:43amalloygfrlog: using pidgin
17:43gfrlogemacs has pidgin now? :P
17:43amalloy(i know, right? not hardcore enough at all)
17:45VT_entityok, I just posted it: https://gist.github.com/1045758
17:45gfrlogmuch nicer on the eyes
17:45gfrlognext time give it a name that ends in ".clj" and it'll color everything pretty
17:45VT_entityoooh
17:46VT_entitythere we go
17:46VT_entity.clj
17:46RaynesI don't understand how amalloy can function with Pidgin as an IRC client.
17:46rbuchmannwow, what is that supposed to do?
17:46gfrlogVT_entity: anyhow, you're not looping at any point, so there's no reason for it to do anything more than once
17:46hiredmandigusting
17:46VT_entityI figured the conditional statement would continue the loop as long as the count of the members of examplelist remains above 9
17:46rbuchmannah, reading descriptions helps :-/ Sorry about that
17:46VT_entity0*
17:47VT_entityah, i'll try to add in recure
17:47VT_entityrecur*
17:47gfrlogVT_entity: look at (loop) also
17:47rbuchmannyou'll need something to recur to
17:47rbuchmann(if ...) is not it
17:48amalloyRaynes: i know, i risk making myself an outcast just by mentioning it
17:48VT_entityaaah I understand
17:48dpritchetti'm using xchat on windows
17:48VT_entitywhat if I name the function and make if recur back to itself
17:48dpritchetti don't *love* it but it required a tad less manual reading than irssi
17:48dpritchetthonestly i miss mirc from ten years ago
17:48rbuchmannthat'd word
17:48rbuchmann*work
17:48rbuchmannwhat are you actually trying to do?
17:48VT_entityprobably blow the stack, not optimized I guess
17:49amalloyi think he's just implementing ##(map inc '(1 2 3 4 5))
17:49sexpbot⟹ (2 3 4 5 6)
17:49VT_entitywell, my friend and I were talking about whether it's possible to do something like FOR EACH in a purely functional way.
17:49rbuchmannofcourse
17:49VT_entityso, we came up with the idea of incrementing each item in a list by one.
17:49rbuchmanneither (map ...
17:49rbuchmannor doseq
17:49amalloyrbuchmann: doseq isn't very functional
17:50hiredman~people
17:50clojurebotmax people is 317
17:50amalloy&(for [x [1 2 3 4 5]] (inc x))
17:50sexpbot⟹ (2 3 4 5 6)
17:50rbuchmannnot much worse that recur though :)
17:50VT_entity@______@
17:50dpritchettoh no, a noir patch?
17:50VT_entityoh damn amalloy
17:50ibdknoxjust pushing the latest unstable build
17:50ibdknoxfor those who wish to follow along
17:51hiredman~#7
17:51clojurebot7. It is easier to write an incorrect program than understand a correct one.
17:51VT_entitywait, what's the ampersand?
17:51hiredmanrbuchmann: how is recur not functional?
17:51amalloytells sexpbot to start paying some damn attention
17:51VT_entityoooooh
17:52rbuchmannin a style kind of way :hiredman :)
17:53VT_entityah, but the for is still kind of a FOR EACH isn't it.
17:53hiredmanrbuchmann: what does that mean?
17:53hiredmanloop/recur is a *functional* looping construct
17:54rbuchmannhiredman: of course
17:54rbuchmannnvm :)
17:57ibdknoxI 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:57ibdknox*shrug*
18:11gfrlogibdknox: loop/recur could be done as a higher-order function. I think it's just harder to reason about than other expressions
18:11gfrlog(map) is much easier to understand than the equivalent thing done with loop-recur
18:11ibdknoxgfrlog: very true
18:12gfrlogI should say harder to reason about when there are simpler/other ways of expressing the thing
18:12gfrlogcertainly sometimes loop is the simplest thing to do
18:12gfrlogmaybe that was tautological... :(
18:12ibdknoxhaha
18:13ibdknoxin general, it's true
18:13ibdknoxthat's good enough I think ;)
19:16matthias_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:16matthias_wtf
19:30bsteubermatthias_: "no such namespace" means you need to require/use the namespace, so this makes perfect sense to me
19:31matthias_the namespace is created in the file i'm trying to compile
19:31bsteuberhmm ok, that makes less sense :)
19:32hiredmanmatthias_: what do you mean by compile?
19:32matthias_C-c M-k
19:32matthias_C-c C-c gives me the same error
19:33hiredmanC-c C-k
19:33matthias_ok, wtf
19:33matthias_tried it again and it works
19:34matthias_hmm, C-c C-k works too.
19:34hiredmanC-c C-c will try to run the toplevel form under the cursor in the namespace of the file you are in
19:34hiredmanit will fail if the namespace doesn't exist
19:34matthias_the menu says that's Compile/Load file as opposed to compiel file
19:34hiredman(before compiling)
19:34hiredmanuse C-c C-k
19:34matthias_oh
19:35matthias_so it worked later because i had typed (use 'blabla) in the repl and that compiled it?
19:35hiredmanmost likely
19:35matthias_so that actually makes sense
19:36matthias_thanks :p
19:36hiredmanI 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:37matthias_what does compile and load mean?
19:37bsteuberI expected the two to be synonymous, but maybe they're not
19:37hiredmanthey are for clojure
19:38bsteubersure, for CL it's different
19:38matthias_synonymous? so "compile" doesnt work, but "compile and compile" does? ;)
19:38hiredmancompile is code generation, load is loading (and running) code
19:38hiredmanso, like, for c compiling and loading are very different
19:40matthias_so C-c C-k would run a c program after it's done compiling?
19:41hiredmanC-c C-k is just compile, so it would just compile it to object code or an executable of some kind
19:41hiredmaner
19:41hiredmanC-c M-k
19:41hiredmanC-c C-k would compile and then run it
19:43jcromartieso, has Hiccup won? or what?
19:44jcromartieI don't hear much about enlive, as powerful as it is
19:44jcromartieit seems like Hiccup is easier
19:44amalloyjcromartie: i like hiccup. real web developers like enlive
19:44jcromartie"Real web developers" huh?
19:44jcromartieI am tempted to go with StringTemplate
19:44hiredmandepends if you are looking for templating or just something better then concating strings
19:45scottjjcromartie: ppl other than weavejester :)
19:45gfrlogI lost my ability to write <html> when the rails folk switched to haml; so I use hiccup.
19:45jcromartiehah, Haml is great
19:45gfrloghaml doesn't feel very much like clojure though
19:45jcromartiewell, it was nice being here
19:45jcromartiebye
19:45jcromartie:)
19:45amalloyjcromartie: 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:46jcromartiescrabble
19:46gfrlogjcromartie: scrabble
19:46gfrlogoh I didn't see the typo; I thought "playing scrabble" had something to do with saying "scrabble"
19:46gfrlogso I was joining in
20:28matthias_,(update-in {:test "bla"} [:test] #(%))
20:28clojurebotjava.lang.ClassCastException: java.lang.String cannot be cast to clojure.lang.IFn
20:28matthias_why is that?
20:29matthias_oh it works if i use (fn [s] s). thought that would be the same
20:29hiredman,(macroexpand '#(%))
20:29clojurebot(fn* [p1__803#] (p1__803#))
20:30dnolen,(update-in {:test "bla"} [:test] identity)
20:30clojurebot{:test "bla"}
20:34matthias_i dont understand why #(%) doesnt work
20:34hiredman,(macroexpand '#(%))
20:34clojurebot(fn* [p1__808#] (p1__808#))
20:34matthias_yeah i saw that
20:35hiredmanwell, there you go
20:35matthias_doesnt tell me anything :p
20:35hiredmanuh
20:35hiredmanyou can read the code right?
20:36matthias_i dont know what fn* is. looks like its calling its argument though. which is strange. cause i dont think its supposed to
20:36hiredman,(macroexpand '(fn [x] x))
20:36clojurebot(fn* ([x] x))
20:36hiredmanthat is exactly what #() is
20:38matthias_i must have learned that wrong... but i've been using that # syntax for a while now... ;) (still a clojure newb though)
20:38hiredmanif that is not what #() is, what would #(str %) expand to?
20:39matthias_oh
20:39dnolen,((fn [x] x) "foo")
20:39clojurebot"foo"
20:39dnolen,((fn [x] (x)) "foo")
20:39clojurebotjava.lang.ClassCastException: java.lang.String cannot be cast to clojure.lang.IFn
20:39hiredmanif #(%) expanded to (fn [x] x) then #(str %) would be (fn [x] str x)
20:40hiredmanhardly seems useful
20:41amalloymatthias_: fwiw, what you meant by #(%) is just identity
20:50amalloyseancorfield: interesting. what've you changed in congomongo?
20:53seancorfieldadded 1.3 support
20:54seancorfieldthe 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:55seancorfieldevery other library we depend on is already in a public repo... except congomongo 0.1.5-SNAPSHOT :(
20:56seancorfieldideally, i'd have update permissions on the existing congomongo group on clojars but...
21:00matthias_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:01dnolenmatthias_: that sort of thing is why people use paredit, or a Lisp-aware text editor.
21:01seancorfieldmost of us use an edit mode that balances parens automatically
21:01seancorfieldi use eclipse + ccw
21:02matthias_yeah i use one too. still dont like it.
21:03seancorfieldoh, so you mean some magical syntax that means "close all open parentheses"?
21:03matthias_yeah
21:03seancorfieldlike... #) ...?
21:03seancorfieldas an example
21:03matthias_yeah
21:04matthias_i'm sure its a bad idea for some reason... ;)
21:04amalloyseancorfield: i've heard of some lisps that use ] for that
21:04amalloybut yes, it's a bad idea
21:04matthias_why?
21:04clojurebotwhy not?
21:04seancorfieldamalloy: i had some vague recollection of reading something about that once...
21:04amalloymatthias_: it would be so easy to make mistakes when editing the code
21:05seancorfieldwell, for a start () is a form but ((] looks... wrong... and doesn't balance
21:05amalloyeg, (defun do-stuff (x) (whatever x]
21:05amalloythen later you decide this should be placed inside a closure, or a CLOS class
21:05seancorfieldyeah, then you need to balance the parens anyway
21:06seancorfieldto be honest, i really don't notice the parens these days
21:06amalloyseancorfield: and if you forgot, the error messages would likely be pretty bad
21:06seancorfield:) yup
21:07seancorfieldand it's not like lisp / clojure has the best error messages in the first place
21:07clizzinwhat'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:07clizzinfor clojure projects
21:07seancorfieldwhere would you prefer to keep it?
21:07matthias_really? if you had something like ] bla bla), it should be able to tell you exactly what's wrong i think
21:07clizzinseancorfield: in something like a yml file
21:07clizzinin project root
21:07amalloymatthias_: not so! bla and bla would have compile errors before it got to )
21:07amalloymatthias_: anyway the main thing i'd dislike is the way it makes later editing a landmine in all kinds of ways
21:07seancorfieldso you'd need to read the file at startup...
21:07clizzinit would live only on the app server and in dev environment but not in the repo
21:07clizzinyup
21:08clizzini feel like leiningen supports this somehow, but i don't remember how it's done anymore
21:08amalloybut really, what is the *gain* of having ] anyway? you'd still need to stack up ))))) quite often
21:09seancorfieldwe use a clojure map for our configuration ... and so it is in our source code
21:09amalloy$google clj-config
21:09sexpbotFirst out of 8100 results is: marklazz/clj-record-blog - GitHub
21:09sexpbothttps://github.com/marklazz/clj-record-blog
21:10amalloyhrm
21:10amalloywell, Raynes wrote a super-lightweight config library. it basically just reads from ./config.clj
21:11RaynesIt reads from whatever file you want it to. It's just a wrapper around slurping/spitting etc with some convenience functions.
21:11seancorfieldhttps://github.com/Raynes/clj-config
21:11RaynesI wrote it 100 years ago.
21:11clizzinhaha
21:11amalloyRaynes: "basically", in context meaning "whatever i want it to mean"
21:11seancorfieldmay 3rd 2010 was the first commit :D
21:12clizzinsounds like i should just do my own thing
21:12seancorfieldwe have all the system configs in one environments.clj file and automatically select the appropriate one, based on hostname, at startup
22:02dnoleninteresting, parsing with monads can be slow, http://carlo-hamalainen.net/blog/2011/02/11/parsing-with-monads-can-be-slow/
22:04dnolenI'm assuming Parsec has optimizations to get around this, wonder what similarities they have to optimizing DCGs if any.
22:06Scriptorreading about the difference between next/more here
22:06clojurebotCool story bro.
22:07Scriptorso basically, calling seq() on a sequence forces the evaluation of the first element of that sequence?
22:07dnolenScriptor: yes
22:11Scriptoraha
22:24amalloyScriptor: 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:24amalloyso 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:25amalloythere 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:31amalloygfrlog: in common lisp: (defun count (seq) (if seq (1+ (count (cdr seq))) 0))
22:31amalloygfrlog: doesn't work in clojure, because empty seqs evaluate to true
22:32amalloythe "pun" is treating an empty sequence as false
22:33gfrlogI guess I cdr get it...