2014-10-30
| 00:00 | justin_smith | chenglou: kind of figures - and then each of those items would know how to compare to one another |
| 00:01 | justin_smith | starting with "if they are they same object yes, if they have different hash-codes no" and working forward from there I guess |
| 00:01 | bbloom | oooo i did install the legacy java package on my mac b/c it apparently uninstalled the old sdk |
| 00:02 | chenglou | yeah. Someone ping me if they discover a magical, collision-free hash that can be modified in constant time =) |
| 00:02 | bbloom | when i launched intellij for the first time after yosemite |
| 00:02 | justin_smith | chenglou: lol |
| 00:02 | bbloom | could that have something to do with it? |
| 00:03 | justin_smith | different default heap sizes would be the first difference I would think of |
| 00:06 | bbloom | $ lein pprint |
| 00:06 | bbloom | Error occurred during initialization of VM |
| 00:06 | bbloom | Too small initial heap |
| 00:06 | bbloom | hmmm |
| 00:08 | technomancy | 32-bit jdk? |
| 00:10 | bbloom | technomancy: java -version reports 64-bit server 1.7.0_09 |
| 00:11 | bbloom | i'm not sure how to set the system default heap size for jvm |
| 00:12 | bbloom | computers hate me |
| 00:13 | bbloom | JAVA_OPTS='-Xmx768M' lein repl <- seems to do the trick |
| 00:13 | bbloom | i guess i can just put that in my shell rc |
| 00:14 | bbloom | technomancy: or is that a terrible idea that will break my computer in some unexplained way 6 months from now? |
| 00:22 | justin_smith | Raynes: amalloy: one of you have a template for what the mongodb config for .lazybot/config.clj would look like? I will add it to the default if so, otherwise I will do my best to reverse engineer the config that should be there. |
| 00:25 | amalloy | justin_smith: does it need any? the lazybot instance in here has no mongodb config. i think it just assumes a mongodb server on localhost:default-port, and that it's allowed to write to the lazybot db |
| 00:25 | justin_smith | amalloy: oh, sounds magic! |
| 00:25 | justin_smith | I'll make sure my db is on the default port then |
| 00:25 | justin_smith | and that I am whitelisted to use the db etc. |
| 00:26 | justin_smith | amalloy: shows how much I know about mongodb (jack shit) |
| 00:27 | amalloy | justin_smith: the default mongodb config is to just assume the firewall takes care of everything, so that if you can connect to localhost you have permission to do whatever |
| 00:27 | amalloy | it looks pretty clear from lazybot/core.clj that there's nothing configurable at all |
| 00:27 | justin_smith | amalloy: OK |
| 00:27 | amalloy | except you can use a db name other than lazybot if you want |
| 00:28 | dbasch | justin_smith: mongodb is webscale, almost as fast as /dev/null. That’s pretty much all you need to know. |
| 00:28 | dbasch | oh, and it has shards as its magic secret scalability sauce |
| 00:31 | justin_smith | amalloy: weird, when I run > show dbs I see a lazybot db with contents, but @help gives me a connection error? very weird |
| 00:32 | justin_smith | ahh, never mind - it's an access control exception |
| 00:32 | justin_smith | I need to do that security settings thing |
| 00:58 | raspasov | hey guys does anyone have any idea about function calls within [let] blocks - long time ago I overheard from someone that they are not the most efficient way of executing fn calls in Clojure - is there any truth to that or it does not matter? |
| 01:00 | justin_smith | raspasov: why would a function call inside a let block be less efficient? function call dispatch can be marginally cheaper if you bind the function within a let block so that you never deref the var at runtime, but even then the speedup should be minor |
| 01:01 | raspasov | I see, ok, I was just wondering if there was any truth in that statement |
| 01:05 | tolstoy_ | Andfam.12 |
| 01:21 | andyf | Leiningen question: I have a directory in my project containing Clojure source files that I want to be in the classpath while I run ?lein test?, but I don?t want them in :source-paths, and I don?t want them in :test-paths. Why? Because they are not source files for the project, and they are only indirectly files for testing, by being require?d from my regular test files. Any recommendations? |
| 01:26 | zRecursive | ,(doc ->>) |
| 01:26 | clojurebot | "([x & forms]); Threads the expr through the forms. Inserts x as the last item in the first form, making a list of it if it is not a list already. If there are more forms, inserts the first form as the last item in second form, etc." |
| 01:26 | justin_smith | andyf: isn't test-resources a thing? |
| 01:27 | andyf | justin_smith: Checking Leiningen docs for such a thing... |
| 01:28 | justin_smith | andyf: it's not in the example proejct.clj, so it likely is not a thing |
| 01:28 | justin_smith | but you could set a :resource-path under the :test profile I guess? |
| 01:28 | justin_smith | :resource-paths that is |
| 01:28 | andyf | justin_smith: I have tried putting it into the :resources path in the :dev profile, and that seems to be doing reasonable things, but your suggestion sounds even better. |
| 01:29 | andyf | justin_smith: Sorry, I meant to say in the :resource-paths in the :dev profile |
| 01:30 | andyf | Do :resource-paths in a profile like :dev or :test, and a "global" :resource-paths, concatenate? |
| 01:30 | justin_smith | andyf: there is a merge that is done of the active profiles |
| 01:30 | justin_smith | I think testing pulls in :dev, :user, :test |
| 01:32 | andyf | Duh, the very first example given in output of "lein help profiles" is adding a directory to classpath in :test profile. |
| 01:32 | justin_smith | oh, nice! |
| 01:32 | justin_smith | https://github.com/technomancy/leiningen/blob/master/doc/PROFILES.md this has some good info for showing your effective profile etc. too |
| 01:34 | andyf | Yep, lists and vectors are concatenated when merging profiles. Cool. Bob's my uncle. |
| 01:34 | andyf | (inc justin_smith) |
| 01:34 | lazybot | ⇒ 111 |
| 03:30 | dopamean_ | i am having a nightmare of a time trying to send a simple http request |
| 03:30 | dopamean_ | i know all the information im sending is accurate because when i do it in the terminal with curl i get the expected response |
| 03:30 | dopamean_ | but when using clj-http i get a 400 error every time |
| 03:31 | sveri | dopamean_: did you set the :content-type and :accept key values? |
| 03:34 | dopamean_ | at first no |
| 03:34 | dopamean_ | because i didnt think i needed to for a post request |
| 03:34 | dopamean_ | but then i did add it and its still not working. though its a little unclear to me from the api exactly how it wants the information |
| 03:35 | dopamean_ | this is the offending code: (client/post spotify-access-token-url {:form_params data}) |
| 03:35 | dopamean_ | data is a map with all the necessary stuff in it |
| 03:36 | sveri | dopamean_: Hm, it's been almost a year since I used this and I remember having had problems too, I don't remember what exactly the problem was, but this solved my problem: :as :json in the options map |
| 03:37 | dopamean_ | 400 |
| 03:52 | sveri | dopamean_: I had some success debugging rest services using the postman app from the google chrome store, I know you tried already with curl, but if you dont get closer to the problem I guess it's worth to try it |
| 03:56 | dopamean_ | i started with postman |
| 03:56 | sveri | it does work with postman? |
| 03:56 | dopamean_ | no |
| 03:56 | dopamean_ | which means im not setting something correctly |
| 03:56 | dopamean_ | something that curl is doing automatically |
| 03:56 | sveri | yep |
| 03:57 | dopamean_ | all i specified for curl was a bunch of -d tags |
| 03:57 | sveri | I guess you just have to figure this out by trial and error |
| 03:57 | dopamean_ | and then the url |
| 03:57 | dopamean_ | ive been at it for 3 hours |
| 03:57 | dopamean_ | https://developer.spotify.com/web-api/authorization-guide/#authorization_code_flow |
| 03:57 | dopamean_ | im on step 4 of that |
| 03:57 | dopamean_ | requesting the new access token |
| 03:58 | dopamean_ | can you read that and tell me if there is something glaringly obvious that im missing? |
| 03:58 | dopamean_ | it says send a post request and then it says request body parameters... |
| 03:58 | dopamean_ | is that not form-params? |
| 03:59 | sveri | it should be |
| 03:59 | sveri | However, this is hard to debug remotely, all I can ask is if you set all the params from step 4 correctly |
| 03:59 | sveri | which you did, I guess |
| 04:00 | dopamean_ | yup |
| 04:01 | dopamean_ | if i left all the params off, just to see what happened, do you tihnk a 400 response would make sense? |
| 04:01 | sveri | I am sorry then, I guess I am of not much value here |
| 04:01 | dopamean_ | or should it be something else? |
| 04:01 | dopamean_ | its all good |
| 04:02 | sveri | Yea, that would make sense |
| 04:04 | dopamean_ | hmm |
| 04:04 | dopamean_ | i just sort of got it to work |
| 04:04 | dopamean_ | in postman |
| 04:04 | dopamean_ | changed from "form-data" to "x-www-form-urlencoded" |
| 04:05 | sveri | nice, maybe curl does some kind of auto negotiation |
| 04:05 | dopamean_ | perhaps |
| 04:05 | dopamean_ | now if i can just get clj-http to do the same thing |
| 04:07 | shem | dopamean_: did you check if it does a OPTIONS query first? cljs-ajax/POST does that and had me baffled for a while |
| 04:07 | dysfun | i was going to recommend http-kit which has a quite nice promise-driven API. i'm a bit mystified to find it's not on clojure-toolbox |
| 04:08 | dysfun | oh, it's under servers |
| 04:08 | dopamean_ | what do you mean by options query/ |
| 04:09 | shem | if i call POST with json content-type, it first does OPTIONS to the same uri |
| 04:10 | shem | and your server endpoint might be confused with that |
| 04:10 | dopamean_ | maybe thats whats happening |
| 04:10 | dopamean_ | i have no idea |
| 04:16 | dopamean_ | well |
| 04:16 | dopamean_ | i feel dumb for wasting so much time on this |
| 04:16 | dopamean_ | it works fine with http-kit |
| 04:18 | sveri | dopamean_: Hehe, I wasted time on much easier things, that's part of programming |
| 05:11 | jzinedine | hey guys, anyone knows about a seed project wiring pedestal service and reagent together? |
| 05:12 | jzinedine | I'm looking for a sample app to start with, and follow the patterns to build my app. |
| 05:49 | borkdude | https://gist.github.com/anonymous/53423c327ffda7faf852 |
| 06:15 | celwell | I'm using lein-beanstalk, how can I define the application name to be something other than the name I have for my lein project (defproject ...)? |
| 06:18 | celwell | Hmmm, looking at the source, this seems promising, will try: https://github.com/weavejester/lein-beanstalk/blob/master/src/leiningen/beanstalk/aws.clj#L50 |
| 06:24 | Glenjamin | is anyone around familiar with figwheel? I'm trying to figure out a way to have the :on-jsload callback fire once on initial page load |
| 06:24 | Glenjamin | on a related note, thanks to everyone who recommended reagent to me the other day - it's excellent |
| 06:38 | OliverJAsh | i'm learning clojure and have a JS background. i'm familiar with functional-reactive programming. i've used RxJS. can anybody tell me if clojure’s sequence data structures (seq?) are the same concept as what Rx calls "observables"? |
| 06:39 | TEttinger | sequences are a very common type in clojure. they can be lazy seqs or finite seqs. |
| 06:40 | TEttinger | lazy seqs you can generate with something like |
| 06:40 | TEttinger | ,(repeat "infinite") |
| 06:40 | clojurebot | ("infinite" "infinite" "infinite" "infinite" "infinite" ...) |
| 06:40 | TEttinger | and here, clojurebot limits how many items it will print |
| 06:41 | TEttinger | you could get just two items out of an infinite lazy seq with "take" |
| 06:41 | TEttinger | ,(take 2 (repeat "infinite")) |
| 06:41 | clojurebot | ("infinite" "infinite") |
| 06:41 | TEttinger | seqs are printed with single parentheses, like lists |
| 06:41 | TEttinger | I'm not sure what observables are, but I hope that clears up a bit |
| 06:42 | OliverJAsh | does a sequence represent data over time? i.e. can you add new values to the sequence through time, and the data will be "pulled through", like in functional reactive programming? |
| 06:44 | OliverJAsh | i think i'm confusing seq and FRP when they are totally different things :) |
| 06:45 | TEttinger | you might be thinking of core.async (a popular clojure lib)'s concept of channels |
| 06:45 | mavbozo | in core.async, (thread) and (go) return channel |
| 06:45 | TEttinger | I can't explain channels |
| 06:45 | mavbozo | what can I do with those channel, any easy example? |
| 06:47 | mavbozo | (thread (+ 1 2)) |
| 06:48 | mavbozo | never mind, found it myself |
| 06:49 | mavbozo | (def c (thread (+ 1 2))) |
| 06:49 | mavbozo | (<!! c) |
| 06:52 | shriphani | hi, anyone here used core.matrix ? I want to compute a row-sum and I was wondering if a reduce is the right way to go ? |
| 07:06 | ustunozgur | hi all, in cider, what's the easiest way to send C-M-x output to repl? |
| 07:07 | ustunozgur | that's, I want to see the output in the repl, not in the mini buffer. |
| 07:10 | mavbozo | ustunozgur: so far, the solution is to create a elisp function and bind that function to keystroke |
| 07:11 | mavbozo | ustunozgur: i found the function in the README of clojure core async tutorial here https://github.com/halgari/clojure-conj-2013-core.async-examples |
| 07:13 | ustunozgur | mavbozo: thanks ,look promising, although cider-find-or-create-repl-buffer seems to be gone. maybe renamed |
| 07:13 | mavbozo | ustunozgur: here's my elisp snippet https://github.com/mavbozo/mavbozo-dotemacs/blob/0ca56487242f5b222fc3ac7a7c8c7243b4a1a0a6/mavbozo-custom.el#L149-L164 |
| 07:14 | mavbozo | ustunozgur: yeah, I still use cider 0.70 |
| 07:15 | ustunozgur | thanks a lot. |
| 07:16 | ustunozgur | I slightly modified it to execute the top level form instead. |
| 07:17 | mavbozo | ustunozgur: I am still a emacs newb, I would like to see your code, thanks |
| 07:20 | ustunozgur | mavbozo: here you go |
| 07:20 | ustunozgur | https://gist.github.com/ustun/0f1a86142b95a391773c |
| 07:20 | ustunozgur | I bound to Alt-Enter |
| 07:20 | ustunozgur | so anywhere within the form will execute the outermost form in repl |
| 07:21 | mavbozo | ustunozgur: fantastic! thanks a lot |
| 07:22 | ustunozgur | this is actually slightly different from how cider sends it to the repl but good enough for my demo purposes. |
| 07:22 | ustunozgur | giving a talk today to a java user group |
| 07:22 | ustunozgur | the difference between this and cider's C-M-x is that |
| 07:22 | ustunozgur | if you are in a different namespace in cider it will send that to that namespace |
| 07:22 | ustunozgur | whereas this will send the code to the current namespace the repl is in. |
| 07:24 | mavbozo | ustunozgur: have a great talk! |
| 07:24 | ustunozgur | thank you! |
| 07:28 | edbond | I use lein new with template and it seems old version of template is used. |
| 07:29 | pandeiro | edbond: did you `lein install` the template from a local repo with the same version? |
| 07:29 | edbond | https://github.com/magomimmo/om-start-template |
| 07:30 | edbond | pandeiro, no, used lein new om-start as in Readme |
| 07:30 | pandeiro | edbond: or maybe the clojars version is behind the github |
| 07:30 | edbond | maybe I had an old version |
| 07:30 | pandeiro | edbond: no i think lein new always checks |
| 07:30 | edbond | pandeiro, thanks, I'll check clojars |
| 07:31 | pandeiro | edbond: so you could do `git clone git://github.com/magomimmo/om-start-template && cd om-start-template && lein install` |
| 07:31 | edbond | pandeiro, thanks. Clojars have more recent version that github :) |
| 07:32 | edbond | https://clojars.org/om-start/lein-template 0.0.7 |
| 07:32 | edbond | https://github.com/magomimmo/om-start-template/blob/master/project.clj here is 0.0.6 |
| 07:32 | pandeiro | wow that's a first |
| 07:32 | pandeiro | i think `lein new ...` should always by default get the latest version from clojars |
| 07:34 | edbond | I have 0.0.7 jar here /home/eduard/.m2/repository/om-start |
| 07:36 | edbond | yes, clojars is a bit behind. Thanks, pandeiro |
| 07:36 | edbond | (inc pandeiro) |
| 07:36 | lazybot | ⇒ 2 |
| 07:38 | fairuz | hey guys, if let say I open 2 terminals, with one runing lein repl. Then I modify one of my function, and compile using lein compile. Do I need to reload the repl? |
| 07:41 | clgv | fairuz: why dont you just reload the namespace of the function? |
| 07:41 | clgv | fairuz: sounds like what you describe will fail |
| 07:42 | clgv | fairuz: development gets much easier if you have editor and repl integrated since you can use commands like "evaluate that function definition in repl" |
| 07:46 | TimMc | fairuz: None of Leingingen, the default REPL, or Clojure itself will automatically reload code. |
| 07:46 | fairuz | clgv: TimMc: Ok. I'm still learning on how to develop/debugging efficiently using repl. |
| 07:47 | fairuz | so how to reload a namespace? |
| 07:47 | fairuz | redo a (use xxx)? |
| 07:47 | clgv | fairuz: use one of the editor+repl combinations or IDEs |
| 07:47 | clgv | fairuz: with :reload or :reload-all yes |
| 07:49 | fairuz | clgv: Ok cool. Does not want to start an IDE war, but what are recommended IDEs? LightTable is more than enough I suppose? |
| 07:49 | clgv | fairuz: options for dev envs are Emacs+Cider, Vim+Fireplace, Eclipse+Counterclockwise,IntelliJ+Cursive, Nightcode ... maybe others I currently forgot |
| 07:49 | clgv | ah right LightTable ^^ |
| 07:50 | TimMc | fairuz: My usual pattern is this: lein repl; edit files; (require 'foo.bar.baz :reload); repeat |
| 07:51 | TimMc | I don't use lein compile because I'm not using AOT. |
| 07:51 | clgv | TimMc: you dont use any integrated editor + repl combo? |
| 07:51 | TimMc | Nope. |
| 07:51 | clgv | wow O_o |
| 07:52 | fairuz | TimMc: I just want to ask about that :) we actually don't need to compile each time we modify the files right? |
| 07:52 | TimMc | clgv: One f these days I will try setting up cider again, but the last time I tried it all fell apart. |
| 07:52 | clgv | TimMc: I am only using lein repl on remote machines and sometimes if it gets more complicated I connect with my dev env to the remote nrepl |
| 07:52 | TimMc | fairuz: Right, reloading will compile on the fly (not to disk, just in memory.) |
| 07:53 | clgv | TimMc: haha yeah, seems that cider thing breaks often surprisingly |
| 07:53 | fairuz | TimMc: got it |
| 07:53 | TimMc | clgv: I version my .emacs.d so it shouldn't be too bad once I get it working, but I need to get a stable version in there. |
| 07:54 | clgv | TimMc: last posts on the ML suggest that even the stable version might break spontaneously - no idea if thats true |
| 07:54 | TimMc | fairuz: Or usually (require '[foo.bar.baz :as f] :reload) since I'll be calling it a lot. |
| 07:54 | TimMc | clgv: This does not surprise me. |
| 07:55 | TimMc | It also doesn't really fit with my windowing preferences. I like having my REPL in a totally separate window. |
| 07:56 | clgv | TimMc: yeah thats the setup I use with counterclockwise as well |
| 07:57 | TimMc | Bronsa suggested using emacsclient in order to accomplish that, but... eh, another thing to set up the next time I want to work. |
| 07:59 | clgv | TimMc: hehe. I think I'll never leverage the power of emacs since I am not good at remembering many complicated shortcut combinations... |
| 07:59 | shem | emacs can sprout several proper windows of course |
| 08:00 | clgv | TimMc: I used it 2 months for the SBCL course exercise I was organizing |
| 08:05 | TimMc | fairuz: Oh, just a tip -- you'll eventually find yourself in a situation where you have fn B that calls A, you rewrite and reload both repeatedly, but you fail to do it in the right order, and it works in your REPL because an old version of A is in memory but B doesn't work with the A on disk. |
| 08:06 | TimMc | You should be aware that this can happen so that you'll recognize it when it does. (This gets worse with defrecords and deftypes and multimethods -- different symptoms, same essential problem.) |
| 08:07 | TimMc | `lein test` or restarting your REPL will give you a more honest view of the world. |
| 08:14 | whodidthis | how does a human being test a ring middleware that depends on another middleware |
| 08:17 | foofoobar | Hi. (first „hello“). Why is this \h instead of h ? |
| 08:18 | clgv | foofoobar: notation for character literals |
| 08:18 | clgv | ,(str (first "hello")) |
| 08:18 | clojurebot | "h" |
| 08:18 | clgv | above it is a string instead of a character ^^ |
| 08:18 | foofoobar | ,(str \h) |
| 08:18 | clojurebot | "h" |
| 08:18 | foofoobar | ah, okay. thanks |
| 08:18 | elfenlaid | well, strings aren't sequential by default, but can transform to sequence; and sequence from string is a list of chars |
| 08:19 | clgv | elfenlaid: that's a complicate explanation. strings are arrays of chars on the jvm would suffice ;) |
| 08:19 | clgv | at least internally ;) |
| 08:20 | elfenlaid | ow, ok :) |
| 08:22 | clgv | ,(mapv #(nth "hello" %) (range (count "hello"))) |
| 08:22 | clojurebot | [\h \e \l \l \o] |
| 08:29 | mavbozo | whodidthis: by mocking the required middleware |
| 08:35 | fairuz | TimMc: thanks for the tip. Really appreciate any advice now since I'm just started :) |
| 08:36 | whodidthis | i liked the ((wrap-whatever identity) {:body "my-request"}) approach, whats a cool way of testing something that depends on another, should i just ((mw/wrap-something identity) ((mw/wrap-else identity) {:body "my-request"})) |
| 08:37 | whodidthis | just request parsing middleware |
| 08:41 | mavbozo | whodidthis:(-> {:body "my-request"} (mw/wrap-else identity) (mw/wrap-something identity)) |
| 08:42 | mavbozo | whodidthis: threading macro -> is better |
| 08:42 | whodidthis | cool, always room for some magic |
| 08:43 | mavbozo | whodidthis: better to use threading macro -> in your case |
| 08:43 | perplexa | thread-first macro* |
| 08:43 | perplexa | :P |
| 08:47 | whodidthis | although if i want to use a threading macro thingie i guess i would have to (as-> {:body ""} _ ((mw/wrap-else identity) _) ((mw/wrap-something identity) _)) |
| 08:53 | clgv | fairuz: better make your first steps with LightTable since you have already installed it ; |
| 08:59 | mavbozo | whodidthis: or, (def test-app (constantly {:body ""})) |
| 09:00 | mavbozo | whodidthis: (-> test-app mw/wrap-else mw/wrap-something ) |
| 09:16 | si14 | how would you translate CLJS app? I've come up with a simple macro, but it's still not obvious how to compile two different artifacts for different languages. |
| 09:17 | si14 | of course I can use environ or somethings like this and do TRANLSATION=en lein cljsbuild once production, but this seems a bit messy to me |
| 09:24 | perplexa | si14: you can use #+clj and #+cljs macros, if i understand you correctly |
| 09:24 | perplexa | oh wait, you're actually talking about languages and not clj and cljs ;p |
| 09:24 | si14 | perplexa: no, sorry, I meant human languages :) like compiling two different artifacts for English and Esperanto languages |
| 09:25 | perplexa | haha yeah just realised :D |
| 09:25 | perplexa | sorry |
| 09:25 | si14 | :) |
| 09:25 | si14 | thanks for an advice, anyways :) |
| 09:26 | perplexa | si14: i don't understand your use case. |
| 09:27 | si14 | perplexa: webapp with i18n |
| 09:27 | perplexa | languages are something chosen by the client, so shouldn't you include all resources and then decide inside of your application which one to use? |
| 09:27 | perplexa | not at compile time |
| 09:27 | perplexa | that would diminish the purpose of i18n |
| 09:30 | si14 | perplexa: I can compile two different artifacts and give a choice on a landing page, I think |
| 09:30 | si14 | basically, two different webapps |
| 09:31 | perplexa | shouldn't be a different app at all, the logic stays the same, just the strings are different |
| 09:31 | perplexa | maybe use something like https://github.com/ptaoussanis/tower |
| 09:32 | perplexa | and decide which language to use based on browser accept headers |
| 09:34 | si14 | perplexa: I also need quite a lot of language-specific resources, so it be unwieldy to include them in app if they will not be needed |
| 09:35 | ustunozgur | anyone encountering erros with swing gui (frames) not appearing with cider? |
| 09:36 | ustunozgur | it returns visible=true but the gui is no where in sight |
| 10:01 | perplexa | do people actually use type hints? |
| 10:09 | Glenjamin | generally only to remove reflection on iterop |
| 10:09 | Glenjamin | personally |
| 10:22 | justin_smith | perplexa: they can make a massive difference in performance when you need them |
| 10:24 | perplexa | justin_smith: so it's preferable to just add them :) |
| 10:25 | Glenjamin | i'd say add this https://github.com/technomancy/leiningen/blob/master/sample.project.clj#L255 to your project.clj |
| 10:25 | Glenjamin | then do whatever it tells you |
| 10:28 | perplexa | Glenjamin: i'll give it a shot |
| 10:34 | si14 | oh wow. pretty epic |
| 10:34 | si14 | there are no externs for Web Audio API in Closure Compiler that is used by CLJS |
| 10:36 | si14 | (erroneous /me, sorry) |
| 10:36 | Glenjamin | https://code.google.com/p/closure-compiler/issues/detail?id=710 looks relevant |
| 10:38 | zot1 | question on idiom: i'm trying to do something like update-in, but where the "rhs" also needs the same keyed structure. my raw version is above, and my first attempt at making it generic below. suggestions on how to improve? https://gist.github.com/anonymous/90213a0f47091e287bfc |
| 10:41 | justin_smith | zot: I think there is a misplaced paren in that reduce |
| 10:42 | zot | justin_smith: could be, it was 'scratchpad' idea, although it at least parsed in the repl, i think |
| 10:42 | si14 | Glenjamin: yeah, but it doesn't work now |
| 10:42 | justin_smith | ,(reduce +) |
| 10:42 | Glenjamin | you can just pull in additional externs in the build config |
| 10:42 | clojurebot | #<ArityException clojure.lang.ArityException: Wrong number of args (1) passed to: core/reduce> |
| 10:42 | justin_smith | zot: you should have seen that error |
| 10:43 | zot | i just pasted it again w/ no problem, although there is definitely a paren off. strange. |
| 10:43 | justin_smith | zot: anyway, unless I am mistaken, the paren to the right of ks should be before m1 in that reduce call |
| 10:44 | zot | yep i've fixed it here, and will repaste if useful :) |
| 10:45 | zot | is there a cleaner way to pull it off? the anon func for reduce is … awkward, but i haven't (so far) imagined a better way, other than maybe as a walk that update-in's the peer structure. important to note is that both trees can be sparse, so update-in, or sth else that will create missing structure, is preferred. |
| 10:47 | justin_smith | zot: I like the reduce version (the version of it with correctly balanced parens at least) |
| 10:48 | zot | justin_smith: ok, good to hear from somebody else… trying to learn with the notion of using func composition instead of tricky anon fns… and this one befuddles ;) |
| 10:49 | justin_smith | zot: I don't see a straightforward way to do this with function composition though |
| 10:50 | zot | justin_smith: ok — i'm still finding my way in clojure, so sometimes there's a super awesome way that i've just never seen, forgotten, or can't find via google :) |
| 10:51 | zot | justin_smith: tnx for taking a look! |
| 10:53 | EvanR | is there a type which is just a date, and not a java Date which is taking liberties with midnights and time zone assumptions |
| 10:55 | zot | EvanR: familiar with clj-time? |
| 10:55 | EvanR | no |
| 10:55 | zot | google it. it can probably do what you want, and way way more. |
| 10:55 | irctc | hi |
| 10:55 | irctc | :) |
| 10:56 | EvanR | ok |
| 10:56 | irctc | is this a place where a newbie can ask questions? |
| 10:56 | EvanR | also i just discovered java GregorianCalendar |
| 10:57 | andyf_ | irctc: yes |
| 10:57 | ohpauleez | irctc: Most certainly! |
| 10:57 | hyPiRion | EvanR: prefer clj-time and joda-time whenever you can |
| 10:58 | EvanR | im reading the doc, it might work |
| 10:59 | irctc | i'm looking at https://github.com/aphyr/riemann/blob/master/src/riemann/email.clj at the function (defn email-event i'm trying to understand it |
| 10:59 | irctc | so [smtp-opts msg-opts events] are arguments ok so far :) |
| 11:00 | irctc | then "(let [events (flatten [events])" what does it means exactly it flattens events and places it in events? |
| 11:00 | irctc | i don't get it |
| 11:01 | Glenjamin | irctc: it takes any single item or nested sequence of sequences, and gives you a single sequence of events |
| 11:01 | irctc | why is it flattening events at all? |
| 11:01 | irctc | ok |
| 11:01 | irctc | so it suspecteed it would be nested i understand |
| 11:01 | Glenjamin | [1 [ 2 ] [3 [4] ] ] => [ 1 2 3 4]; but also 1 => [1] and [1 2] => [1 2] |
| 11:01 | irctc | and i'm allowed to override like this the same variable name? |
| 11:01 | irctc | events it flattened and named as events again... |
| 11:01 | Glenjamin | yes, a let binding runs in order and can re-bind locals |
| 11:02 | irctc | ok |
| 11:02 | irctc | then this "subject ((get msg-opts :subject subject) events)" what is the first "subject" is it a function i lost it at that point |
| 11:03 | EvanR | clj-time youre my only hope |
| 11:03 | EvanR | at least one industrial time lib may actually make sense |
| 11:04 | andyf_ | irctc: I don't know exactly what the args to this function are, but (get msg-opts :subject subject) is an expression that either returns a function, or a value like a map or vector that can be used as a function |
| 11:04 | andyf_ | irctc: Whatever that is, it is then called with the argument events, and the return value of that is bound to subject |
| 11:05 | andyf_ | irctc: If it makes it clearer, it could be written in two lines instead like so: |
| 11:05 | andyf_ | irctc: some-fn (get msg-opts :subject subject) |
| 11:05 | andyf_ | irctc: subject (some-fn events) |
| 11:06 | andyf_ | irctc: I should have started with your question, though: subject there is just another name that is being bound to a value in the let |
| 11:07 | irctc | ok got it about the first subject |
| 11:07 | irctc | yes its an array i missed that so we are bidning 3 items events subject and body |
| 11:08 | andyf_ | irctc: yes, the let is binding 3 values to those names |
| 11:08 | irctc | so about the inner "(get msg-opts :subject subject) " its get from map named "msg-opts" the field :subject and the default would be the last "subject" if not found? |
| 11:08 | andyf_ | irctc: yes |
| 11:08 | EvanR | sweet |
| 11:08 | irctc | but can i be sure there is a default "subject"? what if was not bound yet? |
| 11:09 | justin_smith | irctc: if subest was not bound yet, that would not even compile |
| 11:09 | justin_smith | ,(get {} :foo foo) |
| 11:09 | clojurebot | #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: foo in this context, compiling:(NO_SOURCE_PATH:0:0)> |
| 11:10 | andyf_ | It looks like the original value for subject is coming from the :use on line 5 |
| 11:10 | irctc | ok |
| 11:11 | irctc | is it aggregating somehow the subjects from all the events into a single one? or the body from multiple events into a single one? i don't get how it achieves this.. |
| 11:11 | andyf_ | irctc: That would be much less obvious if subject were def'd in namespace postal.core, which has (:use postal.core) up near the top, since that will bring in every public def in postal.core into this namespace. That is one reason why many Clojure programmer recommend against an "unlimited" use like that. |
| 11:12 | irctc | hmmm |
| 11:12 | irctc | i see this |
| 11:12 | irctc | in riemann.common |
| 11:12 | irctc | subject is also a function named "defn subject" |
| 11:13 | irctc | so wow with a field named subject, a default value, and a function all named subject !! :) |
| 11:13 | andyf_ | irctc: Again, I'm not familiar with the exact context here, but I would guess subject is a function. It can take whatever events is (probably a sequence of events), and calculate a subject line, probably a string, to use in an email message. |
| 11:14 | andyf_ | irctc: riemann.common/subject is the default function to use for calculating the subject, but it can be overridden by putting a key named :subject into the map msg-opts, whose value is a different function to use instead |
| 11:14 | irctc | so in this"subject ((get msg-opts :subject subject) events)" the first subject is a "string" and third subject is a function!? |
| 11:15 | andyf_ | irctc: that would be my guess |
| 11:15 | irctc | oh sorry default |
| 11:15 | irctc | in anyway the main thing that mixed me up is that subjet was a function defined something else i just looked for the concatenation somehwere.. |
| 11:15 | andyf_ | irctc: I am not claiming that those are the best names to use for clarity of purpose :) |
| 11:15 | irctc | :) |
| 11:16 | irctc | ok i think i got some of the subject :) |
| 11:17 | justin_smith | irctc: yeah, the naming here is kind of odd, here is a hopefully less clever and more clear version that does exactly the same thing https://www.refheap.com/92484 |
| 11:20 | irctc | https://www.refheap.com/92484 --> *much more clearer!!* |
| 11:20 | irctc | https://www.refheap.com/92484 --> *much clearer!!* |
| 11:21 | andyf_ | irctc: My inner grammar Nazi thanks you |
| 11:22 | perplexa | i there a better way than (* (int (/ x y)) y) to make x a multiple of y? |
| 11:22 | perplexa | without casting to an int in the middle ;p |
| 11:22 | clgv | justin_smith: tsktsk to much :use there ;) |
| 11:22 | irctc | :))) |
| 11:22 | justin_smith | clgv: I did not touch the ns form at all |
| 11:22 | andyf_ | perplexa: Not much different, but you could use (quot x y) instead of (int (/ x y)) ? |
| 11:22 | perplexa | like, i have x=11, y=2, expected result is 10 |
| 11:22 | justin_smith | clgv: it is just there to provide context in the function I reworkd below it |
| 11:23 | clgv | ,(- x (mod x y)) |
| 11:23 | clojurebot | #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: x in this context, compiling:(NO_SOURCE_PATH:0:0)> |
| 11:23 | clgv | oh comma :P |
| 11:23 | perplexa | ah yeah, andyf_! that looks a bit better :) gracias |
| 11:23 | andyf_ | clgv: I'm curious -- I understand that 'unlimited' :use's like that are frowned upon in most uses, but do you use them in test code, e.g. (:use clojure.test) ? |
| 11:24 | perplexa | clgv: that also, yes ;p |
| 11:25 | perplexa | but i remember from back when i cam across some C algos that subtraction is usually more expensive than multiplication/division |
| 11:25 | perplexa | no idea how jvm handles that, it's probably bad either way :D |
| 11:26 | andyf_ | perplexa: I would think that it is usually the opposite, i.e. + and - are fastest integer ops, and multiply and divide are slower. This is likely getting more historical now, as * quot and mod are probably all just as fast as + and - on integer ops on most modern processors. |
| 11:26 | justin_smith | perplexa: with out immutible data structures and laziness and runtime polymorphism, we have much bigger optimization targets than the cost difference of subtract vs. multiply |
| 11:27 | justin_smith | *with our |
| 11:28 | andyf_ | clgv: I ask because right now Eastwood warns on all 'unlimited' use's, but I've been wondering whether I should disable that warning for source files in :test-paths |
| 11:28 | perplexa | mmh :) |
| 11:29 | cbryan | andyf_: or just do :require [... :refer :all] |
| 11:29 | cbryan | eastwood is fine with that |
| 11:29 | mgaare | andyf_: replacing them with (require '[whatever :refer :all]) should shut up eastwood too |
| 11:29 | mgaare | doh |
| 11:29 | cbryan | ;) |
| 11:29 | Glenjamin | heh, i'm not clear why :refer :all is considered nicer than :use |
| 11:30 | andyf_ | Sure. My main curiosity is, for people who frown on unlimited :use, do you use them in test code? I do, and it seems relatively common. |
| 11:30 | justin_smith | andyf_: to me :use makes sense if there is a clear "referent" namespace, where your code only makes sense if read in parallel with that namespace (whether you are wrapping it, or testing it, or extending it...) |
| 11:30 | justin_smith | andyf_: but even then, more than one :use is a problem |
| 11:31 | Glenjamin | i'd rather just list out the 5 or 6 functions i need |
| 11:31 | andyf_ | justin_smith: because? Sorry, not obvious to me why. |
| 11:31 | Glenjamin | it's not that often to have a namespace with more than that many you need to use |
| 11:31 | andyf_ | Glenjamin: Even in a test namespace? |
| 11:32 | Glenjamin | do you mean for clojure.test, or for the system-under-test? |
| 11:32 | justin_smith | andyf_: if the namespace is about wrapping / extending / testing one other ns, then it only makes sense in context of that ns and one would be looking at both together, with more than one ns used, that introduces the ambiguity and refactoring difficulty that to me are the real pain points in :use |
| 11:32 | andyf_ | Glenjamin: either, but if you have reasons for doing it differently for each, I'm curious. |
| 11:32 | mgaare | andyf_: the more places you have to look to answer the question, "now where did this symbol come from?", the unhappier I get :D |
| 11:32 | Glenjamin | andyf_: well clojure.test, only is, testing and deftest are really used that often i'd have though |
| 11:32 | Glenjamin | system-under-test i usually :as to a single letter |
| 11:34 | andyf_ | So perhaps if Eastwood never warned about (:use clojure.test), but kept its current warning for such a use of any other namespace, not many people would mind that behavior? |
| 11:35 | Bronsa | andyf_: I :use clojure.test in all my tests |
| 11:35 | andyf_ | I look at Eastwood warnings on quite a few projects on a regular basis, so certain warnings I can get tired of seeing, and I imagine others woudld, too. |
| 11:35 | Glenjamin | Bronsa: how many different vars from clojure.test do you think you use often? |
| 11:35 | andyf_ | Bronsa: You and nearly everyone else :) |
| 11:35 | Bronsa | Glenjamin: just is and deftest probably, but it's just too much of a hassle to :refer them |
| 11:35 | Glenjamin | i'm interested in whether :use clojure.test is habit, or because it's annoying not to |
| 11:36 | Bronsa | andyf_: which version of t.a.jvm is eastwood using atm? |
| 11:36 | andyf_ | Glenjamin: Can't speak for others, but for me it is annoying to pick exactly what I want, even though it is a copy-and-paste if I wanted to go to that trouble. |
| 11:37 | Glenjamin | i don't use clojure.test very often, but i'd have expected something like [clojure.test :as test :refer (is testing)] would cover most usage |
| 11:37 | andyf_ | Bronsa: Latest Eastwood release 0.1.4 is getting creaky old: t.a(.j) version 0.2.2 :-( |
| 11:37 | Bronsa | andyf_: no I mean SNAPSHOT :P |
| 11:37 | andyf_ | Bronsa: Getting real close now to another release. Testing the latest masters of t.a(.j) as we type |
| 11:37 | justin_smith | Glenjamin: most would refer deftest too I think |
| 11:38 | Glenjamin | mm |
| 11:38 | andyf_ | I think I just committed that about an hour ago |
| 11:38 | Glenjamin | but still, not many, out of the, what?, 20 or so vars in there |
| 11:38 | Bronsa | andyf_: ah cool, asking because 0.6.3 should be more than twice as fast than 0.2/0.3 |
| 11:38 | Glenjamin | i count 29 vars |
| 11:39 | Bronsa | ,(require 'clojure.test) |
| 11:39 | clojurebot | nil |
| 11:39 | Bronsa | ,(count (ns-interns 'clojure.test)) |
| 11:39 | clojurebot | 40 |
| 11:39 | justin_smith | ,(count (ns-publics 'clojure.test)) |
| 11:39 | clojurebot | 37 |
| 11:39 | andyf_ | Glenjamin: I think everyone who uses clojure.test uses deftest and is. A fraction use testing, and an even smaller fraction use are |
| 11:39 | justin_smith | use would only give us the publics, right? |
| 11:40 | Bronsa | justin_smith: ah yeah |
| 11:40 | andyf_ | Glenjamin: Past that, I haven't even looked at what else is in clojure.test |
| 11:40 | justin_smith | Bronsa: though for compilation tooling you usually care about the interns, I am sure :) |
| 11:40 | Glenjamin | mostly stuff to run tests |
| 11:41 | justin_smith | and fixtures! |
| 11:41 | justin_smith | I guess those count as running stuff actually |
| 11:41 | Glenjamin | fixtures would probably be ok using test/use-fixtures ? |
| 11:42 | justin_smith | Glenjamin: sure, I usually use test/testing too, and in many namespaces I even do test/is |
| 11:49 | andyf_ | justin_smith: You've stunned the room into silence with that one. We are all mentally reeling :) |
| 11:50 | justin_smith | haha |
| 11:58 | donbonifacio | can I deconstruct a variadic function to a hash? (defn hey [*hash-obj*] ...) and call (hey :name "Lucy" :age 1) |
| 12:02 | gfredericks | (defn hey [& {...}] ...) |
| 12:04 | cbryan | is there a preferred pastebin for this channel? |
| 12:04 | benzap | if I understand correctly, gfredericks is saying that optional arguments when passed to a function are presented as a list after the set of arguments through a defined var (defn [x & args] ...) where 'args' is a list of arguments succeeding the the variable 'x' |
| 12:05 | noonian | cbryan: refheap |
| 12:05 | justin_smith | ,((fn [& {a :a b :b}] [a b]) :b 2 :a 1) |
| 12:05 | clojurebot | [1 2] |
| 12:06 | justin_smith | benzap: he meant that ^ |
| 12:06 | benzap | justin_smith: thank you for clarifying |
| 12:07 | donbonifacio | thanks justin_smith gfredericks |
| 12:07 | justin_smith | donbonifacio: another thing is that using rest args map destructuring is controversial |
| 12:07 | benzap | i didn't supply a name for defn, so my example is probably confusing |
| 12:07 | justin_smith | donbonifacio: it is often easier to just use a hash as an argument |
| 12:07 | cbryan | is there a more idiomatic way to write this? the (some? (some ...)) feels wrong https://www.refheap.com/92486 |
| 12:07 | donbonifacio | I see |
| 12:08 | whodidthis | if a human being, using yesql, has (defqueries "file.sql") in a file, can the queries be referred to from another file |
| 12:08 | justin_smith | donbonifacio: for example if you want to provide that set of keys / values to some function, and you have them in a map already |
| 12:08 | benzap | this actually brings up something that bothers me regarding defprotocol, where you are limited to providing nothing but arguments, with no & rest statements |
| 12:08 | benzap | but i'm guessing this a limitation when trying to communicate with a java interface |
| 12:08 | justin_smith | whodidthis: by requiring that namespace and accessing them from said namespace, right? |
| 12:10 | whodidthis | right |
| 12:12 | justin_smith | whodidthis: yeah, yesql just creates a call to def https://github.com/krisajenkins/yesql/blob/master/src/yesql/types.clj#L51 |
| 12:12 | justin_smith | so you can access it as you would any other def from another ns |
| 12:14 | whodidthis | sweet |
| 12:24 | SagiCZ1 | the other i read something about meta data.. and i wanted to ask, would it be possible to save some kind of benchmark data to some functions in my program, and look for bottlenecks this way? i was thinking, that each time the function gets called, it updates its own metadata, thats possible right? and can i extract this metadata later? i would like to implement this with minimal impact to my existing program |
| 12:24 | justin_smith | SagiCZ1: profilers do a much better version of this |
| 12:24 | justin_smith | jvisualvm comes with the jdk, yourkit is popular (and you can get it free for open source work) |
| 12:25 | SagiCZ1 | justin_smith: i've tried a profiler but showed some low level clojure core functions as hot spots.. useless for me |
| 12:26 | noonian | cbryan: i think you can leave off the some? calls since everything in clojure except nil and false is truthy in conditionals |
| 12:26 | Glenjamin | maybe that means your app isn't slow? |
| 12:27 | SagiCZ1 | Glenjamin: there is one of my functions which could be improved from linear to constant time, and the profiler wasnt able to identify this. |
| 12:27 | cbryan | noonian: ah cool! thanks |
| 12:27 | justin_smith | Glenjamin: more likely just a forst / trees issue, with noise from the lower level stuff that the functions are constructed from |
| 12:27 | Glenjamin | SagiCZ1: if it wasn't a hotspot, then it suggests that n is small enough that the constant factor / overhead dwarfs the time complexity |
| 12:28 | SagiCZ1 | Glenjamin: i think it suggest, that jvisualvm is maybe good for java but not so much for clojure |
| 12:28 | Glenjamin | i've managed to use it very well on clojure, and speed up clojure functions which were bottlenecks |
| 12:29 | Glenjamin | are you running the profile on your app generally, or while running a specific bit of code? |
| 12:29 | SagiCZ1 | Glenjamin: it is running some heavy computation that takes minutes to finish |
| 12:29 | SagiCZ1 | in the list of functions that the profiler identifies there is non of my own functions.. |
| 12:29 | Glenjamin | and you start profiler, run computation, stop profiler? |
| 12:30 | SagiCZ1 | yes |
| 12:30 | Glenjamin | are you using the top-down view? |
| 12:30 | Glenjamin | or just looking at self times? |
| 12:31 | SagiCZ1 | Glenjamin: i was sorting them by time |
| 12:33 | Glenjamin | try using the top-down view, it'll let you drill down by times that include the timing of the functions that call |
| 12:36 | SagiCZ1 | Glenjamin: is there a difference between 'sampler' and 'profiler'? in jvisualvm? |
| 12:36 | Glenjamin | the only difference i've seen is that i've never got the profiler to work, but i have got the sampler to work :) |
| 12:36 | SagiCZ1 | Glenjamin: same here |
| 12:38 | SagiCZ1 | Glenjamin: where would i find the top down view? |
| 12:38 | justin_smith | I've seen the profiler work for heap profiling |
| 12:41 | SagiCZ1 | Glenjamin: also, is it wrong, that i am profiling the repl running the task? |
| 12:46 | EvanR | is there a function to take a value, return it unless nil, in which case throw an exception |
| 12:46 | SagiCZ1 | i have found some info by using the "snapshot" option ... not sure what it all means |
| 12:46 | justin_smith | (assert v) |
| 12:46 | justin_smith | err, no |
| 12:47 | justin_smith | ,(and (assert v) v) |
| 12:47 | clojurebot | #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: v in this context, compiling:(NO_SOURCE_PATH:0:0)> |
| 12:47 | EvanR | fantastic |
| 12:47 | EvanR | ,(assert 3) |
| 12:47 | clojurebot | nil |
| 12:47 | justin_smith | oh wait... |
| 12:47 | justin_smith | not and |
| 12:47 | justin_smith | ,(do (assert 3) 3) |
| 12:47 | clojurebot | 3 |
| 12:47 | justin_smith | ,(do (assert nil) nil) |
| 12:47 | clojurebot | #<AssertionError java.lang.AssertionError: Assert failed: nil> |
| 12:47 | EvanR | ,(assert false) |
| 12:47 | clojurebot | #<AssertionError java.lang.AssertionError: Assert failed: false> |
| 12:48 | EvanR | looks like a function is in order |
| 12:48 | justin_smith | there is that too - perhaps you want something using nil? |
| 12:48 | justin_smith | ,(do (assert (not (nil? false))) false) |
| 12:48 | clojurebot | false |
| 12:50 | EvanR | can i customize the error message |
| 12:51 | justin_smith | ,(assert nil "that should not have been nil") |
| 12:51 | clojurebot | #<AssertionError java.lang.AssertionError: Assert failed: that should not have been nil\nnil> |
| 12:51 | EvanR | ,(assert false "foo") |
| 12:51 | clojurebot | #<AssertionError java.lang.AssertionError: Assert failed: foo\nfalse> |
| 12:52 | EvanR | ,(assert false nil) |
| 12:52 | clojurebot | #<AssertionError java.lang.AssertionError: Assert failed: \nfalse> |
| 12:56 | justin_smith | EvanR: you can also use :pre in functions |
| 12:56 | EvanR | in this case im making sure the result is not nil before returning it |
| 12:56 | justin_smith | ,(map (fn [x] {:pre [(not (nil? x))]} x) [0 1 2 nil 3]) |
| 12:56 | clojurebot | #<AssertionError java.lang.AssertionError: Assert failed: (not (nil? x))> |
| 12:57 | justin_smith | ,(map (fn [x] {:post [(not (nil? %))]} x) [0 1 2 nil 3]) |
| 12:57 | clojurebot | #<AssertionError java.lang.AssertionError: Assert failed: (not (nil? %))> |
| 12:57 | EvanR | checking the input is not nil as a post action? |
| 12:57 | justin_smith | that's not input |
| 12:57 | justin_smith | % stands for the potential return value |
| 12:57 | EvanR | x? |
| 12:57 | EvanR | oh |
| 12:58 | EvanR | could be good |
| 12:59 | justin_smith | ,(map (fn [x] {:post [(not (nil? %))]} [x]) [0 1 2 nil 3]) |
| 12:59 | clojurebot | ([0] [1] [2] [nil] [3]) |
| 12:59 | justin_smith | does not trigger, because not nil any more |
| 13:03 | justin_smith | EvanR: another factor here is that you can decide at runtime whether asserts are checked (and this includes :pre and :post condition asserts) |
| 13:03 | justin_smith | so the consequences there are twofold: you can be more ambitious about assertion and not worry too much about the effect on performance, and if you want real exception handling don't use assertions |
| 13:03 | EvanR | production mode seems like the last place i want to omit debug support |
| 13:05 | EvanR | yeah this is not exception handling |
| 13:06 | justin_smith | if you are writing a lib, you should consider the fact that users of the lib are allowed to turn assertions off |
| 13:06 | justin_smith | so assertions should be used as a dev-time verification of correctness of code, rather than a debugging-of-runtime-condition thing (maybe logging is a better fit for that?) |
| 13:07 | technomancy | contracts! |
| 13:07 | technomancy | or something |
| 13:07 | EvanR | if they turn assertions off, it shouldnt matter, because they shouldnt be happening |
| 13:07 | EvanR | the errors |
| 13:07 | justin_smith | technomancy: schema! |
| 13:08 | technomancy | racket! |
| 13:09 | justin_smith | EvanR: well we do have core.typed for typechecking code, and schema for runtime data validation |
| 13:09 | EvanR | i looked at core.typed, i did not understand the filters part |
| 13:09 | EvanR | and schema refers to prismatic? |
| 13:10 | justin_smith | yeah, prismatic/schema provides tools for verifying certain properties of clojure data |
| 13:10 | EvanR | it sounds good |
| 13:10 | justin_smith | things like "this has to be a map with the :a key having a number value" |
| 13:11 | EvanR | in this particular case, its asserting that what im looking for in a dictionary is actually there |
| 13:11 | EvanR | rather than a structural assertion |
| 13:11 | justin_smith | EvanR: right, so you could describe the dictionary with a schema as always having a value at a particular key |
| 13:11 | justin_smith | that is a structural assertion |
| 13:11 | EvanR | the keys are dynamic |
| 13:12 | justin_smith | EvanR: schema doesn't fully describe the data |
| 13:12 | noonian | EvanR: you can do that too i believe |
| 13:12 | justin_smith | it just says "it at least needs this kind of value in this place" |
| 13:12 | EvanR | which place? |
| 13:12 | justin_smith | the one you specify! |
| 13:13 | justin_smith | as I said above, for example you could specify "this is a map, it has a key :a, the value at that key is a number" |
| 13:13 | justin_smith | that is a schema |
| 13:13 | EvanR | this is another mismatch on usage of a map |
| 13:13 | EvanR | its not a record, its a lookup table |
| 13:14 | justin_smith | EvanR: then use deftype |
| 13:14 | EvanR | all i can say about it is its a map with String keys and the values are vectors |
| 13:14 | noonian | maps are often used as records in clojure |
| 13:14 | EvanR | i know this. |
| 13:14 | EvanR | i am not using it as one here |
| 13:14 | noonian | you can describe what you just said you the schema library is all justin_smith is saying |
| 13:14 | justin_smith | EvanR: and exactly what you said is expressable as a schema |
| 13:15 | EvanR | justin_smith: runtime checking this fact how often? |
| 13:15 | EvanR | on inserts? |
| 13:15 | justin_smith | EvanR: checking it when you invoke the check, that's up to you, they just provide the checker. I think there is a shortcut for doing it on the arg on each invocation of a function. But you can invoke the checking wherever. |
| 13:16 | justin_smith | EvanR: it's not a typing system, it is a validation tool |
| 13:16 | noonian | yeah, you can either annotate the fns metadata so it is always run with validation or you can only validate it when you want to |
| 13:16 | EvanR | yeah so all i was saying is that a check that the particular key i need is there isnt a schema thing |
| 13:16 | justin_smith | how not? |
| 13:17 | noonian | we're talking about the library called schema, not the abstract concept of what a schema is |
| 13:17 | EvanR | its a map from strings to maps, not even known to be non empty |
| 13:18 | EvanR | thats about all i can think of using schema for in this case |
| 13:18 | noonian | which is a perfectly valid use case for schema |
| 13:18 | noonian | if you care to ensure that the data you get conforms to the specification you just said |
| 13:18 | EvanR | a runtime lookup that a key is there, that i am already looking up anyway, i dont see a library here |
| 13:18 | noonian | sure, thats up to you |
| 13:19 | justin_smith | EvanR: I can understand if you don't like this abstraction, but this abstraction does address your data validation issue |
| 13:19 | EvanR | so... it equips a map with some extra stuff to never return nil? |
| 13:19 | EvanR | all lookups return something? |
| 13:19 | justin_smith | no |
| 13:19 | EvanR | ok because that would seem like a weird role for something called schem |
| 13:19 | mgaare | you use it to instrument your functions, iirc |
| 13:20 | EvanR | it makes total sense to describe record structures |
| 13:20 | noonian | it doesn't modify a map, it describes what a map at a certain part of your program is expected to look like |
| 13:20 | justin_smith | EvanR: it is an abstract description of a data structure, and a function that tells you whether the input data matches that description |
| 13:20 | noonian | you annotate the function, not the data |
| 13:20 | EvanR | the exact structure of my dynamic lookup table at runtime might be describable with dependent types or something |
| 13:21 | EvanR | i would need a program to run to describe exactly which keys are in there |
| 13:21 | EvanR | and really it doesnt matter, as long as im not ending up with an invalid key |
| 13:21 | justin_smith | EvanR: schema doesn't fully describe the keys, but validates that set of properties you ask it to validate |
| 13:22 | noonian | (def my-schema {s/Keyword s/Any}) describes a map of keyword keys to anything |
| 13:22 | noonian | you could ensure that the values are maps of course |
| 13:22 | noonian | or that the keys are a subset of a specific set of keywords |
| 13:23 | justin_smith | noonian: or that at least key foo is present, with a value of type F |
| 13:23 | EvanR | yes that makes sense |
| 13:23 | EvanR | that though would not |
| 13:23 | EvanR | neither would, for my case |
| 13:24 | noonian | 'its a map from strings to maps, not even known to be non empty' |
| 13:24 | noonian | you can describe that easily |
| 13:24 | EvanR | id like an environment that separates the concept of records from A -> B maps to avoid confusion on the topic |
| 13:24 | noonian | {s/Str {s/any s/any}} |
| 13:24 | EvanR | noonian: not even known to be non empty, is a non-constraint |
| 13:24 | justin_smith | EvanR: in clojure records (as defined by defrecord) are maps |
| 13:25 | EvanR | the situation is very simple |
| 13:25 | EvanR | justin_smith: i understand its all the same here |
| 13:25 | justin_smith | not if you use deftype |
| 13:25 | EvanR | so they are the same but not |
| 13:25 | justin_smith | which I brought up before, if you want a type, use deftype |
| 13:26 | EvanR | that would make sense, today i have not brought up any usecase for a record / type |
| 13:26 | EvanR | yesterday though i was talking about records, and people thought i was wanting to know about lookup tables, uniform keys values |
| 13:26 | EvanR | very frustrating |
| 13:27 | justin_smith | EvanR: does clojure even have any concept of uniform keys in a lookup table? other than numeric index I guess |
| 13:27 | EvanR | uniform key type |
| 13:27 | EvanR | string, keyword, number |
| 13:27 | EvanR | the values is the more interesting thing to be uniform |
| 13:28 | justin_smith | but we have no abstraction (other than arrays / vectors) that has uniform key type as a property |
| 13:28 | justin_smith | not to mention values! |
| 13:28 | EvanR | not unexpected |
| 13:29 | EvanR | does prismatic schema allow recursive schemas |
| 13:30 | justin_smith | EvanR: https://github.com/Prismatic/schema/issues/35 addressed here |
| 13:30 | technomancy | amalloy_: I remember you saw a use of flatten in lein that was somewhat justified? was it in lein clean? |
| 13:31 | EvanR | yurg, cyclic data structure is not what i was expecting |
| 13:32 | justin_smith | EvanR: a schema is a data structure, a recursive schema would need to be a cyclic data structure |
| 13:32 | EvanR | seems like a limitation of the schema rep |
| 13:32 | justin_smith | OK |
| 13:33 | justin_smith | EvanR: the set of concerns / interests you have here makes me wonder if you wouldn't prefer using scala over clojure. Not saying "get out of here if you feel that way", just I think scala dev is more aligned with those concerns. |
| 13:33 | noonian | schema supports recursive schemas now: https://github.com/Prismatic/schema/wiki/Recursive-Schemas |
| 13:33 | justin_smith | (inc noonian) |
| 13:33 | lazybot | ⇒ 9 |
| 13:33 | noonian | i think they just don't guarantee them to be fast when validating |
| 13:33 | justin_smith | noonian: I guess I found some out of date info |
| 13:33 | EvanR | good enough |
| 13:34 | noonian | justin_smith: yeah, that issue was closed at the bottom by an accepted PR :P |
| 13:34 | justin_smith | noonian: haha, reading ftw |
| 13:35 | EvanR | since i have all this java stuff set up i guess it wouldnt be out of realm of possibilities to install and try scala |
| 13:35 | EvanR | but seems scary as hell |
| 13:35 | justin_smith | EvanR: agreed |
| 13:36 | justin_smith | EvanR: for example, this type signature freaks me out https://twitter.com/extempore2/status/430341743779659776 |
| 13:37 | EvanR | wtf |
| 13:37 | robstory | there are scarier things, like clobbering immutable namespace with a single import: https://gist.github.com/wrobstory/60750cec022650bf27b1 |
| 13:37 | justin_smith | EvanR: but clojure has its wtfs too, as we both know |
| 13:39 | justin_smith | robstory: does that prevent the original immutible version from being avaialable, or change which version library code would end up using? |
| 13:40 | {blake} | I'm trying to get a form going with hiccup and keep getting a "Key must be integer" exception. |
| 13:40 | amalloy | {blake}: you have too many parens probably |
| 13:40 | {blake} | Minimal example: (defn test-form [] |
| 13:40 | {blake} | (f/form-to [:post "/posts/new"])) |
| 13:40 | amalloy | ,([:x] [:y]) |
| 13:40 | clojurebot | #<IllegalArgumentException java.lang.IllegalArgumentException: Key must be integer> |
| 13:40 | {blake} | amalloy, Too many parens? Unpossible! |
| 13:40 | EvanR | you can never have too many parens |
| 13:41 | {blake} | Well, that's what I thought. I'm copying and pasting examples from git and elsewhere, and the common thread is that error. |
| 13:42 | robstory | justin_smith: for the former, you can still call scala.collection.mutable.Set, and have to do so explicitly. For the latter, I do not believe it would trickle down into lib code. Should stay contained in that particular scope. |
| 13:42 | {blake} | amalloy, Oh...so...okay, that's an error you get when you've executed a function you didn't want and made something a parameter you didn't mean. |
| 13:43 | amalloy | well, when you try to call a vector with something that's not an integer |
| 13:43 | {blake} | I need that macro thing. macroexpand! |
| 13:46 | {blake} | Well, that didn't help. |
| 13:46 | noonian | ,(get [1 2 3] :foo) |
| 13:46 | clojurebot | nil |
| 13:46 | noonian | hmm |
| 13:46 | noonian | ,([1 2 3] :foo)_ |
| 13:46 | clojurebot | #<IllegalArgumentException java.lang.IllegalArgumentException: Key must be integer> |
| 13:47 | amalloy | {blake}: i think you need a less minimal example, because that one looks fine |
| 13:48 | amalloy | noonian: get is more forgiving; it works on anything, and never throws an exception |
| 13:48 | noonian | interesting |
| 13:49 | amalloy | well, "never". you could create a type that responds to get by throwing an exception, but you'd have to do it on purpose |
| 13:51 | dbasch | ,(get get get get) |
| 13:51 | clojurebot | #<core$get clojure.core$get@48b1ca> |
| 13:51 | dbasch | ^ four get |
| 13:51 | justin_smith | dbasch: I only just now realized it was a rebus |
| 13:52 | justin_smith | ,((get get get get) (get get get get) (get get get get) (get get get get)) |
| 13:52 | clojurebot | #<core$get clojure.core$get@48b1ca> |
| 13:56 | turbofail | we need to go deeper |
| 13:58 | noonian | sounds like a job for ben affleck and bruce willis |
| 13:58 | amalloy | ,((fn [n] (nth (iterate (fn [get] (get get get get)) get) n)) 10) ;; arbitrarily deep, with example tenth-order usage |
| 13:58 | clojurebot | #<core$get clojure.core$get@48b1ca> |
| 13:59 | amalloy | plus, i got to write *six* gets in a row |
| 14:00 | justin_smith | (inc amalloy) |
| 14:00 | lazybot | ⇒ 182 |
| 14:22 | technomancy | amalloy: hey, I remember you saw a use of flatten in lein that was somewhat justified? was it in lein clean? |
| 14:23 | amalloy | technomancy: that's the only use of flatten in leiningen at all, now that i've removed the others |
| 14:23 | technomancy | amalloy: I just got a PR for lein clean that uses it and I almost flipped out |
| 14:23 | amalloy | i'm not really convinced it's justified, but taking it out could break back-compat in ways i'm not competent to diagnose |
| 14:23 | technomancy | but then I took a closer look, and it seems necessary to support both singular and plural paths |
| 14:23 | technomancy | :classes-path vs :source-paths |
| 14:24 | amalloy | you still don't need a whole flatten for that, just (mapcat (fn [x] (if (coll? x) x [x])) whatever) |
| 14:25 | technomancy | true, but that's super noisy in comparison |
| 14:25 | amalloy | sure. but you can define that somewhere, and then use it in a non-noisy way. call it squish-a-little |
| 14:26 | justin_smith | sounds like we need a version of concat that takes both collections and single items (and would look a lot like amalloy 's anonymous fn above) |
| 14:26 | hiredman | venial-flatten |
| 14:26 | justin_smith | haha |
| 14:27 | amalloy | (inc hiredman) |
| 14:27 | lazybot | ⇒ 60 |
| 14:29 | technomancy | trying to keep my LOC numbers down here amalloy, geez |
| 14:29 | amalloy | dem bytes ain't cheap |
| 14:30 | technomancy | if we get within an order of magnitude of the lines of sbt we won't be allowed to make fun of them as effectively |
| 14:32 | TimMc | technomancy: Longer lines. |
| 14:33 | turbofail | you can still make fun of them for taking a ridiculously long time to do anything |
| 14:33 | technomancy | turbofail: let he who is without sin cast the first stone |
| 14:35 | turbofail | lein seems to do most operations significantly faster |
| 14:35 | turbofail | even with the clojure startup time |
| 14:35 | EvanR | how would venial flatten know if you really wanted to flatten something or treat it as a "single item" |
| 14:36 | justin_smith | EvanR: it only flattens the args, not any of their contents |
| 14:36 | TimMc | EvanR: coll? |
| 14:37 | EvanR | i guess i should have specified, how would it know if you wanted to flatten a coll |
| 14:37 | EvanR | a subcoll |
| 14:37 | justin_smith | EvanR: if you wanted that, you are calling the wrong function |
| 14:37 | amalloy | EvanR: easy: you don't, or you wouldn't have called venial-flatten |
| 14:38 | justin_smith | ,(defn venail-flatten [& args] (apply concat (map #(if (coll? %) % [%]) args))) |
| 14:38 | clojurebot | #'sandbox/venail-flatten |
| 14:38 | amalloy | it's like, how does + know you don't want to multiply one of the items instead? |
| 14:38 | turbofail | asking the important questions |
| 14:38 | justin_smith | ,(venial-flatten "a" ["b" "c" ["d"]] ["e" "f"]) |
| 14:38 | clojurebot | #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: venial-flatten in this context, compiling:(NO_SOURCE_PATH:0:0)> |
| 14:38 | EvanR | i misunderstood the purpose here, its concats args |
| 14:38 | amalloy | justin_smith: s/apply-concat+map/mapcat/ |
| 14:38 | EvanR | rather than flattening something |
| 14:38 | justin_smith | ahh, yeah |
| 14:38 | justin_smith | ,(defn venial-flatten [& args] (mapcat #(if (coll? %) % [%]) args)) |
| 14:38 | clojurebot | #'sandbox/venial-flatten |
| 14:39 | justin_smith | ,(venial-flatten "a" ["b" "c" ["d"]] ["e" "f"]) |
| 14:39 | clojurebot | ("a" "b" "c" ["d"] "e" ...) |
| 14:39 | justin_smith | EvanR: right, but it replaces a use case where otherwise flatten got called |
| 14:39 | EvanR | another thing i was thinking of was, your structure might not have enough info in it to tell an operation what to do with it, would be another style if it did |
| 14:39 | amalloy | i think the version of it that would be useful for lein doesn't take &args, but sure, a general one might |
| 14:40 | {blake} | amalloy, You're right; because the error is in the calling code, which is trying to call the result of the routine. |
| 14:40 | justin_smith | EvanR: yeah, this is reading a config file (project.clj) |
| 14:40 | justin_smith | EvanR: as such it has "conveniences" for the writer |
| 14:40 | amalloy | {blake}: speaking of which: stacktraces!!! so important. it would be pretty easy to have told you that, if you'd gisted a stacktrace along with the error message |
| 14:41 | {blake} | amalloy, OK, I have another opportunity, since it's back. =P |
| 14:41 | EvanR | ,(concat [1] [2] [3] [4]) |
| 14:41 | clojurebot | (1 2 3 4) |
| 14:41 | turbofail | we need a "fatten" function. though i'm not exactly sure what it will do |
| 14:41 | EvanR | ,(concat [1] [2] 3 [4]) |
| 14:41 | clojurebot | #<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Long> |
| 14:42 | EvanR | ,(concat [1] [2] #{3} [4]) |
| 14:42 | clojurebot | (1 2 3 4) |
| 14:42 | amalloy | turbofail: ##((fn fatten [x] (nth (iterate list x) 10)) 5) |
| 14:42 | lazybot | ⇒ ((((((((((5)))))))))) |
| 14:42 | turbofail | this will suffice |
| 14:42 | EvanR | ,(concat [1] [2] {3 5} [4]) |
| 14:42 | clojurebot | (1 2 [3 5] 4) |
| 14:42 | EvanR | yurg |
| 14:43 | justin_smith | ,(seq {4 5 6 7}) |
| 14:43 | clojurebot | ([4 5] [6 7]) |
| 14:43 | EvanR | ,{1 2 3} |
| 14:43 | clojurebot | #<RuntimeException java.lang.RuntimeException: Map literal must contain an even number of forms> |
| 14:43 | justin_smith | ,(flatten {4 5 6 7}) |
| 14:43 | clojurebot | () |
| 14:43 | EvanR | im glad that case is taken care of |
| 14:44 | amalloy | justin_smith: a classic |
| 14:45 | {blake} | justin_smith, Wow, that's really flat. |
| 14:45 | justin_smith | {blake}: inorite |
| 14:45 | EvanR | very zen |
| 14:46 | {blake} | So, here's my new "key must be integer" (now! with stack trace!) https://www.refheap.com/92490 |
| 14:46 | justin_smith | (dec flatten) |
| 14:46 | lazybot | ⇒ -4 |
| 14:46 | {blake} | lol |
| 14:46 | EvanR | (dec flatten) |
| 14:46 | lazybot | ⇒ -5 |
| 14:47 | {blake} | Hiccup seems easy enough to use, but not being able to figure out how to glue it into my ring app is why I started rolling a few simple routines to do my own HTML. |
| 14:51 | justin_smith | {blake}: I think the issue could have to do with the ambiguity of providing a function to be called on the request, vs creating the response inline. I haven't used compojure in ages, but you are clearly directly specifying a response with one route, while naming a function to be called in another |
| 14:52 | {blake} | justin_smith, Hmmmm. |
| 14:54 | justin_smith | what happens if you change the first route to do (test-form spreadsheet) |
| 14:54 | {blake} | justin_smith, OK, thanks. Let me see if I can't find out how those are supposed to work together. |
| 14:55 | csd_ | Is it necessary to escape user passwords when developing a web app? |
| 14:56 | mgaare | csd_: are you not hashing user passwords? |
| 14:56 | csd_ | i am--good point |
| 14:57 | EvanR | users should be allowed to put any text they want for a password |
| 14:57 | csd_ | how do you guys guard against sql injection |
| 14:57 | csd_ | in general |
| 14:58 | amalloy | csd_: always use parameterized queries, of course |
| 14:58 | amalloy | never ever ever ever write (str "insert into x (password) " user-password) |
| 14:59 | EvanR | ideally the library doesnt even let you use a string |
| 14:59 | amalloy | meh |
| 14:59 | csd_ | amalloy: korma/jdbc are fine though right? |
| 14:59 | amalloy | csd_: sure, as long as you never build query strings yourself |
| 15:00 | amalloy | EvanR: i think it'll be a few more generations before we see a no-strnigs sql library that actually lets you do the things you want to do and is as approachable/flexible as sql |
| 15:00 | EvanR | in clojure? |
| 15:00 | dbasch | passwords should be hashed as soon as possible on the server, and the plaintext forgotten forever |
| 15:01 | EvanR | if you use a query type which is almost like strings but doesnt support strcat that would do it |
| 15:02 | EvanR | where ? and ?? are replaced with args or lists of args |
| 15:02 | mgaare | then you've lost composability |
| 15:02 | amalloy | mgaare: well, you don't really have that with sql anyway. it's not much of a loss |
| 15:03 | mgaare | I felt like this had some good ideas, just didn't quite get there: https://github.com/LauJensen/clojureql |
| 15:04 | amalloy | mgaare: right, it's the lisp curse: 20 different people each solving 80% of the same problem |
| 15:05 | mgaare | I've got some ideas for yet another crack at the problem |
| 15:05 | EvanR | just drop sql the language |
| 15:05 | dbasch | that happens in every language, someone solves the interesting 80% of something and never gets to the tedious 20% that would take forever |
| 15:06 | csd_ | coughlighttablecough |
| 15:06 | mgaare | one insight for me is that combining query generation with query executiotn is a mistake |
| 15:07 | {blake} | csd_ lol |
| 15:08 | EvanR | in what sense are they combined? |
| 15:08 | amalloy | dbasch: you've read the lisp curse, i presume? |
| 15:09 | dbasch | yes |
| 15:09 | mgaare | EvanR: in the sense that many libraries are built around doing both together |
| 15:10 | EvanR | im sure youre right but which one are you thinking of |
| 15:10 | mgaare | korma, clojureql, hyperion are a few off the top of my head |
| 15:11 | EvanR | looking at korma, wow jeez |
| 15:12 | EvanR | i guess this is for quick and dirty |
| 15:12 | clojurebot | Ok. |
| 15:13 | EvanR | you can wrap these in lambdas, but good luck mixing and matching where clauses |
| 15:13 | mgaare | Chris Granger later on said he regretted the way he designed korma, that it was the result of being new to the language and applying too much thinking from elsewhere |
| 15:14 | EvanR | now im even more curious, elsewhere where? |
| 15:14 | csd_ | as someone who just recently used korma id love to know a better alternative |
| 15:14 | turbofail | honeysql is an example of a library that doesn't combine the two |
| 15:14 | mgaare | other languages |
| 15:14 | mgaare | there's a lot of ActiveRecord influence in there |
| 15:14 | EvanR | right that one |
| 15:15 | justin_smith | mgaare: ahh, so he was a rubyist? |
| 15:15 | mgaare | yeah, HoneySQL is pretty good |
| 15:15 | mgaare | justin_smith: I'm not sure of his full background. I know that he used to work at Microsoft on VS |
| 15:16 | justin_smith | mgaare: ahh, you are referring to the general active record concept, not the specific ruby lib called ActiveRecord? |
| 15:16 | turbofail | honeysql has some issues of its own, don't remember exactly what they were |
| 15:16 | {blake} | "The Lisp Curse" is brilliant. And reminds me of my desire to implement Clojure in Smalltalk. |
| 15:17 | dbasch | aka ORM |
| 15:17 | dbasch | years ago I had an employee who implemented his own ORM in Java because he didn’t like Hibernate |
| 15:17 | mgaare | justin_smith: yeah, I just think of ruby's ActiveRecord being so dominant in mindshare that I sometimes use the terms interchangeably |
| 15:17 | rubber_duck | why do people bother wrapping up SQL :\ |
| 15:18 | rubber_duck | YeSQL takes care of the nasty string embedding issues |
| 15:18 | rubber_duck | one of the primary reasons I use clojure is because it works with data so nicely it's super easy to consume results of raw SQL queries |
| 15:18 | justin_smith | mgaare: from some googling I discover there is also a lib called ActiveRecord for php |
| 15:18 | dbasch | rubber_duck: because at some point people thought that you could abstract away the fact that there was a sql database under your persistent object store |
| 15:19 | turbofail | rubber_duck: sometimes i want to generate queries, not merely paramterize them on data |
| 15:19 | justin_smith | dbasch: because the differences in semantics between your object system and the database are just useless noise, of course :) you can just ignore them |
| 15:19 | mgaare | rubber_duck: ah, yesql looks pretty cool. Hadn't seen this before |
| 15:20 | rubber_duck | turbofail, aside from trying to implement a custom DSL -> SQL compiler I think I'd still rather work with strings |
| 15:20 | dbasch | justin_smith: there’s even a wikipedia page for the concept http://en.wikipedia.org/wiki/Object-relational_impedance_mismatch |
| 15:21 | turbofail | rubber_duck: suit yourself. i happen to think working with strings is a disaster |
| 15:21 | EvanR | "oop vs relational war" |
| 15:21 | EvanR | circa 1991 |
| 15:21 | mgaare | it reminds me of how things worked with html libraries somewhat... I used enlive for a while, super complex and powerful, eventually said "f it" and went all the way over to selmer |
| 15:22 | mgaare | yesql seems like an overreaction in the same way |
| 15:22 | rubber_duck | EvanR, that's the beautiful part of clojure - there's no OOP - SQL is just another data returning function - you don't care about "keeping your objects synchronized" because you're working with values by default |
| 15:23 | justin_smith | rubber_duck: to be fair there is some OOP, but we can usually avoid it, and it's on the layer of "how to tell jdbc what to do" not on the layer of representing the queries and results |
| 15:24 | EvanR | yeah i tried reading about that stuff in the history books, and it made no sense |
| 15:24 | EvanR | so many assumptions about how you have to do stuff, it was all a figment of their imaginations |
| 15:24 | amalloy | EvanR: a string type that doesn't support concatenation is certainly interesting. you could do even better in haskell, with a newtype wrapper around String such that you can concat query bits with each other but not with user-input strings |
| 15:25 | bbloom | mgaare: yesql is only an overreaction if you have a genuine need to abstract over sql dialects or compose queries from fragments |
| 15:25 | EvanR | amalloy: the haskell lib mysql-simple and postgres-simple is what i was thinking of, it overload string literals for this |
| 15:25 | amalloy | right |
| 15:25 | bbloom | if you don't need to abstract over sql dialects, you can use database-specific abstraction and composition mechanisms |
| 15:25 | amalloy | i haven't actually used those, but overloaded strings did seem like the natural thing when you suggested it |
| 15:26 | EvanR | but the point about it not being as flexible is true, in which case you really want your field names, joins, where clauses, group bys, orders, limits, and unions to be their own types which you just nest |
| 15:26 | EvanR | thats the simple way |
| 15:26 | EvanR | or you could make this sql compiler thing |
| 15:26 | mgaare | bbloom: The pile-of-strings approach is not very resilient to change either |
| 15:26 | bbloom | mgaare: the question is: what changes? |
| 15:27 | bbloom | mgaare: in my experience it's easier to change sql queries than it is to change ORM invocations |
| 15:27 | bbloom | you're more likely to get analysis errors trying to execute fixed queries than you are trying to generate queries reflectively from schema |
| 15:28 | mgaare | I think we can agree that ORM is not the way |
| 15:28 | amalloy | it's no coincidence that ORM shares two letters with MURDER |
| 15:28 | bbloom | sure, so ORM is clearly out, but the question is whether or not you want a metalanguage for queries |
| 15:28 | EvanR | "how do i do X" "dont do X" mapper |
| 15:28 | bbloom | korma etc are decidedly ORM-like |
| 15:28 | rubber_duck | as much as I love clojure reading it's source to reverse engineer protocols/specs makes me want to bang my head against the wall, I wish core.typed was at the point it could be baked in to the language :) |
| 15:28 | EvanR | sql is already a meta language for queries |
| 15:28 | bbloom | but there's stuff like ClojureQL etc that are arguably more composable |
| 15:28 | EvanR | a sucky one |
| 15:29 | hiredman | really, you just want something that makes generating sql strings better |
| 15:29 | EvanR | and you always want a better language for doing X rather than beating your keyboard like a caveman |
| 15:29 | Bronsa | ,(meta (seq (with-meta (lazy-seq []) {:foo 1}))) |
| 15:29 | bbloom | right, but there's always costs |
| 15:29 | clojurebot | nil |
| 15:29 | hiredman | relational algebra is fine and good, the result sets you get back from java.jdbc are fine |
| 15:29 | bbloom | coding directly to a SQL AST may be preferable in some cases |
| 15:29 | hiredman | bbloom: right |
| 15:29 | bbloom | but SQL wasn't designed to be coded to at the AST level like a lisp was |
| 15:30 | bbloom | so there's naturally some abstract vs concrete syntax mismatch |
| 15:30 | bbloom | so the developer has to bear the weight of that cost |
| 15:30 | bbloom | if you're not metaprogramming queries (or not doing it often) it may not be worth it to pay that cost for all other concrete queries |
| 15:30 | EvanR | until some developer makes a better language that other developers recognize as good |
| 15:30 | hiredman | speaking of everyone having an 80% solution https://github.com/hiredman/graph/blob/master/src/com/manigfeald/graph/rel.clj is what I wrote last time I had to write a lot of sql joins |
| 15:30 | mgaare | SQL was designed for businesspeople to use, and it was at least more successful at that than the previous efforts at that objective like Cobol |
| 15:30 | bbloom | btw, i'm a big fan of C#'s Linq to SQL |
| 15:31 | bbloom | it's exceptionally well done |
| 15:31 | EvanR | yeah thats a good example |
| 15:31 | bbloom | it has both solid concrete sytnax and is very robust both in terms of reliability and completeness |
| 15:31 | rubber_duck | F# typeproviders look even sexier |
| 15:31 | hiredman | bbloom: indeed |
| 15:32 | EvanR | foo to sql compiler |
| 15:32 | EvanR | design pattern |
| 15:33 | justin_smith | bbloom: would Linq be usable from clojure-clr? |
| 15:33 | bbloom | justin_smith: the compiler might be, yeah |
| 15:33 | bbloom | justin_smith: you'd still need a mapping from a clojure data structure to an Expression data type to invoke the compiler |
| 15:34 | rubber_duck | In F# type providers basically both the compiler and the IDE can read your DB schema trough a plugin and generate type info and provide code completion off live DB - that's just :O |
| 15:34 | justin_smith | bbloom: that seems more tractable than string based stuff at a glance |
| 15:34 | bbloom | justin_smith: you'd get a good SQL compiler, but you basically now need a clojure to C# compiler |
| 15:34 | bbloom | which is, of course, different than clojure to msil |
| 15:34 | bbloom | linq operates on an expression tree datatype |
| 15:35 | bbloom | seems like that may be as hard, if not harder, than just compiling to SQL |
| 15:35 | EvanR | expression trees without further context sounds way easier to deal with than sql text |
| 15:36 | EvanR | but its c# |
| 15:36 | bbloom | basically, the C# compiler uses the type of an argument to overload the call site to automatically quote the passed expression |
| 15:36 | bbloom | it's basically C#'s macro mechanism |
| 15:36 | turbofail | hm. interesting |
| 15:37 | bbloom | http://msdn.microsoft.com/en-us/library/bb397951.aspx |
| 15:37 | bbloom | it's similar to scala's call by name, but scala does not let you inspect a call by name argument |
| 15:37 | bbloom | to do that, you must write a scala compiler plugin |
| 15:41 | turbofail | this doesn't seem to allow for compile time shenannigans. though on the plus side, it doesn't seem to allow for compile time shenannigans |
| 15:43 | turbofail | though it also appears you can compile at run time, as in clojure. so the distinction is kind of fuzzy |
| 15:51 | andyf | Bronsa: Would you prefer I test latest tools.reader over the revert change you suggested? |
| 15:54 | Bronsa | andyf: yeah |
| 15:56 | EvanR | apt-get installing scala, im feeling bored with life |
| 15:57 | perplexa | does anybody use clojure to build GUI apps? |
| 15:58 | perplexa | and if yes, what libs do people use? i just saw seasaw but it seems unmaintained |
| 15:58 | sveri | Hi, name one beginner friendly .emacs.d repo, at best with an overview of the shortcuts, pleas |
| 15:59 | andyf | A few have created some: Nightcode clooj clj-ns-browser. Seesaw is a good swing lib wrapper |
| 15:59 | perplexa | thx andyf! |
| 15:59 | andyf | Why did it seem unmaintained ? |
| 16:00 | perplexa | commits are from 4-1 year ago |
| 16:01 | andyf | There is an email list where some q & a still occurs. Not sure if it is still being enhanced. |
| 16:01 | noonian | you could also go the cljs + node webkit route |
| 16:02 | perplexa | btw andyf, i didn't mean IDEs ;p |
| 16:02 | amalloy | perplexa: sometimes things are just done. seesaw works fine, as far as i know. there's no need to constantly add new bells and whistles to it |
| 16:03 | perplexa | i'll give it a try then |
| 16:03 | andyf | Seesaw is not specific to IDEs. They are just examples I knew without looking up more |
| 16:05 | ustunozgur | try this: google for java rationale |
| 16:06 | amalloy | perplexa: also, it looks like he's been merging pull requests regularly. Last one merged a month or two ago |
| 16:08 | {blake} | Crap. Hiccup doesn't have a date control? |
| 16:08 | Bronsa | http://sprunge.us/LZTB |
| 16:10 | EvanR | you know very well source code degrades over time naturally and must be constantly updated to maintain a constant level of workingness |
| 16:10 | amalloy | that's interesting, Bronsa. does the compiler just choose arbitrarily among equally-good overloads? |
| 16:10 | AimHere | EvanR, binary code degrades faster, of course |
| 16:11 | EvanR | lol |
| 16:11 | Bronsa | amalloy: that's what it looks like |
| 16:11 | seangrove | {blake}: I assume you must mean something like hiccup (in clojure) throws an error if you do [:date ...]? |
| 16:11 | perplexa | amalloy: fixing typos in comments ;/ |
| 16:11 | amalloy | perplexa: so, it works so well that the only pull requests people are sending him are comment typos, and he's even merging those? where is the bad news? |
| 16:12 | justin_smith | {blake}: seangrove: yeah that confused me too, all hiccup does is output tagged elements, why would it care if it was a date or not? |
| 16:12 | {blake} | seangrove, I'm looking for a "date-field". |
| 16:13 | Bronsa | amalloy: the funnt thing is that it doesn't do that at compile time, those compile into a reflective call |
| 16:13 | amalloy | right |
| 16:13 | perplexa | i thought there would be the need to update it, but seems swing is consistent in its api, but i really have no idea :) |
| 16:13 | seangrove | {blake}: Post some code and error output |
| 16:13 | AeroNotix | dakrone: hey when are you going to release clj-http 1.0.2? |
| 16:14 | {blake} | seangrove, Nothing to post. There's no "date-input". Maybe I'm supposed to use "input-field"--but that's a "defn-". |
| 16:14 | AeroNotix | not trying to rush you but a weird bug between elastisch and clj-http seems resolved when using 1.0.2-SNAPSHOT |
| 16:15 | seangrove | {blake}: Surely it's just [:input {:type "date"}] ? |
| 16:15 | {blake} | seangrove, Like maybe it's supposed to be called (inputfield "date" "mydate") |
| 16:15 | amalloy | Bronsa: what order do the methods come out in when you use reflection to look up the methods named foo and bar? |
| 16:16 | seangrove | Weird, I had never even seen this https://github.com/weavejester/hiccup/blob/1.0.5/src/hiccup/form.clj#L89 |
| 16:16 | seangrove | I've never used the helper functinos I guess |
| 16:16 | justin_smith | {blake}: I think what you may be missing is that hiccup is really about constructing a fairly straightforward edn that can be translated to html, and you don't need a specific function to create that edn, you can put it in literally or write your own function that outputs edn |
| 16:16 | seangrove | justin: Did you know about those helper elems? |
| 16:16 | {blake} | justin_smith, Yeah. Sounds plausible. |
| 16:16 | justin_smith | seangrove: I have looked at them, but never really needed them |
| 16:17 | Bronsa | amalloy: yeah they come out in reverse order |
| 16:17 | amalloy | it looks to me like the issue is that (clojure.lang.Compiler/subsumes (into-array [Long]) (into-array [Integer/TYPE])) and (clojure.lang.Compiler/subsumes (into-array [Integer]) (into-array [Long/TYPE])) are both true |
| 16:17 | {blake} | justin_smith, seangrove Leave it to the noob to find the obscure stuff... |
| 16:17 | justin_smith | hehe |
| 16:17 | amalloy | so the compiler considers those both perfect matches, and doesn't bother looking to see if there's another equally-good match |
| 16:18 | justin_smith | {blake}: another approach would be to use the same macros that are being used in the code seangrove linked to |
| 16:18 | Bronsa | amalloy: I gave up months ago trying to understand how all that actually can work, I just accept it does most of the time |
| 16:18 | amalloy | a solid plan |
| 16:19 | {blake} | justin_smith, I am using those; that's why I was looking for a "date-field". |
| 16:20 | justin_smith | {blake}: I mean the macros that generate those definitions |
| 16:20 | justin_smith | (it's macros all the way down) |
| 16:21 | {blake} | justin_smith, Till you get to the turtles, anyway. I was thinking about the "input-field" function. Was there a macro I could use instead? |
| 16:22 | andyf | Bronsa: Maybe I am getting overly worried by your example, but does that mean that Math/abs could truncate longs to ints with no way to predict? |
| 16:22 | noonian | as long as the last one never gets expanded then you |
| 16:22 | noonian | you're good right? |
| 16:22 | {blake} | OK, here's a more general-purpose question: I'm used to having a substring function that handles out-of-bounds conditions...gracefully...like (subs "" 0 4) returning "", rather than "HOW DARE YOU!?!" Is there such a thing in Clojure? |
| 16:22 | justin_smith | {blake}: in seangrove's link they use "defelem" |
| 16:23 | justin_smith | great simile about system design: "like putting a pig heart in an alligator because mammals are clearly better than reptils" |
| 16:23 | {blake} | justin_smith, So I could make a "defelem date-field", IOW. Yeah... OK, feasible. |
| 16:23 | EvanR | sounds tastey |
| 16:24 | {blake} | It's bacon that eats you! |
| 16:24 | justin_smith | EvanR: there's a cajun place nearby, open real late, you can get a killer mac+cheese+alligator sausage |
| 16:26 | amalloy | andyf: looks possible to me, yes |
| 16:26 | noonian | justin_smith: where at? |
| 16:27 | justin_smith | noonian: portland, OR |
| 16:27 | noonian | justin_smith: i know, i mean where in pdx? |
| 16:27 | noonian | is the cajun place you're talking about |
| 16:28 | justin_smith | montage, se industrial |
| 16:28 | noonian | i've never had alligator |
| 16:28 | noonian | ah right, one of my friends seears by montage |
| 16:29 | justin_smith | it's an intense place, definitely not a laid back atmosphere |
| 16:29 | Bronsa | andyf: yeah it would look like so |
| 16:29 | Bronsa | andyf: OTOH (fn [a] (Math/abs a)) would emit a reflection warning |
| 16:29 | amalloy | andyf: if you decompile (fn [x] (Math/abs x)), it boils down to a reflective call that hinges on clojure.lang.Reflector/paramArgTypeMatch |
| 16:30 | amalloy | and it says that a Long arg matches an int param |
| 16:32 | amalloy | and the way it unboxes is via Long.intValue(), which silently overflows |
| 16:32 | andyf | Uncool |
| 16:37 | andyf | Bronsa: I suppose it makes sense that the combination of how tools.reader adds more file loc metadata than the Clojure reader, and how syntax quote works, that some code could throw method too large with tools.reader when eval'd but not with standard reader ? |
| 16:37 | Bronsa | andyf: yeah probably |
| 16:37 | Bronsa | andyf: it might choke on the <clinit> method |
| 16:37 | amalloy | andyf: i'm a little surprised. at least in the reflective case, your code is really slow already anyway; Reflector could do an overflow check when unboxing, and throw an exception |
| 16:38 | andyf | I have only seen that occasionally so far. Will let you know if it gets worrisome. |
| 16:38 | Bronsa | andyf: I remember seeing that for midje a while ago |
| 16:39 | amalloy | Bronsa: just in general, not for tools.reader, right? |
| 16:39 | andyf | I suppose best workaround would be to disable some of that extra metadata in tools.reader ? |
| 16:40 | Bronsa | amalloy: some midje macros output a *huge* amount of code for even relatively small inputs, tools.reader adds >2x the amount of metadata that LispReader does and that's enough to trigger a methodwhatever exception |
| 16:41 | Bronsa | andyf: ATM there's no way to control what metadata is attached where in tools.reader |
| 16:42 | andyf | I know how to use grep for end-column :-) |
| 16:42 | Bronsa | heh |
| 16:42 | Bronsa | andyf: it's not only end-column/end-line though |
| 16:42 | Bronsa | andyf: tools.reader adds line info on vector/set/map literals too |
| 16:43 | Bronsa | and maybe on symbols or something like that, I don't remember |
| 16:43 | Bronsa | andyf: cljs needs this to emit accurate source-maps |
| 16:43 | andyf | Ok. Good to know, but not urgent. |
| 16:44 | hiredman | on that basis I continue to blame midje for everything |
| 16:46 | amalloy | Bronsa: i remember long ago that midje was regularly emitting enough code to break the compiler even using the ordinary reader, so i can't really blame tools.reader for this |
| 16:49 | TimMc | I feel like this is probably a usecase for generative testing. :-) |
| 16:50 | TimMc | Oh nvm, you're talking about the sheer quantity of code. |
| 16:50 | TimMc | We've run into that at work a couple times, but it's slightly our fault. |
| 16:50 | Bronsa | amalloy_lunch: the real issue IMHO is that the compiler doesn't split methods when they start getting big enough they could hit the limit & doesn't compress the data when building the constant table in <clinit> |
| 16:51 | Bronsa | those are both things I'd like to address in tools.emitter.jvm but I have an awful long list of things to do before I can start playing again with t.e.jvm |
| 16:54 | andyf | (zinc Bronsa) |
| 16:54 | andyf | (inc Bronsa) |
| 16:54 | lazybot | ⇒ 65 |
| 16:54 | andyf | I hope you are not now, or ever, covered in zinc |
| 16:55 | TimMc | unless it's sunscreen |
| 16:55 | TimMc | Bronsa: Is there a Jira ticket for that? I'd like to vote for it. |
| 16:55 | andyf | I like to think there are 2.5 people working on Eastwood, and Bronsa is 2 of them :-) |
| 17:00 | TimMc | Hah! Who is .5? |
| 17:00 | andyf | Me |
| 17:06 | Bronsa | TimMc: no ticket that I'm aware of |
| 17:06 | technomancy | ~theology |
| 17:06 | clojurebot | It's greek to me. |
| 17:07 | tim___ | ooh, that's a good one |
| 17:07 | Bronsa | andyf: that's totally untrue and you know it. both eastwood and t.a would be nowhere near what they are now if it wasn't for your hard work |
| 17:08 | andyf | It's a humbler- than-I-actually-am joke |
| 17:08 | technomancy | tim___: not actually the response I was expecting, but that works surprisingly well. |
| 17:09 | technomancy | ~geometry |
| 17:09 | clojurebot | Titim gan éirí ort. |
| 17:09 | technomancy | ~theology is <reply>Clojure needs some theology and geometry; some taste and decency. I suspect we are teetering on the edge of an abyss. |
| 17:09 | clojurebot | 'Sea, mhuise. |
| 17:09 | technomancy | ^ what I think of when I hear that midje is emitting enough code to break the compiler |
| 17:12 | justin_smith | technomancy: among the many things we have in a lisp that scale to great ends thanks to our compible tools, is space usage |
| 17:13 | tbaldridge | and it's not just Midge, try using core.match with core.async's go macro... |
| 17:14 | tbaldridge | or writing any large function in something like core.match or core.async |
| 17:16 | technomancy | one of the many reasons it bums me out that pattern matching isn't part of the language |
| 17:27 | EvanR | im using core.match, should i be worried? |
| 17:29 | andyf | Probably not, unless you mix with core.async and/or large functions |
| 17:30 | technomancy | I can't use it because it would lock all lein plugins into a specific version =\ |
| 17:30 | technomancy | but if you don't have a big plugin ecosystem that shouldn't be a problem for you |
| 17:30 | technomancy | it used to have a bunch of AOT bugs, but it sounds like those have been taken care of |
| 17:30 | andyf | technomancy: Not if you renamed the namespace of the one you use :-) |
| 17:31 | Bronsa | andyf: hah, I was waiting for this comment |
| 17:31 | justin_smith | andyf: and the jar dep too? |
| 17:31 | andyf | I don't recommend that. I am a masichist in some ways. |
| 17:32 | technomancy | don't give me any crazy ideas |
| 17:32 | technomancy | I have plenty of my own, and it gets confusing when I have to tell them apart from other peoples' crazy ideas. |
| 17:32 | technomancy | =) |
| 17:32 | andyf | justin_smith: No jar dep. copy the source & rename the namespaces |
| 17:33 | andyf | Assuming licenses are compatible |
| 17:33 | technomancy | like what clojure does with asm, I guess |
| 17:33 | justin_smith | oh, of course |
| 17:39 | amalloy | i would support a jar rename of core.match by technomancy. it would have to be called technomatchy or matchnomancy or something |
| 17:39 | amalloy | and it would be sufficiently advanced to be indistinguishable from matchic |
| 17:40 | justin_smith | phil.matchelberg |
| 17:40 | amalloy | (inc justin_smith) |
| 17:40 | lazybot | ⇒ 112 |
| 17:41 | andyf | Any technology distinguishable from magic is insufficiently advanced. |
| 17:42 | jamieenglish | Hi all, I'm looking to build a load testing web app and want to use JMeter as a library, rather than an executable. Is this a bad idea?? |
| 17:42 | lazybot | jamieenglish: Uh, no. Why would you even ask? |
| 17:43 | andyf | Man, lazybot has no empathy |
| 17:43 | justin_smith | lazybot, are you silly?? |
| 17:43 | lazybot | justin_smith: Definitely not. |
| 17:44 | arohner | ok, real stupid question. clj-time surely has a date time formatter that will take an #inst, right? |
| 17:44 | arohner | (with the #inst part stripped) |
| 17:44 | dbasch | lazybot is distinguishable from magic |
| 17:44 | hiredman | #inst will actually take a lot of things |
| 17:44 | arohner | hiredman: my goal is to take a string generated by #inst, and parse into joda (and then later spit joda times into strings that resemble #inst) |
| 17:45 | jamieenglish | Well, lazybot, jmeter is cool as a cli, but there doesn't seem to be much info on using it to programatically build and run load tests :( |
| 17:45 | arohner | I know I can write the formatter, I'm just amazed it doesn't exist yet |
| 17:45 | arohner | or I'm unable to find it |
| 17:45 | justin_smith | jamieenglish: in case it is not clear, lazybot answers anything ending in ?? with a random yes or no |
| 17:45 | amalloy | jamieenglish: lazybot is a bot; he's just guessing that because your question ended with ?? you are asking something to which the answer is probably "no" |
| 17:45 | EvanR | ?? |
| 17:45 | lazybot | EvanR: Uh, no. Why would you even ask? |
| 17:45 | clojurebot | CLABANGO! |
| 17:45 | amalloy | justin_smith: not so! |
| 17:45 | EvanR | ??? |
| 17:45 | lazybot | EvanR: Yes, 100% for sure. |
| 17:46 | amalloy | is there a way to force lazybot to answer with a yes??? |
| 17:46 | lazybot | amalloy: Yes, 100% for sure. |
| 17:46 | justin_smith | amalloy: oh, TIL |
| 17:46 | EvanR | ? ? |
| 17:46 | jamieenglish | justin_smith: I got that :) |
| 17:46 | amalloy | justin_smith: the ?? ending is the only part of it that seemed to me to be actually a good heuristic; i put in the ??? thing so i could use lazybot as a stooge |
| 17:46 | EvanR | #"\?\s*?\d*$" |
| 17:47 | justin_smith | amalloy: look for a ‽ trigger in my pr for lazybot |
| 17:48 | technomancy | we had someone get super mad at that in #leiningen the other day |
| 17:48 | technomancy | but it was about a windows question and he was actually pretty mad to begin with afaict |
| 17:48 | amalloy | is it possible that amalloy is secretly pulling all the strings behind lazybot‽ |
| 17:48 | lazybot | "no, no way that would ever happen" |
| 17:49 | amalloy | lol, silly me. put in ""s as if IRC were a clojure repl |
| 17:49 | justin_smith | amalloy: I read the quotation marks as sarcasm |
| 17:49 | EvanR | hhkklklhkjh |
| 17:49 | hiredman | ~amalloy |
| 17:49 | amalloy | EvanR: vim is over there |
| 17:49 | clojurebot | amalloy only uses locally sourced, free range electrons |
| 17:50 | amalloy | technomancy: it's a fun feature, but i probably wouldn't add it today, just because he does occasionally upset people who don't get it |
| 17:51 | amalloy | sometimes those people deserve it, but uninformed newbies don't need any extra confusion in their lives |
| 17:51 | justin_smith | jamieenglish: your question piqued my curiosity, and all I find so far is forum threads about whether it would be a good idea (with many people saying it is crazy) and no guides to embedding jmeter, or examples of using it that way. |
| 17:51 | dbasch | amalloy: we can all use more confusion http://www.scientificamerican.com/podcast/episode/confusion-helps-us-learn-12-06-25/ |
| 17:51 | technomancy | amalloy: I'd say it's not bad in high-traffic channels where the bot is unlikely to be the only response |
| 17:51 | sdegutis | Hi bbloom. Thanks for the fun conversation about religion on Twitter. |
| 17:52 | technomancy | but timezones make it more complicated too |
| 17:52 | bbloom | sdegutis: that isn't appropriate to bring up here |
| 17:52 | hiredman | I dunno, I mean, I seem to recall hearing that the less informed you are about a topic the more confident you are in your opinions on it |
| 17:52 | sdegutis | Oops. |
| 17:52 | hiredman | so maybe confusion is called for |
| 17:52 | dbasch | not sure, I’m meta-confused |
| 17:52 | technomancy | relevant https://twitter.com/geektastic/status/527456651578966017 |
| 17:53 | justin_smith | hiredman: dunning-kruger? that's kind of a curve |
| 17:53 | jamieenglish | justin_smith: thanks for looking. I'll have a quick stab at it and hopefully report back if I get anywhere |
| 17:54 | technomancy | "We come here upon what, in a large proportion of cases, forms the source of the grossest errors of mankind. Men on a lower level of understanding, when brought into contact with phenomena of a higher order, instead of making efforts to understand them, to raise themselves up ... |
| 17:54 | justin_smith | jamieenglish: I bet ##java would have more actual insight |
| 17:54 | technomancy | to the point of view from which they must look at the subject, judge it from their lower standpoint, and the less they understand what they are talking about, the more confidently and unhesitatingly they pass judgment on it." |
| 17:54 | technomancy | ^ tolstoy had a good explanation for why people go "ugh parens" |
| 17:54 | amalloy | technomancy: solution to non-problem: tell lazybot to /nick lazyBOT-this-is-a-BOT |
| 17:54 | jamieenglish | justin_smith: cheers, I'll try there |
| 17:54 | technomancy | amalloy: nope, people would still miss it. |
| 17:55 | amalloy | technomancy: a non-solution to a non-problem, then. seems like a good plan |
| 17:57 | mmeix | justin_smith hyPiRion P.S. to the problem I had yesterday: found another solution without reduce :-) https://www.refheap.com/92493 |
| 17:57 | EvanR | /nick NOT-A-BOT |
| 17:58 | kenrestivo | well i for one enjoy lazybot and clojurebot's weird quirkd |
| 17:59 | hugod | bbloom: re your conversation on stevedore, dsl's, etc, I am generally unhappy with stevedore being more than a syntactic translation. I would really like to be able to try using an equivalent of racket's #lang support to have stevedore look more like plain shell, and just add interpolation of clojure values. |
| 18:00 | amalloy | mmeix: (defn runs [coll] (flatland.useful.seq/glue conj [] #(= %2 (inc (peek %1))) coll)) |
| 18:00 | hoangelos | I'm using the clojure client. Is there a way to get the delete-directory to be recursive? |
| 18:00 | justin_smith | hoangelos: "the clojure client"? |
| 18:01 | hoangelos | well. it's just a wrapper around the java client... |
| 18:01 | hoangelos | oops |
| 18:01 | justin_smith | hoangelos: what's the referent here? |
| 18:01 | bbloom | hugod: interesting |
| 18:01 | hoangelos | hilarious wrong room |
| 18:01 | mmeix | amalloy (flatland.useful.seq/glue) is new to me ... looks useful though |
| 18:01 | amalloy | mmeix: it's super useful for batching of all sorts |
| 18:01 | kenrestivo | well of course it's useful, it's useful. |
| 18:02 | amalloy | and this has the upside that it's lazy-ish, or at least as lazy as partition is |
| 18:02 | mmeix | amalloy thanks! will try |
| 18:03 | justin_smith | mmeix: amalloy: not to be confused with gfredericks/useless |
| 18:03 | mmeix | how do you people know about sich a lib? I wouldn't know how to search for something like that .. |
| 18:03 | technomancy | same way you solve every problem |
| 18:03 | clojurebot | Titim gan éirí ort. |
| 18:03 | amalloy | mmeix: i wrote it |
| 18:03 | technomancy | ask on IRC! |
| 18:03 | justin_smith | mmeix: well, amalloy knows about it because he wrote it |
| 18:03 | justin_smith | heh |
| 18:03 | mmeix | ah! ok ... so: |
| 18:04 | dbasch | mmeix: now you know about it because you asked |
| 18:04 | mmeix | (inc amalloy) |
| 18:04 | lazybot | ⇒ 183 |
| 18:04 | amalloy | but useful is broad enough that it has answers to a lot of common problems; it might be worth your while to skim it and take note of anything you might want later |
| 18:04 | amalloy | http://flatland.org/useful/ |
| 18:04 | dbasch | contagiousness is the essence of virality |
| 18:05 | mmeix | thanks - this IRC channel is a constant source of wisdom for a beginner ... |
| 18:07 | amalloy | oh nice, i forgot i added flatland.useful.fn/ap |
| 18:08 | amalloy | the number of times i've written something like (-> xs (foo) (bar) (apply update-in [:x] inc)) and then been like "what the heck why doesn't this work"... |
| 18:09 | amalloy | er, except that inc of course doesn't want to be applied; imagine some other function for the example |
| 18:09 | amalloy | when clearly i should be writing (-> xs (foo) (bar) ((ap update-in) [:x] inc)) |
| 18:10 | mmeix | BTW: does anyone know about a introductory tutorial for derive? |
| 18:11 | mmeix | (maybe I should immerse myself into Joy of Clojure for this ...) |
| 18:12 | mmeix | but for this evening: studying the treasures of flatland :-) |
| 18:13 | justin_smith | mmeix: my suggestion around derive was you can use multimethods to describe behaviors on various kinds of input, and then derive to build heirarchies of things with behaviors |
| 18:13 | mmeix | aha! ok ... |
| 18:13 | justin_smith | mmeix: the embryo of an idea there being that one could model musical domain knowledge about rules that way |
| 18:14 | justin_smith | but it's not a totally solidified thing, may be hare-brained |
| 18:15 | mmeix | so derive is about multi-methods ... |
| 18:15 | mmeix | worth learning anyway I guess |
| 18:15 | justin_smith | mmeix: yeah, it's about describing a kind of inheritance or taxonomy |
| 18:16 | mmeix | in terms of methods? |
| 18:16 | justin_smith | mmeix: methods use isa? and isa? respects the taxonomies / heirarchies built by derive |
| 18:17 | mmeix | ah, it's a more generalized concept |
| 18:17 | mmeix | something to let sink in for some days, I guess |
| 18:17 | justin_smith | ,(derive ::cat ::animal) |
| 18:17 | clojurebot | nil |
| 18:17 | justin_smith | ,(derive ::cat ::heatsink) |
| 18:17 | clojurebot | nil |
| 18:17 | justin_smith | ,(isa? ::cat ::animal) |
| 18:17 | clojurebot | true |
| 18:18 | justin_smith | ,(isa? ::cat ::heatsink) |
| 18:18 | clojurebot | true |
| 18:19 | mmeix | and ::cat would be a method/function ... , or just anything? |
| 18:19 | mmeix | sounds a bit like OO inheritance to my naive understanding |
| 18:19 | mmeix | (I'm really a beginner still...) |
| 18:19 | justin_smith | mmeix: a multimethod could have a method for ::animal |
| 18:20 | justin_smith | mmeix: a bit |
| 18:20 | mmeix | ok |
| 18:20 | amalloy | mmeix: it kinda is, yes. but it's a small piece of the object model (namely, polymorphic dispatch) without the rest bundled into it |
| 18:20 | justin_smith | right |
| 18:20 | mmeix | ah! ::cat would be a dispatch value |
| 18:20 | amalloy | yes |
| 18:20 | justin_smith | mmeix: when provided with ::cat, it would match ::animal |
| 18:21 | mmeix | (light bulb) |
| 18:21 | mmeix | ok, something to ponder on |
| 18:21 | justin_smith | in another context, it might match ::heat-sink |
| 18:21 | justin_smith | because a ::cat has many purposes, of course |
| 18:21 | mmeix | I guess I have to learn about the :: notation and it's meaning beforehand |
| 18:22 | justin_smith | mmeix: oh, that's pretty simple |
| 18:22 | amalloy | mmeix: you can pretend, for this conversation, that ::x is the same as :x |
| 18:22 | justin_smith | ,::foo |
| 18:22 | clojurebot | :sandbox/foo |
| 18:22 | EvanR | a keyword which has lower probability of colliding with someone elses |
| 18:22 | mmeix | sort of privileged keyword? |
| 18:23 | EvanR | namespaces |
| 18:23 | mmeix | ok, will read into this |
| 18:24 | mmeix | thanks to all! (again & again) |
| 18:25 | mmeix | (reading & REPLing) |
| 18:28 | justin_smith | dbasch: that object-relational-mismatch wikipedia article you linked has some hilarious barely-hidden edit war argument going on in it |
| 18:32 | EvanR | is there a function to convert an empty array to nil, only if empty |
| 18:32 | EvanR | i love nils |
| 18:32 | justin_smith | seq |
| 18:32 | amalloy | &(doc not-empty) |
| 18:32 | lazybot | ⇒ "([coll]); If coll is empty, returns nil, else coll" |
| 18:33 | EvanR | ,(seq ()) |
| 18:33 | clojurebot | nil |
| 18:33 | EvanR | ,(seq (1)) |
| 18:33 | clojurebot | #<ClassCastException java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.IFn> |
| 18:33 | EvanR | ,(seq '(1)) |
| 18:33 | clojurebot | (1) |
| 18:33 | dbasch | justin_smith: “I am mostly concerned about link to “How Vietnam Can Still Be Won” ... whereas the parent article is genuinely scholarly-like article on issue with OR/M technology, the latter is mostly (self-?)advertising heavily criticized in its comments as valueless.” |
| 18:33 | amalloy | could be seq or not-empty, depending on what you actually need |
| 18:34 | justin_smith | dbasch: wat |
| 18:34 | EvanR | ,(not-empty '(1)) |
| 18:34 | clojurebot | (1) |
| 18:34 | EvanR | ,(not-empty ()) |
| 18:34 | clojurebot | nil |
| 18:34 | dbasch | justin_smith: from http://en.wikipedia.org/wiki/Talk:Object-relational_impedance_mismatch |
| 18:34 | amalloy | EvanR: the difference is what they do when called on [1] |
| 18:34 | justin_smith | ,(not-empty [1 2]) |
| 18:34 | clojurebot | [1 2] |
| 18:34 | Bronsa | ,[(not-empty [1]) (seq [1])] |
| 18:34 | clojurebot | [[1] (1)] |
| 18:34 | justin_smith | yeah, not-empty is a better default if you care about the type of the input |
| 18:34 | EvanR | ,(not-empty [1]) |
| 18:34 | clojurebot | [1] |
| 18:35 | justin_smith | seq is just the one I use more often / remember more quickly |
| 18:35 | amalloy | i picked not-empty because EvanR said "array" |
| 18:35 | amalloy | and "only if empty" |
| 18:35 | justin_smith | but there is no such thing as an empty array! |
| 18:35 | EvanR | well in my mind its an array, but after going through these other standard functions it probably isnt |
| 18:35 | justin_smith | but vector, yeah |
| 18:35 | justin_smith | :) |
| 18:35 | SagiCZ1 | (doc derive) |
| 18:35 | clojurebot | "([tag parent] [h tag parent]); Establishes a parent/child relationship between parent and tag. Parent must be a namespace-qualified symbol or keyword and child can be either a namespace-qualified symbol or keyword or a class. h must be a hierarchy obtained from make-hierarchy, if not supplied defaults to, and modifies, the global hierarchy." |
| 18:35 | EvanR | but not-empty seems more obvious maybe |
| 18:35 | amalloy | EvanR: probably not |
| 18:35 | amalloy | seq is a better default |
| 18:35 | EvanR | theres no empty arra? |
| 18:35 | amalloy | only use not-empty if you have some concrete reason to do so |
| 18:35 | justin_smith | EvanR: empty vectors sure |
| 18:36 | justin_smith | but arrays are fixed size |
| 18:36 | justin_smith | EvanR: what would you do with an empty collection, with no facility for adding new elements? |
| 18:36 | SagiCZ1 | if i am frequently acessing last item of some sequence, should i use reverse-chronological list (this accessing its head) or should a vector suffice? |
| 18:36 | amalloy | either sounds fine, SagiCZ1 |
| 18:37 | justin_smith | SagiCZ1: imho vectors are great for that, since you also get the intuitive behavior for first, nth, etc. |
| 18:37 | EvanR | justin_smith: pass it to something that doesnt have a special case for empty |
| 18:37 | EvanR | map filter etc work on empty things just fine |
| 18:37 | SagiCZ1 | alright thanks |
| 18:37 | justin_smith | EvanR: ? what would that thing do with it? you can't change dimensions of an array |
| 18:38 | EvanR | i dont remember the last time i wanted to change the dimensions of an array |
| 18:38 | justin_smith | EvanR: so what would you do with a 0 length array? |
| 18:38 | justin_smith | I change dimensions of collections all the time |
| 18:38 | justin_smith | ,(conj [] 1) |
| 18:38 | clojurebot | [1] |
| 18:38 | dbasch | justin_smith: here’s the original article they referred to https://web.archive.org/web/20120329012639/http://www.thefreelibrary.com/Object+Relational+Mapping%3B+How+Vietnam+Can+Still+Be+Won-a01073854068 |
| 18:38 | EvanR | thats mutating? |
| 18:39 | justin_smith | EvanR: that's making a new collection, with the other as a basis, arrays can't do that |
| 18:39 | justin_smith | vectors can |
| 18:40 | amalloy | i think EvanR's usage is not defined nearly well enough to be giving opinions about what the right way to do things is |
| 18:40 | EvanR | this is a very interesting way to distinguish between various basically the same thing |
| 18:40 | EvanR | an abstract vector of things which supports "concat" (not mutating, not implying any implementation or optimizations or performance) should really have an identity element |
| 18:41 | justin_smith | OK, just saying that in terms of impl, if there is a way to make a zero length array, I don't know of it |
| 18:41 | amalloy | justin_smith: ??? |
| 18:41 | lazybot | amalloy: Yes, 100% for sure. |
| 18:41 | amalloy | &(object-array) |
| 18:41 | lazybot | clojure.lang.ArityException: Wrong number of args (0) passed to: core$object-array |
| 18:41 | EvanR | the notion in my mind sort of sounds like why does javascript have empty string |
| 18:41 | amalloy | &(object-array 0) |
| 18:41 | lazybot | ⇒ #<Object[] [Ljava.lang.Object;@22b0ded4> |
| 18:41 | justin_smith | amalloy: d'oh! |
| 18:41 | justin_smith | thanks |
| 18:41 | EvanR | but i did not know java cant make zero length arrays |
| 18:42 | EvanR | that is interesting |
| 18:42 | justin_smith | EvanR: it can |
| 18:42 | amalloy | EvanR: it does, of course |
| 18:42 | EvanR | alright |
| 18:42 | amalloy | zero-element arrays are not very useful as things to write to, of course |
| 18:42 | EvanR | right... you can write to arrays ;) |
| 18:43 | EvanR | its all coming back to me |
| 18:43 | EvanR | i never even thought about writing to an empty array |
| 18:44 | dbasch | zero-length arrays are useful mostly for api compatibility |
| 18:44 | dbasch | e.g. you get an array of search results from a java api, but there are no matches |
| 18:45 | justin_smith | dbasch: good point, I guess I would have expected Null for that, but that isn't handled so well in java |
| 18:46 | amalloy | of course java methods that work with arrays have not been very hip since like java 1.1. collections are a lot more workable |
| 18:46 | dbasch | null would be bad design, because really you’re getting empty results and you’d have to special-case a null check |
| 18:46 | dbasch | amalloy: I’m talking specifically about Lucene |
| 18:47 | justin_smith | dbasch: my brain is too lispy, sometimes this is a problem |
| 18:47 | EvanR | in lisp, empty list is the same as null? |
| 18:47 | amalloy | EvanR: varies by language |
| 18:48 | EvanR | interesting choice if it is |
| 18:48 | justin_smith | EvanR: historically (common lisp) it is, and it is reflected in clojure in places |
| 18:48 | justin_smith | ,(cons 1 nil) |
| 18:48 | clojurebot | (1) |
| 18:48 | amalloy | EvanR: your background is haskell, right? in common lisp, for example, a list is defined basically like: data List a = Cons a d | Nil |
| 18:49 | amalloy | so the only way you could have an empty list is nil |
| 18:49 | amalloy | (and yes, i got the data declaration wrong, but i think you get the idea) |
| 18:49 | dbasch | although the Lucene api has changed, and it looks like the examples are out of date |
| 18:49 | dbasch | e.g. “ScoreDoc[] hits = isearcher.search(query, null, 1000).scoreDocs;” |
| 18:50 | bbloom | <3 this clojure 1.7 :warn-on-boxed setting. got some nice wins on some otherwise reasonably well tuned code |
| 18:50 | EvanR | Nil being a special symbol for Nil, nevermind, i vaguely remember reading about flamewars over this |
| 18:51 | dbasch | but Lucene is one of the highest quality java libraries I know of |
| 18:53 | andyf | bbloom: give puredanger mad incs |
| 18:53 | bbloom | (mad-inc puredanger) |
| 18:53 | bbloom | (inc puredanger) ; plus a regular one |
| 18:53 | lazybot | ⇒ 20 |
| 18:57 | justin_smith | dbasch: other gems of that talk page include the argument that relational databases will inevitably be replaced by systems that tie data to code |
| 18:58 | dbasch | that would be web scale |
| 18:58 | dopamean_ | does anyone know of a good resource for adding things to the session map that ring provides? |
| 18:58 | justin_smith | dopamean_: assoc / assoc-in |
| 18:58 | dopamean_ | right |
| 18:58 | justin_smith | dopamean_: it's just a map |
| 18:58 | dopamean_ | however i thought i could only add i when a response was being sent or something |
| 18:59 | justin_smith | ? you can add it whenever you like, just make sure to supply your modified version to the next stage |
| 18:59 | dopamean_ | right thats the part that im confused about |
| 19:00 | dopamean_ | the function that responds to the request calls another function that renders some stuff with enlive |
| 19:00 | justin_smith | you add new data to the request map under the :session key, and then you pass that along |
| 19:00 | amalloy | dopamean_: you want a middleware like: (defn with-magic [handler] (fn [req] (handler (assoc-in req [:session :magic] :activated)))) |
| 19:00 | amalloy | (or anyway you might want such a thing) |
| 19:01 | justin_smith | dopamean_: {:body (enlive/whatever input) :session (update-session (:session request)) :status 200} |
| 19:01 | dopamean_ | damn |
| 19:02 | dopamean_ | that seems kind of obvious |
| 19:02 | justin_smith | dopamean_: well, it's using standard clojure data structures, but some of the consequences can be interesting and subtle if you are used to doing things another way |
| 19:03 | amalloy | (inc justin_smith) |
| 19:03 | lazybot | ⇒ 113 |
| 19:03 | bbloom | https://github.com/clojure/clojure/blob/b01adb859c66322c5cff1ca9dc1ad98585f2cdc1/src/jvm/clojure/lang/Compiler.java#L7552-L7553 |
| 19:03 | dopamean_ | thanks a ton |
| 19:03 | dopamean_ | this helps a lot. |
| 19:03 | amalloy | hey, that is my second inc of you today. i must be in a generous mood |
| 19:03 | bbloom | ^^ seems like that'll break w/ more than HASHTABLE_THRESHOLD fields (16) |
| 19:05 | hiredman | bbloom: the bare array map constructor doesn't do any checks |
| 19:05 | bbloom | hiredman: ah yes, it doesn't call assoc |
| 19:05 | bbloom | cool thanks |
| 19:06 | bbloom | always seemed a tad sketch to me that array map knows about hash map |
| 19:06 | bbloom | but such is the price of avoiding an extra level of indirection, i suspect |
| 19:06 | andyf | bbloom: Not sure why it would break, but Clojure definitely can create array maps larger than the threshold |
| 19:07 | bbloom | andyf: https://github.com/clojure/clojure/blob/b01adb859c66322c5cff1ca9dc1ad98585f2cdc1/src/jvm/clojure/lang/PersistentArrayMap.java#L200-L201 |
| 19:07 | EvanR | what is "array map" |
| 19:08 | justin_smith | EvanR: one of the concrete implementations underlying clojure's hash-map |
| 19:08 | andyf | Not by that line of code, though :-) |
| 19:08 | justin_smith | ,(class {:a 0}) |
| 19:08 | clojurebot | clojure.lang.PersistentArrayMap |
| 19:08 | justin_smith | ,(class (apply hash-map (range 100))) |
| 19:08 | clojurebot | clojure.lang.PersistentHashMap |
| 19:08 | EvanR | and "hash-map" is referring to just the map { } |
| 19:08 | dbasch | EvanR: https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/PersistentArrayMap.java |
| 19:09 | bbloom | andyf: yeah it's just jamming an array in there directly |
| 19:09 | EvanR | whats persistent about it, beyond the usual? |
| 19:09 | justin_smith | EvanR: hash-map always creates a PersistentHashMap iirc, but literals can create ArrayMaps |
| 19:09 | andyf | I didn't track down how it happens, but saw some when adding some debug prints when fixing something else |
| 19:10 | justin_smith | EvanR: nothing, the naming differentiates from java stuff that is mutable |
| 19:10 | justin_smith | EvanR: well, nothing beyond the usual "persistent collection" meaning |
| 19:10 | amalloy | it's funny because array-map is one of the things in clojure that isn't really very persistent |
| 19:10 | danielszmulewicz | so many sql abstraction libraries... what's your favorite? |
| 19:11 | andyf | justin_smith: EvanR: Wikipedia has article with reasonable dean of persistent data struct. It means something. |
| 19:11 | justin_smith | andyf: yes, sorry, I meant persistent in this case just means that, not that persistent was not a meaningful thing |
| 19:11 | amalloy | andyf: heh. "dean of persistent data structures" is a position i'd take |
| 19:12 | justin_smith | andyf: maybe I misunderstood his "beyond the usual" qualifier |
| 19:12 | andyf | Durn auto correct: dean -> defn |
| 19:12 | EvanR | so it means immutable |
| 19:13 | amalloy | EvanR: persistent actually means something stronger than that, but it's often used loosely to include anything immutable |
| 19:13 | EvanR | this arraymap implementation is nice and simple, i can see how a small map can get some performance out of this |
| 19:13 | amalloy | it's kinda questionable to call PersistentArrayMap "persistent", but not totally wrong either |
| 19:13 | EvanR | i dont know what it means but im guessing it doesnt mean its still there after your jvm shutsdown |
| 19:14 | EvanR | and your computer reboots |
| 19:14 | justin_smith | EvanR: immutible, and also capable of sharing data as needed (though I am not sure if that is neccessary for the definition) |
| 19:14 | EvanR | yep that would be a free benefit of immutable |
| 19:14 | dbasch | EvanR: for that matter, databases are not too persistent in the face of potent magnets |
| 19:14 | amalloy | EvanR: have you read the wikipedia article andyf suggested? |
| 19:15 | justin_smith | EvanR: not quite free - you need the right kind of tree structure to make it really work |
| 19:15 | dbasch | but persistent has a very specific meaning when it comes to data structures |
| 19:15 | dbasch | that has little to do with durability |
| 19:15 | amalloy | you guys are talking at cross purposes, justin_smith/EvanR |
| 19:15 | justin_smith | OK |
| 19:15 | EvanR | which article |
| 19:15 | amalloy | http://en.wikipedia.org/wiki/Persistent_data_structure |
| 19:16 | EvanR | interesting |
| 19:16 | EvanR | the context is an api which "modifies" an object |
| 19:16 | amalloy | justin_smith was trying to talk about efficient structural sharing, where to EvanR it just sounded like pointer sharing |
| 19:16 | EvanR | im still not fully understanding what that means in clojure |
| 19:17 | justin_smith | amalloy: yeah, because that, to me, is what differentiates persistent data structures for other immutible data structures |
| 19:17 | dbasch | EvanR: there’s a good talk by bbloom about persistent trees |
| 19:17 | dbasch | let me find it |
| 19:18 | dbasch | EvanR: https://www.youtube.com/watch?v=j649Tr25RyA |
| 19:18 | dbasch | slides http://www.slideshare.net/g33ktalk/software-dendrology-by-brandon-bloom |
| 19:18 | justin_smith | EvanR: maybe not so much about "modifying" an object, as making a variation without needing to copy the entire object in the process, while still not effectively altering the original |
| 19:18 | amalloy | that was a good talk. does he talk about the definition of persistence? i don't remember that part. i guess even so it's a good introduction to the data structures clojure uses to get well-performing persistent values |
| 19:18 | bbloom | dbasch: i'm glad you enjoyed my talk! but i think zach allaun gives the best intro to how the structures work: http://www.infoq.com/presentations/julia-vectors-maps-sets |
| 19:19 | bbloom | i didn't really set out to cover that |
| 19:19 | justin_smith | bbloom: that was like a reverse kanye |
| 19:19 | bbloom | justin_smith: i'm not going to let you finish, since somebody else did the best thing OF ALL TIME |
| 19:20 | TEttinger | that thing being https://www.youtube.com/watch?v=bP2FpVKlp1s |
| 19:21 | TEttinger | my brother made that, I just added two frames of video and uploaded it |
| 19:21 | EvanR | ok, yeah, it makes sense to have a name for this when immutable is not the default |
| 19:21 | bbloom | it's more than immutable |
| 19:21 | EvanR | even though the apis in clojure ive seen so far dont have much to do with updating in place |
| 19:22 | bbloom | it's about structural sharing |
| 19:22 | bbloom | you can achieve immutable w/ full clone on all writes |
| 19:22 | justin_smith | EvanR: it's not about mutation |
| 19:22 | EvanR | yeah, the java code to support this stuff has the option to copy or not, or update in place or not |
| 19:22 | justin_smith | EvanR: it's an implementation detail for immutability |
| 19:24 | EvanR | is there anything that does copy on write? |
| 19:24 | EvanR | hmm, i guess thats the default |
| 19:24 | amalloy | EvanR: well, array-map |
| 19:24 | amalloy | which is why i said it's a bit awkward to call it PersistentArrayMap |
| 19:24 | EvanR | i meant to ask, is there anything that mutates if it knows nobody will be affected |
| 19:24 | EvanR | in place |
| 19:24 | amalloy | EvanR: transients |
| 19:25 | EvanR | ok |
| 19:25 | amalloy | for one example, see the definition of mapv |
| 19:25 | justin_smith | for values of "it knows nobody will be affected" that include "it's your own fault if you thought you wouldn't be affected" |
| 19:25 | amalloy | which modifies a transient vector in place until it's ready to return it, then converts it to a persistent |
| 19:26 | EvanR | map doesnt just do that? |
| 19:26 | justin_smith | meaning not that transients are sneaky, but there are ways to misuse them if you are not careful |
| 19:26 | EvanR | oh map produces a seq |
| 19:26 | amalloy | EvanR: it can't, because of laziness |
| 19:26 | EvanR | nevermind |
| 19:27 | EvanR | in ruby / javascript you get used to only have one "array" |
| 19:27 | justin_smith | yeah we have list / lazy-seq / queue / vector / array |
| 19:27 | justin_smith | all very distinct |
| 19:27 | EvanR | and map |
| 19:27 | EvanR | didnt know about queue |
| 19:27 | justin_smith | yeah, that's not even sequential |
| 19:28 | EvanR | i didnt think it was, but its supporting all these sequential interfaces |
| 19:28 | amalloy | EvanR: speaking of ruby, mutability, and being used to having just one array: https://docs.google.com/presentation/d/1mGihUBBIKMQn5Uz-5DvQ1Vu24qSuk3o4yUoPoBZW3tI/edit#slide=id.g432ac727f_023 |
| 19:28 | justin_smith | ,(into [] (-> clojure.lang.PersistentQueue/EMPTY (conj :a) (conj :b) pop)) |
| 19:28 | clojurebot | [:b] |
| 19:29 | justin_smith | ^ queue |
| 19:29 | SagiCZ1 | can if-let check if all the bindings are not nil? i know it works for one.. |
| 19:29 | amalloy | justin_smith: queue isn't sequential? |
| 19:29 | justin_smith | amalloy: I listed it with the sequential ones |
| 19:29 | justin_smith | I was saying map was not |
| 19:29 | amalloy | oh, i see |
| 19:29 | EvanR | never use basically anything in ruby's array library |
| 19:30 | amalloy | EvanR: clojure's seq interface is a bit like Foldable. it's not just for things which are sequential, but for things which you can get a sequential view of |
| 19:30 | EvanR | no ! doesnt mean no shenanigans |
| 19:30 | amalloy | man i forget if you are the guy with a haskell background or not |
| 19:30 | amalloy | if not this was a silly comparison |
| 19:30 | EvanR | "haskell background" lol |
| 19:30 | SagiCZ1 | ,(if-let [a 5 b 6] (println a b)) |
| 19:30 | clojurebot | #<CompilerException java.lang.IllegalArgumentException: clojure.core/if-let requires exactly 2 forms in binding vector in sandbox:, compiling:(NO_SOURCE_FILE:0:0)> |
| 19:30 | EvanR | does that exist yet |
| 19:30 | amalloy | it's like ruby's enumerable, kinda |
| 19:30 | SagiCZ1 | okay |
| 19:30 | amalloy | EvanR: huh? haskell's been around for over a decade |
| 19:31 | amalloy | probably over two, but i'm not sure |
| 19:31 | dbasch | ruby bang is pretty random as an indicator of mutability |
| 19:31 | justin_smith | amalloy: ~2, for sure, I remember hearing about it in the late '90s and it wasn't brand new |
| 19:32 | dbasch | it’s more like “I bet you didn’t expect this to mutate stuff, did you?” |
| 19:32 | dbasch | there are plenty of bang-less methods that mutate things |
| 19:32 | EvanR | the similarly named ruby functions keep_if is the opposite of delete_if but doesnt mutate |
| 19:32 | EvanR | for some reason |
| 19:33 | technomancy | I read ruby bang as a "there's another version of this that's non-destructive; that's probably the one you want" marker |
| 19:33 | amalloy | justin_smith: 1990 for 1.0, apparently |
| 19:33 | dbasch | technomancy: to me it’s more like “read the docs for this because it may do unexpected shit” |
| 19:33 | justin_smith | cool, gonna be on a third decade before we know it |
| 19:34 | dbasch | technomancy: e.g. compact and compact! on arrays |
| 19:34 | EvanR | read the docs, then give up and read the source code, if you can |
| 19:34 | EvanR | because they write it using instance_eval |
| 19:36 | hiredman | /win 5 |
| 19:37 | justin_smith | dbasch: let's change the names to pmap‽ and flatten‽ |
| 19:37 | EvanR | amalloy: seq's interface seems to be, "get the next thing" and "unget a thing" https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/ISeq.java |
| 19:38 | EvanR | rather than foldable |
| 19:38 | dbasch | with the bonus that the interrobang makes them harder to type and you have to wait for autocompletion |
| 19:38 | amalloy | well, there's get the current thing and get the rest of the things, which is isomorphic to foldable |
| 19:38 | noonian | its get the next thing, and get everything else |
| 19:38 | amalloy | cons is not exactly related to that |
| 19:39 | EvanR | foldable is about reducing all the things with an accumulator |
| 19:39 | EvanR | the cons thing is curious |
| 19:40 | amalloy | yes, and? that's the same as head/tail, in that you can implement one in terms of the other |
| 19:41 | EvanR | i dont think you can implement a head/tail with foldable |
| 19:42 | EvanR | might be wrong |
| 19:49 | amalloy | EvanR: maybe not. it's easy to get head, but getting a tail that preserves the type is harder than i thought. they serve similar purposes, but i guess may not be isomorphic |
| 19:51 | hyPiRion | a tail that preserves type with foldr assumes the underlying structure has a tail in the first place. That's not necessary with foldable |
| 19:52 | amalloy | hyPiRion: i was imagining you could return a new foldable thing which delegates to the first one and ignores the first value of it, or fold over it with a function that knows how to ignore exactly one value |
| 19:52 | amalloy | the first is impossible; the second actually is probably doable now that i think about it |
| 19:52 | hyPiRion | amalloy: oh right, that you can do |
| 19:52 | amalloy | but both of those are really hard if you want to return something of exactly the same type as your input |
| 19:52 | amalloy | when all you know is that the input is foldable |
| 19:52 | hyPiRion | That's like, drop for foldables |
| 19:53 | amalloy | hyPiRion: right, which is easy in clojure, but not at all obvious for a more strictly typed thing. like, writing `rest :: Foldable t => t a -> t a` is harder than i thought |
| 19:55 | SagiCZ1 | i decided to work with vectors but most clojure functions return seq.. should i always make sure to convert them into a vector? |
| 19:55 | hyPiRion | amalloy: it's possible to return a foldable though (t a -> Foldable a). Don't think you can be isomorphic |
| 19:55 | amalloy | hyPiRion: for sure that's possible, yes |
| 19:55 | amalloy | because you can just write `rest = tail . toList` |
| 19:56 | hyPiRion | right |
| 19:57 | amalloy | SagiCZ1: usually you should work with vectors only when you need some property of theirs that seq doesn't have; at other times, use a seq |
| 19:58 | SagiCZ1 | amall |
| 19:58 | SagiCZ1 | amalloy: i see, thanks |
| 20:00 | SagiCZ1 | take-last sometimes returns something called Clojure.lang.Cons, why? |
| 20:00 | justin_smith | ,(type (cons 1 nil)) |
| 20:00 | clojurebot | clojure.lang.PersistentList |
| 20:01 | SagiCZ1 | i did (take-last n vector-coll) and then (vector-coll index) and that throws clojure.lang.Cons cant be cast to clojure.lang.IFn |
| 20:01 | hyPiRion | justin_smith: you have it the other way around: Cons returns list, list* returns cons |
| 20:01 | hyPiRion | ,(type (list* 1 2 3 ())) |
| 20:01 | clojurebot | clojure.lang.Cons |
| 20:02 | justin_smith | hyPiRion: d'oh, of course, how could I not remember something so simple! |
| 20:02 | SagiCZ1 | i dont know if i should care about it or stick to vectors or what :( |
| 20:02 | justin_smith | SagiCZ1: the return value of take-last is not callable, even if its input was |
| 20:03 | technomancy | just don't pay attention to the class |
| 20:03 | technomancy | pay attention to the interfaces |
| 20:03 | amalloy | SagiCZ1: take-last is not a thing that vectors can do efficiently. maybe it's time to step back and think about what you need to be able to do to your collections |
| 20:05 | SagiCZ1 | i really just need to just add a new value to it sometimes, read last n values from it.. and sometimes i need to trim some old values to keep it from growing too big |
| 20:05 | justin_smith | SagiCZ1: trim from which end? |
| 20:05 | amalloy | that sounds mostly like a queue |
| 20:05 | justin_smith | amalloy: I was wondering, yeah |
| 20:06 | justin_smith | ,(into [] (-> clojure.lang.PersistentQueue/EMPTY (conj :a) (conj :b) pop)) |
| 20:06 | clojurebot | [:b] |
| 20:06 | justin_smith | reusing an example I shared before |
| 20:06 | SagiCZ1 | from the beginning |
| 20:06 | SagiCZ1 | queue... |
| 20:06 | justin_smith | the into is just being used for display purposes - it doesn't print nicely |
| 20:06 | technomancy | clojurebot: queuefish? |
| 20:06 | clojurebot | I don't understand. |
| 20:06 | technomancy | clojurebot: the hell you don't |
| 20:06 | clojurebot | Excuse me? |
| 20:06 | SagiCZ1 | wait it totally is queue |
| 20:07 | technomancy | bots these days |
| 20:07 | technomancy | lazy slackers |
| 20:07 | SagiCZ1 | :) |
| 20:07 | justin_smith | ~quefish |
| 20:07 | clojurebot | I don't understand. |
| 20:07 | hyPiRion | lazybot: you heard him |
| 20:08 | SagiCZ1 | the weird thing about queue is that you usually add new item to the head right? .. but that should be considered the "last" or "newest" item.. which usually has the highest index which is associated with tail in my head |
| 20:09 | noonian | thats an implementation detail of a queue imo |
| 20:09 | justin_smith | SagiCZ1: you can try out variations of what I put in above to see how it works - conj adds to the end, pop takes off the left (peek gets the item you would have popped) |
| 20:10 | SagiCZ1 | and is that the only way to create this queue in clojure? there is nothing similar to 'vec', 'vector' or something? |
| 20:10 | amalloy | SagiCZ1: curiously enough, no, there is no better way built in |
| 20:11 | justin_smith | SagiCZ1: because you always start with an empty one, right? |
| 20:12 | SagiCZ1 | justin_smith: i guess so |
| 20:12 | justin_smith | though many of us would like a prettier syntax for the empty one built in |
| 20:12 | justin_smith | that's what technomancy was talking about with queuefish |
| 20:12 | SagiCZ1 | ,(clojure.lang.PersistentQueue) |
| 20:12 | clojurebot | #<ClassCastException java.lang.ClassCastException: java.lang.Class cannot be cast to clojure.lang.IFn> |
| 20:12 | technomancy | justin_smith: no, this is clearly the deranged utterings of a madman |
| 20:12 | SagiCZ1 | ,(clojure.lang.PersistentQueue/EMPTY) |
| 20:12 | clojurebot | #<PersistentQueue clojure.lang.PersistentQueue@1> |
| 20:12 | technomancy | don't try to read sense into it |
| 20:13 | justin_smith | SagiCZ1: it's an empty coll, not a function that generates an empty coll |
| 20:13 | justin_smith | oh wait, it also returns itself when you call it? funny |
| 20:13 | justin_smith | never thought to try that |
| 20:13 | justin_smith | oh wait |
| 20:13 | justin_smith | ,(Math/PI) |
| 20:13 | clojurebot | 3.141592653589793 |
| 20:13 | justin_smith | it's that thingy |
| 20:13 | justin_smith | interop can be weird |
| 20:13 | technomancy | bot quirk? |
| 20:13 | SagiCZ1 | wait what, thats odd |
| 20:14 | SagiCZ1 | works in my repl too |
| 20:14 | justin_smith | technomancy: nope, it's a legacy thing I guess? |
| 20:14 | technomancy | huh |
| 20:14 | justin_smith | it's always worked |
| 20:14 | SagiCZ1 | it was actually a newb mistake, i didnt want to use the parens |
| 20:14 | justin_smith | it's weird |
| 20:14 | amalloy | technomancy, justin_smith: (Foo/bar) worked before Foo/bar was introduced |
| 20:14 | justin_smith | SagiCZ1: right, then I tried to figure out why it worked :) |
| 20:14 | justin_smith | amalloy: right, legacy |
| 20:14 | technomancy | no kidding |
| 20:14 | technomancy | deep magic from the dawn of time |
| 20:15 | SagiCZ1 | i guess i could just make some tiny wrappers for the queue to make it more readible in my code.. what's stopping me right |
| 20:15 | amalloy | SagiCZ1: folks usually do |
| 20:15 | justin_smith | ,queue-fish |
| 20:15 | clojurebot | #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: queue-fish in this context, compiling:(NO_SOURCE_PATH:0:0)> |
| 20:15 | justin_smith | ~queue-fish |
| 20:15 | clojurebot | Pardon? |
| 20:15 | SagiCZ1 | ~tired? |
| 20:15 | clojurebot | Gabh mo leithscéal? |
| 20:16 | justin_smith | anyway queue-fish is https://groups.google.com/forum/#!topic/clojure-dev/GQqus5Wycno |
| 20:16 | SagiCZ1 | thanks |
| 20:19 | justin_smith | I think a readable print is a bigger deal with queues - unlike anything else that is sequential and persistent, they don't have a nice printed representation that shows the contents. |
| 20:20 | SagiCZ1 | justin_smith: how come? isnt queue also a sequence of some sort? |
| 20:21 | justin_smith | it is, but it prints ugly |
| 20:21 | justin_smith | ,(conj clojure.lang.PersistentQueue/EMPTY 1) |
| 20:21 | clojurebot | #<PersistentQueue clojure.lang.PersistentQueue@20> |
| 20:21 | justin_smith | no hint of the contents |
| 20:21 | justin_smith | ,(seq (conj clojure.lang.PersistentQueue/EMPTY 1)) |
| 20:21 | clojurebot | (1) |
| 20:22 | SagiCZ1 | oh i see |
| 20:26 | justin_smith | but anyway, if you want to add on one end, and drop from the other, you do definitely want a queue, probably that one |
| 20:26 | justin_smith | even if it doesn't print nicely |
| 20:27 | technomancy | clojurebot: queuefish is print-method magic to get (conj (conj clojure.lang.PersistentQueue/EMPTY 12) 9) ; -> <-(12 9)-< |
| 20:27 | clojurebot | 'Sea, mhuise. |
| 20:27 | technomancy | clojurebot: queue-fish is queuefish |
| 20:27 | clojurebot | c'est bon! |
| 20:28 | hiredman | ~queuefish |
| 20:28 | clojurebot | queuefish is print-method magic to get (conj (conj clojure.lang.PersistentQueue/EMPTY 12) 9) ; -> <-(12 9)-< |
| 20:28 | hiredman | ~queuefish |
| 20:28 | clojurebot | queuefish is print-method magic to get (conj (conj clojure.lang.PersistentQueue/EMPTY 12) 9) ; -> <-(12 9)-< |
| 20:28 | hiredman | blegh |
| 20:28 | hiredman | some day |
| 20:29 | amalloy | hiredman: hm? |
| 20:29 | justin_smith | ,(seq (conj clojure.lang.PersistentQueue/EMPTY 12 9)) ; bike shedding a factoid |
| 20:29 | clojurebot | (12 9) |
| 20:30 | technomancy | http://p.hagelb.org/mrfp.gif |
| 20:30 | hiredman | amalloy: clojurebot assumes 'is' means equivalence so it is free to permute and infer |
| 20:30 | amalloy | right...which i thought technomancy was using on purpose to create two copies of that factoid |
| 20:31 | hiredman | but you also get queuefish is queue-fish out of that too |
| 20:31 | technomancy | I was hoping for a redirect but ... who can fathom the mysteries of clojurebot |
| 20:31 | technomancy | dang |
| 20:31 | justin_smith | ~queue-fish |
| 20:31 | clojurebot | queue-fish is queuefish |
| 20:31 | hiredman | hence my "some day" |
| 20:38 | Bronsa | bbloom: the compiler silently ignores type hints in so many places it's not even funny |
| 20:39 | amalloy | *sigh* i just wrote a lexicographic sort for vectors of 1-2 elements out by hand. why didn't i just use some standard sort thingy? |
| 20:40 | justin_smith | amalloy: I am sure your version is unrolled and super-duper optimized |
| 20:40 | tuft | amalloy: at least you haven't typed it in yet |
| 20:42 | gfredericks | ,(sort [[1 3] [5 4] [3 3]]) |
| 20:42 | clojurebot | ([1 3] [3 3] [5 4]) |
| 20:42 | amalloy | gfredericks: that's fine for 2 elements |
| 20:42 | amalloy | try 1-2 |
| 20:42 | andyf | Bronsa: t.a.j used to throw on (extend-type (class (log-window-proxy nil)) ...) but latest does not. That sound intentional to you? I think it was. |
| 20:42 | gfredericks | ,(sort [[1 3] [5 4] [3]]) |
| 20:42 | clojurebot | ([3] [1 3] [5 4]) |
| 20:42 | gfredericks | ,(sort-by (juxt first second) [[1 3] [5 4] [3]]) |
| 20:42 | clojurebot | ([1 3] [3] [5 4]) |
| 20:43 | amalloy | hm, that's a good point |
| 20:43 | amalloy | ,(sort [nil 4]) |
| 20:43 | clojurebot | (nil 4) |
| 20:43 | gfredericks | woah did I just show amalloy how to use juxt to solve a problem |
| 20:43 | gfredericks | I think I just beat #clojure |
| 20:43 | justin_smith | (inc gfredericks) |
| 20:43 | lazybot | ⇒ 101 |
| 20:43 | andyf | Andyf's mind also blown |
| 20:44 | andyf | gfredericks: Wait, you can still hear us? You were supposed to go to the next level. |
| 20:44 | Bronsa | andyf: t.a.j should still throw on that, it's probably getting caught by the wrong-tag handler though |
| 20:44 | Bronsa | andyf: by eastwood's wrong-tag-handler, that is |
| 20:45 | Bronsa | (inc gfredericks) |
| 20:45 | lazybot | ⇒ 102 |
| 20:45 | andyf | Bronsa: Got it. I still need to tweak the wrong tag linter better |
| 20:45 | gfredericks | andyf: hold on let me take out the cartridge and blow in it |
| 20:46 | andyf | gfredericks: No like red/blue pill next level |
| 20:48 | Bronsa | andyf: btw have you seen missing line/col info by any chance? |
| 20:49 | andyf | Bronsa: Some but not a lot. I try to improve thosr when I can but I may run out of steam on some of them for nect |
| 20:49 | andyf | Next release , except to create an issue |
| 20:50 | andyf | Steam, meaning enthusiasm for debigging every last thing |
| 20:50 | andyf | I am on fire with typos today |
| 20:51 | amalloy | debigging. apple autocorrect strikes again? |
| 20:51 | amalloy | i can't imagine that's even in their dictionary though |
| 20:51 | andyf | To manager: yeah I just need to debig my code a bit more and we'll be ready to ship. |
| 20:51 | gfredericks | s/ship/shup/ |
| 20:52 | justin_smith | "this is messed up because of a method too large error, time for some debigging" |
| 20:52 | andyf | That was just iPhone fat fingers |
| 20:52 | gfredericks | andyf: you're halfway to the correct kiwi pronunciation |
| 20:52 | Bronsa | andyf: yeah no worries, I was just asking bcos I saw some missing source info earlier and that shouldn't happen |
| 20:52 | Bronsa | I think I have a fix though. |
| 20:53 | andyf | Nice |
| 20:58 | bbloom | Bronsa: yeah, true |
| 20:59 | bbloom | Bronsa: i guess the issue i hit was that the type hints are inconsistent between symbols and class objects |
| 20:59 | amalloy | well, in fairness to me it looks like i at least got the case analysis right on my hand-unrolled compare-via-juxt |
| 20:59 | dbasch | debigging code embiggens my salary, it’s a perfectly cromulent use of my time |
| 21:00 | Bronsa | bbloom: andyf can attest how many open source libs (even big ones) have wrong/useless tags |
| 21:00 | bbloom | yeah, i'm ok with useless tags |
| 21:00 | bbloom | i rather over tag than under if they aren't doing harm |
| 21:00 | bbloom | i'm just not ok with silent slowness that i can't find easily |
| 21:00 | Bronsa | bbloom: by useless I mean possibly useful tags in position where the compiler will ignore them |
| 21:00 | bbloom | and i really do believe slow and working is a better default than ONLY FAST but compiler type checking headache trying to get it there |
| 21:01 | andyf | The rules for which ones are useful are not something I keep on my head even yet |
| 21:01 | bbloom | yeah |
| 21:01 | bbloom | i have this project that has a bunch of bits that need to be super fast, but those bits are also really tricky to get right and have a ton of duplication that macros can solve for me |
| 21:01 | bbloom | getting fast code generated is proving reasonably tricky |
| 21:02 | bbloom | and it's probably likely i'll convert a bunch of key bits to java to get the maximum perf in some corner cases |
| 21:03 | bbloom | takes some mental energy to resist the urge to optimize/rewrite like crazy, but it's worth the mental energy savings in being able to work in clojure to start with |
| 21:03 | dbasch | but sometimes it’s necessary to leave the clojure bike and drive the java minivan |
| 21:04 | bbloom | but fixing some unboxed math right now involved some definlines and whatnot... got me a 40% win on one of the most important fast paths |
| 21:04 | Bronsa | nice |
| 21:04 | bbloom | i haven't dug too deep in to the byte code, but i suspect that i can do even better |
| 21:05 | Bronsa | ... according to core definline/:inline should be avoided |
| 21:05 | hiredman | core is so weird |
| 21:07 | bbloom | given the commitment to back compat, seems unlikely for definline to go away |
| 21:07 | hiredman | indeed |
| 21:08 | bbloom | and although it's ugly as hell to template-ize syntax-quote whole functions, it considerably speeds up my inner loop |
| 21:08 | bbloom | i've got 3 definline usages, for a total of about 15 lines of code and 7 call sites in a ~5k program that does some pretty funky low level stuff to begin with |
| 21:09 | bbloom | i'm comfortable w/ the tradeoffs, although i wish for a language that scaled to the lowest level more gracefully |
| 21:09 | bbloom | that said, clojure is surprisingly graceful at it compared to pretty much any other dynamic language i've ever used (although i've never done any perf work in CL) |
| 21:11 | turbofail | you can do all sorts of grungy low-level things in SBCL, including going down to assembly |
| 21:11 | turbofail | oh hey look that /msg spammer is back |
| 21:11 | turbofail | zoom__: find a new link at least |
| 21:11 | TEttinger | solo hoy! |
| 21:11 | TEttinger | only now! can you be spammed |
| 21:18 | marcuscreo | howd |
| 21:18 | marcuscreo | howdy |
| 21:21 | Bronsa | andyf: source-info should be fixed for good now |
| 21:23 | andyf | I'll give it a whirl and see what happens. |
| 21:30 | mdeboard | hiredman: Is techsonian.net related to techsonian.com? |
| 21:46 | gfredericks | does clojurescript include a format function these days? if not where would I get one? |
| 21:48 | justin_smith | gfredericks: clojurescript.net lets me use format |
| 21:49 | gfredericks | grepping the cljs repo suggests it's not provided |
| 21:49 | gfredericks | I think it was in the past though |
| 21:49 | justin_smith | http://clojurescript.net/ works in this repl |
| 21:50 | gfredericks | http://dev.clojure.org/jira/browse/CLJS-324 |
| 21:50 | gfredericks | clojurescript.net is a whole nother impl amirite? |
| 21:51 | justin_smith | oh yeah, it is the self hosting version from kanaka |
| 21:51 | justin_smith | never mind that then |
| 21:51 | gfredericks | I guess I'll try goog.string.format |
| 21:52 | gfredericks | actually I think that's probably what this code was using implicitly anyhow |
| 22:11 | csd_ | Anyone know how to set autoreconnect=true in Korma? |
| 22:21 | arrdem | dbasch: ping |
| 22:21 | dbasch | pong |
| 22:26 | danneu | i didn't know assoc could take more than 1 k/v pair. slightly nicer than using merge when the kvs you're merging weren't already in a map. |
| 22:27 | justin_smith | how would merge be better if they were? |
| 22:28 | justin_smith | ,(assoc {:a 0} :a 42 :b 1 :c 2) |
| 22:28 | clojurebot | {:c 2, :b 1, :a 42} |
| 22:28 | danneu | when you're actually merging map data |
| 22:28 | justin_smith | mow, merge-with on the other hand |
| 22:28 | justin_smith | oh, I misread |
| 22:29 | justin_smith | *a map |
| 22:30 | gfredericks | ,(merge-with #(list %1 %2 %1 %2) {:a 0 :b 5} {:b 7 :c 8}) |
| 22:30 | clojurebot | {:c 8, :b (5 7 5 7), :a 0} |
| 22:31 | gfredericks | ,(merge-with #(list %1 %2 %1 %2) {:a 0 :b 5} {:b 7 :c 8} {:b 2}) |
| 22:31 | clojurebot | {:c 8, :b ((5 7 5 7) 2 (5 7 5 7) 2), :a 0} |
| 22:31 | gfredericks | wee |
| 22:35 | justin_smith | ,(defn combine [a & rest] (letfn [(vectorize [v] (into {} (map (fn [[k v]] [k [v]]) v)))] (reduce (fn [a b] (merge-with into a (vectorize b))) (vectorize a) rest))) |
| 22:35 | clojurebot | #'sandbox/combine |
| 22:35 | justin_smith | ,(combine {:a 0 :b 1} {:a 42 :b 420} {:a -1 :b 666}) |
| 22:35 | clojurebot | {:b [1 420 666], :a [0 42 -1]} |
| 22:36 | justin_smith | ,(combine {:a 0 :b 1} {:a 42 :b 420} {:a -1 :b 666 :c 3}) |
| 22:36 | clojurebot | {:c [3], :b [1 420 666], :a [0 42 -1]} |
| 23:30 | ddellacosta | folks: https://groups.google.com/forum/#!topic/clojure/AYe1opodrGA |
| 23:31 | ddellacosta | (hope it's okay I push that here) |
| 23:31 | ddellacosta | (let me know if not and I'll abstain) |
| 23:39 | amalloy | ddellacosta: seems totally fine to link to once. more than once would probably be uncouth |
| 23:39 | ddellacosta | amalloy: gotcha, thanks--I'll leave it at that. It's on the list so presumably folks will find it there anyways. |
| 23:52 | TimMc | ddellacosta: My only feedback is that I don't know why I'd bother clicking the link, other than that I'm a folk. :-P |
| 23:53 | ddellacosta | TimMc: ah, good point. Job posting for Clojure dev/sysadmin devops position. :-) |
| 23:53 | TimMc | Best of luck! |
| 23:53 | ddellacosta | TimMc: thanks! |
| 23:56 | TimMc | Have you tried http://functionaljobs.com/ ? |
| 23:57 | ddellacosta | TimMc: not yet, we are still going through our options |
| 23:57 | TimMc | If I were looking for a Clojure position, that's probably the first place I'd check, but maybe 'cause I just happen to know about it. |
| 23:59 | ddellacosta | TimMc: hmm, good to know! |