2014-12-28
| 00:04 | andyf | Here it is: https://github.com/technomancy/leiningen/issues/1750 |
| 00:58 | kenrestivo | alter-var-root is the monkeypatcher's dream |
| 03:11 | suppi | this triangle is killing me :( |
| 04:11 | tucker | hey, can someone please explain to me how |
| 04:11 | tucker | the lazy seq in |
| 04:11 | tucker | (defn- coll-or-scalar [x & _] (if (coll? x) :collection :scalar)) (defmulti replace-symbol coll-or-scalar) ; <label id="code.replace-symbol.multi"/> (defmethod replace-symbol :collection [coll oldsym newsym] (lazy-seq ; <label id="code.replace-symbol.lazy-seq"/> (when (seq coll) (cons (replace-symbol (first coll) oldsym newsym) (replace-symbol (rest coll) oldsym newsym))))) (defmethod replace-symbol :scalar [obj oldsym ne |
| 04:11 | tucker | better yet: https://github.com/stuarthalloway/programming-clojure/blob/e10099afa98f342647ab6ec89e826b360272c8c7/src/examples/replace_symbol.clj |
| 04:11 | tucker | breks the recursion |
| 04:11 | tucker | better yet, how does lazy-seq work here? |
| 04:12 | tucker | i don't understand how it can prevent the stack being blown |
| 04:12 | tucker | there is still recursion |
| 04:14 | Dynasty | is there an order in which macros are expanded? ie, are outer macros expanded first when there is a nesting situation? |
| 04:28 | nuwanda_ | tucker: (seq col) |
| 04:28 | nuwanda_ | is an idiomatic way of saying not-empty? col |
| 04:39 | Manaphy91 | Why if I have a namespace like a.b-c and in `b_c.clj` I have a typed named `Foo` I need to use it like a.b_c.Foo in my REPL? |
| 04:39 | Manaphy91 | *type |
| 04:50 | SagiCZ1 | nuwanda_: yes, u should prefer (seq coll) to ((complement empty?) coll) |
| 05:25 | visof | ,(do (println "Hello") (println "world")) |
| 05:25 | clojurebot | Hello\nworld\n |
| 05:25 | visof | is this the best way to group the statements ? |
| 05:28 | Bronsa | visof: that's what do is for, yes |
| 05:28 | visof | Bronsa, Good, Thanks |
| 05:33 | borkdude | do a lot of people here still use lib-noir? |
| 05:33 | SagiCZ1 | i find myself doing a lot of (map #(hash-map :a %) coll) i there a shorter way? |
| 05:34 | Bronsa | visof: obviously inside other macros that have implicit `do`s, you won't need it |
| 05:34 | SagiCZ1 | visof: let, fn, when and others have implicit do's .. note that if does not |
| 05:35 | SagiCZ1 | visof: 'let', 'fn', 'when' and others have implicit 'do's .. note that 'if' does not |
| 06:06 | cfleming | SagiCZ1: Your only other option is to use an fn: (map (fn [i] {:a i}) coll) |
| 06:06 | cfleming | SagiCZ1: Which is not much shorter, but arguably clearer and also uses more efficient small maps |
| 06:08 | SagiCZ1 | cfleming: oh.. so {} are different than hash-map? |
| 06:09 | cfleming | SagiCZ1: Yes, I believe it uses PersistentArrayMap for up to 8 items - larger maps will use a hash map. |
| 06:10 | cfleming | SagiCZ1: See http://blog.factual.com/using-clojure-to-generate-java-to-reimplement-clojure for a very interesting discussion of the technique, and a patch that will hopefully be in Clojure 1.8 |
| 06:11 | cfleming | SagiCZ1: That will extend that technique to other data types too |
| 06:13 | cfleming | SagiCZ1: I'm not sure how much difference it will make in practice in your case though. |
| 06:14 | cfleming | SagiCZ1: I often have a similar need with vectors when using into with maps: (into {} (map (fn [i] [(name i) i]) coll)) |
| 06:17 | SagiCZ1 | cfleming: very good to know, thank you.. i wonder if changing the all the hash-map calls in my project will speed things up.. all of these are usually one key maps |
| 06:18 | SagiCZ1 | (inc cfleming) |
| 06:18 | lazybot | ⇒ 6 |
| 06:19 | cfleming | SagiCZ1: I'm not sure, you'd have to test it - if you use them a lot in tight loops it might help |
| 06:19 | cfleming | SagiCZ1: mostly I just think the code is a little clearer since I think most people don't use hash-map much |
| 06:20 | whysoserious- | Hi, I have a probably noob question but I 've already been stuck for >15 minutes: |
| 06:20 | whysoserious- | When trying to compile my project I see this error: |
| 06:21 | SagiCZ1 | yeah.. i was too keen on using the #(..) construct everywhere.. but (fn [.] .. ) is not much worse |
| 06:21 | whysoserious- | ption: reduce already refers to: #'clojure.core.async/reduce in namespace: caniche.server, compiling:(/Users/jan/Dev/caniche/src/caniche/server.clj:1:1) |
| 06:21 | whysoserious- | uh, once again: |
| 06:21 | whysoserious- | |
| 06:21 | whysoserious- | CompilerException java.lang.IllegalStateException: reduce already refers to: #'clojure.core.async/reduce in namespace: caniche.server, compiling:(/Users/jan/Dev/caniche/src/caniche/server.clj:1:1) |
| 06:21 | whysoserious- | and my ns sexp looks like this: |
| 06:21 | whysoserious- | (ns caniche.server |
| 06:21 | whysoserious- | (require [clojure.java.io :as io] |
| 06:21 | whysoserious- | [compojure.core :refer :all] |
| 06:21 | whysoserious- | [compojure.core :as route] |
| 06:21 | whysoserious- | [clojure.core.async :as async :refer :all] |
| 06:21 | whysoserious- | [ring.adapter.jetty :as ring] |
| 06:21 | whysoserious- | [ring.util.codec :as c] |
| 06:21 | whysoserious- | [ring.middleware.multipart-params :as multipart-params]) |
| 06:21 | whysoserious- | (import [org.apache.commons.io IOUtils])) |
| 06:22 | SagiCZ1 | easy fix would be choosing an alias for core.async |
| 06:22 | SagiCZ1 | instead of :refer :all |
| 06:22 | SagiCZ1 | oh |
| 06:22 | SagiCZ1 | just delete the :refer :all |
| 06:22 | whysoserious- | but |
| 06:22 | SagiCZ1 | because you already have an alias there |
| 06:22 | whysoserious- | I don't use reduce anywhere |
| 06:22 | SagiCZ1 | that doesnt matter |
| 06:23 | cfleming | Or explicitly referring the symbols you use, which most core.async code I've seen does |
| 06:23 | whysoserious- | I see |
| 06:23 | whysoserious- | So, as I understand, there is another reduce function defined elsewhere |
| 06:23 | SagiCZ1 | yes |
| 06:23 | whysoserious- | probably in clojure.core ;) |
| 06:23 | SagiCZ1 | in clojure.core |
| 06:23 | SagiCZ1 | ,(reduce + (range 10)) |
| 06:24 | clojurebot | 45 |
| 06:24 | cfleming | whysoserious-: :refer :all pulls in c.c.async/reduce, which overwrites clojure.core/reduce |
| 06:24 | whysoserious- | , (prn "Lol nice!") |
| 06:24 | clojurebot | "Lol nice!"\n |
| 06:24 | cfleming | whysoserious-: Whether you use it or not |
| 06:24 | whysoserious- | I see |
| 06:25 | whysoserious- | So, most reasonable solution would be to import only a few functions right? |
| 06:25 | weavejester | Yes, you typically :refer only the minimum number of functions. |
| 06:26 | weavejester | I usually have something like [clojure.core.async :as a :refer [go <! >!]] |
| 06:27 | whysoserious- | Hmm, let me check it.. |
| 06:28 | whysoserious- | cfleming: Awesome, works! |
| 06:35 | SagiCZ1 | does anybody have an experience with plotting in incanter or jfreechart for that matter? i have a hard time configuring the colors and such |
| 07:01 | augustl | in liberator, I want to implement :processable? to handle JSON parsing and custom validation. What's the best way to ensure that it only does this validation on post and put? |
| 07:01 | augustl | manually check the ctx? |
| 07:27 | tom39291 | { :name "Anakin Skywalker" :children [ { :name "Luke Skywalker" :children [] } ] } |
| 07:27 | tom39291 | vs |
| 07:27 | tom39291 | { :name "Anakin Skywalker" :children [ { :name "Luke Skywalker" } ] } |
| 07:27 | tom39291 | Which is most idiomatic? (The difference is whether lack of children should be represented as an empty list or as absense of that key) |
| 07:28 | cfleming | tom39291: Either is fine, it's a matter of taste really |
| 07:29 | cfleming | tom39291: Most collection operations treat nil like an empty collection, so generally they're mostly equivalent. |
| 07:34 | tom39291 | cfleming: Thanks |
| 07:52 | frankie_ | Hi everyone |
| 07:52 | frankie_ | Happy holidays |
| 07:54 | frankie_ | I'm looking for somebody who knows his/her way around the Clojure class loader |
| 07:54 | frankie_ | I'm facing this issue with generated Java classes and I'm stuck https://groups.google.com/forum/#!topic/clojure/dwrJy5ZmcE4 |
| 07:54 | tom39291 | cfleming: What bit me is http://clojurepastebin.appspot.com/11589001 |
| 07:55 | tom39291 | I just wondered whether my "fix" (use "seq" as I have done on line 15) was the right fix. Perhaps the right fix is for me to not use represent lack of children as an empty list. |
| 07:56 | augustl | how would you map /, /users and /users/:user-id with bidi? |
| 07:57 | Bronsa | tomjack: do you have a minimal reproducible case? |
| 07:57 | Bronsa | err, frankie_ ^ |
| 08:00 | frankie_ | @Bronsa any :gen-class that :extends javax.annotation.processing.AbstractProcessor and then is loaded at compile time |
| 08:01 | frankie_ | When the service loader is trying to create that class using Meta-INF/services you get ExceptionInInitializerError |
| 08:02 | Bronsa | frankie_: I don't have time to try and reproduce it myself but do you mind trying a patched version of clojure to see if that fixes your issue? |
| 08:02 | luxbock | does anyone here have experience with memory-mapping files with Clojure? I'm building a web app that allows one to explore the results of a computation that results in a large tree like structure, and I'm afraid that I might run into issues with limited memory if I load the entire file into memory every time the service needs to access a portion of it |
| 08:02 | luxbock | I found this library: https://github.com/thebusby/clj-mmap |
| 08:02 | frankie_ | @Bronsa I'll be happy to |
| 08:03 | frankie_ | I can also build a minimal project that reproduces the issue |
| 08:03 | Bronsa | frankie_: then try http://dev.clojure.org/jira/secure/attachment/13631/CLJ-979-v7.patch |
| 08:04 | Bronsa | frankie_: removing the lein dependency from the steps required to reproduce the issue would be the best incredibbly helpful |
| 08:04 | luxbock | right now my plan is to have files contain a header which contains rules for the structure of the tree structure stored, which I could then use to calculate the proper index to read from the file |
| 08:05 | frankie_ | Sorry, what do you mean by removing the lein dependency? |
| 08:05 | Bronsa | frankie_: not requiring `lein uberjar` to reproduce |
| 08:06 | luxbock | so in this case the nodes of the tree would be stored as an array where the index matches up with the depth-first search order of the tree |
| 08:06 | luxbock | but if I could somehow use memory-mapping with a Clojure map-like abstraction on top of it then that'd be very nice |
| 08:12 | tom39291 | My problem is that zipper's children fn needs to return a seq, but in my "broken" implementation, I am not returning a seq. I am returning a list, which is not a seq. |
| 08:13 | luxbock | ##(seq? (list 1 2 3)) |
| 08:13 | lazybot | ⇒ true |
| 08:13 | machty | from http://clojure.org/special_forms#recur: "Note that recur is the only non-stack-consuming looping construct in Clojure. There is no tail-call optimization and the use of self-calls for looping of unknown bounds is discouraged. recur is functional and its use in tail-position is verified by the compiler." |
| 08:14 | machty | i'm reading Joy of Clojure and they show how you can convert a mundane-recursive implementation of pow to tail-recursive using a clojure and an accumulator |
| 08:15 | tom39291 | luxbock: Okay. Oops. [1,2,3] is a vector, not a list. It's time I read up on collections in clojure, rather than winging it, as I've been doing so far. |
| 08:16 | luxbock | tom39291: you can call (seq x) on most (all?) Clojure data structures to convert them |
| 08:17 | machty | so is there tail-recursive optimizaiton or not? the docs on recur seem to imply there's not... |
| 08:17 | machty | ohhh nevermind, sorry, didn't realize the inner helper closure used `recur`... disregar |
| 08:18 | luxbock | machty: the point of recur is that wherever you can use, the compiler can optimize the call |
| 08:18 | luxbock | so when defining a recursive function, you can make sure you are getting the optimization by using recur instead of calling itself |
| 08:18 | machty | luxbock: confirm, and (current versions of) clojure won't tail-optimize otherwise |
| 08:23 | jonathanj | how does one correctly reverse a string in Clojure? ie. (correct-reverse "noël") => "lëon" |
| 08:23 | Bronsa | ,(clojure.string/reverse "noël") |
| 08:23 | clojurebot | "lëon" |
| 08:24 | jonathanj | clj-codetip.handler=> (string/reverse "noël") |
| 08:24 | jonathanj | "l̈eon" |
| 08:24 | Bronsa | jonathanj: that looks like an issue in the encoding of your repl |
| 08:25 | jonathanj | ah, right you are, i guess this shell is old (i recently switched shells and didn't resource all of my terminal tabs) |
| 08:31 | jonathanj | Bronsa: actually the issue seems to be using a precomposed version versus the combining character version |
| 08:32 | jonathanj | ,(vec "noël") |
| 08:32 | clojurebot | [\n \o \e \̈ \l] |
| 08:32 | Bronsa | jonathanj: that makes sense then |
| 08:32 | jonathanj | ,(vec "noël") |
| 08:32 | clojurebot | [\n \o \ë \l] |
| 08:39 | dysfun | no, the behaviour is predictable perhaps, but it does not make sense |
| 09:26 | augustl | does Prismatic/schema have functions for returning data about the error instead of throwing an exception? |
| 09:31 | Kristien | FTR you can easily construct a wrapper yourself: https://gist.github.com/rightfold/66b0397e1b1ad3e265e6 |
| 09:38 | augustl | Kristien: yeah, but I was hoping my users would get something more, not just a string :) |
| 09:40 | Kristien | oof |
| 09:52 | luxbock | augustl: Clojure or CLJS? |
| 09:53 | vivekramaswamy | Hello all a quick question, this does not work (take 10 (repeatedly #((rand-int 10))) but this works (take 10 (repeatedly (fn [] (rand-int 10)))) why? |
| 09:55 | luxbock | ##(macroexpand-1 '#((rand-int 10))) |
| 09:55 | lazybot | ⇒ (fn* [] ((rand-int 10))) |
| 09:55 | luxbock | vivekramaswamy: think of #(...) as the body of a (fn [] ...) |
| 09:57 | vivekramaswamy | ok, but isn't #(...) a shortcut for a function itself |
| 09:58 | luxbock | vivekramaswamy: yes but the way you are using it expands to (fn [x] ((rand-int 10)), so you end up trying to call a random integer as though it was a function |
| 09:58 | luxbock | if you swap it with #(random-int 10) it will work |
| 09:58 | luxbock | err, #(rand-int 10) |
| 09:59 | vivekramaswamy | Thanks a lot for the explanation, I think I get it. |
| 10:02 | akkad | how do you resolve an ip in dns in clj? |
| 10:03 | davorb | what is the preferred way to install clojure on ubuntu/debian? apt seems to have a rather old version (1.4, or does that not matter?) |
| 10:04 | davorb | and wtf is cider? what advantages does that have over slime? |
| 10:04 | akkad | davorb: lein |
| 10:05 | expez | davorb: are you sure that's the most recent? clojure 1.4 is from like 2012. |
| 10:05 | akkad | http://www.emacswiki.org/emacs/nREPL.el |
| 10:05 | davorb | expez, yeah, i just did apt-cache search clojure and got 1.4 as the latest |
| 10:05 | expez | davorb: slime is for common lisp, cider is for clojure. |
| 10:06 | vivekramaswamy | here is link that explains cider quite well https://www.youtube.com/watch?v=4X-1fJm25Ww |
| 10:06 | expez | you could use a clojure backend for slime, swank-clojure IIRC, but you don't get much clojure specific functionality doing that |
| 10:06 | akkad | if anyone ever complains about clojure being difficult to learn, have them implement what they are doing in CL for a couple of weeks. |
| 10:07 | davorb | don't know much about clojure, but i like cl. except some stuff... like loop and how it handles files. and threads support isn't anything to write home about either. |
| 10:07 | expez | davorb: if you don't give a shit about tooling and just want a repl then you can use this instead of cider: https://github.com/clojure-emacs/inf-clojure |
| 10:08 | davorb | expez, i just want to know what the most popular choice is. cl-folks use slime. what do clojure-men use? |
| 10:08 | expez | davorb: cider is the most popular option for emacs users |
| 10:09 | davorb | guess i'll use that then |
| 10:10 | vivekramaswamy | :davorb many of the people I know are using cider also cursive that runs as a plugin in intellij seems to be getting quite popular |
| 10:11 | mi6x3m | hey clojure, I have a protocol implemented for a java interface Foo |
| 10:11 | davorb | vivekramaswamy, i'll be staying away from intellij. |
| 10:11 | mi6x3m | but somehow it's not resolved for a class implementing Foo |
| 10:11 | mi6x3m | could this bee? |
| 10:11 | mi6x3m | -e |
| 10:12 | mi6x3m | never mind |
| 11:05 | hellofunk | davorb: what's wrong with intellij? i've been thinking about switching to Cursive |
| 11:05 | hellofunk | davorb: most of what i've seen has been positive, so i'm curious to know about gotchas |
| 11:21 | profil | How do I connect to the same repl as my ring application runs in? I start it by running `lein ring server-headless`. |
| 11:31 | justin_smith | expez: actually slime-swank has a lot of clojure specific functionality, it has better debugging than cider has ever had. slime-swank was discontinued because the upstream slime protocol kept breaking in incompatible ways and it was a pain in the ass to develop against. But it is still usable at its last released state. |
| 11:33 | expez | justin_smith: yeah, nobody is interested in working on clojure debugging. Personally I think that's a shame, but tools.trace / spyscope usually get the job done. |
| 11:33 | borkdude | I'm looking for a library that can help me optimize/compress uploaded jpeg files in clojure, any tips? |
| 11:33 | justin_smith | the ironic thing is that we dropped slime-swank because breaking changes happened too often, then lo and behold we replace it with cider, which has *even more frequently breaking changes* |
| 11:33 | justin_smith | expez: not nobody. cursive has good clojure debugging. |
| 11:33 | justin_smith | and slime-swank clojure debugging still works |
| 11:34 | expez | justin_smith: cider is lacking integration tests. It's getting so large nobody is using the entire feature set so breakage sometimes goes unnoticed for some time heh |
| 11:34 | justin_smith | that's a small part of the issue |
| 11:34 | justin_smith | it's also that apis are changed frequently, and due to elisp's compilation model, this requires full cleans and recompiles of elc code |
| 11:35 | justin_smith | but the upgrade of versions does not do this automatically |
| 11:35 | expez | anyway, some breakage is to be expected prior to version 1.0 imo |
| 11:35 | expez | when I upgrade the old cider is always deleted and the new one recompiled |
| 11:35 | expez | I have no idea how people end up in situations with outdated .elc files lying around |
| 11:35 | justin_smith | expez: I use a lot of pre-1.0 stuff, I have never seen anything else that unstable |
| 11:36 | justin_smith | expez: it's easy |
| 11:36 | justin_smith | for example, update cider but don't upgrade clojure-mode |
| 11:36 | justin_smith | boom, you have stale broken elc files |
| 11:36 | justin_smith | the auto-updater doesn't catch that |
| 11:37 | expez | cider requires clojure-mode 3.0 according to its package info |
| 11:37 | justin_smith | expez: right - but the next cider will *also* require clojure-mode 3.0 |
| 11:38 | justin_smith | and clojure-mode will break if you replace cider and don't also recompile clojure-mode |
| 11:38 | justin_smith | elisp is weird |
| 11:38 | Bronsa | clojurebot: elisp is weird |
| 11:38 | clojurebot | Roger. |
| 11:38 | expez | justin_smith: that sounds unbelievable |
| 11:39 | justin_smith | expez: it happens to a lot of us, just check out the cider bug tracker |
| 11:39 | justin_smith | happened to me more than once |
| 11:39 | expez | clojure-mode as no deps, how can it possibly require a recompile just because cider changed? Oo |
| 11:39 | justin_smith | I've used emacs for over a decade, never had anything break as much and as badly as cider |
| 11:41 | samebchase | Hi Everyone, I'm trying to remotely run a function using https://github.com/clojure/java.jmx . Basically a function that does some cleanup before the jar can be shutdown. In the documentation there, it looks like the `:gc` operation is invoked. How do I invoke an arbitary function using JMX? Thanks. |
| 11:42 | justin_smith | expez: I'm perfectly willing to accept I am wrong about what caused / fixed my issue. Point remains that weird things broke in weird ways that were only fixable by nuking it all from orbit. |
| 11:42 | expez | :D |
| 11:43 | justin_smith | expez: and the critical difference was going from nuking cider, to nuking cider+clojure-mode |
| 11:43 | expez | writing integration tests for cider is actually a hard problem, because it depends on cider-nrepl for much of what it does |
| 11:43 | expez | we're not writing any integration tests for clj-refator for the same reason. We just couldn't manage to talk to the refactor-nrepl middleware using ecukes |
| 11:43 | clojurebot | I don't understand. |
| 11:44 | expez | so we only have integration tests for the elisp bits, but we have to mock out the replies from the middleware |
| 11:45 | justin_smith | expez: I have developed elisp that integrates with an external process forming a unified "app", I feel your pain |
| 11:46 | borkdude | Here I see a library called imagez at version 0.3.2 https://github.com/mikera/imagez/blob/master/project.clj - yet on clojars I see a library imagez with version 0.5.0, but the group id is a bit different. Cant' seem to find the source code of the newer one. |
| 11:46 | justin_smith | borkdude: are the clj files not inside the jar itself? |
| 11:47 | borkdude | hmm, yeah, good one |
| 11:47 | borkdude | but still I would like to see the repo somewhere |
| 11:47 | justin_smith | many editors can open a jar directly, and browse files inside it |
| 11:47 | justin_smith | borkdude: yeah, good luck on that part... |
| 11:47 | borkdude | http://crossclj.info/ns/net.mikera/imagez/0.5.0/project.clj.html no link here either, I could ask the author |
| 11:48 | justin_smith | borkdude: I think he is on twitter with the same handle? |
| 11:48 | borkdude | justin_smith yes |
| 12:30 | kl | https://github.com/clojure/core.match I'm a little confused - as core, shouldn't I just be able to require it, without specifying dependencies to maven/lein ? |
| 12:30 | Empperi | kl: core.* is different than core |
| 12:31 | Empperi | so no, you need to require those |
| 12:32 | kl | Empperi: by "require those", do you mean put dependency info into maven/lein too, or just (require) ? |
| 12:32 | Empperi | dependency too |
| 12:32 | kl | so, what's "core" about it? |
| 12:32 | Empperi | they are considered to be part of core in the future |
| 12:33 | Empperi | and if I'm not mistaken they need the Clojure contributor agreement to allow contribution |
| 12:34 | justin_smith | if they are ever to be included in clojure.core that would be a prerequisite, yes |
| 12:34 | Empperi | so one can think them as "part of official Clojure project but not part of Clojure the language" |
| 12:38 | kl | Thanks, that fits my mental model now :) |
| 12:57 | kl | [org.clojure/core.match "0.3.0-alpha4"] shouldn't pasting this into the repl work, for getting the dependency? |
| 12:58 | kl | It's listed under "Leiningen dependency information:" for clojure/core.match's readme |
| 12:58 | kl | I'm getting: CompilerException java.lang.ClassNotFoundException: org.clojure, compiling:(NO_SOURCE_PATH:0:0) |
| 13:00 | zinfandel | Hi. What's the right way to define tests which would use data from a sequence? Let's say I want to test function f and I have a sequence [{:in x, :out (f x)}...{:in x20, :out (f x20)}] and based on these data I want to define 20 tests. So basically, I want to expand that sequence into the body. I guess it's possible with macros but isn't there a simpler way, which I can't find? |
| 13:00 | ambrosebs | kl: that goes in the :dependencies vector in your project.clj |
| 13:00 | zinfandel | Let's say I am using clojure.test or midje it doesn't really matter |
| 13:01 | andyf | zinfandel: With clojure.test you can call the is macro inside of functions, or the body of a doseq. Not sure if that will do what you want, but it is one way to invoke is 20 times without writing it 20 times. |
| 13:04 | dnolen_ | kl: you need to put that in your project.clj or if you're using Maven directly your pom.xml |
| 13:05 | justin_smith | zinfandel: it does kind of matter because clojure.test is very flexible in comparison to midje |
| 13:06 | justin_smith | you can do all kinds of fancy things with clojure.test just by using function composition / first class function passing. midje is much more restrictive about how you use it, and you'll usually need to write a macro in that case. |
| 13:06 | zinfandel | andyf: Tried it before. The problem was that it was running the tests each time I did :reload. Tried again now and that problem disappeared. Thanks. |
| 13:08 | zinfandel | justin_smith: Good to know. I was got such assumption when I saw => macro. I was like, "Eh, how does it work, and how do I manipulate with this thingy" |
| 13:08 | zinfandel | s/was got/got/ |
| 13:09 | kl | Thanks guys |
| 13:12 | zarkone | hello all. May be somebody knows about isomorphic Om + Nashorn apps? is it possible nowdays? |
| 13:13 | zinfandel | andyf: (doseq [test tests] (is (= :out (f :in))) does work, but is it possible to deftest inside doseq? |
| 13:14 | zinfandel | The first problem is that deftest wants Symbol |
| 13:14 | andyf | I don't know. You want that to get extra messages when a test fails? |
| 13:14 | justin_smith | zinfandel: why would you need to deftest? |
| 13:14 | andyf | If so, is takes a last arg that is a string containing whatever you want, e.g. return value of a format call. |
| 13:15 | justin_smith | zinfandel: you can put that whole doseq inside a deftest |
| 13:16 | zinfandel | Yes I realize that. But it would be messy when I have a lot of tests. In fact each element in the collection is a map with tests of different type. |
| 13:17 | zinfandel | So I want to define a specific test with specific name for each element of top collection. |
| 13:17 | justin_smith | then you want a macro that creates a deftest form, inside doseq |
| 13:17 | justin_smith | but why do you need those names? there is also test/testing |
| 13:17 | justin_smith | or as andyf mentions, the third arg to is |
| 13:18 | zinfandel | justin_smith: I want to see on which input data it failed. |
| 13:19 | zinfandel | Yeah, I guess third arg to 'is would do the job. |
| 13:19 | justin_smith | zinfandel: test/testing, and the third arg to is, are both capable of providing that context |
| 13:20 | justin_smith | err, second arg actually? |
| 13:20 | zinfandel | Actually my use case goes even deeper, I have a sequence of maps that contain maps of sequences of tests for different types of data. :) |
| 13:21 | justin_smith | so a combo of testing / extra if args would help |
| 13:21 | zinfandel | justin_smith: Yes, but well, it's the third element in the form |
| 13:21 | justin_smith | you'll get a) test that failed b) testing clause message c) is extra arg d) actual failed expression for each failure |
| 13:22 | justin_smith | a won't be worth much, because you are bundling a loop like that, but b-d should all provide useful info |
| 13:24 | zinfandel | Yes, that should do the job, however they wouldn't be logically grouped, of course I can put strings like "test1.subtest1.subsubtest1" but they still wouldn't be grouped at the data-structure level. |
| 13:25 | zinfandel | Thanks |
| 13:26 | justin_smith | they could be logically grouped though |
| 13:26 | justin_smith | (doseq [group test-groups] (testing (:message group) (doseq [test (:tests group)] ...))) |
| 13:27 | justin_smith | then you don't need to do that silly string construction at all |
| 13:27 | zinfandel | Oh, I see. |
| 13:27 | zinfandel | I thought that I can group them only with deftest. |
| 13:28 | justin_smith | well that whole thing would be inside a deftest form |
| 13:28 | justin_smith | but yes, the point of testing is that it is for grouping |
| 13:29 | zinfandel | Yes, and I thought that I have to use deftest inside a doseq |
| 13:31 | munderwo | Hi all. I’m getting a wierd error in this code. |
| 13:31 | munderwo | https://www.refheap.com/95493 |
| 13:31 | munderwo | its saying that “<! used not in (go …) block .. |
| 13:32 | Bronsa | munderwo: for expands its body in a (fn [] ..), go blocks cant cross fn boundaries |
| 13:32 | munderwo | I dont understand as it IS in a go block. is there something im missing? does a for loop not remove the go block for some reason? |
| 13:32 | munderwo | ahhhH! bugger. |
| 13:32 | Bronsa | munderwo: aka you can't <! & co inside a for statement in a go block |
| 13:33 | munderwo | macro expansion… dammit |
| 13:33 | munderwo | any suggestions to work around this? |
| 13:33 | justin_smith | munderwo: the glib answer would be "don't use for" |
| 13:34 | AimHere | Could it be that the for block is lazy |
| 13:34 | AimHere | So it's resolved only after you left the go block |
| 13:34 | justin_smith | AimHere: it is lazy, but that's not the issue here |
| 13:34 | Bronsa | AimHere: no, read my first answer |
| 13:34 | justin_smith | AimHere: the merge-with forces it |
| 13:34 | AimHere | Fair enough |
| 13:34 | munderwo | right. which I guess I could do…. its the nested for loop that I want. Is there a nicer way to do the nested iteration? |
| 13:34 | AimHere | I just had a similar problem just yesterday |
| 13:34 | munderwo | nicer/other |
| 13:35 | Bronsa | munderwo: I believe you're stuck with using loop/recur or refactoring the go block |
| 13:35 | justin_smith | munderwo: another thing to look out for is (keyword sha) is likely to make keywords that are technically illegal |
| 13:35 | justin_smith | not that they keyword function cares |
| 13:35 | justin_smith | ,(keyword " this is a ...... keyword.///////") |
| 13:35 | clojurebot | : this is a ...... keyword./////// |
| 13:36 | munderwo | right. So loop/recur doesnt expand to a (fn []) |
| 13:36 | munderwo | yeah, I’ve got to sort out my keyword stuff. but im putting that off for a bit right now |
| 13:36 | justin_smith | munderwo: not that this is likely to break anything as is |
| 13:37 | justin_smith | but it could come up if you try to serialize to edn |
| 13:37 | justin_smith | or if you try to use hypothetical stricter future clojure version |
| 13:37 | munderwo | yeah. its fine at the moment. ok. i’ll keep that in mind for edn. I have worse keywords :) |
| 13:37 | munderwo | :/foo/bar/file.clj springs to mind :) |
| 13:38 | justin_smith | munderwo: also, you could avoid some complexity by just not turning the keys into keywords |
| 13:38 | justin_smith | (bbloom has a few nice rants on this topic) |
| 13:38 | munderwo | it would be nice if keyword didnt create invalid keywords. but I can see why they might. |
| 13:38 | munderwo | I thought the idiomatic way of creating map keys in clojure WAS to use keys ? |
| 13:38 | munderwo | *keywords |
| 13:39 | justin_smith | munderwo: for literal keys, sure |
| 13:39 | justin_smith | but these are constructed keys that do not exist as literals anywhere in your code |
| 13:39 | justin_smith | so making it a keyword gains you little to nothing |
| 13:39 | munderwo | ahh I see the distinction… that makes sense. |
| 13:40 | justin_smith | strings are interned, so you get similar fast lookup iirc |
| 13:40 | munderwo | ok so suggestions on doing a nested loop not using for? some kind of loop recur? |
| 13:41 | dysfun | am i misunderstanding :repl-options :init for leiningen? i can't seem to make it automatically call a function because it complains the var doesn't exist. i've even tried injecting a require into there, but it still complains. any ideas? https://www.refheap.com/95494 |
| 13:44 | justin_smith | &(loop [i 3 a []] (if (zero? i) a (recur (dec i) (conj a (loop [j 3 b []] (if (zero? j) b (recur (dec j) (conj b [i j])))))))) |
| 13:44 | lazybot | ⇒ [[[3 3] [3 2] [3 1]] [[2 3] [2 2] [2 1]] [[1 3] [1 2] [1 1]]] |
| 13:44 | justin_smith | munderwo: ^^ something like that |
| 13:44 | justin_smith | ugly, I'll admit, but it works |
| 13:45 | munderwo | cool. I’ll give it a try. I also just realised that I can probably macro-expand the function as it exists now and I might get some idea of how its structured to see how I can implement it . |
| 13:45 | justin_smith | munderwo: the best way to macro-expand for is to take mushrooms first and wait until you are peaking |
| 13:46 | justin_smith | it won't make any more sense |
| 13:46 | justin_smith | but the lack of sense will be more entertaining |
| 13:46 | munderwo | ha! it probably makes even less sense in clojurescript :) |
| 13:46 | dysfun | justin_smith: some of the code i've seen might better be explained by heroin |
| 13:47 | justin_smith | dysfun: no man, look at ##(macroexpand '(for [i (range 10)] (dec i))) |
| 13:47 | lazybot | ⇒ (let* [iter__4760__auto__ (clojure.core/fn iter__17887 [s__17888] (clojure.core/lazy-seq (clojure.core/loop [s__17888 s__17888] (clojure.core/when-let [s__17888 (clojure.core/seq s__17888)] (if (clojure.core/chunked-seq? s__17888) (clojure.core/let [c__4758__auto__ (... https://www.refheap.com/95495 |
| 13:47 | dysfun | cool |
| 13:47 | justin_smith | dysfun: that is only explainable by wizardry or hallucinagens |
| 13:48 | justin_smith | (be sure to follow that refheap link) |
| 13:48 | justin_smith | dysfun: munderwo: look at that refheap link, and consider the fact that all that was iterating on was (range 10) |
| 13:48 | dysfun | uhuh |
| 13:48 | andyf | for and doseq have a lot of options like :when and :let that make them more useful, and more complex in their implementation |
| 13:49 | justin_smith | andyf: looking at that expansion (which uses none of those features), the chunking optimizations seem to be the biggest obfuscator |
| 13:49 | andyf | but the main thing adding extra code there is optimizing for chunked sequences. |
| 13:49 | munderwo | yeah… the for form was super nice. |
| 13:50 | andyf | pprint, man, pprint! |
| 13:50 | andyf | still not pretty, to be sure, but less of a wall. |
| 13:50 | TEttinger | &(mapv #(mapv (partial vector %) (range 3)) (range 3)) |
| 13:50 | lazybot | ⇒ [[[0 0] [0 1] [0 2]] [[1 0] [1 1] [1 2]] [[2 0] [2 1] [2 2]]] |
| 13:51 | justin_smith | TEttinger: that leads back to the original problem - the main logic is inside an fn |
| 13:51 | justin_smith | TEttinger: he needs a way for the body of the expression not to be in an fn |
| 13:51 | TEttinger | ah |
| 13:51 | munderwo | because of the core.async infection :( |
| 13:51 | munderwo | and the fact that everything is async…. |
| 13:52 | TEttinger | I'm not familiar with core.async right now |
| 13:52 | munderwo | once you go core.async…. everything is core.async .... |
| 13:53 | TEttinger | core.a-sunk |
| 13:53 | munderwo | well not everything.. but you find your-self adding go blocks all over the place… well thats what I’ve found anyway |
| 13:53 | justin_smith | munderwo: ztellman's talk at the last conj is on that topic btw |
| 13:53 | munderwo | ooh… I was there for the conj, but I think I missed that talk. I’ll have to watch it. |
| 13:53 | justin_smith | munderwo: he contrasts core.async, his manifold lib, and prismatic/plumbing - each does a very similar thing, with varying levels of contagion / generality |
| 13:54 | justin_smith | plumbing being super general and not at all infectious, and async being the opposite extreme |
| 13:54 | dysfun | is it online? i'm using manifold with core.async because aleph |
| 13:54 | munderwo | the reason I have all this core.async stuff is using nodejs libs… which are all async… so I need a way to deal with all the callback stuff. |
| 13:54 | justin_smith | yeah, it's on the clojure conj youtube account |
| 13:55 | justin_smith | $google clojure ztellman manifold conj video youtube |
| 13:55 | lazybot | [Clojure/conj 2014 Notes - Forays into simplicity] http://eigenhombre.com/clojure/2014/11/27/conj-notes/ |
| 13:55 | justin_smith | oops, wrong link! |
| 13:55 | munderwo | close though |
| 13:55 | justin_smith | https://www.youtube.com/watch?v=3oQTSP4FngY&index=17&list=PLZdCLR02grLoc322bYirANEso3mmzvCiI this is the one |
| 13:55 | munderwo | $google clojuretv ztellman minifold conj youtube |
| 13:56 | justin_smith | their api limits kind of suck lately :( |
| 13:56 | justin_smith | need to get that duckduckgo plugin in |
| 13:57 | munderwo | as a relative newcomer to IRC im always amazed by all the little tools that people have. |
| 13:58 | justin_smith | munderwo: it's fun working on the channel bot, because you get to see people use it (unlike working on other software, where theoretically you know it gets used but you don't get the direct gratification) |
| 13:58 | justin_smith | (I did a pretty major lazybot update not long ago) |
| 14:00 | benmoss | is there a better idiom for doing things like `(map #(if (foo? %) (modify %) %) coll)` ? |
| 14:00 | justin_smith | benmoss: it would be nice to have an "update-if" |
| 14:01 | justin_smith | macro |
| 14:01 | CodeWar | [Question about implementing a language on top of JVM] Do you just compile the source to ByteCode and classes and give it to the VM and wash your hands off or is there an interpreter that is written by the language designer |
| 14:01 | justin_smith | maybe it exists in useful, or one of those other util libs |
| 14:01 | benmoss | yeah i suppose it would have to be a macro |
| 14:01 | justin_smith | CodeWar: clojure has no interpreter |
| 14:02 | AimHere | That doesn't necessarily mean you can't write one for your own purposes, mindyou |
| 14:02 | CodeWar | justin_smith: so its straight source to bytecode and let JVM interpret and JIT on its own |
| 14:02 | justin_smith | CodeWar: clojure emits bytecode and has the vm run it directly (and hotspot likely improves said bytecode depending on host settings) |
| 14:02 | justin_smith | well, the jvm doesn't quite interpret per-se, but yeah |
| 14:03 | CodeWar | AimHere: care to elaborate how? Meaning how do I load a class let JVM transfer control over to me until I can interpret profile and then occasionally for parts of the program transfer control back to the VM |
| 14:03 | justin_smith | CodeWar: the vm is the only thing that is ever doing anything |
| 14:03 | CodeWar | I am aware of Graal but curious if there is something that already exists that languge designers make use of |
| 14:03 | justin_smith | clojure uses the asm lib |
| 14:04 | mi6x3m | hey clojure, what would you rather call an event listener function? |
| 14:04 | mi6x3m | on-xyz or xyz-handler? |
| 14:04 | clojurebot | No entiendo |
| 14:04 | justin_smith | CodeWar: in fact, clojure embeds a copy of the asm lib inside its own source |
| 14:08 | CodeWar | justin_smith: what libraries/frameworks do you use for Source to AST generation |
| 14:09 | justin_smith | CodeWar: Clojure is that library, and the AST transformation is trivial, Clojure code is very close to being an AST already |
| 14:09 | justin_smith | but Bronsa or arrdem could tell you more detail |
| 14:12 | justin_smith | CodeWar: big picture, a reader expands certain forms, then macros are expanded, and finally the resulting tree is turned into an AST by some relatively straightforward tree operations |
| 14:12 | CodeWar | justin_smith: got it. I forget this is a dialect of LISP so its likely easier than other languages |
| 14:49 | augustl | any liberator peeps around? Looking for advice on composing decision functions |
| 14:49 | augustl | I could just copy `(if (vector? decision) (first decision) decision)` but that seems a bit lame |
| 14:51 | AimHere | You could multimethod it |
| 14:54 | TEttinger | there really should be a general "if seqable? then the first item, else the item" idiom, but it gets weird with strings and maps |
| 14:54 | TEttinger | ,(sequential? {}) |
| 14:54 | clojurebot | false |
| 14:54 | TEttinger | ,(sequential? {:a :b}) |
| 14:54 | clojurebot | false |
| 14:54 | TEttinger | ,(seq {:a :b}) |
| 14:54 | clojurebot | ([:a :b]) |
| 14:54 | augustl | seems like most libraries has landed on [true result] and [false error] for returning values that signify either success or error |
| 14:55 | dysfun | yeah, it's sort of reminiscent of the 'Either' datatype in haskell |
| 14:57 | augustl | hmm, in the case of liberator, I also have to actually manually merge the truthy values as well |
| 14:58 | mi6x3m | is there some version of case which returns nil on default? |
| 15:06 | Frozenlock | mi6x3m: this? (case "allo" "not-allo" true nil) |
| 15:06 | TEttinger | hm ##(case 2 0 "zero" 1 "one") |
| 15:06 | lazybot | java.lang.IllegalArgumentException: No matching clause: 2 |
| 15:06 | andyf | case takes an optional last arg which is an expression returning a default value |
| 15:06 | TEttinger | ##(case 2 0 "zero" 1 "one" nil) |
| 15:06 | lazybot | ⇒ nil |
| 15:07 | TEttinger | neat andyf |
| 15:08 | TEttinger | (inc andyf) |
| 15:08 | lazybot | ⇒ 18 |
| 15:08 | andyf | Doc strings can be informative sometimes :) |
| 15:09 | Frozenlock | I rest my case. |
| 15:09 | Frozenlock | *badum tss* |
| 15:10 | justin_smith | case is definitely underappreciated |
| 15:10 | justin_smith | (or maybe it's just that cond is overused - one of these) |
| 15:20 | augustl | decision composition for liberator https://gist.github.com/augustl/518abd83173444747cd2 |
| 15:20 | augustl | need to familiarize myself with the stdlib, I use loop way too often.. |
| 15:24 | justin_smith | augustl: I think you'll find things get simpler if you always have cur-fn return a vector (even if it is a vector of only one item) |
| 15:25 | justin_smith | never mind, now I see what happens there |
| 15:26 | dnolen_ | cfleming: found out the source of the unresolved issue - was reverting my IntelliJ file |
| 15:27 | justin_smith | augustl: why can't (if (= truthy (if result true false)) ...) just be (if result ...)? |
| 15:30 | augustl | justin_smith: I need to make termination on truthy or falsy pluggable, since liberator has :processable? (truthy) and :malformed? (falsy) |
| 15:30 | augustl | justin_smith: so the "if" returns true or false depending on the truthyness of result, and then I compare with the "truthy" argument passed in |
| 15:30 | augustl | not sure if there are better ways of doing that |
| 15:30 | augustl | s/the "if"/the inner "if"/ |
| 15:31 | justin_smith | (if ({:malformed false} result result) ...) |
| 15:31 | justin_smith | that will be false for :malformed and otherwise just be the input |
| 15:31 | justin_smith | oops, I missed the ? |
| 15:32 | augustl | so it'll be called like `:processable? (comp-decision true foo bar)` or `:malformed? (comp-decision false baz maz)` |
| 15:32 | justin_smith | ahh |
| 15:32 | augustl | the liberator state machine needs false or true to continue depending on the hook :) |
| 15:32 | justin_smith | in that case just replace (if result true false) with (boolean result) |
| 15:33 | augustl | ah, that's much better |
| 15:33 | justin_smith | ,(map boolean [nil false 1 0 true []]) |
| 15:33 | clojurebot | (false false true true true ...) |
| 15:33 | justin_smith | clearly I didn't get the subtlety of what you were doing with liberator there though |
| 15:33 | augustl | this is pretty "low level" stuff so perhaps a manual "loop" makes sense |
| 15:34 | justin_smith | looks like it could easily be a reduce to me |
| 15:34 | augustl | justin_smith: normally, you'd have something like :processable? (fn [ctx] (if whatever true [false {:add-this "to the context"}])) |
| 15:34 | justin_smith | you always go through the list in order, you have an accumulator that is updated at each step |
| 15:34 | augustl | the vector is so that liberator can add stuff to the context while returning what liberator considers a "falsy" value |
| 15:35 | augustl | hmm, will try to rewrite as a reduce |
| 15:35 | augustl | liberators definition of "falsy" is documented under "decision functions" here FYI http://clojure-liberator.github.io/liberator/doc/execution-model.html |
| 15:37 | justin_smith | (reduce (fn [acc cur-fn] (let [decision (cur-fn ctx) [result context-update] (if (vector? decision) decision [decision decision]] (if (= truthy (boolean result)) (liberator.core/update-context ctx context-update) (reduced decision))) initial-ctx fns) |
| 15:37 | justin_smith | something like that |
| 15:38 | justin_smith | my parens are likely off |
| 15:38 | justin_smith | clearly acc should be ctx or visa versa |
| 15:38 | justin_smith | but that's the gist of it |
| 15:39 | justin_smith | notice the destructuring cleverness with decision (too clever?) |
| 15:40 | augustl | destructuring is neat :) |
| 15:40 | augustl | who says Clojure doesn't have "weird syntax" :) |
| 15:41 | justin_smith | haha |
| 15:41 | kl | Is it possible to exit early from a reduce? Or is there some alternative that would permit such? |
| 15:41 | justin_smith | kl: reduced |
| 15:41 | justin_smith | (doc reduced) |
| 15:41 | clojurebot | "([x]); Wraps x in a way such that a reduce will terminate with the value x" |
| 15:42 | kl | justin_smith: I'm not sure how that relates to folding/reduceing? |
| 15:42 | justin_smith | ,(reduce (fn [acc x] (if (> x 10) (reduced (+ acc x)) (+ acc x))) (range)) |
| 15:42 | clojurebot | 66 |
| 15:42 | justin_smith | kl: it says "such that reduce will terminate with the value x" |
| 15:43 | justin_smith | that is precisely and only about reducing |
| 15:43 | justin_smith | note above I passed an infinite sequence to reduce, but it only used the values up to 10 |
| 15:43 | kl | Ahh, so it's used *inside* a reduce, I see |
| 15:44 | justin_smith | well values up to 11 or whatever but hopefully you get the point |
| 15:48 | kl | justin_smith: thank you mate. This is really useful |
| 15:50 | ordnungswidrig | justin_smith: it's an interesting proposal to use a reduce to execute the decision graph |
| 15:51 | justin_smith | ordnungswidrig: the logic of augustl 's loop maps perfectly to reduce |
| 15:51 | justin_smith | hehe, maybe I should have said "projects perfectly", map is a bit overloaded around here as a term :) |
| 15:51 | ordnungswidrig | yes, it would even reduce the stack :-) |
| 15:52 | ordnungswidrig | But you're missing that the fns are not know a priori. But a loop recur would work. |
| 15:53 | ordnungswidrig | Or a reduction over an infinite sequence that it ignored, *cough* *cough* |
| 15:53 | justin_smith | ordnungswidrig: in his case they are, they are a sequence and he repeatedly gets the next item |
| 15:53 | ordnungswidrig | Oh, sorry, I skipped that par. |
| 15:53 | justin_smith | and having some case that hits reduced will deal with the infinite sequence as nicely as the loop version did |
| 15:54 | justin_smith | like I said, reduce is a perfect projection of the logic of his loop :) |
| 15:54 | ordnungswidrig | yes, absolutely |
| 15:54 | ordnungswidrig | I toyed around with decision function composition à la ring middleware the other day but I did not find some expressive and clear way yet. |
| 15:55 | justin_smith | ordnungswidrig: have you looked at prismatic/graph? |
| 15:55 | justin_smith | it's an interesting and elegant data driven approach to the domain |
| 15:55 | justin_smith | I mean function composition can also be pretty elegant, but I like the declarative style of graph |
| 15:57 | justin_smith | graph is part of the "plumbing" lib https://github.com/Prismatic/plumbing |
| 15:57 | ordnungswidrig | justin_smith: yes, it's very promising. However I'm not sure how it would fit liberator. I see that there's need to factor out common functionality that might span multiple of liberator decision functions and thus raises the question of how to compose them. |
| 15:58 | ordnungswidrig | But I'm currently thinking that is something you can build on top of liberators decision map abstraction, not something to be provided by liberator |
| 15:58 | justin_smith | ordnungswidrig: the graph examples show quite complex interactions between values in a graph block |
| 15:59 | justin_smith | ie. the map providing the count, mean, mean-square, variance built on top of each other |
| 15:59 | ordnungswidrig | you could for sure build something like liberator on top of plumbing. |
| 16:00 | justin_smith | yeah, I don't know the specifics of how liberator uses stuff yet (I have planned to look into it), so I can't comment on that side of it |
| 16:00 | augustl | justin_smith: makes sense with a recur, that's conceptually what I'm doing |
| 16:01 | augustl | building a return value for a collection |
| 16:01 | augustl | s/recur/redue/ |
| 16:02 | justin_smith | one of my a-ha moments in clojure was when I learned to recognize the signs that something could be expressed as reduce |
| 16:02 | justin_smith | (because often if it can be, that is the best representation of the algorithm) |
| 16:03 | augustl | was not aware of "reduced" though, that helps |
| 16:03 | augustl | I some times miss my "break" :) |
| 16:03 | justin_smith | yeah, reduced is a total game-changer |
| 16:03 | justin_smith | along with reducers and transducers if you want to get advanced |
| 16:03 | augustl | does it actually terminate the reduction though? In the example it just returns a static value |
| 16:03 | augustl | for me it's important that I actually return the value being reduced at that specific point, and doesn't go further |
| 16:04 | justin_smith | augustl: if you add a print to the function body you will see nothing else is calculated after it hits reduced |
| 16:04 | justin_smith | and yes, definitely returns the precise value you pass to reduced, that's kind of the whole point :) |
| 16:11 | TMA | ,(doc reduce) |
| 16:11 | clojurebot | "([f coll] [f val coll]); f should be a function of 2 arguments. If val is not supplied, returns the result of applying f to the first 2 items in coll, then applying f to that result and the 3rd item, etc. If coll contains no items, f must accept no arguments as well, and reduce returns the result of calling f with no arguments. If coll has only 1 item, it is returned and f is not called. If val i... |
| 16:11 | TMA | ,(doc range) |
| 16:11 | clojurebot | "([] [end] [start end] [start end step]); Returns a lazy seq of nums from start (inclusive) to end (exclusive), by step, where start defaults to 0, step to 1, and end to infinity. When step is equal to 0, returns an infinite sequence of start. When start is equal to end, returns empty list." |
| 16:12 | TMA | ,(reduce + (range 12)) |
| 16:12 | clojurebot | 66 |
| 16:15 | TMA | is there a common lisp's (reduce f seq :from-end t) equivalent? or shall I just reverse the sequence manually? |
| 16:17 | augustl | updated the liberator decision composition gist fyi https://gist.github.com/augustl/518abd83173444747cd2 |
| 16:17 | justin_smith | TMA: reverse manually, but use rseq if the input is a vector |
| 16:17 | justin_smith | rseq is basically free because of how vectors are implemented |
| 16:18 | justin_smith | augustl: opted against the destructuring magic I see |
| 16:19 | augustl | justin_smith: how sloppy of me :) forgot all about it |
| 16:21 | TMA | ,(map (fn [x] (apply (fn ([] :a) ([x] :b) ([x y] :c) ([& r] :d)) x)) [[] [1] [1 2] [1 2 3]]) |
| 16:21 | clojurebot | #<CompilerException java.lang.RuntimeException: Can't have fixed arity function with more params than variadic function, compiling:(NO_SOURCE_PATH:0:0)> |
| 16:21 | TMA | ,(map (fn [x] (apply (fn ([] :a) ([x] :b) ([x y] :c) ([x y & r] :d)) x)) [[] [1] [1 2] [1 2 3]]) |
| 16:21 | clojurebot | (:a :b :c :d) |
| 16:22 | TMA | oh, nifty |
| 16:22 | justin_smith | haha, an arity counter |
| 16:36 | kl | is there an idiomatic way to format s-expressions, as far as indentation goes? |
| 16:38 | mearnsh | kl: https://github.com/bbatsov/clojure-style-guide#body-indentation |
| 16:43 | kl | mearnsh: how about where the closing parens go? |
| 16:43 | kl | Whoops: " Place all trailing parentheses on a single line instead of distinct lines." |
| 16:43 | expez | ^ |
| 16:43 | kl | Why is that a good thing? It harms readability for me |
| 16:44 | expez | That's just habit |
| 16:45 | andyf | kl: takes unnecessary vertical whitespace. People who program a Lisp for a while tend to not look at the parens very often, but expect it to be indented well, usually automatically by their text editor/IDE, and use that. |
| 16:46 | andyf | kl: If you want to show Lisp/Clojure/Scheme code to someone else and ask for comments or review, and you have trailing parens each on a line on their own, they will cringe. |
| 16:47 | expez | in 99% of the cases indentation makes it clear what goes with what. In the other rare case your editor probably has facilities for highlighting pairs of parens which you can rely on. |
| 16:47 | expez | Nobody ever argues that Python code is unreadable due to missing { } pairs :) It's just habit. |
| 16:49 | tolstoy | To be honest, when using a {} language, I now wish it was okay to condense lines of "}" onto a single line. |
| 16:49 | tolstoy | ... else { return finish(); }}}}} |
| 16:49 | justin_smith | kl: it's natural for good style to be dependent on that language. In fact it's helpful to me that lisps do not use trailing brackets, because then I can transition from reading a lisp to reading an algol (like c, c++, java, js) more easily. |
| 16:50 | dnolen_ | cfleming: hrm, actually no, still happening, I've got a screenshot for you. |
| 17:38 | cfleming | dnolen_: Cool, can you send it to cursive@cursiveclojure.com? |
| 17:39 | dnolen_ | cfleming: done |
| 17:39 | cfleming | dnolen_: There's actually something else you could try. It's very strange to get a symbol resolution problem that's sporadic - normally it always works, or it doesn't. I'm wondering if your indexes might have been corrupted. Try File->Invalidate Caches and Restart, that will force an index rebuild. |
| 17:40 | dnolen_ | cfleming: will try that next time - there's no rhyme or reason to the bug as far as I can tell |
| 17:41 | dnolen_ | cfleming: it usually happens when I switch to a file/tab |
| 17:41 | cfleming | dnolen_: So it will suddenly happen in a file you already have open in a tab when you switch to it? |
| 17:42 | dnolen_ | cfleming: I believe so but I will have to verify |
| 17:43 | cfleming | dnolen_: Ok - don't spend much time on it, I suspect it's actually your indexes, especially since no-one else has reported it. You don't have to wait for the problem to rebuild your indexes, if you do it now with any luck the problem won't come back. |
| 17:43 | dnolen_ | cfleming: ok invalidated / restarted, will let you know if I see it again |
| 17:44 | cfleming | dnolen_: Great, thanks. |
| 17:44 | SagiCZ1 | most of the time when Cursive bugs out or does something weird, restarting and invalidating caches helps |
| 17:45 | cfleming | Yeah, they still have some bugs in their indexing framework, although it seems to happen more with Clojure than with Java - it might be bugs in my code, or I'm just using their framework in different ways |
| 17:45 | cfleming | which I almost certainly am. |
| 17:45 | SagiCZ1 | i dont even know what the indexes are for |
| 17:46 | cfleming | Basically any information that has to be visible globally is indexed - in Cursive that's things like metadata about vars, information about all the namespaces and so forth. |
| 17:47 | cfleming | That's why when that gets screwed up the first thing to go is the symbol resolution. |
| 17:47 | SagiCZ1 | i see.. by the way are way any closer to being able to slurp into quoted strings? |
| 17:49 | gfredericks | SagiCZ1: do what? |
| 17:49 | SagiCZ1 | i think there is no reason why paredit slurping cant work on strings |
| 17:50 | SagiCZ1 | "hello |" world --- slurp --> "hello world" |
| 17:50 | cfleming | SagiCZ1: No, no reason other than that I haven't got around to it yet. I have a backlog of paredit related issues, I'm going to do a paredit focused release soon. |
| 17:51 | SagiCZ1 | cfleming: alright, sweet |
| 18:08 | michaniskin | tolstoy: re }}} https://github.com/boot-clj/boot/blob/master/boot/base/src/main/java/boot/App.java#L230 |
| 18:09 | michaniskin | haha i do it all the time now |
| 18:09 | michaniskin | it rules |
| 18:10 | dnolen_ | cfleming: didn't solve the issue |
| 18:11 | Bronsa | michaniskin: my eyes |
| 18:12 | michaniskin | i think it's artistic |
| 18:12 | Bronsa | I guess that's a way to put it :) |
| 18:12 | michaniskin | you should see how i do php |
| 18:14 | Bronsa | michaniskin: thanks, I'm good |
| 18:14 | michaniskin | to late though, you can't un-imagine it |
| 18:15 | Bronsa | michaniskin: as humans we have developed selective amnesia exactly for cases like this |
| 18:15 | michaniskin | it will haunt you |
| 18:15 | michaniskin | you'll see |
| 18:15 | michaniskin | single curlies on a line by themselves don't have to be tolerated anymore |
| 18:16 | michaniskin | the seed is planted |
| 18:22 | justin_smith | to me that says "I would rather be writing lisp code write now" |
| 18:23 | visof | hi |
| 18:23 | visof | how can i convert this java to clojure ODatabaseRecordThreadLocal.INSTANCE.set( database1 ); ? |
| 18:23 | visof | (.get (ODatabaseRecordThreadLocal/INSTANCE) database1) ? |
| 18:25 | justin_smith | what is the relationship between ODatabaseRecordThreadLocal and INSTANCE? |
| 18:26 | justin_smith | static member of a class? |
| 18:26 | visof | http://www.orientdb.org/releases/latest/javadoc/com/orientechnologies/orient/core/db/ODatabaseRecordThreadLocal.html |
| 18:26 | justin_smith | oh, I guessed right |
| 18:27 | justin_smith | (.set ODatabaseRecordThreadLocal/INSTANCE database1) |
| 18:27 | justin_smith | since it's a static field, no invocation is needed on it |
| 18:27 | Bronsa | but it would have worket either way :P |
| 18:27 | Bronsa | ,(Integer/MAX_VALUE) |
| 18:28 | clojurebot | 2147483647 |
| 18:28 | justin_smith | Bronsa: but not with .get :) |
| 18:28 | Bronsa | ,Integer/MAX_VALUE |
| 18:28 | clojurebot | 2147483647 |
| 18:28 | Bronsa | justin_smith: uuuh really? |
| 18:28 | justin_smith | Bronsa: I mean, yes, parens or no, both work (but no parens is better) |
| 18:28 | Bronsa | ah, ok |
| 18:28 | justin_smith | but he should definitely switch his .get to .set |
| 18:29 | Bronsa | ah! didn't notice that. you're right |
| 18:30 | justin_smith | :) |
| 18:43 | dnolen_ | just pushed some big changes to ClojureScript that considerably improve the REPL experience. Rhino REPL can start ~1 second. added real support for in-ns and require. doc is loaded into REPLs by default. things feel considerably less wonky now. |
| 18:44 | ambrosebs | dnolen_: sounds awesome |
| 18:47 | justin_smith | dnolen_: is that ~1s from jvm startup to rhino repl, or ~1s for startup inside an existing vm?> |
| 18:48 | dnolen_ | justin_smith: jvm startup is 86ms on my machine, this meme has to end |
| 18:48 | justin_smith | dnolen_: no, I' |
| 18:48 | justin_smith | m not trying to pick on the jvm |
| 18:48 | dnolen_ | JVM startup is ridiculously fast |
| 18:48 | justin_smith | just asking a clarifying question |
| 18:48 | justin_smith | I know the JVM can start fast |
| 18:48 | dnolen_ | everything that is slow in the Clojure ecosystem is of our own doing |
| 18:48 | justin_smith | I know, I know |
| 18:49 | justin_smith | I've timed the startup of java hello world |
| 18:49 | justin_smith | that wasn't what I was getting at at all |
| 18:49 | dnolen_ | ~1s is about 800ms of Clojure 1.6.0 boot time - the rest is is loading AOTed ClojureScript and reading some EDN files off disk |
| 18:49 | clojurebot | Ack. Ack. |
| 18:50 | justin_smith | dnolen_: that's pretty great actually |
| 18:50 | justin_smith | thanks for clarifying |
| 19:02 | cfleming | dnolen_: Well damn |
| 19:03 | cfleming | dnolen_: Can you zip your project directory up and mail it to me, and I'll take a look to see if there's anything funky about it? |
| 19:04 | dnolen_ | cfleming: I could put it wouldn't be any different from the ClojureScript repo, I've been committing ClojureScript.iml changes |
| 19:04 | dnolen_ | s/put/but |
| 19:04 | cfleming | dnolen_: Ok, I'll download that and check it out. |
| 20:18 | kenrestivo | heh, on the embedded ARM platform i'm using, jvm and clojure is 10 minutes to start up. |
| 20:18 | justin_smith | kenrestivo: what about jvm for java helloworld? |
| 20:19 | kenrestivo | a uberjar loads faster, a couple minutes. but lein trampoline repl :headless is ~10 minutes. |
| 20:19 | kenrestivo | of 99% CPU usage |
| 20:20 | justin_smith | kenrestivo: I was amazed by how much of the "lein repl" startup time is due to nrepl |
| 20:20 | kenrestivo | i dunno, helloworld is kind of useless to me. the experiment was to see if doing embedded development with a clojure repl was powerful. it is, in a way, but sllloooowwwwww in other ways. |
| 20:20 | justin_smith | kenrestivo: fair enough, just wondering what the vanilla java baseline was |
| 20:21 | kenrestivo | huh, maybe it is nrepl then. i remember doing some experiments and noticing it had a tight loop that consumed 90% cpu under normal conditions (i think this was with visualvm). i asked chas about it, and he said something to the effect of, oh yeah, it does that. |
| 20:21 | kenrestivo | that was a couple years ago, maybe it's all been massively improved since. |
| 20:22 | justin_smith | try just running clojure.main next time, for comparison at least |
| 20:22 | kenrestivo | all i know is, i've been spending a *lot* of time hanging around in #clojure to kill time while waiting for the repl to start |
| 20:22 | kenrestivo | for the last month |
| 20:23 | dweave | i’m trying to figure out exactly what core.async is and how it relates to futures / promises. Is it built on top of futures? |
| 20:23 | justin_smith | dweave: it uses a thread pool |
| 20:24 | justin_smith | dweave: it's more about queues between threads, and waking up blocks of code when they have data on their queue |
| 20:24 | dweave | is it “probably” a more suitable solution if I’m using futures |
| 20:25 | justin_smith | do the futures communicate with anything else? if not, core.async won't gain you anything |
| 20:25 | dweave | i see |
| 20:25 | dweave | justin_smith is that kinda like actors without their own state? |
| 20:25 | justin_smith | if they need to do extensive coordination, then yeah, core.async has nice ways of coordinating between threads of execution |
| 20:26 | justin_smith | dweave: they also have state, it's a more flexible setup than actors though |
| 20:27 | justin_smith | dweave: core.async implements something called CSP, concurrent sequential processes, there are papers on the model if you look for them |
| 20:27 | justin_smith | sorry s/concurrent/communicating |
| 20:27 | justin_smith | http://en.wikipedia.org/wiki/Communicating_sequential_processes |
| 20:27 | dweave | k |
| 20:28 | dnolen_ | kenrestivo: there a recent post on the ClojureScript mailing list on using using ClojureScript+Node.js / C++ for Raspberry Pi dev - probably more realistic route |
| 20:28 | kenrestivo | hmm... yeah i heard there's some new node goodness for cljs. too late on this project, but maybe in the future |
| 20:29 | kenrestivo | exciting stuff though, i saw your blog post on it. |
| 20:30 | dweave | justin_smith: might this be a good use case for core.async: Multiple async http requests all of which need to report back to the main thread which will do some data crunching on each result? |
| 20:33 | justin_smith | dweave: yeah, I could easily see a primary go block that reads each http result of a channel and processes it, and then a bunch of others that each put an http result onto that channel |
| 20:34 | dweave | justin_smith what state do channels have? They just seem like queues |
| 20:34 | justin_smith | but for something that simple, you could just use one of the queues from java.util.concurrent too (reading from the queueu in a loop in the main thread, writing to it from each http request in a future), but if you need more back and forth, that's when core.async makes more and more sense |
| 20:34 | justin_smith | dweave: they are queues with some limitations |
| 20:35 | justin_smith | for example you can't check if they have data for you - your options is to read or not |
| 20:36 | dweave | starting to make sense |
| 20:36 | dweave | so asyn channels are more about like 2 way communication |
| 20:36 | justin_smith | each channel is one way |
| 20:36 | justin_smith | but you can of course have a channel to go each direction, of course |
| 20:36 | dnolen_ | dweave: core.async is really just that, a fantastic DSL over queues - concurrent or not |
| 20:37 | dweave | ok |
| 20:54 | gfredericks | hey look I made a regex to match JSON with bounded nesting: https://www.refheap.com/95500 |
| 20:55 | warz | hi all, im aiming for a basic clojure environment in emacs. im new to emacs, so i was hoping for something that works out of the box. i was trying cider, and i followed the install directions, but my emacs does not look like the screenshot on cider's github repo: https://raw.githubusercontent.com/clojure-emacs/cider/master/screenshots/cider-overview.png |
| 20:55 | warz | should my emacs look like this screenshot, after installing? |
| 20:55 | andyf | please tell me you didn't type that regex in by hand |
| 20:55 | gfredericks | andyf: I didn't type that regex in by hand |
| 20:56 | gfredericks | it seems like a natural example of a situation where you could add a feature to regexes to make them dramatically more succinct but no more powerful |
| 20:56 | gfredericks | a let-like feature |
| 20:56 | andyf | Yeah, I think they call them context-free grammars :) |
| 20:56 | gfredericks | "no more powerful" <-- trying to distinguish from CFGs |
| 20:57 | kl | hmm |
| 20:57 | gfredericks | CFGs are letrec, I'm talking about regular let |
| 20:57 | kl | what is the difference between a transducer and a partially applied function |
| 20:57 | andyf | In Perl you can assign regexes to variables, and then use the values of those variables in other regexes. Should work in Clojure, too, via string concatenation. |
| 20:57 | kl | andyf: i tried looking at the wiki page for context-free grammars and i just got confused. is there a simple definition? |
| 20:58 | andyf | yes |
| 20:58 | gfredericks | andyf: well that's where I got mine from; but you're expending a lot of resources with that approach, building strings and parsing the resulting regexes |
| 20:59 | gfredericks | andyf: there's probably some sort of recursion-limited grammar that would be more or less what I'm talking about |
| 20:59 | justin_smith | kl: you can apply a transducer to another transducer, and you get a transducer that is the composition of their behaviors |
| 20:59 | justin_smith | kl: that's not how normal partially-applied functions would behave |
| 20:59 | andyf | kl: The examples might be easier to read than the definition. |
| 21:00 | gfredericks | andyf: this might be it: http://en.wikipedia.org/wiki/Regular_grammar |
| 21:01 | gfredericks | I take it back |
| 21:01 | gfredericks | seems like a different kind of limitation |
| 21:01 | justin_smith | warz: are you referring specifically to the completion dropdown? |
| 21:01 | andyf | Basically you have some 'non-terminal symbols' which are usually capital letters in the examples. You start with one of them, and at each step you take a nonterminal symbol and replace it using one of the rules in the grammar, which look like: S->aSSb, which means to replace an S with aSSb. When you have replaced all non-terminal symbols so no more remain, you have a legal string in the language your grammar defines. |
| 21:02 | alandipert | gfredericks: epic regex man |
| 21:04 | warz | justin_smith, the whole theme and everything, the 3 panes, etc |
| 21:04 | justin_smith | warz: I know nothing about the theme, and I wouldn't expect anything about cider to set the color theme or font etc. |
| 21:05 | justin_smith | warz: in terms of the panes, managing windows in emacs is very different from other apps |
| 21:05 | kl | justin_smith: I see, I think I get that, thanks. It sounds like an idea that wouldn't be peculiar to clojure, do you find them elsewhere, too? |
| 21:05 | gfredericks | alandipert: heythanks |
| 21:05 | justin_smith | warz: they are more dynamic, and they don't even have the same names they have in newer software |
| 21:07 | justin_smith | kl: they do what one might intuitively expect nested calls to map / filter / etc. to do if you had a "smart" compiler. Clojure's compiler isn't super clever like ie. haskell's though. |
| 21:08 | justin_smith | kl: functionality wise they don't do anything wrapping one stream transform in another wouldn't, performance wise they are a big change though. |
| 21:10 | kl | justin_smith: sorry, I'm probably being dumb, but I'm trying to work out (again) how this differs from partial application. A partially applied map given a partially applied filter, given a value - is pretty much the same thing, is it not? |
| 21:10 | justin_smith | kl: no |
| 21:10 | justin_smith | because the mapping and filtering (though you would naively expect them to) don't happen in one go |
| 21:11 | amalloy | gfredericks: putting honest, hard-working regex craftsmen out of work with your automated regex factories? |
| 21:11 | justin_smith | transducers combine them in a way that the function composition doesn't yet, and eliminate some fiddly stuff in the middle |
| 21:12 | justin_smith | kl: as I was trying to say, at first you would expect this to be automatic, but Clojure doesn't typically try to be that clever (see also our usage of "recur" instead of automatic tco) |
| 21:12 | kl | justin_smith: so isn't what you said effectively what I said, BUT going over a lazy stream? |
| 21:12 | kl | (Trying to reconcile a proper mental model) |
| 21:13 | justin_smith | kl: a map over a filter is still two lazy streams, a transduced map+filter can be one lazy stream, or feed input to one reduce without creating a lazy stream, or... |
| 21:14 | gfredericks | amalloy: hey regex factories create jobs |
| 21:15 | kl | justin_smith: thanks, you've been much help :) |
| 21:15 | kl | + justin_smith 1 |
| 21:15 | justin_smith | kl: what's different isn't the behavior, but the implementation (and thus how well it performs, and incedentally, transducers also make it easy to port all of map, filter, reduce, etc. to a new data source / sink) |
| 21:55 | uris77 | alert: newbie question - How do I render a response as edn in ring? |
| 21:58 | verma | uris77: you could return something like: {:status 200 :body (pr-str obj) :headers { "Content-Type" "application/edn"}} from your ring handler |
| 21:58 | verma | ,(def res {:status true :values [:hello :world]}) |
| 21:58 | clojurebot | #'sandbox/res |
| 21:59 | verma | ,{:status 200 :body (pr-str res) :headers {"Content-Type" "application/edn"}} |
| 21:59 | clojurebot | {:status 200, :body "{:status true, :values [:hello :world]}", :headers {"Content-Type" "application/edn"}} |
| 21:59 | verma | pretty sure there's some middleware somewhere |
| 21:59 | verma | uris77: https://github.com/tailrecursion/ring-edn |
| 22:05 | uris77 | verma: thank you |
| 22:05 | uris77 | googling for clojure stuff (other than lang basics) is a little disappointing. I saw some snippets that had response/edn |
| 22:06 | uris77 | tried that and got a compilation error |
| 22:07 | verma | I just searched for "clojure ring edn middleware" |
| 22:07 | verma | or something similar |
| 22:13 | uris77 | i searched for clojure ring render edn |
| 22:53 | ipaomian_ | test |
| 22:53 | fairuz | test success ipaomian_ |
| 22:54 | ipaomian_ | thanks fairuz |