#clojure logs

2014-08-16

01:03eric_normandanyone going to the conj want to split a room?
01:04ClariceYes, split a room with a total stranger you meet on IRC.
01:05abaranoskyClarice: be a bummer why don't ya
01:05Clarice:)
01:05technomancywe're like a big family in #clojure
01:05technomancy~group hup
01:05clojurebotI don't understand.
01:05Clarice(inc clojurebot)
01:05lazybot⇒ 42
01:06abaranoskybest way to meet people
01:06ClariceIs that a fixed number?
01:06ClariceIs that a fixed number?
01:06Clarice(inc clojurebot)
01:06lazybot⇒ 43
01:06abaranoskyor die
01:06ClariceOh! No, better keep it at 42.
01:06Clarice(dec clojurebot)
01:06lazybot⇒ 42
01:06abaranoskyhow bad could it be
01:06technomancysome day we hope to have the technology to help you understand, clojurebot
01:09TEttingereric_normand: try couchsurfing?
01:09abaranoskywhat do you all think of transducers?
01:09TEttingerthey're just as much people as cisducers
01:09ClariceHahahahah
01:09Clariceabaranosky: I think they're pointless.
01:10TEttingerI haven't used reducers yet, but I see their point
01:10eric_normandTEttinger: hmm. now that would be a total stranger.
01:10TEttingereric_normand, yes but #clojure doesn't have reviews of strangers
01:11abaranoskyClarice: I See they're designed so they can be used with sequences and also channels... I haven't looked into how they could be used with other types of things
01:11abaranoskywould it be possible to make them work with other things like futures or promises?
01:13TEttingerabaranosky: megaducers in 1.8.0
01:13ClariceA promise is not a collection.
01:13TEttingerwe're just going to get ducing all over
01:13TEttingerevery version a new *ducer
01:14mthvedti demand recursively enumerable ducers
01:14TEttingerduceducers
01:14TEttingerparaducers, xenoducers
01:15mthvedtnonconstructable ducers
01:15Clariceepiducers
01:15abaranoskyyeah sucks... I wish if they'd made a general abstraciton it could've been truly general
01:15abaranoskylike in other languages you can map over a future, which is what I was thinkin gof
01:15TEttingerthe first being a transducer that runs in parallel to another transducer, the second like F#'s type downloader thing that can transduce over unknown data
01:16ClariceYou can't map over a future in clojure?
01:16abaranoskyI hadn't read the implementation of reducers enough to know if it was collection-specific
01:16abaranoskyClarice: no
01:16abaranoskyClarice: futures are very thin wrappers around java Futures
01:17ClariceWhy don't you force the future when you come across it?
01:17TEttingerpanducers, which generate mexican pastries whenever you run them
01:18TEttingeromniducers, which run over your entire program
01:19Clariceabaranosky: As in, why doesn't the function you map with just call future? on its argument, and if true... you dereference its value.
01:19abaranoskyClarice: I'm not sure I understand your question?
01:19abaranoskyit doesn't do that because CLojure doesn't work that way.
01:20abaranoskymap would need to be specified as part of some Functor protocol
01:20abaranoskyTEttinger: I like it, keep em coming
01:21TEttingerswearducers, which turn your program into swearjure and then overwrite the file
01:21TEttingerpreducers, which run before you start the program to evade JVM startup
01:22TEttingertheoducers, which work if you believe they will
01:23TEttingerfranzducers, which if the process is killed, start a world war
01:26TEttingerchronoducers, which manipulate how the rest of your program perceives time
01:27TEttingerschroducers, which are both running and not running simultaneously until dereferenced, at which point your program collapses
01:30TEttingerinducers, which make your program do things it would really rather not do
01:31TEttingerdeducers, which are just a fancy name for core.logic
01:32TEttingerLANducers, which distribute your program over every gaming console in the immediate vicinity
01:33TEttingertreeducers, which brick your computer to stop wasting electricity
01:34TEttingerviducers, which are exactly like transducers but only work if you edit the code in vi or vim
01:35TEttingerbiducers, which are simultaneously two different types of *ducer
01:35TEttingertriducers, which are simultaneously 3, and WHYducers, which are simultaneously all of them
01:38TEttingerI'm done ducing
01:38justin_smithduck duck transduck
07:38justin_smith$ping
07:38lazybotjustin_smith: Ping completed in 0 seconds.
07:39justin_smithwow, exactly 6 hours, that wasn't on purpose
09:28luxbockwhen I use (read-line) in my Emacs nREPL I get prompted for input, but the function hangs after that
09:29luxbockbut the next time I call it, the it returns the thing I typed in the previous prompt
09:29luxbockis there some way to make act normal?
09:35justin_smithworks like normal here, what version are you using?
09:36luxbockClojure 1.6.0, cider 0.8.0-SNAPSHOT
09:36justin_smithnrepl 0.2.0 doesn't have that bug (and the Clojure version should be irrelevant here)
09:36justin_smithmaybe #clojure-emacs can help, or you could open an issue on the cider github?
09:37luxbockit works fine when I run it from `lein repl`
09:37luxbockyeah I'll do that
09:38justin_smithI maen nrepl.el 0.2.0, in case that wasn't clear
09:38justin_smithsome day cider will have a stable enough version that I'll feel like migrating, maybe
09:57visofquit
11:09jonasenHi! Is it possible to configure the Clojure repl to not print the return value of a repl interaction?
11:09jonasenlike this: https://www.refheap.com/89224
11:10jonasenand with "the clojure repl" I mean any of them (REPLy, the built in one, etc..)
11:13justin_smithso you don't want return values, only printouts? why not create a fifo, open the fifo for writing, and set that as *out*?
11:13justin_smithI don't know if anything like that exists in nrepl though
11:15jonasenjustin_smith: not totally sure what you mean with "fifo"
11:15justin_smitha fifo is a special file that only exists for immediate IO
11:15justin_smithfile-in-file-out
11:15justin_smitha kind of socket
11:19justin_smithnever mind, it's simple than that
11:20justin_smith(defn quiet-repl [] (while true (eval (read)) (print "=> ") (flush)))
11:20justin_smiththen run (quiet-repl)
11:20justin_smithfor bonus points, instead of true, you can check an atom that tells it whether you are done with the quiet repl or not
11:21jonasenjustin_smith: That's great! thank you.
11:21justin_smiththat doesn't bind *1 / *2 etc. though, and it doesn't let you use the built in readline
11:21justin_smithbut I guess it might be good enough
11:22jonasenand it breaks repl history
11:22jonasenit's at least a starting point
11:22justin_smithyeah, the history is part of readline
11:22justin_smithmake readline work, and you get history back
11:23justin_smithor you could just use rlwrap (if it exists for your platform)
11:24jonasenrlwrap works fine
11:25justin_smithpst still works
11:25justin_smithand *e
11:26justin_smithoh, I think pst only worked because we did not have a try catch, so the exception threw me back into a normal repl
11:27justin_smithso yeah, you may or may not want a try catch around that while
11:27acagle1exit
11:27acagle1hostname
11:27justin_smithls
11:27lazybotbin dev lost+found mnt proc root run sys
11:45_ggherdovhi. I am toying around trying to build a server that offers a REST api. I am following this tutorial from 2010, but the dependancies in project.clj are outdated http://mmcgrana.github.io/2010/08/clojure-rest-api.html
11:45_ggherdovwhat was that site where I can check all latest versions of modules?
11:45justin_smith_ggherdov: you could use that as is, and then run "lein ancient" to list latest versions
11:45justin_smithno need to go to any website
11:45_ggherdovok thanks justin_smith
11:46justin_smithnp
11:47justin_smithalso, you could start with "lein new compojure my-app"
11:47justin_smithand then adapt that result to the tutorial
11:47_ggherdovok
11:47justin_smiththat would be much less work actually
11:47justin_smiththough lein ancient is good if you have an actual project to update, and not just a tutorial to follow
11:49justin_smithalso, best of luck, and don't be shy to come back with any questions, this is channel is very open to newcomers to the language, and many of us have professional experience making clojure REST services (myself included)
11:50_ggherdovjustin_smith: thanks!
12:56jdkealyin om, if i had a root view that dispatched main-view routes (and had the nav-bar up top), and if i transact on one of the views that it calls, is there any way to get the views it calls to update on an om/transact without having the parent dispatcher view also re-update ?
12:59rbolkeyhas anyone written a transit handler (assuming it's possible) for writing datomic EntityMaps?
13:31jumblemuddleProbably a old question around here, but I'll ask it anyways. As far as I can tell there are two main web servers for clojure (compojure and ring). Are there any benefits to learning one over the other? I know that I can probably easily migrate to a different one in the future, but I figured I'd ask.
13:31llasramjumblemuddle: compojure is a routing library built on top the ring abstraction
13:31llasramAnd neither are servers
13:32jumblemuddleOh, then I'm definitely lost. Is compojure the standard then?
13:32llasramRing an abstraction for describing HTTP requests and responses as (mostly) just Clojure data. This lets HTTP service handlers just be plain functions which accept request data and return response data
13:33llasramCompojure is a library which lets you build a handler composing other handlers, choosing the backing handler to dispatch to based upon routing criteria in the request (such as the request path)
13:34llasramPretty much everything in the Clojure Web ecosystem uses Ring, and there's a spec describing how HTTP requests and responses map to Clojure data for ring
13:35llasramCompojure is the defacto standard routing library, but there are others
13:36jumblemuddleAlright, so compojure is a web framework? I've seen a lot of other clojure web frameworks. (Pedestal?) I just want to make sure I'm starting off on the right track.
13:36justin_smithCompojure is more of a utility than a framework
13:37llasramClojure doesn't really have a standard end-to-end web framework. For the most part there are lots of little libraries speaking common abstractions, which you then glue together yourself
13:37justin_smiththe f-word is not super popular in the clojure world
13:37llasramPedestal is its own thing, not built on top of Ring
13:37llasramThe closes thing to a common-core Web framework is probably Luminus http://www.luminusweb.net/
13:38llasramBut not even really as Luminus itself -- more that the libraries it glues together are (generally) the most popular
13:38jumblemuddleAlright, thanks. I think I'm understanding it now. So, starting off with compojure is a good idea?
13:38llasramIt's definitely a good place to start
13:39llasramI'd honestly start with plain Ring. You probably won't use it to build full applications on its own
13:39justin_smithjumblemuddle: also if for some reason you really miss ORM RoR / Django style development, Caribou is out there (I contributed extensively to it, though I would never have made something like that from scratch - it was made as an RoR replacement by a previous employer of mine)
13:39llasramBut it'll give you an understanding of the underlying abstractions
13:40jumblemuddlellasram: That seems like a good idea. I'll go look into that.
13:40justin_smithplain ring is a good idea; yeah, routing is pretty plugable, and for your first couple simple projects you can just use a regex or something
13:40jumblemuddlejustin_smith: Interesting, I'll look into that.
13:41ToBeReplacedlots of routers available and they all do things slightly differently, optimized for slightly different use cases; i think the most basic is clout for "i just want to ship"
13:41justin_smithjumblemuddle: it's great for an agency wanting to RaD push out yet another CMS / SQL backed site (comes with a web based admin interface out of the box), but may be a bad way to actually learn clojure
13:42jumblemuddleYa, I think I'll start with the lower level stuff first, so I'll actually learn how it's all working.
13:44justin_smithalso Caribou has a different use case than most clojure web libs, for example no clojure syntax in the templates and no clojurescript (it is assumed the frontend guys don't do clojure, but the backend do -- tailored to the dynamics of our particular company)
13:45justin_smithas opposed to nice things like enlive that you can use if the same person developing the page markup also does clojure
13:45justin_smithor garden
13:45justin_smithetc.
14:02jdkealyhow can i tell in should-update exactly what has changed in a component in om ?
14:11m-r-rHello
14:15luxbockI'm a bit confused of where the type-hint for a functions return value goes
14:15luxbockbefore or after the function name?
14:16m-r-rI have two strings, i'm wondering how i can get the longest substring at the beginning of both strings
14:17oskarkvm-r-r you mean that they share?
14:18llasram,(count (take-while true? (map = "foobar" "foobaz")))
14:18clojurebot5
14:18m-r-roskarkv: Yes. e.g. is the strings are "foobaz" and "foobaz", the function would return "foo"
14:18oskarkvm-r-r "fooba" :p
14:18justin_smith,(apply str (map first (take-while (fn [[a b]] (= a b)) (map list "spamtastic" "spamalot"))))
14:18clojurebot"spam"
14:18justin_smiththere is probably a better way to do that
14:18m-r-roskarkv: yes x-D
14:20justin_smith,(apply str (map first (take-while #(apply = %) (map list "spamtastic" "spamalot" "space out")))) ; varargs version
14:20clojurebot"spa"
14:20m-r-rWow. In fact i didn't knew (map) could take multiple lists.
14:22m-r-rjustin_smith: The second code is just what i was looking for, thanks :-)
14:24justin_smithit will be less gee-wiz-clojure-sure-is-elegant and more performant if you combine the two maps into one, even more so if you calculate an index for a substring and not use map in the first place
14:25justin_smithbut if you don't need the best possible performance, at least it will be correct :)
14:30ben_vulpesi'm considering writing a page counter backed by datomic using db fns to increment the counter. i'm fairly confident that i should be able to get the value of that counter over an arbitrary range as well by traversing the transaction - does anyone see any problems with this approach?
14:31ben_vulpesspam in #clojure again...
14:35justin_smithben_vulpes: you could also do it in regular sql, even calculating the number of requests in a date range server side, with a simple table having a single timestamp column and nothing else
14:35justin_smithnot that this is likely to be performance critical of course
14:37ben_vulpesjustin_smith: not a bad idea. this is for an existing datomic project though.
14:37justin_smithin that case I don't see a downside to your plan at all
14:37ben_vulpesbut now that you mention it a "view" attr consisting of an instant might be a better model.
14:38justin_smithyou could also have a path/query parameter, so you could get custom data for the whole site, or a single blog post or service, or whatever
14:38ben_vulpesthat's also a good idea, although there are other constraints that will help me infer that information.
14:39ben_vulpeseach venue only shows an ad of one size, so tracking per-venue views is probably adequate.
14:39ben_vulpesFAMOUS LAST WORDS.
14:40justin_smithadequacy and flexibility, the schylla and charybdis of programming
14:40ben_vulpes{venue-entid :van.venue/pageview (.toDate (time/now))}, something like that.
14:42ben_vulpesthanks justin_smith!
14:59m-r-rWhat is an "ISeq" ?
15:00TEttingerm-r-r, the interface that all clojure seqs implement in the Java implementation code
15:00Jaoodm-r-r: https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/ISeq.java
15:00m-r-rTEttinger: but what is a seq ? Is it an s-expr ?
15:01justin_smithm-r-r: it's a thing that implements ISeq, of course :)
15:01TEttingerm-r-r, uh, maybe read up on the seq abstraction on the clojure site before getting into the java implementation
15:02justin_smithm-r-r: a seq is a sequential datatype where you can do things like "add an item" or "go through the items in order"
15:02m-r-rAh ok :-)
15:03justin_smithby implementing ISeq, that means that a bunch of clojure functions will know how to use your data
15:03justin_smith(things like map, filter...)
15:04m-r-rSo, if i have an error "Don't know how to create ISeq form: java.lang.Character", it means the software expected an array or a list, and got a character ?
15:04justin_smitharray, list, vector, something like that, yeah
15:04justin_smithyou can even seq a map or set
15:05justin_smith,(seq #{1 2 3 4})
15:05clojurebot(1 4 3 2)
15:05TEttingerm-r-r, an example that causes that error: ##(map str \c)
15:05lazybotjava.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Character
15:05justin_smith,(seq "or a string for that matter")
15:05clojurebot(\o \r \space \a \space ...)
15:05TEttingerm-r-r, an example of one way that doesnt cause that, ##(map str [\c])
15:05lazybot⇒ ("c")
15:06m-r-rOk, i think understood :-) thanks
15:16arohnerwhat was the name of the other clojurescript repl project?
15:16arohnernot austin, but ...?
15:16martinklepschweasel
15:16arohnerthanks!
16:39arohnerthere was a blog post that came out last week about using Om with non-react JS. anyone have a link, or remind me something to google for?
16:39augustlcan (import) do static imports, or even better, :refer style static imports?
16:39arohneraugustl: wdym by 'static' import?
16:40rhg135where class fields have global symbols resolving to them
16:41arohnerhuh? import a single field from a class?
16:41rhg135basically
16:42augustlarohner: java style static imports
16:43justin_smithaugustl: the closest thing I think is (def PI Math/PI)
16:43justin_smithand we have no import * at all
16:44justin_smith(though if you really wanted it that much one could clearly do that via a macro and some reflection)
16:44arohnerhrm, java.lang.reflect.Method is marked final
16:44arohnerotherwise after IFn becomes a protocol, you could extend it
16:45arohnerfinal is such a terrible idea
16:45augustljustin_smith: I see
16:45justin_smithyou'd probably want a ^:const metadata on a def like that too
16:45Bronsaarohner: what has final have anything to do with protocols?
16:46arohnerBronsa: ah, you're right. I'm mixing up my bugs
16:46Bronsaanyone got spammed by nanaima here?
16:46arohnerBronsa: yes
16:48justin_smithCome to think of it, a macro that turns (import-fields Math PI E INFINITY) into (do (intern *ns* PI Math/PI) (intern *ns* E Math/e) (intern *ns* INFINITY Math/INFINITY)) would not be so hard
16:48Bronsajustin_smith: there was already something like that in old contrib
16:48justin_smithBronsa: not surprised at all
16:49justin_smithof course this would only be for fields, not methods
16:49thesaskwatchHi, I have a question .. why -main function starts with minus?
16:49Bronsajustin_smith: why not methods?
16:50justin_smithBronsa: The reflection gets trickier. I guess you could still do it after all.
16:50Bronsajustin_smith: it wouldn't that hard, really
16:50arohnerthesaskwatch: if you use (:gen-class), that indicates 'main' should be a method on the generated class
16:50justin_smithOK
16:50justin_smithBronsa: it would not be as trivial as the macro that defines constants from static fields though
16:51Bronsajustin_smith: right
16:51thesaskwatcharohner: thanks :)
16:53alxlithello, i've been toying around with an asset pipeline with clojure-ish sensibilities
16:53alxliti've got a working prototype and wanted to get some feedback, github.com/alxlit/venturi
16:54alxliti.e. it's not a sprockets implementation
16:58arohneralxlit: the readme could use more info on how it's different from existing solutions, why I should pick it, etc
16:59augustlhmm, cheshire blows up when generating SMILE for a byte array
17:00augustlas in, (cheshire.core/generate-smile {:body my-byte-array :status :ok})
17:00justin_smithaugustl: that's odd, because smile was invented by the jackson people, and cheshire is a wrapper for jackson
17:01augustlgetting a JsonGenerationException, Cannot JSON encode object of class: class [B: [B@40b98fb
17:03augustltried passing a ByteArrayOutputStream just for laughs, same problem there
17:03augustltime to find another format I guess..
17:03justin_smithhmm - I see docs of generating byte-arrays from smile, but not for encoding them into smile
17:04augustlyeah, same :)
17:05augustlthe smile format itself seems to support it - http://wiki.fasterxml.com/SmileFormatSpec#Token_class:_Misc.3B_binary_.2BAC8_text_.2BAC8_structure_markers
17:05justin_smithaugustl: look into cheshire.generate/add-encoder
17:05justin_smiththat should do your trick
17:05justin_smith(you would need to also add a decoder on the other end, of course)
17:24augustljustin_smith: transit to the rescue :)
17:26justin_smithoh, of course
17:27augustlit's only being used internally for talking between services so I can use whatever I want ;)
18:03augustlhow do you do MyClass.class with java interop?
18:04llasram,String
18:04clojurebotjava.lang.String
18:04llasramaugustl: Just the bare class name refers to the class object
18:04augustlah
18:06augustlhmm, will that work for a signature like java.lang.Class<T> type ?
18:06augustljust passing a bare class yields a "No matching method found" error
18:06llasramMore context?
18:06augustltrying to invoke this https://code.google.com/p/metadata-extractor/wiki/GettingStarted
18:07augustlin particular, metadata.getDirectory(ExifSubIFDDirectory.class);
18:07augustl(.getDirectory my-metadata com.drew.metadata.exif.ExifSubIFDDirectory) throws "java.lang.IllegalArgumentException: No matching method found: getDirectory for class java.lang.Class"
18:08llasramSounds like you `my-metadata` identifier refers to a class instead of an instance
18:09augustlgood point, perhaps it's a threading macro gone wrong
18:09llasramThe basic structure you've posted is right
18:31justin_smithany x() is just x followed by ()
18:37guest43justin_smith: yeah. got that much. need a way to ensure one function has completed before next is invoked. Single-threaded execution...
18:38justin_smithlet and fn both have implicit do blocks
18:38guest43(do (1st-fn) (then-2nd-fn) (only-after-first-two-complete-call-third-fn) )
18:38justin_smithmost things in clojure are actually sequential
18:39justin_smith,(let [a 0 b (inc a) c (inc b)] (print a b c) (print a b) (print a))
18:39clojurebot0 1 20 10
18:40justin_smithok, lack of spaces actually makes that weirder than it should be
18:41thesaskwatchhow to access java style field: Field.Store.YES .. how to translate this to clojure? Field/Store/YES doesn't work.
18:41SagiCZ1hi
18:41bbloom_thesaskwatch: you can only have one slash in a symbol
18:42bbloom_thesaskwatch: symbols have two parts: a namespace and a name
18:42SagiCZ1in brave clojure there is thsi sentence "You'll learn how to create new functions with apply,partial, and complement." is really "apply" in the same group as partial and complement?
18:42llasramthesaskwatch: Is `Store` an inner class of `Field`?
18:42bbloom_thesaskwatch: the namespace may be a classname, and inner classes are separated with $ (which is also true of java internals)
18:42thesaskwatchbbloom_: so .. doing this twice should work? Not sure .. I don't have source code.
18:42llasramthesaskwatch: If so: Field$Store/YES (after importing Field$Store)
18:43bbloom_thesaskwatch: inner classes in java are actually compiled to just specially named normal classes
18:43thesaskwatchbbloom_: llasram: thanks .. I'll check it
18:43thesaskwatchI did have to import Field$Store .. but after this it worked .. thanks :)
18:44justin_smithSagiCZ1: they all create new functions
18:44justin_smitherr.. I guess apply doesn't never mind
18:49virtuous_slothHello, I have a question about the difference between a bare list and a (list) list
18:50virtuous_sloth(type '(1 2 3)) => clojure.lang.PersistentList and (type '(list 1 2 3)) => clojure.lang.PersistentList
18:51virtuous_slothbut (second (list 1 2 3)) => 2 while (second (1 2 3)) => ClassCastException java.lang.Long cannot be cast to clojure.lang.IFn user/eval125 (NO_SOURCE_FILE:39)
18:52SagiCZ1i recently read about how lazy sequences work and that they actually produce chunks of their elements 32 pieces in each chunk... but how would this behavior work if the function that creates the next lazy element takes some large amount of time > 5 sec? would i have to wait 32 * 5 sec before clojure constructs one chunk and only then i can get the first element i wanted?
18:52virtuous_slothIs this just a artifact of the inability to consistently parse a bare list as a list? Requiring an explicit list construct for those cases?
18:53hyPiRionSagiCZ1: Not necessarily. Some things are chunked, others are not.
18:54SagiCZ1hyPiRion: how would i know? for example i create my lazy sequence by using the lazy-seq function..
18:54justin_smithvirtuous_sloth: that is not what actually happened
18:54justin_smitherr, I mean 1 is not a function
18:54hyPiRion,(first (map #(do % (print \.)) (range 10)))
18:54clojurebot..........
18:54hyPiRion,(first (map #(do % (print \.)) (iterate inc 1)))
18:54clojurebot.
18:55hyPiRionSagiCZ1: ^ I test it out like that usually.
18:55justin_smithvirtuous_sloth: also '(list 1 2 3 4) is a list of 5 elements, one function and four numbers
18:55SagiCZ1hyPiRion: ok so you test it by having the function do some side effect right? (aka printing ".")
18:55hyPiRionSagiCZ1: right
18:56hyPiRionat some point you know what's going to be chunked and what isn't though. Using lazy-seq is not chunked
18:56hyPiRionerr, the result of lazy-seq is not chunked, is what I meant.
18:56SagiCZ1hyPiRion: i see..
18:57SagiCZ1hyPiRion: i guess its chunked wherever it would make sense
18:57SagiCZ1but it also means that any lazy sequences shorter than 32 elements dont actually have any benefits over non lazy sequence
18:57justin_smith,,(let [chunksize (atom 0)] (first (map #(do % (swap! chunksize inc)) (range 100))) @chunksize)
18:57clojurebot32
18:58justin_smithI guess not giving range an argument would be more elegant
18:58SagiCZ1,(range)
18:58clojurebot(0 1 2 3 4 ...)
18:58SagiCZ1justin_smith: this explained atoms and swap! to me :)
18:59justin_smithoh, good
18:59SagiCZ1however i should strive to use non-side-effect functions in "map" or "lazy-seq" .. is that correct?
18:59justin_smithyes
19:00justin_smiththis uses side effects because it is measuring side effects
19:00justin_smithin pure functional code, chunk size is irrelevant
19:00justin_smith(for correctness, not resource usage, obviously)
19:00SagiCZ1justin_smith: could you elaborate on why would it be irrelevant?
19:00SagiCZ1ok
19:00SagiCZ1that cleared it up
19:01SagiCZ1off topic - do you guys ever sleep? i've been here in all kinds of different time-zones and i still see the same names.. except amalloy :)
19:02justin_smithI leave my client logged in, and browse scrollback
19:02justin_smithmany people have virtual machines that they leave connected and logged in
19:02SagiCZ1well i didnt mean "logged in" i meant actually participating in conversation ..
19:02amalloyand others use a bouncer
19:03SagiCZ1ok amalloy is here too
19:03justin_smithahh - well, programmers keep erratic hours don't we
19:03SagiCZ1amalloy: as in http://cdn5.droidmatters.com/wp-content/uploads/2012/02/bouncer.jpg ?
19:03akurilinquick question: does anybody know if there's a way of enforcing "at least one of these optional keys has be present" in prismatic's Schema, within Schema itself and not as a separate check?
19:04justin_smithSagiCZ1: http://en.wikipedia.org/wiki/BNC_(software)
19:05SagiCZ1ok.. close enough
19:07akhudekLooking for a highly available session store. Aphyr, shows all the solutions are faulty. Yay!
19:09virtuous_slothjustin_smith: If I understand you correctly, then the list function wraps up an actual clojure list such that partner functions list first and second can operate on them?
19:11justin_smithvirtuous_sloth: no, it creates a list
19:11justin_smith,(list 1 2 3)
19:11clojurebot(1 2 3)
19:12justin_smithvirtuous_sloth: the tricky part is quoting anything parenthisized also makes a list (instead of an invocation of the first item)
19:12justin_smith,'(list 1 2 3)
19:12clojurebot(list 1 2 3)
19:13justin_smiththat list contains the list function inside it
19:13justin_smith,'(+ 1 2 3)
19:13clojurebot(+ 1 2 3)
19:13justin_smithand that one the + function
19:13justin_smith(well really the symbols, which resolve to the functions...)
19:14virtuous_slothI think I understand now.
19:15virtuous_sloththanks
19:19justin_smithvirtuous_sloth: try out some corner cases in the repl, see if various things really do what you expect, and when they don't, find out why
19:19justin_smithclojure is good for exploration like that
19:19AeroNotixs/clojure/anything with a decent repl/g
19:20virtuous_slothI see that its the difference between a list being evaluated and appearing as pure data... I think I was thrown off by the tutorial suggestion to use (type 'foo) to tell me the type of an object
19:21justin_smithyeah, 'foo is a symbol
19:21justin_smith,(type '1)
19:21clojurebotjava.lang.Long
19:21justin_smith,(type 'foo)
19:21clojurebotclojure.lang.Symbol
19:21justin_smith,(type 'clojure.core)
19:21clojurebotclojure.lang.Symbol
19:22virtuous_slotherr, bad terminology, the type of whatever the text foo is... so I expected (second (1 2 3)) to be able to operate on the list (1 2 3) without understanding that it first tries to execute (1 2 3)
19:23justin_smithyeah, lisps are usually simpler than you first expect them to be, coming from another language family
19:23justin_smithbut that simplicity has benefits too
19:24justin_smithfor example, if I see matched delimiters of any kind, I can figure out what their contents represent without looking outside those delimiters
19:24justin_smithwhich is not true in more conventional languages
19:24justin_smith(there are things that fudge those rules, but they are few in number)
19:25virtuous_slothso (list 1 2 3) is an almost-empty function that returns the list
19:25justin_smithit's not a function, it's a function call
19:25justin_smiththere are so many things that implicitly or explicitly create sequences, seeing list use directly in clojure is actually sort of rare
19:26justin_smithon the other hand (partial list 1 2 3) is a function :)
19:26virtuous_slothyes, I just find it easier to write the use of the function "list" than to say "list" is regular prose because it is ambiguous when conversing
19:27virtuous_sloth<whosh> I'm sure that's a funny joke but I don't know enough to appreciate the humour
19:27justin_smith,(map (partial list 1 2 3) (range 3))
19:27clojurebot((1 2 3 0) (1 2 3 1) (1 2 3 2))
19:29virtuous_slothThanks Justin... I'm just a systems guy whose programming experience is fairly limited
19:30justin_smithOK, you can ignore that fancier stuff if you are not ready yet
19:30justin_smithtry a site like 4clojure if you haven't yet
19:30justin_smithor maybe clojure koans
19:30justin_smith~books too
19:30clojurebotGabh mo leithscéal?
19:30justin_smith~books
19:30clojurebotbooks is book
19:30justin_smith~book
19:30clojurebotbook is http://clojurebook.com/ http://joyofclojure.com/
19:30virtuous_slothYes, just a matter of putting in the time ;-)
19:30justin_smith(one of these days I'll know how to use the bot properly)
19:32virtuous_slothI was working through Closure from the Ground Up at http://aphyr.com/
19:32justin_smithcool, that's a good one
19:33justin_smithvirtuous_sloth: systems as in OS or as in models and information flows?
19:34virtuous_slothOS, integration... my education is physics though
20:01BAMbandaIf I want to play with a library from clojars from a repl, but don't want to use lein to build out a full project structure, how can I do this?
20:01BAMbandalike if I wanted to pull in a networking library from the repl fired by "java -cp clojure-1.6.0.jar clojure.main"
20:03justin_smithBAMbanda: you add the apropriate jars to the classpath
20:03justin_smithBAMbanda: I find it useful to use lein to create a non-project repl, then have alembic in my profiles.clj as a dependency. I can use alembic to resolve, potentially download, and then load jars at runtime.
20:04justin_smithor you can just know all the jars you want ahead of time, and put them all in the java classpath when you invoke clojure
20:04justin_smithhttps://github.com/pallet/alembic
20:04BAMbandajustic_smith, sweet thanks
21:08xeqiBAMbanda: there is also https://github.com/rkneufeld/lein-try
21:09imancwould you say that clojure's let form is similar to python's with ?
21:10imanchmmm - just trying to see the purpose of 'let' - I see what it does, I just don't see why it's all that important
21:11justin_smithimanc: def is only for globals
21:11justin_smithyou need something that creates per-form bindings
21:11imancahhh globals as per the current namespace?
21:12gfredericksand defs should be immutable from most of your code's perspective
21:12justin_smithyes, so if two threads call your function, and the function uses def, your code will likely break
21:12gfredericksi.e., it's unidiomatic to redef something as part of an algorithm or application logic
21:12justin_smithgfredericks: arguably that should go for globals in any language
21:13gfredericksjustin_smith: no argument there
21:14justin_smithimanc: don't use def inside a function, any more than you would redefine a class's definition inside a python method
21:14imancjustin_smith: if two threads call my function and the function modifies def'd symbol, it'll break?
21:14justin_smithimanc: because there is only one copy of the def
21:14imancok, good rule of thumb
21:14justin_smithyour algorithm may or may not work any more
21:15justin_smithimagine if you had a python method that redefined your class, and it was possible to call it from two overlapping threads - would you expect anything sane to result from that?
21:15imancnope
21:15imancmakes sense
21:18justin_smithluckily for python, its threads cannot actually overlap except at function boundaries - mutation of any sort outside of a local context would be insane otherwise. But in clojure threads can fully overlap, unless you explicitly lock some code body. But luckily we also don't redefine globals at runtime, and we use immutible datatypes, so we can actually use that full concurrency to our advantage.
21:25imancjustin_smith: " But luckily we also don't redefine globals at runtime" So are you saying that a global def should not be redef'd?
21:26justin_smithright
21:26justin_smithexcept under very specific circumstances (first app startup / config, or at the repl to test new code)
21:27justin_smithin a production app, after the first minutes of startup time when configuration gets applied, no redefs happen in any of my code.
21:27justin_smithever so rarely I use an atom for something that can be updated, but that's less commonly needed than you might think
21:28lpvbHow do I access the enumerations of this nested static class? http://docs.oracle.com/javase/7/docs/api/javax/sound/sampled/AudioFormat.Encoding.html
21:28imanclet's say we're building a web app ... where data will change per request, such as the user agent, ip address, etc.
21:28justin_smithimanc: those are arguments provided by ring to your handler
21:28lpvbI tried AudioFromat/Encoding/PCM_SIGNED
21:28justin_smiththey are not variables, they are function arguments
21:28imancokay
21:29justin_smithimanc: because, for example, you can easily serve as many requests at one time within one app as you have cores on your machine
21:29justin_smithimanc: and if you do any disk IO, you can have more than that going on at a time even
21:29justin_smithif that data was mutable, how would simultanious requests even work?
21:29imancyeh
21:29imancIt's slowly sinking in (emphasis on 'slowly')
21:30justin_smithsure
21:30lpvbgot my own answer, use $ to access inner static classes
21:30justin_smithimanc: it's actually provable that anything you can do via mutating a variable can be done via recursion and a different function argument
21:30justin_smith(modulo the difference in resource usage, if any, of course)
21:31justin_smithso instead of changes of state, you have function calls with different arguments
21:31imancright
21:31justin_smithin ring, to go back to that example, the request is a big map
21:32justin_smithit's trivial to take your mutation of state logic that accesses variables, and instead get each value from a big map
21:32imancyeh in a ways it seems like a reasonably trivial change
21:33justin_smiththat request map has the client IP, any query data, and also you can define middleware that adds / removes / augments / cleans up your data before the handler sees it
21:34justin_smithor even an additional middleware that looks at the response you create (which can be a string, or a stream, or a map, or whatever) and does any post-processing you need
21:34justin_smiththese things are *possible* when you do things via mutation, but they are much harder to get right
21:38justin_smithfor another example I like: unit testing with clojure.test. A test is just a function. You can run any test by calling the function it defines. You can redefine the test by reloading the definition. You can make pre and post actions by composing with other functions. It turns out that most of the weird things that testing frameworks need to do in a normal language are trivial to do with standard clojure idioms.
21:40justin_smiththe way I like to think of it: immutibility is a restriction that gives you extra power, kind of like airbags and seatbelts and bumpers make it possible to drive at highway speeds, immutibility means you can do fancy things like concurrency and high level code transformations without breaking everything.
21:42lpvbimmutability is like defining a mathematical axiom so you can further your theory
21:42justin_smithsure, you really wouldn't want to mutate axioms on the fly either
21:42justin_smiththat is a good building block metaphor to be sure
21:43gfredericksdoes anybody know of a way to adapt paredit to work with data literals?
21:43justin_smithgfredericks: which ones give you problems?
21:43imancI guess imperative code is going to be closer to the underlying hardware/low level OS calls though? And if so, is there a performance to FP?
21:43imanc* performance hit to FP, particularly clojure?
21:44gfredericksjustin_smith: {forward,backward}-sexp
21:44gfredericksnot a big deal in normal life but e.g., the align-cljlet lib breaks because of it
21:44justin_smithimanc: sure- clojure can't beat the performance of raw java, but also consider that if code is incorrect, it doesn't matter how fast it is any more
21:45justin_smithand fp in general is pretty good at correctness
21:45TravisDIs there a command to view the current grammar?
21:45TravisDer.. wc sorry :)
21:46justin_smithTravisD: http://ia.media-imdb.com/images/M/MV5BMjEyNjkxODM5N15BMl5BanBnXkFtZTcwMTU3NDE1Mg@@._V1_SY317_CR9,0,214,317_AL_.jpg :P
21:46TravisDheh, I dont understand
21:47justin_smithhis name is Kelsey Grammer
21:47TravisDlol
21:47justin_smithyou just viewed him
21:47TravisDAnd he was current.
21:47justin_smithrelatively, at least
21:49justin_smithimanc: one more thing about performance - since you brought up python before, there are few examples of python being as fast as clojure
21:49imancwow
21:50justin_smithclojure is closer to java performance than python is to clojure performance
21:50clojurebotRoger.
21:50imancthat's good to know
21:50justin_smithpython is very poorly designed from a performance perspective though, so it's not a super fair comparison
21:51imancthere is pypy
21:51justin_smith~clojure
21:51clojurebot"[Clojure ...] feels like a general-purpose language beamed back from the near future."
21:51turbofailpython's better designed for performance than ruby, to some extent
21:51imancruby is horrid
21:51imancnice language, ish, but speed wise...
21:51justin_smithimanc: pypy does not really compare even
21:52justin_smithturbofail: sure, it's faster than using an abacus too :)
21:52imancHow does clojure compare to counterparts e.g scheme, erlang?
21:52justin_smithhow, performance wise?
21:53imancyep
21:53turbofailclojure ime has been faster than most scheme implementations, dunno about erlang
21:53justin_smiththere are a few faster schemes (and many slower ones). Erlang is also slow (though I don't know how it compares to eg. python)
21:53justin_smithturbofail: racket can kick clojure's ass though
21:53imanci know scheme is also built on java
21:53TEttingercommon lisp is probably faster on single-core, but slower multi-core
21:53justin_smithit can be
21:53turbofailjustin_smith: i haven't had that experience
21:54justin_smithreally? I could be way off base on that I guess
21:54imancA company I'm probably going to start working for as a python dev, are using clojure - hence my interest in it :)
21:54p_l... performance comparisons between languages are usually useless
21:54TEttingerp_l, yeah good point
21:54p_lthat said, certain languages are pretty much defined by their implementations, and those implementations make kicking their arses in speed easy
21:54p_lfor example, Python
21:54TEttingerI will say, clojure can be tricky to optimize sometimes, and extremely easy others
21:54justin_smithp_l: certain designs are inherently bad for performance - the language definition itself can act as a bottleneck
21:55justin_smithp_l: it's not just one python impl, the semantics of python demand slowness
21:55p_ljustin_smith: there's this funny old phrase about sufficiently smart compiler ;)
21:55imancthen there's the GIL
21:55turbofailjustin_smith: dunno, i did a fairly idiomatic text processing thing in both clojure and racket and the clojure version was way faster
21:56justin_smithp_l: it would have to be a sufficiently wrong compiler, because python guarantees certain behaviors that are incompatible with good optimizations
21:56TEttingerI also have had fun times where the official racket IDE crashes if your program does
21:56p_ljustin_smith: heh, haven't touched python in a long time, so I'll concede on that point ;)
21:56imancjustin_smith: can you give an example of the ways in which the python lang is incompatible with good optimsiation?
21:56justin_smithturbofail: racket has a very small core language, and a small compiled executable size, so I may just have been wowed by the small scale advantages :)
21:57turbofailsure, a racket program will start a lot faster
21:57TEttingerI'm guessing the dictionaries everywhere thing is bad for python
21:57TEttingerno lookup is direct, IIRC, but I don't use python
21:57turbofaili was processing a lot of crap though, so for my purposes throughput was way more important
21:58p_lTEttinger: technically you can elide them a bit, but that depends on not doing some magic nor hot patching
21:58justin_smithimanc: for a not totally official one, removing the global interpreter lockbreaks massive numbers of commonly used libraries
21:58turbofailthough i think awk ended up being slightly faster than my idiomatic clojure program
21:58imancthere's also issues with obj.__dict__ which has been rectified in python 3.4 with a shared dict, and with __slots__ on earlier versions. But this results in enormous memory usage for large numbers of instances
21:58turbofaila less idiomatic version beat awk
21:58imancjustin_smith: yep, agreed
21:58p_ljustin_smith: GIL is implementation detail (that is unfortunately embedded in anything that calls to native code, which means lots of code)
21:59imancyeh it's a cPython issue
21:59justin_smithp_l: yes, as I said, not official limitation (but one everyone codes against)
21:59justin_smithnot just cPython - it also messes with class initialization
22:00justin_smithunless you swap it out for per-class locks or something
22:02imancif defs shoud only occur on the module level (not sure if that's the correct terminology) what is the purpose of defonce ?
22:02justin_smithalso, I am not finding the details now (sorry), but there are also issues with what is redefinable at runtime (where Clojure takes the "it's possible to redefine it, but we don't promise anything doesn't break" route, python allows redefinition, which rules out massive numbers of optimizations
22:02justin_smith)
22:03justin_smithimanc: a module can be loaded multiple times
22:03justin_smithimanc: clojuer is very repl-centric
22:03justin_smithimanc: you edit a file, then load it into a repl again
22:03imancahhh
22:03justin_smithdefonce means the next time, it doesn't get defined again
22:04justin_smithmany oddities about clojure become totally understandable once you consider the fact that coding from a repl and loading and running files from a jar should have identical semantics
22:04justin_smith(with the big exception of gen-class of course)
22:05gfredericksand something else
22:05justin_smithwhich something else is that?
22:05gfrederickscan't remember :)
22:05justin_smithI am sure there are a few examples
22:05gfredericksyeah
22:05justin_smithI mean protocols and defmethods don't play nicely with reloading
22:05gfredericksinevitably
22:06justin_smithbut within one repl, they do just work if you don't redefine
22:06justin_smithand it's informative that we rarely run into these gotchas - which means they are dark corners and they don't affect us day to day
22:07gfredericksit's difficult to get a sense for how *ns* works at the repl
22:07gfredericksbecause it's always set to your repl's namespace. but when running non-repl code it's set to user I think
22:07justin_smithwait, how often would you use *ns* outside the repl?
22:07justin_smithahh
22:07gfredericksdepends on how confused you are about how it works :)
22:08justin_smithoh, of course
22:08gfredericksit's easy to assume it just always refers to the namespace you're typing in
22:08justin_smiththat makes sense
22:08justin_smithbrb, dinner
22:08imancI thought ns needed to correlate with the file name/ directory structure?
22:09justin_smithns declared in a file ns statement yes
22:09justin_smithbut then there is *ns*
22:09justin_smith,*ns
22:09clojurebot#<CompilerException java.lang.RuntimeException: Unable to resolve symbol: *ns in this context, compiling:(NO_SOURCE_PATH:0:0)>
22:09justin_smitherr
22:09justin_smith,*ns*
22:09clojurebot#<Namespace sandbox>
22:09justin_smiththe current working namespace
22:09justin_smithwhich is a more repl-centric concept usually
22:10justin_smithunless you are trying to do something really weird
22:10imancahhh
22:11justin_smithyou can easily declare and create namespaces that don't have any correspondign file via the repl - for example you can invoke ns there
22:11gfredericksI think of it as more about compile-time
22:11gfredericksin particular macros can use it effectively
22:11justin_smithahh - I am kind of afraid of macros, so I can't address that part very well
22:11justin_smithanyway, actually going this time, brb
22:11gfrederickse.g., clojure.tools.logging uses it to pick the appropriate logger
22:12gfredericksotherwise it would have no idea what namespace you're calling from
22:12imancI read something about haskell developers believing that lisp macros enable 'cowbow coding' and producing faulty dsl's.
22:14imancI obviously don't have enough experience to comment either way, but my gut feeling is that it could easily be abused
22:14gfredericksthere's a reason people yell at you while you write macros
22:15gfredericksbut that doesn't mean we'd be better off without them
22:15imancheh
22:16gfredericksmost of clojure's control flow functionality is macros that you could have written yourself, and can write variants of
22:16gfredericksi.e., you are not depending on rich hickey having selected the perfect set of language features
22:17imancyeh
22:17kenrestivoi like how rich put it "clojure is a consenting adults language"
22:18gfredericksclojure makes it easy for you to not overuse the messier parts of clojure :)
22:18imancsimilar to the python statement re's the lack of class access modifiers "we're all consenting adults here"
22:19imanci can imagine disregarding the "don't redefine symbols" you could write clojure that is somewhat imperitive
22:19gfredericks,(def x 38)
22:19clojurebot#'sandbox/x
22:19imanceven if behind the scenes the same memory addresses are not being overwritten
22:19gfredericks,(dotimes [n 4] (def x (inc x)))
22:19clojurebotnil
22:19gfredericksx
22:19gfredericks,x
22:19clojurebot42
22:20imancoo
22:20imancheh
22:20gfrederickshere's a fun one
22:20gfredericks,(defn y [] (def z 1))
22:20clojurebot#'sandbox/y
22:20gfredericks,z
22:20clojurebot#<Unbound Unbound: #'sandbox/z>
22:21kenrestivowat?
22:21kenrestivo,y
22:21clojurebot#<sandbox$y sandbox$y@1ae541e>
22:21gfredericks,(y)
22:21clojurebot#'sandbox/z
22:21gfredericks,z
22:21clojurebot1
22:21imancso z has local scope to teh function?
22:22gfredericksthe weird part is that z exists at all before you call y for the first time
22:22bbloom_gfredericks: i guess the def is resolved during compilation?
22:22bbloom_actually, i know it is
22:22imancyeh
22:22bbloom_oddly
22:23gfredericksit makes sense from a compilation perspective
22:23gfredericksthe function has to contain a reference to the var
22:23gfredericksso it has to exist
22:23gfrederickswouldn't want to go checking that it exists every time you call it
22:24gfredericksimanc: it doesn't matter that this is weird because you're not supposed to do it anyhow
22:24kenrestivowhat would be the use case for def'ing inside of a function body? seems fraught with danger to me.
22:24gfredericksI don't think there is one
22:27bbloom_if you had to do it, you'd use intern
22:27bbloom_(doc intern)
22:27clojurebot"([ns name] [ns name val]); Finds or creates a var named by the symbol name in the namespace ns (which can be a symbol or a namespace), setting its root binding to val if supplied. The namespace must exist. The var will adopt any metadata from the name symbol. Returns the var."
22:28rhg135what's the difference anyway
22:29bbloom_intern is a function
22:29bbloom_def is a special form
22:29bbloom_as a function, intern fully evaluates its arguments
22:30rhg135oh ic
22:30bbloom_but there isn't much need to be messing with that in normal programming anyway
23:06ilargslets say you wanted to create a new type that has properties of both a vector and a map. how do you find out the clojure/clojurescript protocols you have to implement? browsing source or is there a doc somewhere.
23:07justin_smithilargs: check out (doc deftype) in your repl
23:07justin_smith(it's way too long for here)
23:08justin_smithlong story short, you can specify any number of protocols or interfaces in a deftype declaration, and specify the method implementations for each
23:09ilargsso i see the usual background and more detail which is always good. but for example, IPersistentVector, how do you kown which methods you have to define for it? or will compiling tell you which you are missing?
23:10rhg135isn't a vector an associative from ints to vals while maps are more general?
23:19justin_smithyes, and maps are unordered while vectors are ordered
23:19Bird|otherboxyeah, also, maps have amortized constant time lookup (as they're hashtables under the hood) while vector lookup is O(1), just like a diamond is forever.
23:20justin_smithilargs: actually I kind of wish protocols and interfaces had doc strings the way vars do
23:20kristof...What exactly is the difference between "amortized constant time" and O(1)?
23:20justin_smiththere may be a better way to do it, but I tend to look up the implementation for a protocol or the javadoc for an interface
23:20kristofI thought the point of O(1) asymptotic behavior was that the value is constant.
23:21justin_smithI think amortized accounts for worst case
23:21kristofHrm. Gotcha.
23:21justin_smithwhile O(x) will sometimes specify the best or average
23:22justin_smith"At the heart of the method is the idea that while certain operations may be extremely costly in resources, they cannot occur at a high enough frequency to weigh down the entire program because the number of less costly operations will far outnumber the costly ones in the long run, "paying back" the program over a number of iterations."
23:22justin_smithso it's not just worst case, but overall actual usage?
23:22justin_smithhttp://en.wikipedia.org/wiki/Amortized_analysis
23:24kristofeffective operational complexity, then
23:24justin_smithsounds right, not sure
23:27ilargsi have a lot to read!
23:27ilargsthanks guys.
23:27justin_smithnp
23:27justin_smithgood luck