#clojure logs

2016-03-08

00:51AndreasO(Select root [:#tag]) seesaw. How do I address the root widget?
01:03TEttingerAndreasO: I seem to remember a method that goes up in the hierarchy... let me check
01:04TEttingerhttp://daveray.github.io/seesaw/seesaw.core-api.html#seesaw.core/to-root
01:13AndreasOTEttinger: I think that function returns the root of the widget that triggers the event. In my case a button is pushed and triggers an action that should paint a canvas.
01:15TEttingerto-root takes a widget as an argument, you could pass it the event-triggering widget or another widget in a different frame/window
01:15AndreasOTEttinger: can I pass a tag?
01:16TEttingeryou could select one first I think
01:16TEttingerdo you not have the root to pass to select, so you can't use the tag for that reason?
01:30AndreasOTEttinger: I'm not sure what count as the root.
01:30AndreasOI'll bin the codefinger
01:32AndreasOTEttinger: pastebin.com/E63QbV7C
01:33AndreasOTEttinger: line 11-13 and 60-68
01:33AndreasODamn. Pastebin not codefinger
01:33TEttingerhm, well Draw shouldn't be capitalized
01:37AndreasOI've been banging my head for days. I made simple GUIs before, this is somwath more complicated.
01:39TEttingerohhh
01:39TEttingerthis looks oddly familiar
01:39TEttingerI seem to recall a swing thread thing that the demos used
01:40TEttingersee the thing with invoke-later ? https://github.com/daveray/seesaw#tldr
01:42AndreasOI found a nother mistake now, draw needs one more arg... g2d?
01:46TEttingerseems to be a Graphics2D, doesn't look like that section is meant to be used often
01:48TEttingerhttps://github.com/daveray/seesaw/blob/master/test/seesaw/test/examples/clock.clj uses it
01:51AndreasOI'll try that.
01:51TEttingerit seems to be a :paint related thing
01:51AndreasOI might be overthinking this.
01:52TEttingerso you can call g2d-taking methods when you're in a fn that is called as a callback from :paint
01:52TEttingersince :paint gives the current g2d with it
01:53AndreasOOkay
01:53TEttingeralso the require statement at the top seems weird, two slashes is not normally what I see
01:54TEttingerit may be because it isn't used yet that it isn't causing trouble
01:55AndreasOYou mean the photomath?
01:56TEttingerYEAH
01:56TEttingeryeah
01:58AndreasOWell that's my own lib. It worked well in a nother test I did.
02:02AndreasOI'll look into the clock example, hopefully I'll get it. :-)
02:02TEttingerhm, not sure where the / is appropriate in those require sections
02:02TEttingerit's the part at the bottom
02:03TEttinger(canvas :id :canvas :background "#BBBBBB" :paint paint-clock)
02:03TEttingerpaint-clock is called with a g2d as one of its args
02:04AndreasOThanks!
02:05TEttingerI'm not sure how to explain the root thing other than "I tried a bunch of stuff and found some stuff that worked"
02:06TEttingerone of the things I did that I don't know if it's recommended is to, instead of using def to immediately create a widget, use defn to make a fn I can call when everything's ready and only then make the widget
02:08AndreasOI see, seems a redesign is in order.
02:10AndreasO(run :dispose)?
02:17AndreasOTEttinger: still there?
02:22TEttingeryeah
02:22TEttingerit does seem like it needs some moving around
02:22TEttingergraphics-related stuff needs to essentially modify a canvas or something like it... I think....
02:23AndreasOI se an error. Yes, you can :paint at the moment of creation as in the clock example. But to change it after creation you need to use the config! Command.
02:24TEttingerhm?
02:25TEttinger:paint is given a fn, it calls it whenever it repaints
02:25TEttingerI don't think config! would help here since it would just change the fn but not tell it to use it
02:27AndreasOHmm... I see. Maybe I can put values in a vector that the :paint function reads .
02:29AndreasOThe lines and dots need to bee saved anyway.
02:29TEttingermakes sense, I think
02:29TEttingerif they change you might want them in an atom, or you might want to pass them into the next update somehow
02:32AndreasOI did something similar in Python. APOS80
02:33AndreasOGitHub.com/APOS80/GeoCad
02:34AndreasOSome things is made to be mutable.:-)
02:47AndreasOTEttinger: thank you!!! I have now painted a circle!!
02:48TEttingerwoohoo!
02:49TEttingeryeah, the examples for seesaw were the most valuable resource I had trying to learn it
02:49TEttingerI did make some tiny things early on, it's good for a lot of stuff. One I'm proud of was a nutrition DB searcher for my grandma
02:50TEttingershe had bizarre nutrition constraints, like couldn't have much phosphorus, and that isn't on most labels
02:51AndreasOFor some reason I always try things that don't work instead of doing it right in the first place.
02:51TEttingerGUI is much better for grandma than CLI, haha
02:51AndreasOI like cli, but a cad in cli?? Nono
02:51p_lAndreasO: ever seen AutoCAD?
02:52AndreasOI use topical at work
02:52p_lor BRL-CAD (which is even more CLI-oriented)
02:52amalloyed | cad
02:52AndreasOTopocad
02:53p_lalso, OpenSCAD seems to be currently popular thingy on the lower end
02:53AndreasOHmmm... What graphical lib is used for cli?
02:53p_lCadence CAD tools aren't CLI oriented, but IIRC include Lisp REPL :)
02:54TEttingerOpenSCAD is good
02:54p_lAndreasO: depends on environment - a CAD can have CLI despite being very graphical (the interaction might be through CLI)
02:55p_lhttps://en.wikipedia.org/wiki/OpenSCAD#/media/File:Openscad_screen_english.png <--- example from openscad
02:55p_lhttps://upload.wikimedia.org/wikipedia/commons/e/eb/BRL-CAD_screenshot.jpeg <--- upper left corner has the main editor interface, iirc
02:56p_lAndreasO: quite possibly lots of old CAD tools worked well in xterm thanks to its vector graphics support, too :)
02:59AndreasOTrue, but isn't a little more complicated?
02:59p_lAndreasO: not necessarily. And can be a godsend when you need to manipulate precisely
03:00p_lAutoCAD had very good interface in this which coupled command line with mouse/tablet
03:01p_lfor example, how easy it is to convey by mouse that you want exactly X milimeters?
03:02AndreasOIsn't autocad written in lisp?
03:02AndreasOHeard that
03:02p_land most of those CAD programs are directly extensible (AutoCAD with AutoLisp, Cadence stuff in SKILL - a lisp dialect, etc)
03:02p_lAndreasO: it isn't
03:02p_lit has a very old-school lisp dialect however
03:03AndreasOLike scheme?
03:03p_lused for interaction and automation (though, similarly to AutoCAD REPL, had been pushed to wayside)
03:03p_lAndreasO: Scheme is very modern lisp dialect :D
03:03p_lAutoLISP is old style, really old
03:04p_lolder than elisp by now, because elisp evolved
03:04p_llast time I checked, AutoLISP still didn't have lexical scope
03:16AndreasOI'm new to lisp, I like it.
05:28spbaHas anyone here worked through HtDP?
05:32ridcullyis it "safe" to have a fn and an aliased ns with the same name. e.g. defn json and cheshire :as json - seems to work as expected in the repl, but maybe this is foolish?
05:43hyPiRionridcully: should be safe, yes
05:44amalloyridcully: yes, it's intended to work fine. you can always distinguish from context whether a namespace is meant or a var
05:45ridcullyhyPiRion, amalloy: thanks. i thought it would since str is often used for clojure.string - but i was never sure, if that would shadow (str)
06:16clgvHello, in Cursive is there something similar to CTRL+W that extends the selection to the next complete s-expr on the left or on the right?
06:25Emppericlgv: check Edit -> Structural Editing
06:25Empperiyou can bind those to any shortcuts you wish
06:26clgvEmpperi: sure, but which one is it`
06:26Empperiwell, I don't know what "CTRL+W" is so :)
06:28clgv"extend selection to the next full s-expression" is what I am looking for
06:29clgv"CTRL+W" is "extend selection" which will select all expressions with an s-expression, then the whole s-expression and so on
06:29Empperihmm, still not sure what that means, so you want to extend selection so that it contains a full s-expression? Yeah, there is that. But it's not in Cursive but in Idea and it works everywhere
06:30Empperiah yeah, it's that then
06:30Empperiit's in Idea itself
06:30Empperisearch for "shrink selection" and "extend selection" in keymap bindings
06:30Empperiand it will work in every editor
06:30clgvI want (->> xs |(map bla)| (map blubb)) to (->> xs |(map bla) (map blubb)|) where the selected part is enclosed in | |
06:31Empperiok, that's not then exactly the same thing :)
06:31clgvI am used to that from CCW ;)
06:32Empperishrink/grow would grow from |(map bla)| to both left and right
06:33Empperidunno if there's a selection functionality exactly for that
06:33Emppericfleming will know if anyone knows :)
06:33clgvis there bugtracker for cursive?
06:36ridcullyclgv: i used https://github.com/cursive-ide/cursive/issues the last time - still seems active
06:38clgvridcully: ok, thanks
06:38Empperiyeah, that is the place
06:38EmpperiCursive itself isn't opensource
06:39clgvbtw is (.-some_field some-deftype-instance) preferred over (.some-field some-deftype-instance) for field access on deftypes?
06:39clgvCursive tries to convince me strongly
07:04Empperiwell, deftypes compile to java classes
07:04Empperiand you can't name java fields into private Foo some-field;
07:05Empperiit's a syntax error
07:05Empperisure they don't compile to java source code but same rules apply on bytecode level
07:05Empperimore or less
07:05Empperiso yeah, I'd say it's better to stick with those conventions
07:06Empperinot sure actually how that will work on bytecode, it just might work
07:06Empperifield names with - in them that is
07:06Empperibut if you try to access those from java code...
07:07Empperiso at least for the sake of java interop you should avoid those
07:23irctcHello, please forgive me just jumping into a question, my ignorance and the assumption that Datomic questions are relevant here. I think I understand queries across history in Datomic. What I'm unsure of is can one create a branch in that history and continue adding data? Can one create a tree of db states or can db history be linear only?
07:36Empperiirctc: https://groups.google.com/d/msg/datomic/jYjWvut3v3E/GZeod3hYaRQJ
07:36Empperifrom 2012 but I guess that's still correct
07:37Empperihowever this seems to indicate that branching is currently supported http://vvvvalvalval.github.io/posts/2016-01-03-architecture-datomic-branching-reality.html
07:38Empperimuch less official source though but also much more recent
07:43hyPiRionirctc: you also have the notion of sagas, which is explained at the later parts of the presentation named "understanding and using reified transactions" over at http://www.datomic.com/videos.html
07:44hyPiRion(I think that's what they're sort-of used for?)
07:46justin_smithTEttinger3: regarding ATS and the benchmarks game - the ATS that wins is idiomatic ATS and is not calling assembly libs - it's a low level language with very strong typing. It's a hard language to learn though. Imagine Haskell where gc is explicit instead of implicit.
07:46justin_smithalso it uses the type system to ensure correctness of resource usage (mem used but not provably freed, or files opened but not provably closed, are type errors)
08:10clgvEmpperi: yes you can name them like that - Clojure takes care of that
08:10irctc_Great, thanks for the resources regarding branching and Datomic!
08:11clgvEmpperi: I was just asking whether the preferred field access syntax in Clojure changed when they introduce the .- syntax which is compatible with ClojureScript
08:13Empperino idea
08:16Kah0onaQuick question; i'm using compojure-api, and for one route I want to stream back a file rather than JSON data.
08:16Kah0onawhat is the recommended way for setting up such a route, should it use compojure-api at all?
08:16Kah0onaor should i drop down to native compojure routes?
08:27Empperiwell, no point in defining the return type then
08:27Empperiyou can use compojure-api
08:27Empperijust don't define return schema
08:27Kah0onaah so not defining it as s/Any then? :-)
08:27Kah0onathanks
08:28Empperiwe have it like that without :return and works nice
08:28Kah0onacool will try
08:28Empperithen you have to handle response building yourself but that's what you want in that case
08:28Empperiactually we stream data through our app from another app of ours straight to browser
08:28Empperiit never sits in memory on our servers since we just use InputStreams all the way
08:36Kah0onayeah i'm planning to do the same, when generating PDFs for instance, don't want them to hit the disk
08:41Empperiyeah, we are actually serving PDFs too
08:41Empperisome of them are HUGE
08:41Kah0onagreat this works neat :-)
08:41Kah0onaneatly*
08:42Empperiyeah, it's nice that you can just throw InputStream for ring and it handles it correctly
08:42Kah0onayeah
08:42Kah0onaI used to have pretty ugly servlets 'back' in the java days :-)
08:42Kah0onathis is really elegant
08:42Kah0ona<3
08:46Empperiservlets were revolutionary back when they were introduced
08:47Empperibut yeah, that was some time ago now :)
08:47Empperiworld has gone forward
08:48sharmsIf I have a nested map of maps that occassionally has a {:key1 {:key2 {nil nil}} and want to create a new map with {nil nil} replaced with the (:key2 (:key1 another-map)), what is the clojure way to do it?
08:48sharmswhere :key1, :key2 ... :keyN
08:49Empperiuse walk api
08:49Empperihttps://clojuredocs.org/clojure.walk
08:50sharmsWould you happen to know how I could get the keys required to get to the point I have walked to?
08:50sharmsI have tried a few walk functions, tree seq etc but I am a bit hung up
08:51the-kennyIs there no way to use a :gen-class via `lein repl` *without* having to call `lein compile` first? I'd rather not introduce another step for devs to start developing
08:51Empperiwell, your scenario isn't trivial
08:51Empperiwould take some time to implement the solution with walk api
08:52Empperiwould love to help but I've spent too much time doing all other stuff except the stuff I'm supposed to do :D
08:52sharmsoh that is ok, I just wanted to make sure something like this wasn't a "oh just type this one line in" type thing
08:52Empperidon't want to sound like a total prick leaving you in distress but really, I need to do some work :/
08:52Empperisorry
08:52sharmsthank you for your help
09:33the-kennyOkay, I'm out of ideas: I've got a custom Exception generated via :gen-class in a namespace, foo.ValidationException. Now I want to import that in some other namespace, for example foo.model. As soon as I add it to the :import of foo.model, leiningen won't compile nor repl anymore, saying it can't find foo.ValidationException. I got it in my :aot in project.clj and tried *every* combination of aot, different
09:33the-kennynamespaces, adding :name to gen-class, requiring the namespace of the exception, running compile beforehand, etc. etc.
09:34the-kennyA colleague next to me did *exact* the same thing in clj-oauth2 before (some years ago): https://github.com/DerGuteMoritz/clj-oauth2/blob/master/src/clj_oauth2/OAuth2Exception.clj
09:34the-kennyAll I get is ClassNotFoundExceptions everywhere.
09:36the-kennyThe only "solution" I see right now is removing all usage of ValidationException in our codebase, running `lein compile`, then uncomment all usages.
09:40justin_smithdo you require the namespace that defines the exception in the code that wants to throw that exception?
09:40the-kennyTried that.
09:41the-kennySame result.
09:41justin_smithif the namespace is compiled before the other namespace tries to use the class, then you should not see this error. You ensure this by using require.
09:41justin_smithOK
09:42justin_smithso you both require the namespace, you import the exception in the same ns that requires the namespace, and the exception defined in the required namespace is not available?
09:43justin_smithcan you make a minimum reproduction of this error (eg. two namespaces, one tries to throw an exception defined in the other)?
09:43the-kennyYeah, that's likely the next step.
09:43the-kennyWorking on it, give me a minute
09:48the-kennyjustin_smith: https://github.com/the-kenny/clojure-custom-exception-minimal-case
09:49the-kennyerror is different, give me another minute. My brain doesn't really work today
09:49the-kennyokay, it works in that minimal example. I'll be damned
09:50the-kennyOkay, I'm getting some food and throw my day's work away afterwards and starting from scratch.
09:51justin_smiththe-kenny: my suspicion is the whole package vs. namespace vs. class thing, it's a messy corner conceptually, even when people think they get it it's easy to confuse things
09:51the-kennyjustin_smith: Yes, I'm aware of that. It's just that this is closest to the working example I've found. And I want to minimize the complexity.
09:53justin_smithI think the interactions are weird - the class does not exist unless you require the namespace but requiring the namespace doesn't import the class yadda yadda
09:54Kah0onai've got something weird. I return a response with Content-Length 30705, but somehow it shows Content-Length 0 in the response header.
09:55Kah0onaIt seems to be reset by compojure-api / compojure / ring?
09:55Kah0onaThe header code is picked up, because if i change Content-Length to Content-Length2 it'll show that Content-Length2 header in the response
09:56Kah0onahow can i figure out which response middle ware (is there even such a thing?) is working in my compojure-api route?
09:56justin_smithKah0ona: yeah, many middleware will alter the response
09:57justin_smithKah0ona: the idea of a middleware is that it is free to alter the parameters before they hit your handler, or the response that comes out
09:57Kah0onaokay so how can i actually see what middleware is active? because my handler code just returns a response map of which I know it is correct
09:57justin_smith(by returning a new function that wraps a handler and does those things)
09:57EmpperiKah0ona: if you are using cursive then you can just use the debugger
09:57justin_smithKah0ona: the only way I know of is to look into the compojure api code you are calling and seeing which middleware it inserts
09:57Kah0onayeah i see the point of mw, but since there are some defaults being put in place by compojure-api
09:57justin_smithEmpperi: oh, great point
09:58justin_smithKah0ona: yeah, compojure-api is just a bunch of middlewares iirc
09:58Empperiwell, that and some macro magic to build the route mapping :)
09:58Kah0onayeah with some macro's that does some coercion and checking
09:58Kah0onayeah
09:58Kah0onaokay so i gotta figure out which mw resets my content-length to 0
09:59Empperipretty much
09:59Empperidefault compojure-api mws shouldn't do it
09:59Empperisince we have compojure-api in use
09:59Empperiso I'd look at something else at first
09:59Kah0onahmm don't have much else there actually...
10:00Kah0onaonly some mw that modifies the request, but not the response
10:06Empperiso are you setting the content-length into your response headers correctly?
10:06Empperiand are you 100% certain of that?
10:06Empperiobviously ring cannot do that for you when you pass InputStream for it
10:08justin_smith,(.available (java.io.ByteArrayInputStream. (.getBytes "hello")))
10:08clojurebot5
10:08justin_smithnot in the general case, but sometimes
10:13Kah0onayeah i'm certain
10:13Kah0onaand i think the middleware: wrap-format-response causes it
10:13Empperijustin_smith: yeah but that is far from reliable
10:13Kah0onahttps://github.com/ngrunwald/ring-middleware-format/blob/master/src/ring/middleware/format_response.clj#L202
10:14Kah0onahow can i disable that one for a certain route
10:14Empperifor a single route?
10:14Kah0onai somehow find the compojure-api docs not really clear on how to disable a preconfigured mw
10:14Kah0onayeah i have one /files?file_id=1
10:14Kah0onaroute
10:14Empperijust define it separately from your other routes
10:15justin_smithKah0ona: one option is a middleware wrapping that middleware that knows how to fix your Content-Length
10:15Kah0onayeah but i defined it using compojure-api
10:15justin_smithKah0ona: another is to replace the default middleware stack with something that behaves correctly
10:15Kah0onaah like a new mw that undo's it
10:15Kah0onahm
10:15justin_smithyeah, should be easy to write - it checks for your :real-content-length and applies it if present?
10:15Empperihacky but would work
10:16Kah0onaok i'll try that
10:16justin_smiththe cleaner fix is to build your own custom middleware stack that isn't broken - depends on time available, how much work you want to put into it
10:16Empperiwe actually have something like that in place for one of our custom middlewares
10:16ikitommi_Kah0ona: what mw's do you have outside of c-api `api`?
10:16Empperiwhich prevents it from doing it's magic for responses
10:16Kah0onaah care to share?;-)
10:16EmpperiKah0ona: now you got compojure-api author to help you ;)
10:16Empperiikitommi_ that is
10:16Kah0onayeah i see that :-)
10:17Kah0onawell i dont have any that modify the response
10:17Kah0onaonly some that modify the request
10:17Kah0onaatleast, as far as i can tell now
10:17ikitommi_can you throw in a gist?
10:17Kah0onaikitommi_, : i'll make a little gist of the defroute
10:17Kah0onayeah
10:17Kah0onak
10:18ikitommi_the default mw-stack in c-api touches the reponse in two ways: 1) response coercion IF the endpoint has defined a Schema for it 2) using ring-middleware-format
10:20ikitommi_and the response coercion is defined in the endpoint, so if your route doesn't define a return schema, r-m-f is the only party doing something
10:20justin_smithikitommi_: he just linked to the middleware that is setting his content-length - wrap-format-response
10:21justin_smithso maybe that means compojure-api is misled about the type of response or how to handle it?
10:22Kah0onahttps://gist.github.com/Kah0ona/11c338cef61cd83ec7f0
10:22Kah0onaso i already got the hint of Empperi to _not_ put a `:return something` key in the options
10:23Kah0onawhich got me around the default json encoder that tried to encode my file as json
10:23Kah0onabut now since content-length is always 0 i can't download my file (or it is empty that is)
10:23Kah0onabut it would be nice to also define this route in compojure-api
10:25Kah0onafor the purpose of this single route disabling the ring-middleware-format would probably fix my problem
10:25ikitommi_lot's of extra middlewares, is it possible to test without those?
10:25Kah0onayeah okay i will try to disable them all
10:25Deraenr-m-f should do nothing with response body is not collection (i.e. it is Stream) and when no `:return` is not set
10:27Kah0onaby the way, i'll update the gist to show my file download function, which uses PipeInputStream
10:27ikitommi_yes, your compojure-api GET is really just a Compojure GET, so it's rendering rules apply (https://github.com/weavejester/compojure/blob/master/src/compojure/response.clj)
10:28Kah0onaone of which appearantly sets the Content-length automatically by checking the body, which, since it is a stream, doesnt give the correct Content-Length?
10:29Kah0onaso what is the best way to fix this?
10:29clojurebotTitim gan éirí ort.
10:30Kah0onathanks so far by the way, for pointing in the right direction
10:31DeraenI don't think Compojure Renderable matters in this case. If response is map, it is used nearly as is.
10:32ikitommi_it could, if find-and-stream-file returns a stream and some evil external code has overridden the Stream-responses. Not likely thou.
10:32Kah0onahttps://gist.github.com/Kah0ona/9c52f4932cc4de4219ae
10:33Kah0onathis is my fn that creates the stream by the way
10:33cortexmananyone using parinfer? https://github.com/edpaget/parinfer-mode
10:33cortexman(for emacs)
10:35prohobohey guys, i have a problem
10:35prohobonvm
10:35TimMcphew
10:36DeraenInterestingly file download code I have doesn't set content-length but the response has correct value, and the response body is a InputStream from Mongo GridFS
10:36ikitommi_Kah0ona: have to go, hopefully you find a solution for this with @Deraen & @Empperi
10:37Kah0onayeah i go for the 'undo middle ware' approach
10:37Kah0onathanks all
10:37Kah0onathen at least i think i ca nget it working without too much fuss
10:38TimMcI just took a look at the parinfer thing cortexman linked... it's weeeeeird.
10:38justin_smithsometimes you just have to add it to the "technical debt" list and go get other shit done, and some day you'll have the lightning bolt of inspiration that tells you how to fix it
10:38justin_smithTimMc: type python, get clojure
10:39the-kennyjustin_smith: Found my issue. My user.clj required foo.core. And user being the repl's init-ns caused much much weirdness.
10:40the-kenny(my user ns requires core to use it in start/stop/reload for Component)
10:40DeraenKah0ona: Btw. if the response is just a File, you don't need to turn it into Stream, you can just send File as response body
10:40justin_smiththe-kenny: (dec user.clj)
10:41justin_smithbecause it's too easy to forget that it's modifying your environment
10:42Kah0onaDeraen aaahhhhh
10:42the-kennyyeah. We even moved it to dev-src/ so it's only loaded in dev environments. Very annoying.
10:42Kah0onathat's a good insight :)
10:42Kah0onaso just return a File?
10:43DeraenYeah. And I think there is a good chance that content-length will be set automatically when you send a File.
10:43Kah0onawill definitely try now
10:47Kah0onalol Deraen that did it
10:48Kah0onaand it removed like 10 lines of custom header building stuff
10:48Kah0onajust remove a File
10:48Kah0onareturn*
10:48Kah0onathanks man!!
10:48justin_smithawesome
10:48DeraenFile response is mentioned in Ring wiki: https://github.com/ring-clojure/ring/wiki/Concepts#responses
10:48Kah0onathanks
10:48Kah0onayeah somehow i sometimes have trouble how thigns work together
10:49Kah0onabecause at some point i'm working with compojure-api, and i now and then miss the link to how it pieces together with compojure/ring
10:49Kah0onawell bugs like this do make that more clear though :)
10:49sdegutisGood evening.
10:50Kah0onagood afternoon! ;-)
10:50sdegutisIt's morning here.
10:51Kah0onanice curveball then
10:51Kah0ona=0
10:51Kah0ona=)
10:52DeraenLooks like http server itself (e.g. http-kit) might overwrite content-length: https://github.com/http-kit/http-kit/blob/master/src/java/org/httpkit/HttpUtils.java#L437-L441 (check bodyBuffer method for code which handles File/InputStream etc. response bodies)
10:53DeraenAleph checks if response already has content-length and only sets it if it is not already set :)
10:59sdegutisHello.
11:00sdegutisIs there a way to make this template function prettier? http://sdegutis.github.io/2016-03-07/clojure-template-no-deps/
11:01sdegutisI'm trying to do it via fricken like -> and/or ->> etc but it like just aint workin or whatever
11:02cortexmani'm wondering if there's a way to use distinct (presumably as a stateful transducer) to distinct-ify objects based on a specific property
11:02justin_smithsdegutis: why not make that fn a helper with real variable names?
11:03sdegutisjustin_smith: wait, what?
11:04sdegutisjustin_smith: oh, you mean /instead/ of having a template function? like, each "usage" of (template) would actually be its own function?
11:04sdegutisjustin_smith: kinda like this? (defn something [bar quux] (str "foo " bar " " bar " " quux)) ?
11:04justin_smithlike (defn apply-key-to-template [s from to] (str/replace s (str "{{" from "}}") to)) (reduce (fn [s [k v]] (apply-key-to-template s (name k) v)) s m)
11:05sdegutisjustin_smith: interestingly enough, I have done that in most places where I was using clostache (which I removed yesterday because it is a clustercluck on clojars and the latest version(s) are all broken with regard to dollar signs)
11:05sdegutisoh
11:05sdegutisjustin_smith: never mind my last statement to you then
11:05sdegutisjustin_smith: I'm always hesitant to make helper functions like that, but..
11:06sdegutisjustin_smith: yeah, even in this case I'm hesitant to extract a helper function (even if it's private) for very little gain
11:06justin_smithsdegutis: bonus with that approach is that things like {{{}}} etc. become much easier
11:06justin_smithor if you want things that call helpers in templates
11:06justin_smithetc.
11:07sdegutishm
11:07justin_smiththat is, the gain is more if you plan on allowing different kinds of substitution
11:07justin_smithif you only do that one kind? leave it as is, it's fine
11:07sdegutisjustin_smith: I see
11:08justin_smithand if you don't plan on doing more than simple substitution, why are you even writing this yourself? lots of libs do that
11:08sdegutisWow. It's hard to imagine that only a year ago I was interested in Haskell and seriously considered it a viable alternative to Clojure: http://sdegutis.github.io/2015-02-10/haskell/
11:09sdegutisThat blog post was extracted from an email I sent to my employers in hopes it might persuade them to consider Haskell instead of Clojure.
11:10justin_smithsdegutis: so if you had more than one kind of interpolation it would be like (comp (apply-key-to-template k v) (apply-escaped-key-to-template k v) (apply-helper-to-template k v)) where each returns a function that takes and returns the template itself
11:10sdegutisjustin_smith: ah I see now, neat
11:11sdegutisjustin_smith: that would be a cool start to an alternative templating library, possibly one with more configurability than clostache has
11:11justin_smithsdegutis: and you could have evil recursive templates if you repeat all steps until output string is equal to input
11:11justin_smithhaha
11:12sdegutisUnfortunately I don't believe I'd ever like such a library. My preferred templating library so far is (comp (partial apply str) (flatten))
11:12sdegutisOops I meant (comp (partial apply str) flatten)
11:13sdegutisSo that you can just return any number of levels of nested strings and then just string-build those suckers together.
11:13sdegutisThat works easiest with the sequence-transforming functions in clojure.core, e.g. for, reduce, range, take-while, etc.
11:14sdegutis~flatten
11:14clojurebotflatten is rarely the right answer. Suppose you need to use a list as your "base type", for example. Usually you only want to flatten a single level, and in that case you're better off with concat. Or, better still, use mapcat to produce a sequence that's shaped right to begin with.
11:14sdegutisWRONG clojurebot, you're WRONG
11:15rcassidyHeh
11:15justin_smith:b4
11:17sdegutis?
11:17justin_smithsdegutis: I added a plugin to my irc client, sometimes I use that plugin wrong
11:17sdegutissilly justin
11:18justin_smithsdegutis: you can pretend that says "C-u 4 M-x switch-to-buffer-by-number"
11:18sdegutishaha
11:19justin_smiththis is simple, but not yet familiar (I think a clojure user can recognize that these can be separate things)
11:19sdegutisoh for sure, I'm an Emacs user remember? :P
11:19sdegutisEmacs is as simple as it can be for my usage given my needs
11:20sdegutisanything simpler would cripple my productivity
11:20sdegutisalso I feel so bad for people who use vim
11:20sdegutislike, how can you get anything done in vim?
11:20justin_smithsdegutis: your sympathy is noted and appreciated.
11:20sdegutismaybe there is a way I just didn't learn about back when I used vim/mvim for a few years
11:21sdegutishaha justin_smith you dont use vim
11:21justin_smithsdegutis: I used evil for a while, it is an easy switch. I used evil because my wrists are mortal and are vulnerable to key chording.
11:21sdegutishaha
11:21sdegutisjustin_smith: but even when I did use vim, I was always using chords, because you just can't use vim without them
11:21sdegutisC-r "
11:21sdegutisthat's a common one
11:21justin_smithsdegutis: I know otherwise. I never use C-r "
11:22justin_smithI don't even know what that does
11:22sdegutishow do you paste from " then justin_smith?
11:22sdegutisjustin_smith: it's a way to paste from " which is like some special thing
11:22sdegutislemme go look it up
11:22justin_smith"*p pastes from my system clipboard
11:22sdegutishmm
11:22sdegutisoh wait
11:22justin_smith"<foo>p pastes from foo
11:22sdegutisi remember now i think
11:22sdegutisC-r " is like when you need to paste while you're in the fake-minibuffer-thing
11:23sdegutisthat's what it was
11:23justin_smithoh, I don't find myself doing that, maybe I'm not yet advanced enough for such things
11:23sdegutisi like how in emacs the minibuffer has the same commands as any other buffer for the most part, so you can backtrack with C-b and copy with M-w etc
11:23sdegutisjustin_smith: dont worry ull get there in time
11:24justin_smithsdegutis: the top priority for me is nothing I do average 10 times a minute or more should be a chord. In vim I have a workflow that pulls that off (given I can use alternate hand for the shift key)
11:26amalloybut where will you find time for piano practice?
11:27sdegutisamalloy: i dont get it
11:27justin_smithamalloy: some day the jazz world will appreciated my unique pointellistic style without chords
11:28amalloysdegutis: if the audience doesn't get it, it wasn't a joke after all
11:28sdegutisamalloy: i vaguely remember that i had practiced piano in like 2013, but i dont recall any association between that and our current vim vs emacs conversation
11:29amalloychords
11:29sdegutisamalloy: oh man wow yeah i got that it just seemed a little too obvious for an amalloy joke
11:30sdegutisbtw, ive given my kids piano sheet music for FFVII songs, and they're killin it
11:30sdegutisi love hearin that while i work, its amazing
11:31sdegutislike, right now, my 12yo son is playing Forested Temple on the piano by ear.. i go and ask him "where did you even hear that?" because he doesnt have sheet music for it, and he said "from your room [office]" lol!!
11:32justin_smithsdegutis: https://www.youtube.com/watch?v=Y-Elr5K2Vuo
11:34sdegutisalso he fricken did Rocky Maridia for his piano recital https://www.youtube.com/watch?v=nAR38Rf4ig4
11:34sdegutiswhich btw is a song off the Super Metroid soundtrack :D
11:41sdegutisI'm still trying to figure out the best way to use Components with a Router component. It feels very ugly to pass the whole system component into the Router component, but it feels even uglier to pass almost every single other component in the system through the router.
11:41sdegutisThis is on account of how the whole Router contains many different kinds of routes, each of which use only some of the system's components, but all of which use almost all of them (probably all except the router).
11:42sdegutisI suppose splitting the routes up and giving them to the Router, per justin_smith's previous suggestion, is one way of de-tangling this, but then each route needs to become its own Component, which feels unnecessarily heavy.
11:43justin_smithsdegutis: what about letting each component define middlewares, and composing those in your router
11:43justin_smithall stateful stuff would be provided via middleware, and not directly in the handler definition
11:43sdegutisIn my experience, Components and/or Records should only be used when a bit of functionality (1) needs to be started/stopped, (2) comes with configuration that it would like to have initialized with only once and carried with it through the lifetime of the system, or (3) I forgot #3.
11:44justin_smithsdegutis: right, and a middleware can be a bridge so that a handler (which the components need not know about / handle) can access something stateful
11:45sdegutisOh right, (3) is when the thing inherently affects an external service (such as sending a live email) and it would be handy to have a "fake" version of that thing.
11:46sdegutisAnd in #3, there would be a Protocol that handles the thing, a live Record and a fake (usually in-memory) Record which both implement the Protocol, which inherently conform to Components and can be reasonably considered a stand-alone component in a system.
11:46sdegutisjustin_smith: that's just an implementation technique of how to include all the system components in the router
11:47sdegutisjustin_smith: it still comes with the drawback of having all the individual system components being passed to the router and thus the individual routes (via the request map).
11:47justin_smithnot if you explicitly pass in only the middlewares - you can have each component optionally return a :middlewares key with a hash-map of keys to middleware provided
11:48justin_smiththen the exposure is just the middlewares you pass in
11:49sdegutisjustin_smith: afaiu, that's just a slight inversion of where the middlewares are defined; but the routes still need to access the component's provided functionality via a key in the request map, right?
11:50justin_smiththe component decides how its state / functionality is exposed
11:51justin_smithvia its definition of the middleware
11:51justin_smithI think that's going to allow clean isolation
11:53justin_smithfor example it can provide a query function, instead of a handle to the db itself
12:05sdegutisjustin_smith: I was thinking it would just provide itself to the request map; for example, the middleware would just (assoc request :db-conn db-conn-component), and then routes would access it via (:db-conn request) and use it like (myapp.interfaces.db-conn/query (:db-conn request)) assuming that query function lives in a Protocol or something.
12:05sdegutisAlso, I cleaned up my thoughts about Components and put them at http://sdegutis.github.io/2016-03-08/when-to-use-clojure-components/ for everyone here
12:06justin_smithsdegutis: but if you do it that way, you need to mock a db. If you provide a query facade, that's much easier to test with, you just pass in a stub for the query facade instead of needing to mock a db api.
12:06justin_smiththat's my theory at least.
12:07sdegutishmm
12:08RedNifreHey there clojuristas.
12:09RedNifre,(+ 1 2)
12:09clojurebot3
12:09RedNifreclojurebot step up your game, you're getting slow!
12:09RedNifre,(def y)
12:09clojurebot#'sandbox/y
12:10sdegutis,(def x #'x)
12:10clojurebot#'sandbox/x
12:10mokusohehe
12:10mavbozo,(get get get get)
12:10clojurebot#object[clojure.core$get 0x6ab31f44 "clojure.core$get@6ab31f44"]
12:10sdegutis,x
12:10clojurebot#'sandbox/x
12:10sdegutis,(x)
12:10clojurebot#error {\n :cause nil\n :via\n [{:type java.lang.StackOverflowError\n :message nil\n :at [clojure.lang.Var fn "Var.java" 363]}]\n :trace\n [[clojure.lang.Var fn "Var.java" 363]\n [clojure.lang.Var invoke "Var.java" 375]\n [clojure.lang.Var invoke "Var.java" 375]\n [clojure.lang.Var invoke "Var.java" 375]\n [clojure.lang.Var invoke "Var.java" 375]\n [clojure.lang.Var invoke "Var.java" 375]...
12:10sdegutisHAHAHA
12:10RedNifreThat output isn't that helpful in my case.
12:10RedNifreSee, I have troubles understanding what an unbound var is.
12:10justin_smithRedNifre: do you know what a var is?
12:11mokuso'(expt 2 2)
12:11mokuso,'(expt 2 2)
12:11clojurebot(expt 2 2)
12:11mokuso,(expt 2 2)
12:11clojurebot#error {\n :cause "Unable to resolve symbol: expt in this context"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to resolve symbol: expt in this context, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6688]}\n {:type java.lang.RuntimeException\n :message "Unable to resolve symbol: expt in this co...
12:11RedNifreWhen I do this in the REPL: (def y) (def x y) (def z) then it looks like x and y point to the same "nothing" but z points to a different "nothing".
12:11mokusomeh
12:11RedNifreWhat exactly does this output mean: #object[clojure.lang.Var$Unbound 0x15b5893c "Unbound: #'user/y"]
12:11mokuso,(math/expt 2 2)
12:11clojurebot#error {\n :cause "No such namespace: math"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: No such namespace: math, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6688]}\n {:type java.lang.RuntimeException\n :message "No such namespace: math"\n :at [clojure.lang.Util runtimeException "Util.java" 221]}]...
12:11justin_smithRedNifre: a var is a container. (def x y) points the container x to hold the uninitialized default value held in the container y
12:12RedNifreWhat's an uninitialized default value? It sounds like it's different from nil?
12:12mokuso,(Math/pow 2 2)
12:12clojurebot4.0
12:12justin_smithRedNifre: yes, it is
12:12justin_smith,(def x)
12:12clojurebot#'sandbox/x
12:12justin_smith,x
12:12clojurebot#'sandbox/x
12:12justin_smithahh, x already existed
12:12justin_smith,(def uninitialized)
12:12clojurebot#'sandbox/uninitialized
12:12sdegutis,(x x)
12:12clojurebot#error {\n :cause nil\n :via\n [{:type java.lang.StackOverflowError\n :message nil\n :at [clojure.lang.Var invoke "Var.java" 379]}]\n :trace\n [[clojure.lang.Var invoke "Var.java" 379]\n [clojure.lang.Var invoke "Var.java" 379]\n [clojure.lang.Var invoke "Var.java" 379]\n [clojure.lang.Var invoke "Var.java" 379]\n [clojure.lang.Var invoke "Var.java" 379]\n [clojure.lang.Var invoke "Var.ja...
12:12sdegutis,(x x x)
12:12justin_smith,uninitialized
12:12clojurebot#object[clojure.lang.Var$Unbound 0x1317c009 "Unbound: #'sandbox/uninitialized"]
12:12clojurebot#error {\n :cause nil\n :via\n [{:type java.lang.StackOverflowError\n :message nil\n :at [clojure.lang.Var invoke "Var.java" 383]}]\n :trace\n [[clojure.lang.Var invoke "Var.java" 383]\n [clojure.lang.Var invoke "Var.java" 383]\n [clojure.lang.Var invoke "Var.java" 383]\n [clojure.lang.Var invoke "Var.java" 383]\n [clojure.lang.Var invoke "Var.java" 383]\n [clojure.lang.Var invoke "Var.ja...
12:13mokuso,(Math/pow 2 (Math/pow 2 4))
12:13clojurebot65536.0
12:13mavbozo,(deref #'sandbox/uninitialized)
12:13clojurebot#object[clojure.lang.Var$Unbound 0x1317c009 "Unbound: #'sandbox/uninitialized"]
12:13RedNifreYeah, so there is this "Unbound" thing and it has this hex number. What's up with that?
12:13justin_smithRedNifre: an unbound var is automatically given that special value - an instance of clojure.lang.Var$Unbound
12:13justin_smithRedNifre: $ is jvm syntax for an inner class
12:13justin_smithUnbound is a class created inside Var
12:14RedNifreOkay, so there is a type Var$Unbound and every unbound var gets a newly created value of that type assigned?
12:14justin_smithunbound vars are initialized to hold an instance of unbound
12:14sdegutis,(apply apply (repeat 10 (constantly 9)))
12:14clojurebot#error {\n :cause "Don't know how to create ISeq from: clojure.core$constantly$fn__4614"\n :via\n [{:type java.lang.IllegalArgumentException\n :message "Don't know how to create ISeq from: clojure.core$constantly$fn__4614"\n :at [clojure.lang.RT seqFrom "RT.java" 542]}]\n :trace\n [[clojure.lang.RT seqFrom "RT.java" 542]\n [clojure.lang.RT seq "RT.java" 523]\n [clojure.core$seq__4357 invokeS...
12:14mavbozo,(type uninitialized)
12:14clojurebotclojure.lang.Var$Unbound
12:14justin_smithRedNifre: exactly
12:14RedNifreSo it's kinda like nil except that there's only one nil but many unbound?
12:14justin_smithRedNifre: and it's less ambiguous where an Unbound came from
12:14mavbozo,(def un-init-0)
12:14clojurebot#'sandbox/un-init-0
12:14justin_smithRedNifre: there's so many ways to generate or end up accidentally with nil
12:14mavbozo,(def un-init-1)
12:14clojurebot#'sandbox/un-init-1
12:15mavbozo,(= un-init-0 un-init-1)
12:15clojurebotfalse
12:15justin_smithRedNifre: the two ways to get an Unbound are to not yet bind a var, or create one on purpose
12:15RedNifreWell, but there's only one null in Java and null is thus equal to null. Is the same true for nil in Clojure? I gather that comparing two unbound vars would be false since they contain different unbounds?
12:15justin_smithRedNifre: nil is null
12:15justin_smiththere is no distinction
12:15justin_smithsame thing, two names
12:16RedNifreokay, so only one nil and it's equal to itself. got it.
12:17RedNifreAre nil and Unbound the only "nothings" in Clojure or are there more? E.g. JavaScript also has undefined which is what you get when you read from a nonexistant var (where Clojure would throw an exception).
12:18justin_smithhmm, does Double/NaN count?
12:18justin_smithdifferent kind of not a thing
12:18RedNifreI guess so, I mean NaN is for Doubles what null is for objects, huh?
12:18justin_smiththere's also a promise that is not realized
12:18justin_smithwhich is also different but kind of "nothing yet"
12:19sdegutisNaN is just weird, never use NaN
12:19sdegutisand never use Doubles or Floats.
12:19sdegutisPrefer to use Strings for all your number manipulation.
12:19justin_smithdoubles and floats would be less useful without NaN though
12:20RedNifreI'm not a fan of NaN either.
12:21justin_smithwould you prefer (/ 0.0 0.0) throw an exception?
12:21justin_smith(not to mention various usages of trig functions)
12:21mavbozo,(/ 0.0 0.0)
12:21RedNifreI'm not sure. Maybe.
12:21clojurebotNaN
12:21sdegutisIt's interesting how often I end up using (reduce).
12:22RedNifreIn the REPL, can I undef something?
12:22justin_smithRedNifre: yes, you can
12:22sdegutis'reduce' is the simplest functionally pure way of transforming something based on the current and any/all past elements in a sequence.
12:22RedNifreGreat. When I need it I'll ask how.
12:22justin_smithRedNifre: remembering...
12:23justin_smithns-unmap
12:23justin_smithI keep forgetting that name though, I keep wanting unintern or something
12:26RedNifreHm, how to use it? From (doc ns-unmap) I thought I should do (ns-unmap user y) but that complains about not finding user.
12:26justin_smithRedNifre: it wants symbols
12:26justin_smith(ns-unmap 'user 'y)
12:26justin_smiththat's why I expect it to be called unintern, intern also uses symbols
12:26RedNifreah.
12:27RedNifreHow do I fetch the current ns?
12:27justin_smith,*ns*
12:27clojurebot#object[clojure.lang.Namespace 0x29fac779 "sandbox"]
12:27sdegutis,(ns-unmap *ns* 'map)
12:27clojurebotnil
12:27justin_smithns-unmap will accept that value
12:27sdegutisHahahha stupid clojurebot.
12:27justin_smith,(map inc [0])
12:27clojurebot(1)
12:27sdegutis,(map inc [1 2 3])
12:27clojurebot(2 3 4)
12:27sdegutiswha?
12:28RedNifreDo these asterisks have a special meaning or is it just the name of the function?
12:28sdegutisOh, it probably creates a new *ns* every time? or something?
12:28sdegutis,*ns*
12:28clojurebot#object[clojure.lang.Namespace 0x29fac779 "sandbox"]
12:28sdegutis,*ns*
12:28clojurebot#object[clojure.lang.Namespace 0x29fac779 "sandbox"]
12:28sdegutishmmmmm
12:28justin_smithsdegutis: you maybe want ns-unalias
12:28sdegutisjustin_smith: no i dont think so
12:28sdegutisns-unmap worked locally for me
12:28justin_smith,(ns-unalias *ns* 'map)
12:28clojurebotnil
12:28sdegutisjustin_smith: alias is for things like str
12:28justin_smith,(map inc [0])
12:28clojurebot(1)
12:28sdegutisclojure.string :as str = alias
12:28justin_smithhrm
12:28justin_smithOK
12:28justin_smithsdegutis: must be clojurebot weirdness then
12:29sdegutis,(do (ns-unmap *ns* 'map) (map inc [1 2 3]))
12:29RedNifre,(def undef [symbol] (ns-unmap *ns* symbol))
12:29clojurebot#error {\n :cause "Unable to resolve symbol: map in this context"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to resolve symbol: map in this context, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6688]}\n {:type java.lang.RuntimeException\n :message "Unable to resolve symbol: map in this conte...
12:29clojurebot#error {\n :cause "Too many arguments to def"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Too many arguments to def, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyzeSeq "Compiler.java" 6875]}\n {:type java.lang.RuntimeException\n :message "Too many arguments to def"\n :at [clojure.lang.Util runtimeException "Util.jav...
12:29sdegutis,(map inc [1 2 3])
12:29clojurebot(2 3 4)
12:29RedNifre,(defn undef [symbol] (ns-unmap *ns* symbol))
12:29sdegutisWHA
12:29clojurebot#'sandbox/undef
12:29sdegutisi think whoever writes clojurebot wised up after i did this last time (2013 maybe?)
12:29RedNifre(def backupinc inc)
12:29RedNifre,(def backupinc inc)
12:29clojurebot#'sandbox/backupinc
12:29RedNifre,(undef inc)
12:29clojurebot#error {\n :cause "clojure.core$inc cannot be cast to clojure.lang.Symbol"\n :via\n [{:type java.lang.ClassCastException\n :message "clojure.core$inc cannot be cast to clojure.lang.Symbol"\n :at [clojure.core$ns_unmap invokeStatic "core.clj" 4048]}]\n :trace\n [[clojure.core$ns_unmap invokeStatic "core.clj" 4048]\n [clojure.core$ns_unmap invoke "core.clj" 4048]\n [sandbox$undef invokeStatic ...
12:30sdegutis,(ns-unmap 'clojure.core 'map)
12:30clojurebotnil
12:30sdegutis(map inc [1 2 3])
12:30sdegutis,(map inc [1 2 3])
12:30clojurebot#error {\n :cause "Attempting to call unbound fn: #'clojure.core/map"\n :via\n [{:type java.lang.IllegalStateException\n :message "Attempting to call unbound fn: #'clojure.core/map"\n :at [clojure.lang.Var$Unbound throwArity "Var.java" 43]}]\n :trace\n [[clojure.lang.Var$Unbound throwArity "Var.java" 43]\n [clojure.lang.AFn invoke "AFn.java" 36]\n [sandbox$eval399 invokeStatic "NO_SOURCE_FIL...
12:30sdegutisHAHAHAHA
12:30sdegutisoh wait
12:30sdegutisoops. sorry everyone.
12:30mike7,(loop for c across "abc" collect c)
12:30clojurebot#error {\n :cause "loop requires a vector for its binding in sandbox:"\n :via\n [{:type java.lang.IllegalArgumentException\n :message "loop requires a vector for its binding in sandbox:"\n :at [clojure.core$loop invokeStatic "core.clj" 4425]}]\n :trace\n [[clojure.core$loop invokeStatic "core.clj" 4425]\n [clojure.core$loop doInvoke "core.clj" 4419]\n [clojure.lang.RestFn invoke "RestFn.java...
12:30RedNifreHm, did you assign map to a backup var first or is it now gone forever?
12:31sdegutis,(do (ns clojure.core) (defn map "Returns a lazy sequence consisting of the result of applying f to the set of first items of each coll, followed by applying f to the set of second items in each coll, until any one of the colls is exhausted. Any remaining items in other colls are ignored. Function f should accept number-of-colls arguments. Returns a transducer when no collection is provided." {:added "1.0" :static true
12:31sdegutis} ([f] (fn [rf] (fn ([] (rf)) ([result] (rf result)) ([result input] (rf result (f input))) ([result input & inputs] (rf result (apply f input inputs)))))) ([f coll] (lazy-seq (when-let [s (seq coll)] (if (chunked-seq? s) (let [c (chunk-first s) size (int (count c)) b (chunk-buffer size)] (dotimes [i size] (chunk-append b (f (.nth c i)))) (chunk-cons (chunk b) (map f (chunk-rest s)))) (cons (f (first s)) (map f (rest s)
12:31sdegutis)))))) ([f c1 c2] (lazy-seq (let [s1 (seq c1) s2 (seq c2)] (when (and s1 s2) (cons (f (first s1) (first s2)) (map f (rest s1) (rest s2))))))) ([f c1 c2 c3] (lazy-seq (let [s1 (seq c1) s2 (seq c2) s3 (seq c3)] (when (and s1 s2 s3) (cons (f (first s1) (first s2) (first s3)) (map f (rest s1) (rest s2) (rest s3))))))) ([f c1 c2 c3 & colls] (let [step (fn step [cs] (lazy-seq (let [ss (map seq cs)] (when (every? identity ss)
12:31clojurebot#<RuntimeException java.lang.RuntimeException: EOF while reading>
12:31sdegutis (cons (map first ss) (step (map rest ss)))))))] (map #(apply f %) (step (conj colls c3 c2 c1)))))))
12:31sdegutishmm
12:31sdegutisyeah we'll just have to wait til clojurebot resets its jvm which afaik happens every few minutes
12:31sdegutismy bad.
12:31RedNifreOr you just write a new map, using for or something :)
12:32sdegutisSmart RedNifre.
12:32sdegutis,map
12:33clojurebot#object[clojure.core$map 0x753294f6 "clojure.core$map@753294f6"]
12:33sdegutisits back i guess
12:34RedNifre,(defn varargs [a & b] (vector a b))
12:34clojurebot#'sandbox/varargs
12:34RedNifre,(varargs 1 2)
12:34clojurebot[1 (2)]
12:34RedNifre,(varargs 1)
12:34clojurebot[1 nil]
12:34RedNifreWhy does the vararg parameter turn into nil instead of () ?
12:35sdegutis,(apply (repeat 5 varargs))
12:35clojurebot#error {\n :cause "Wrong number of args (1) passed to: core/apply"\n :via\n [{:type clojure.lang.ArityException\n :message "Wrong number of args (1) passed to: core/apply"\n :at [clojure.lang.AFn throwArity "AFn.java" 429]}]\n :trace\n [[clojure.lang.AFn throwArity "AFn.java" 429]\n [clojure.lang.RestFn invoke "RestFn.java" 412]\n [sandbox$eval118 invokeStatic "NO_SOURCE_FILE" 0]\n [sandbox...
12:35RedNifreIs it because nil is falsy so it's easier to check whether there are any extra args?
12:35sdegutis,(apply apply (repeat 5 varargs))
12:35clojurebot#error {\n :cause "Don't know how to create ISeq from: sandbox$varargs"\n :via\n [{:type java.lang.IllegalArgumentException\n :message "Don't know how to create ISeq from: sandbox$varargs"\n :at [clojure.lang.RT seqFrom "RT.java" 542]}]\n :trace\n [[clojure.lang.RT seqFrom "RT.java" 542]\n [clojure.lang.RT seq "RT.java" 523]\n [clojure.lang.RT cons "RT.java" 662]\n [clojure.core$cons__4331 ...
12:35sdegutisI'm confused.
12:35sdegutisRedNifre: because it probably uses 'next
12:35RedNifre,(varargs 1 2 3 4)
12:35clojurebot[1 (2 3 4)]
12:36RedNifresdegutis I don't understand that explanation, what's 'next?
12:36sdegutis,(map (juxt next rest) [[] [1] [1 2]])
12:36clojurebot([nil ()] [nil ()] [(2) (2)])
12:36sdegutisHmm. That wasn't very clear.
12:36sdegutisRedNifre: sorry i meant #'next but yeah i could be wrong
12:36RedNifreWell, I understand nothing since I just started with the Joy of Clojure book :)
12:37sdegutisRedNifre: ok
12:37sdegutisbbl
12:38RedNifreSpeaking of JoC, they write that they prefer to always use numbered % e.g. #(bla %1). I find that strange, why number parameters if there's only one? Isn't #(bla %) simpler in this case? Why number it?
12:39ridcully% is just fine; using %1 %2 i find polite to signal, that there is some higher arity at work
12:42RedNifre,(defn fib ([1] 1) ([2] 1) ([n] (- n 2) (- n 1))))
12:42clojurebot#error {\n :cause "Unsupported binding form: 1"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.Exception: Unsupported binding form: 1, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyzeSeq "Compiler.java" 6875]}\n {:type java.lang.Exception\n :message "Unsupported binding form: 1"\n :at [clojure.core$destructure$pb__5167 invoke "core.clj" ...
12:42RedNifreWhat's the correct way to write what I mean?
12:42sdegutisHi!
12:42RedNifrehowdy
12:42RedNifre,(defn fib ([1] 1) ([2] 1) ([n] (- n 2) (- n 1))))
12:42clojurebot#error {\n :cause "Unsupported binding form: 1"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.Exception: Unsupported binding form: 1, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyzeSeq "Compiler.java" 6875]}\n {:type java.lang.Exception\n :message "Unsupported binding form: 1"\n :at [clojure.core$destructure$pb__5167 invoke "core.clj" ...
12:42RedNifre:/
12:42amalloyRedNifre: there's no pattern matching
12:43amalloybut also (- n 2) (- n 1) doesn't make sense even if there were
12:43RedNifrewhy not?
12:43RedNifreYeah, I meant ([n] (+ (fib (- n 2)) (fib (- n 1))))
12:44RedNifreSo how to write this correctly then?: (defn fib ([1] 1) ([2] 1) ([n] (+ (fib (- n 2)) (fib (- n 1)))))
12:47ridcullyRedNifre: http://rosettacode.org/wiki/Fibonacci_sequence#Clojure
12:49sdegutisGood evening.
12:50sdegutisamalloy: hmm, his pattern matching idea would be really cool though
12:50sdegutisIt'd be like a version of defn that has core.match built in.
12:50sdegutisThat said, I would have basically no need for it ever.
12:50sdegutisThe only time I /might/ use it is to replace uses of defmulti/defmethod.
12:50sdegutisBut even then, I might as well just use (case x) within the (defn foo [x] ...)
12:51RedNifreThanks for the rosetta link ridcully. Hm, core.match sounds like it might be interesting as well, I'll check that out next.
12:51justin_smiththe big gotcha is if you combine core.match with things like core.logic or core.async in the same code, it is easy to get method-too-large errors
12:52RedNifrewhat's a method-too-large error?
12:52justin_smiththe jvm has a maximum method size for the resulting bytecode
12:52ridcullyRedNifre: there is also https://github.com/killme2008/defun - i have never tried it, but it looks like it could make your initial version working (it uses core match under the hood)
12:53justin_smithRedNifre: since core.async, core.logic, and core.match all do a lot of code generation, combining them can hit that limit
12:53RedNifreUhm, I thought the bytecode limit was 64KiB? Shouldn't that be enough for everybody?
12:53justin_smithRedNifre: you haven't macroexpanded core.async code have you
12:55RedNifrehuh, interesting.
12:55RedNifredid that ever happen to you? if so, what did you do about it?
12:55amalloyi mean, core.match has something like defn built in. defne or something
12:55justin_smithRedNifre: https://gist.github.com/noisesmith/0fd7db0d239113c1d0c8
12:55amalloyRedNifre: you can macroexpand into some pretty silly stuff
12:56amalloyi actually saw a co-worker go over the 64KB limit in java
12:56RedNifreI'm new to clojure so I don't know what "macroexpand" means. Does it mean looking at the code that gets compiled after all macros got expanded?
12:57justin_smithRedNifre: exactly
12:57amalloybasically by trying to hard-code a several-megabyte Map<String, String>, using sed or something to produce a series of .put calls from a text file
12:57justin_smithamalloy: nice
12:57RedNifreokay, so core-async sounds like it contains macros that add a lot of "synchronized" and locks and stuff like that everywhere?
12:58amalloyRedNifre: a lot of things you do are macros underneath, some of them quite involved
12:58amalloy,(macroexpand-1 '(for [x (range 10), y [x (- x)]] (/ y 10)))
12:58clojurebot(clojure.core/let [iter__5216__auto__ (clojure.core/fn iter__27 [s__28] (clojure.core/lazy-seq (clojure.core/loop [s__28 s__28] (clojure.core/when-first [x s__28] (clojure.core/let [iterys__5212__auto__ (clojure.core/fn iter__29 [s__30] (clojure.core/lazy-seq #)) fs__5213__auto__ (clojure.core/seq (iterys__5212__auto__ #))] (if fs__5213__auto__ (clojure.core/concat fs__5213__auto__ (iter__27 #)) (...
12:58hiredmanthe go macro in core.async doesn't expand to any calls to thing like syncronized (locking)
12:58RedNifreWell, generating a lot of .put calls in Java from a text file through sed is kinda the same as using macros in clojure, huh?
12:58amalloywell, try that in your repl; it's much too large to fit here
12:59RedNifrecan macros read external files?
12:59hiredmanthe locking is all inside the channel operations
12:59amalloyRedNifre: the difference is that in clojure you can use clojure
12:59sdegutis,(defn correct-answer-for [q] (->> q (reverse) (apply str) (read-string) (name) (reverse) (apply str)))
12:59clojurebot#'sandbox/correct-answer-for
12:59sdegutis,(correct-answer-for "Which is better? Ice cream or pizza")
12:59amalloyin java you ahve to use sed
12:59clojurebot"pizza"
12:59sdegutis,(correct-answer-for "sdegutis is better at Clojure than amalloy: true or false")
12:59clojurebot"false"
12:59RedNifrei.e. could I have a macro (big-string-map-from-file "stuff.txt") that expands into a giant map with the text file in it?
12:59sdegutis,(defn correct-answer-for [q] (->> q (reverse) (apply str) (read-string) (name) (reverse) (apply str) (read-string)))
12:59clojurebot#'sandbox/correct-answer-for
13:00amalloyRedNifre: you can, but you generally shouldn't
13:00ridcullyRedNifre: yes, that works. i found that a nice way to have configs etc in clojurescript
13:01sdegutis,(defn correct-answer-for [q] (->> q (reverse) (apply str) (read-string) (name) (reverse) (remove #{\?}) (apply str) (read-string)))
13:01clojurebot#'sandbox/correct-answer-for
13:01justin_smithRedNifre: https://gist.github.com/noisesmith/db3b90abb6b9e5f7f282
13:01sdegutis(correct-answer-for "Will the Bears ever win the super bowl again? I mean, probably not, right?")
13:01sdegutis,(correct-answer-for "Will the Bears ever win the super bowl again? I mean, probably not, right?")
13:01clojurebotright
13:01sdegutisBest function ever.
13:02sdegutis,(correct-answer-for "Who's better at Clojure than rhickey?")
13:02clojurebotrhickey
13:02sdegutistouché clojurebot.
13:04RedNifreWow, those macro expands look incomprehensible to me.
13:04justin_smithhey, I pprinted the second one
13:04RedNifre,(correct-answer-for "Which language should I use when I'm done learning Clojure?")
13:04clojurebotClojure
13:04RedNifrehmkay.
13:05RedNifre,(correct-answer-for "Whazzap?")
13:05clojurebotWhazzap
13:05justin_smithRedNifre: usually the macroexpansion is irrelevant if the macro is well written and used properly, there's just the size gotcha, as I was mentioning, for the crazy ones
13:06justin_smithones where a whole mini language is implemented in a macro
13:06RedNifreYeah, I get that. You saved me from future "Hey, why is my jar so big?"-moments.
13:06justin_smithwell, the expanded code shouldn't usually end up in the jar
13:06justin_smithand you can avoid aot too pretty easily
13:06RedNifrehuh?
13:07RedNifreI thought macros always expand? Or can you compile them as function calls?
13:07justin_smithRedNifre: all you need in a jar is the clojure source.
13:07RedNifrehmmmm
13:07justin_smiththe expansion happens at compilation, which in clojure happens during startup usually.
13:07RedNifreI thought that was unusual and you usually compile to java bytecode?
13:08justin_smithRedNifre: avoiding aot if possible is usually better almost always
13:08RedNifreThat's surprising. Why?
13:08RedNifreWhat's the advantage of a jar full of source code other than the jar size?
13:09justin_smithwhen you aot compile you can end up in a state where the source code conflicts with the byte code on disk
13:09justin_smithwacky scenarios like two classes with the same exact name that are not identical
13:10justin_smithand one extends the protocol you are using and the other does not
13:10justin_smithmost of it comes down to caching issues I think, since laoding byte code and loading the source are two equally valid ways to get the same ns
13:12OscarZ_anyone familiar with cemerick/friend ring auth library?
13:13sdegutisGood morning.
13:14justin_smithRedNifre: also, when you deploy a library, to compile your byte code means you tie your user to the exact library code you developed with, which can interfere with the correctness of their own code
13:15justin_smithso while aot in an app is debatable (I'd argue minimize the amount of code that gets aot compiled as much as possible), you should strictly never aot compile libraries if you want anyone to ever use them
13:28RedNifreI understand that the JVM has no tail call optimization... but why do I have to use recur? Can't the compiler figure out that I want TCO whenever possible?
13:29justin_smithRedNifre: yes, but by requiring the usage of recur we can catch the otherwise common error that someone assumes TCO is applied where it can't be
13:29justin_smithRedNifre: this is a big problem in cl / scheme worlds where it is implicit
13:29RedNifrefair point.
13:30justin_smithbecause you don't even see the problem until you get a big enough stack at runtime
13:56OscarZ_i have a compojure route like this (route/resources "/static") and i'd like to secure this with cemerick/friend library.. i can use macro called "authenticated" to protect any function, but i guess in this case i dont have a function
14:52sdegutisOscarZ_: I've avoided Friend because its API design didn't quite fit into my application. It's not hard to roll your own solution though.
15:39justin_smithI've avoided friend because I'm just too dumb to figure out how I should use it
16:05sdegutisWhy is this returning nil?
16:05sdegutis,(re-matches #"\<h1\>" "<h1>foo")
16:05clojurebotnil
16:06sdegutisHelp me #clojure, you're my only hope.
16:06TMA,(re-matches #"<h1>" "<h1>foo")
16:06clojurebotnil
16:07TMA,(re-matches #"[<]h1[>]" "<h1>foo")
16:07clojurebotnil
16:07TMAsdegutis: no idea. everything apparently does
16:08sdegutis,(re-matches #".*\<h1\>.*" "foo<h1>bar")
16:08clojurebot"foo<h1>bar"
16:08sdegutisThat almost works:
16:08sdegutis,(re-matches #".*\<h1\>.*" "quux \n foo<h1>bar")
16:08clojurebotnil
16:08sdegutisBut it ignores everything after the first newline.
16:08TMA,(re-matches #"\<h1\>" "<h1>")
16:08clojurebot"<h1>"
16:09TMA,(re-matches #"\_.*\<h1\>" "<h1>")
16:09clojurebotnil
16:09TMA(doc re-matches)
16:09justin_smith,(re-matches #"<h1>" "<h1>")
16:09clojurebot"([re s]); Returns the match, if any, of string to pattern, using java.util.regex.Matcher.matches(). Uses re-groups to return the groups."
16:09clojurebot"<h1>"
16:09justin_smithyou don't need to escape anything in that re
16:09justin_smithand it needs to match the whole string, not just a substring
16:10TMA,(re-matches #"(.|\n)*\<h1\>" "<h1>")
16:10clojurebot["<h1>" nil]
16:10sdegutisOh.
16:10TMA,(re-matches #"(?:.|\n)*\<h1\>" "<h1>")
16:10clojurebot"<h1>"
16:10justin_smithTMA: you don't need to escape < or >
16:10justin_smith,(re-matches #"<h1>\w+" "<h1>foo")
16:10clojurebot"<h1>foo"
16:11TMAjustin_smith: yeah, i have read that when you told it before, it does not hurt either
16:11sdegutisHmm, I'm going about this all wrong.
16:11justin_smithit hurts readability
16:11justin_smith,(re-matches #"<h1>(\w+)" "<h1>foo")
16:11clojurebot["<h1>foo" "foo"]
16:11TMAsdegutis: use (?:.|\n)* instead of .*
16:11sdegutisGiven a multi-line string, how can return all occurreeanncces of #"<h\d>" ?
16:12sdegutisI have no idea how to spell ocurances.
16:12TMAsdegutis: occurences
16:12sdegutisYou sure? That doesn't look right.
16:12sdegutisocurrances?
16:12TMAnothing does at the moment
16:12justin_smiththere's also a flag to make . match newlines
16:13TMAsdegutis: I am patently sure there is no -a- in that word
16:13sdegutisI'm not so sure.
16:13sdegutisjustin_smith: how do you specify that flag in a regex Clojure literal?
16:13sdegutis,#"foo"g
16:13clojurebot#"foo"
16:13sdegutisHmm.
16:13sdegutis,#"foo" you suck
16:13clojurebot#"foo"
16:13sdegutishahah clojurebot sucks
16:14sdegutisOh!
16:14sdegutis(?m) at the beginning?
16:14sdegutisYes!
16:14justin_smith,(re-matches #"(?m).*<h1>(\w+)" "\n <h1>foo")
16:14clojurebotnil
16:14sdegutis(re-find #"(?m)(<h1>)" "foo\nbar<h1>quux")
16:14sdegutis,(re-find #"(?m)(<h1>)" "foo\nbar<h1>quux")
16:14clojurebot["<h1>" "<h1>"]
16:14justin_smithsdegutis: hmm, worked in my local
16:14sdegutisYay!
16:15justin_smithnice
16:15TMAsdegutis: there are two -r-s but still no -a-: http://www.merriam-webster.com/dictionary/occurrence
16:15sdegutisTMA: I'm not so sure.
16:15sdegutis"occurrence"
16:16sdegutishuh, yeah
16:16sdegutisweird.
16:17sdegutisWoo!
16:17sdegutis,(re-seq #"(?m)<h\d>" "foo\nbar<h1>quux<h2>")
16:17clojurebot("<h1>" "<h2>")
16:17sdegutistake THAT, clojurebot!
16:20backnforth hiberno
16:20backnforthHey
16:20backnforthShould I use sequences or lists?
16:23backnforthSorry.. I'm new to clojure.
16:23TMAsdegutis: it is a common misspelling (because there are other words like "happenstance" where there is a -stance and there is -currant (blackcurrant) with an -a-) -- the reason for the -e- is that in latin the verb is occurro, occurrere, occurri, occursum; with present participle occurrens [from the unprefixed curro, currere, cucuri, cursum there is english current, currency, course, ...]
16:24TMAbacknforth: lists are a specific kind of sequences
16:24sdegutisbacknforth: lists, always lists
16:24sdegutisbacknforth: avoid anything that conforms to (sequence?), always use lists
16:25TMAbacknforth: notwithstanding the advice of sdegutis, I would consider arrays or lazy sequences too, on a case-by case basis
16:25sdegutis,(map (juxt sequential? map? list? vector? seq?) [() [] #{} {} (lazy-seq)])
16:25clojurebot([true false true false true] [true false false true false] [false false false false false] [false true false false false] [true false false false true])
16:26backnforthSequences are a multi dimensional list to my understanding. Although, yes I would prefer to use arrays.
16:26sdegutis,(map (juxt sequential? map? set? list? vector? seq?) [() [] #{} {} (lazy-seq)])
16:26clojurebot([true false false true false ...] [true false false false true ...] [false false true false false ...] [false true false false false ...] [true false false false false ...])
16:26sdegutisbacknforth: see that clode
16:26sdegutisbacknforth: clode is short for Clojure code. It's a shorthand way of saying "Clojure code"
16:27backnforthI don't understand. I'm new to lisp structured.
16:28backnforthBut yes, there are other structures I could use.
16:29TMAbacknforth: if you need to quickly prepend an item to a beginning of a sequence, use lists. if to the end, use vector, if you need random element access (give me the 3rd, give me the 7th, ...) use vector
16:29TMAbacknforth: if the data might be infinite (like sequence of all primes) use lazy-seq
16:30TMAbacknforth: if the computation is expensive and you might not need all the elements use lazy-seq
16:32backnforthI assume lazy-sequences have better jumps.
16:32TMAbacknforth: and finally, when you need a set use a set, whereas when you need a key->value store use a map
16:33backnforthWhat are sets?
16:34TMAbacknforth: #{} ... you represent whether an element belongs to/is contained in the set
16:35TMAbacknforth: instead of list of visited nodes, you keep a set of them, so that you do not need to traverse the entire list every time to find out, whether a node was visited
16:36backnforthAh
16:37backnforthI should read on sets.. How do I works with the values in a list.. I can't find anything about them in the clojure.org reference
16:40TMAbacknforth: you mostly take the value out of the list and work with the value -- there is nothing magical with the value caused by it being (also) in a list
16:42backnforthI'm looking for syntax
16:42TMAbacknforth: say you have a list of your friends, say Jo, Alex and Xi ... if you write the list of friends somewhere you still interact with the persons the same way as if there were no list
16:43TMAoh
16:43TMAconj prepends an element to a list
16:43TMA,(first '(a b c))
16:43clojurebota
16:43TMA,(rest '(a b c))
16:43clojurebot(b c)
16:44TMAand you can use first and rest to get to the elements
16:44TMA,(conj '(a b c) 'd)
16:44clojurebot(d a b c)
16:45TMAto get to the b you can:
16:45TMA,(first (rest '(a b c)))
16:45clojurebotb
16:45backnforthHow do I simply read the value? And how do I read the index?
16:46TMAin list there is no index
16:47TMAbacknforth: I have shown you how to read the first and second element of the list.
16:47justin_smithbacknforth: you can get an item by index with nth, but you can't find any info about the list (including index or anything else) from the item
16:47sdegutisTMA: i dont think lazy seqs are still recommended for infinite data
16:47sdegutisTMA: i think the new recommended approach is transducers
16:47justin_smith,(nth 3 [:a :b :c :d :e :f :g :h])
16:47clojurebot#error {\n :cause "clojure.lang.PersistentVector cannot be cast to java.lang.Number"\n :via\n [{:type java.lang.ClassCastException\n :message "clojure.lang.PersistentVector cannot be cast to java.lang.Number"\n :at [sandbox$eval121 invokeStatic "NO_SOURCE_FILE" -1]}]\n :trace\n [[sandbox$eval121 invokeStatic "NO_SOURCE_FILE" -1]\n [sandbox$eval121 invoke "NO_SOURCE_FILE" -1]\n [clojure.lang....
16:48justin_smith,(nth [:a :b :c :d :e :f :g :h] 3)
16:48clojurebot:d
16:51backnforthList test[:a :b :c]
16:51backnforth,(nth test 3)
16:51clojurebot#error {\n :cause "nth not supported on this type: core$test"\n :via\n [{:type java.lang.UnsupportedOperationException\n :message "nth not supported on this type: core$test"\n :at [clojure.lang.RT nthFrom "RT.java" 888]}]\n :trace\n [[clojure.lang.RT nthFrom "RT.java" 888]\n [clojure.lang.RT nth "RT.java" 854]\n [sandbox$eval169 invokeStatic "NO_SOURCE_FILE" 0]\n [sandbox$eval169 invoke "NO...
16:52backnforthlist test [:a :b :c]
16:52backnforth,(nth test 3)
16:52clojurebot#error {\n :cause "nth not supported on this type: core$test"\n :via\n [{:type java.lang.UnsupportedOperationException\n :message "nth not supported on this type: core$test"\n :at [clojure.lang.RT nthFrom "RT.java" 888]}]\n :trace\n [[clojure.lang.RT nthFrom "RT.java" 888]\n [clojure.lang.RT nth "RT.java" 854]\n [sandbox$eval193 invokeStatic "NO_SOURCE_FILE" 0]\n [sandbox$eval193 invoke "NO...
16:53backnforthlist test [:a :b :c] ,(nth test 2)
16:53TMAbacknforth: saying "list test whatever" does not have any effect on clojurebot
16:53backnforthWas that the right syntax?
16:54sdegutisbacknforth: that's closer to haskell
16:54ddellacosta&(let [test [:a :b :c]] (nth test 2))
16:54TMA,(let [variable [:a :b :c]] (nth variable 2))
16:54ddellacostaoh, guess lazybot no longer runs
16:54clojurebot:c
16:54ddellacosta,(let [test [:a :b :c]] (nth test 2))
16:54clojureboteval service is offline
16:55ddellacostayeah, thanks so much hiredman
16:55ddellacostanevermind
16:55TMA,test
16:55clojurebot#object[clojure.core$test 0x45d4887d "clojure.core$test@45d4887d"]
16:55backnforth,variable
16:55clojurebot#error {\n :cause "Unable to resolve symbol: variable in this context"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to resolve symbol: variable in this context, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6688]}\n {:type java.lang.RuntimeException\n :message "Unable to resolve symbol: variabl...
16:56backnforth,test
16:56clojurebot#object[clojure.core$test 0x45d4887d "clojure.core$test@45d4887d"]
16:56TMAbacknforth: test is a name, that is already predefined
16:56backnforthI like you, clojurebot.
16:56TMAbacknforth: on the other hand, variable is not predefined
16:57backnforthOk
16:57TMAthat's why there is a difference when evaluating them
17:32GroundhogTestMy speclj tests will not fail.
17:35justin_smithGroundhogTest: are you doing the classic (should [1] vector-of-1) thing and forgetting the =?
17:36justin_smithactually maybe that only happens in clojure.test
17:37GroundhogTestI don't think so. I was using (around [it] (with-out-str it)), though.
17:38GroundhogTestRemoved that, added a throw to my first test, and finally got a failure
17:38justin_smithinteresting
17:38justin_smithyeah, I just checked, should doesn't take multiple args like clojure.test/is anyway
17:41GroundhogTestThinking about putting the around call back in to confirm, but hesitant to make my tests completely useless on purpose
18:55backnforthHow do I create an incrementing for loop like for(i=0;i<n;i++) ... is it: for((range n n+4))
18:57rhg135my brain hurts from the lack of intent. I think that'd be like (dotimes [i 4] ...)
18:58amalloyrhg135: don't provice useless answers to useless questions. figure out how to get enough information that the question becomes useful
18:59backnforthI'm just looking to do a basic loop
19:00backnforthusing some constant as a range
19:00backnforth... the reason for doing is to interact through a list to compare its values with some other value.
19:00rhg135amalloy: usually I would, but the sensible part of my brain is asleep
19:00rhg135or dead or stuff
19:05backnforthHow would I iterate through some list, compare its values with some value, then put values into a new list?
19:05backnforthThe program is to: take some value n, check the list if there exist some value n, then put the locations that n exist in the list into some other list.
19:08backnforthI really want to learn clojure
19:16amalloybacknforth: what do you mean, the locations? what is a location?
19:20rhg135probably indices
20:42troydmlet's say I have character \space, how do I make Clojure print it in a form of \space instead of space character, e.g. unescaped form?
20:47Malnormaluloquote it?
20:47Malnormalulo,'\space
20:47clojurebot\space
20:48Malnormalulonope nevermind that doesn't work for print. Hm, that's a puzzle
20:50amalloy,(pr \space)
20:50clojurebot\space
20:50amalloydon't use print for anything except like...honestly there are not a lot of good reasons to use print
20:51amalloythe pr family of functions is great for printing data readably and unambiguously, and print does a mediocre job of producing human-friendly text
21:02troydmamalloy: thx
21:02troydmalso is there a way to attach comment to variable definition
21:02troydmwhen u defn function you can add description to it
21:03troydmbut I was wondering if it's possible to add description to arbitary variable too
21:03troydmCommon Lisp has this kind of functionality I think
21:07Malnormalulotroydm: def accepts doc strings before the value
21:07troydm,(def a "doc" 1)
21:07clojurebot#'sandbox/a
21:07troydm,(pr a)
21:07clojurebot1
21:08troydmic, thx
21:08Malnormalulo,(meta (def a "doc" 1))
21:08clojurebot{:line 0, :column 0, :file "NO_SOURCE_PATH", :doc "doc", :name a, ...}
21:13TimMcamalloy: What do you mean? println is great when you want to print strings.
21:14amalloyokay true. if you have something that's already a string, print and friends are good
21:16troydmalso I've deftype'd some type and I defn'd some mytype? function which is basicly (= (type %) mytype) is this correct way to handle checking if object is of particular type?
21:23MalnormaluloIt should work, but you might consider using a protocol instead, if you've got a method whose behavior depends on its argument's type
21:25Malnormalulo*if you've got a function
21:25Malnormalulo(curse my hours every day spent in Java)
22:50ajb-Why is bit shift left output on the jvm different from the output in the browser?
22:50TimMcajb: Different numerics between JVM and JS.
22:50TimMcExample?
22:51ajb,(bit-shift-left 53245 16)
22:51clojurebot3489464320
22:51ajbso that's the jvm, and the js output of `53245 << 16` is -805452285
22:53amalloyjavascript doesn't have integers
22:53amalloyso a lot of things are wacky
22:55TimMc1 << 32 // 1
22:56TimMc,(bit-shift-left 1 32)
22:56clojurebot4294967296
22:56TEttinger,(unchecked-int (bit-shift-left 1 32))
22:56clojurebot0
22:57TEttingerajb: I'd strongly distrust JS when it tries to do any bit twiddling
22:58ajbyeah, well I need to since I am trying to render reagent on the server and react requires a checksum for the dom
22:58ajbI wish I didn't have to do any of this in js
22:58TEttingerI'd check for any libs that can compute the checksum
22:59TEttingerthere may be someone who did this already
23:03TEttingernot sure how easy it is to call JS from CLJS, but this might be port-able http://stackoverflow.com/a/3276730
23:03ajbin cljs it does <<, I'm trying to get the same behavior in clj
23:04TEttingerah.
23:04TEttingerwell cljs would be doing that on a float or double, I think, since JS doesn't have integers as amalloy said
23:05kveyjs converts the number type to 32 bit ints for bitwise operations (via research)
23:07TEttinger,(unchecked-int (bit-shift-left 53245 16))
23:07clojurebot-805502976
23:08TEttingerlooks like what you want, almost. the lower bits are off
23:09TEttinger,(Long/toHexString -805452285)
23:09clojurebot"ffffffffcffdc603"
23:10TEttingerthat is not shifted over by 16...
23:10TEttinger,(Long/toHexString (unchecked-int (bit-shift-left 53245 16)))
23:10clojurebot"ffffffffcffd0000"
23:11TEttingerit looks like the shift filled the lower bits with garbage?
23:11TEttingerin the JS one
23:11TEttingerthanks kvey for the 32-bit tip
23:12TEttingeroh. herp derp me
23:12kveywelcome - ajb and I work together
23:13TEttinger,(let [b (Long/toBinaryString (bit-shift-left 53245 16))] [b (count b)])
23:13clojurebot["11001111111111010000000000000000" 32]
23:13ajboh, derp
23:13TEttingerI think it may be outside 32 bits
23:14ajbI just forgot to apply the bit-or to the return value
23:14TEttingerah ok
23:14TEttingerbit-or?
23:14TEttingerI was thinking bit-and
23:14ajbbut thank you, uncheck-ing it made it work
23:14TEttingerah ok! good
23:15TEttingerunchecked-XXX stuff is also pretty fast
23:15TEttingerit's using something very similar to what Java would output in the same set of calls with operators on primitives
23:15kveythanks! - I'd tried uncheck-int'ing the parameters but not the return value haha
23:16TEttingeryeah, surprising that clojure on JVM doesn't have smaller sizes of bit-whatever ops
23:16kveythe unchecked-int should be what's padding the result with garbage like that right?
23:17kveywhereas int throws an exception
23:18TEttingerno, I don't think so
23:18TEttingerhm
23:19TEttinger,(unchecked-int 0xffff0001)
23:19clojurebot-65535
23:19TEttingercorrect
23:19TEttinger,(unchecked-int 0x00000001)
23:19clojurebot1
23:19TEttinger,(unchecked-int 0xf00000001)
23:20clojurebot1
23:20TEttingeryeah, that last one truncated the bits above 32 correctly
23:21TEttingerunchecked casts are useful for when you want something to replicate java or possibly other languages' behavior
23:23TEttingerI think the garbage in the JS version (JVM had 16 0 bits where it had shifted over, JS has 16 random-seeming bits) was maybe the bit-or thing ajb mentioned and was a result of a later step?
23:23TEttingerso not actually garbage data, intentional just from a source I can't see
23:25kveyah I see
23:25kveymakes sense
23:59TimMc,(Long/toBinaryString -805502976)
23:59clojurebot"1111111111111111111111111111111111001111111111010000000000000000"