[ClojureScript] core.async - restriction on macros inside go block?
Hi All, I had a terrible time trying to write a convenience macro for reading from a core.async channel. The idea was to make it easier to do the common dispatch on first part of a message pattern, as in: (let [[msg args] (! my-channel)] (case msg :msg1 (let [[a b] args] ...) :msg2 (let [[x] args] ...))) After a long struggle I came to the conclusion that there is some problem with using macros inside a go block, or at least using ! inside a macro. Is that right? Is this documented anywhere? Thanks Tom -- Note that posts from new members are moderated - please be patient with your first post. --- You received this message because you are subscribed to the Google Groups ClojureScript group. To unsubscribe from this group and stop receiving emails from it, send an email to clojurescript+unsubscr...@googlegroups.com. To post to this group, send email to clojurescript@googlegroups.com. Visit this group at http://groups.google.com/group/clojurescript.
Re: [ClojureScript] core.async - restriction on macros inside go block?
Thanks for your reply. That's pretty much what I'd come to understand. I'm a bit puzzled why this restriction exists though. Of course function calls can't be resolved at macro expansion time, so it makes sense that ! ! inside functions can't be found. But I don't understand why the go macro cannot first expand all nested macros and then apply its transformations to the result. Indeed, clojure.walk contains macroexpand-all specifically for this kind of situation, or that's what I had understood. -- Note that posts from new members are moderated - please be patient with your first post. --- You received this message because you are subscribed to the Google Groups ClojureScript group. To unsubscribe from this group and stop receiving emails from it, send an email to clojurescript+unsubscr...@googlegroups.com. To post to this group, send email to clojurescript@googlegroups.com. Visit this group at http://groups.google.com/group/clojurescript.
Re: [ClojureScript] core.async - restriction on macros inside go block?
OK I've filed this here: http://dev.clojure.org/jira/browse/ASYNC-79 In trying to create a minimal test case I tried a trivial macro (defmacro my-case [expr cases] `(case ~expr ~@cases)) inside a go block, and that worked fine, so it's more subtle than just case in a macro is broken. I didn't try to reproduce the (and) bug spotted by Kevin M. The thing that's still confusing to me, is why the go macro doesn't just macroexpand the body before it does it's thing. -- Note that posts from new members are moderated - please be patient with your first post. --- You received this message because you are subscribed to the Google Groups ClojureScript group. To unsubscribe from this group and stop receiving emails from it, send an email to clojurescript+unsubscr...@googlegroups.com. To post to this group, send email to clojurescript@googlegroups.com. Visit this group at http://groups.google.com/group/clojurescript.
[ClojureScript] Looking for project - cljs data to HTML DOM pretty-printing
Hi All, A while back I came across a project that could take cljs data and render it in a nice readable way as HTML. I was sure I bookmarked it, or starred the github repo, but now that I need it there is no sign of it. Google searches are proving fruitless. There is the abandoned github.com/stuartsierra/cljs-formatter, but this project was much better as I recall. Does anyone know what project this was? Thanks Tom -- Note that posts from new members are moderated - please be patient with your first post. --- You received this message because you are subscribed to the Google Groups ClojureScript group. To unsubscribe from this group and stop receiving emails from it, send an email to clojurescript+unsubscr...@googlegroups.com. To post to this group, send email to clojurescript@googlegroups.com. Visit this group at http://groups.google.com/group/clojurescript.
[ClojureScript] Re: The Essence of ClojureScript Redux
What is the impact of all this new goodness on in-browser development? lein-figwheel + weasel has been the magic formula up until now. Is that still the case? -- Note that posts from new members are moderated - please be patient with your first post. --- You received this message because you are subscribed to the Google Groups ClojureScript group. To unsubscribe from this group and stop receiving emails from it, send an email to clojurescript+unsubscr...@googlegroups.com. To post to this group, send email to clojurescript@googlegroups.com. Visit this group at http://groups.google.com/group/clojurescript.
Re: [ClojureScript] Support for prefix lists in ns?
Fair enough. Are there any tips for reducing the size of large ns forms? For example I have a util namespace, and I consider the functions in there part of my core vocabulary, alongside all the regular core functions and macros. I don’t want to see them with a namespace prefix in my code. Given the lack of refer :all, I end up with a long refer list which I frequently have to maintain. Is there any way around this? Thanks Tom On 20 Feb 2015, at 12:57, David Nolen dnolen.li...@gmail.com wrote: It's not supported. ClojureScript's ns form is a restrictive subset of the functionality provided in Clojure. This is a good thing, what's there already involves an amazing amount of complexity. David On Fri, Feb 20, 2015 at 2:48 AM, Tom Locke t...@tomlocke.com mailto:t...@tomlocke.com wrote: Are prefix lists supported in ClojureScript's (ns ...)? It seems not, unless I am misunderstanding the syntax. e.g. (ns my.namespace (:require (foo [baa baz])) should be equivalent to (ns my.namespace (:require [foo.baa] [foo.baz]) but gives a compiler error Only :as alias and :refer (names) options supported in :require Is this expected? Thanks Tom -- Note that posts from new members are moderated - please be patient with your first post. --- You received this message because you are subscribed to the Google Groups ClojureScript group. To unsubscribe from this group and stop receiving emails from it, send an email to clojurescript+unsubscr...@googlegroups.com mailto:clojurescript%2bunsubscr...@googlegroups.com. To post to this group, send email to clojurescript@googlegroups.com mailto:clojurescript@googlegroups.com. Visit this group at http://groups.google.com/group/clojurescript http://groups.google.com/group/clojurescript. -- Note that posts from new members are moderated - please be patient with your first post. --- You received this message because you are subscribed to a topic in the Google Groups ClojureScript group. To unsubscribe from this topic, visit https://groups.google.com/d/topic/clojurescript/jWqMeJUYU14/unsubscribe https://groups.google.com/d/topic/clojurescript/jWqMeJUYU14/unsubscribe. To unsubscribe from this group and all its topics, send an email to clojurescript+unsubscr...@googlegroups.com mailto:clojurescript+unsubscr...@googlegroups.com. To post to this group, send email to clojurescript@googlegroups.com mailto:clojurescript@googlegroups.com. Visit this group at http://groups.google.com/group/clojurescript http://groups.google.com/group/clojurescript. -- Note that posts from new members are moderated - please be patient with your first post. --- You received this message because you are subscribed to the Google Groups ClojureScript group. To unsubscribe from this group and stop receiving emails from it, send an email to clojurescript+unsubscr...@googlegroups.com. To post to this group, send email to clojurescript@googlegroups.com. Visit this group at http://groups.google.com/group/clojurescript.
[ClojureScript] Re: Multimethods -- problem with :default and multiple dispatch values
Replying to myself : ) My "good enough" solution, in case it's of use to others, is (defn set-hierarchy-root! [x root] (if-let [p (-> x parents first)] (set-hierarchy-root! p root) (derive x root))) (defn with-root [x root] (when-not (isa? x root) (set-hierarchy-root! x root)) x) Then the dispatch function looks like: (defmulti combine (fn [x y] [(with-root (:type x) ::shape) (with-root (:type y) ::shape)])) So, at the cost of an extra call to isa? on every dispatch, any newly seen values (or their final ancestor already in the hierarchy, if any) are automatically declared as being derived from ::shape. Not pretty, but it has the benefit of not needing to know the full set of possible values in advance. T -- Note that posts from new members are moderated - please be patient with your first post. --- You received this message because you are subscribed to the Google Groups "ClojureScript" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojurescript+unsubscr...@googlegroups.com. To post to this group, send email to clojurescript@googlegroups.com. Visit this group at http://groups.google.com/group/clojurescript.
[ClojureScript] Multimethods -- problem with :default and multiple dispatch values
One of the benefits of Clojure(Script)'s multimethods over traditional OO polymorphism is that you can dispatch on multiple values. For example, we can dispatch on the types of all the arguments, instead of just the first one: (defmulti example (fn [x y] [(type x) (type y)])) My question is about the use of :default in such situations. Let's switch to a more clojure-ish example, with plain maps for data: (def a-circle { :type :circle, :radius 10 }) (def a-rectangle { :type rectangle, :width 2, :height 3 }) (defmulti combine (fn [x y] [(:type x) (:type y)])) Now I can define combine for any combination of shapes: (defmethod combine [::circle ::circle] ...) (defmethod combine [::circle ::rectangle] ...) If I happen to have different types of circles, say ::red-circle, and ::blue-circle, I can do (derive ::red-circle ::circle) (derive ::blue-circle ::circle) Now combine can be specialised for these types of circles, but, if not, will fall back to the more general ::circle methods This works because (from the docs): isa? works with vectors by calling isa? on their corresponding elements: (derive ::rect ::shape) (derive ::square ::rect) (isa? [::square ::rect] [::shape ::shape]) -> true Now the problem with :default I can define a single default combine method: (defmethod combine :default ...) which will be called when none of the other methods match. What I CAN"T do, as far as I can tell, is define a method for combining a ::circle with any shape, i.e. this doesn't work (defmethod combine [::circle :default] ...) because support for :default is not part of clojure's hierarchy mechanism, but part of defmulti/defmethod, and it doesn't have the special treatment of vectors. I realise I could call (derive t ::shape) for each t from all the shape types in my program, but in my real code this is not at all convenient, and would introduce a dependency between two modules which I would like to avoid. Am I overlooking a way to work around this? Someone proposed a fix back in 2009: https://groups.google.com/forum/#!topic/clojure/vFGTMEwasuM but I wasn't able to trace where that went, or find any rationale for not merging the patch. Thanks very much, Tom -- Note that posts from new members are moderated - please be patient with your first post. --- You received this message because you are subscribed to the Google Groups "ClojureScript" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojurescript+unsubscr...@googlegroups.com. To post to this group, send email to clojurescript@googlegroups.com. Visit this group at http://groups.google.com/group/clojurescript.
[ClojureScript] Re: Bug (?) in clojure.spec (ClojureScript) with s/or inside s/and
A quick follow-up - if I use s/assert instead of s/valid you can see the problem with the s/or tag (:b in this case) getting into the assertion val (s/assert (s/and (s/or :a (s/and #(empty? (::data %)) #(empty? (::path %))) :b #(= (::val %) (get-in (::data %) (::path % (s/keys :req [::val ::data ::path])) {::data [:zob] ::path [0] ::val :zob}) Error: Spec assertion failed val: [:b {:clarity.cursors/data [:zob], :clarity.cursors/path [0], :clarity.cursors/val :zob}] fails predicate: map? :cljs.spec/failure :assertion-failed -- Note that posts from new members are moderated - please be patient with your first post. --- You received this message because you are subscribed to the Google Groups "ClojureScript" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojurescript+unsubscr...@googlegroups.com. To post to this group, send email to clojurescript@googlegroups.com. Visit this group at https://groups.google.com/group/clojurescript.
[ClojureScript] Re: Bug (?) in clojure.spec (ClojureScript) with s/or inside s/and
Thanks very much - that makes sense now. I had read the guide, and not noticed the fact that conformed values can be used as the *input* to specs. I looked again and the section on composing specs with and and or makes no mention of it. This behaviour does get a mention in the section on spec'ing functions - "The second :args predicate takes as input the conformed result of the first predicate". Is it straightforward to submit a pull request on the docs? I think this could use a sentence or two of clarification. -- Note that posts from new members are moderated - please be patient with your first post. --- You received this message because you are subscribed to the Google Groups "ClojureScript" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojurescript+unsubscr...@googlegroups.com. To post to this group, send email to clojurescript@googlegroups.com. Visit this group at https://groups.google.com/group/clojurescript.
[ClojureScript] Bug (?) in clojure.spec (ClojureScript) with s/or inside s/and
Hi all, I'm writing a spec for a cursor-like type - a map with some ::data, a ::path into the data, and a ::value - the value in the data at that path I've written a spec that captures the constraint that (= (get-in data path) value) (s/valid? (s/and (s/keys :req [::val ::data ::path]) (s/or :a (s/and #(empty? (::data %)) #(empty? (::path %))) :b #(= (::val %) (get-in (::data %) (::path %) {::data [:zob] ::path [0] ::val :zob}) => true However, if I swap the operands to s/and around: (s/valid? (s/and (s/or :a (s/and #(empty? (::data %)) #(empty? (::path %))) :b #(= (::val %) (get-in (::data %) (::path % (s/keys :req [::val ::data ::path])) {::data [:zob] ::path [0] ::val :zob}) => false I have a bigger example where the workaround of swapping the operands doesn't help. Looking at the spec failure message, I notice the :val is not the value I passed, but a vector [:kw x] where x is the actual value, and :kw is one of the keyword tags from an (s/or) used in a sub-spec, which obviously shouldn't be in there. Is this a known issue? If not I'll work on a minimal repro. Thanks Tom -- Note that posts from new members are moderated - please be patient with your first post. --- You received this message because you are subscribed to the Google Groups "ClojureScript" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojurescript+unsubscr...@googlegroups.com. To post to this group, send email to clojurescript@googlegroups.com. Visit this group at https://groups.google.com/group/clojurescript.
[ClojureScript] Switching spec asserts on and off (at compile time)
I'm using a fairly typical build setup with figwheel and lein, and running a repl inside Cursive. Does anyone have a nice solution for (re)building the project with *compile-asserts* either on or off? According to the docs it's "Initially set to boolean value of clojure.spec.compile-asserts system property", which is obviously intended to make it easy to turn on and off, but I've not been able to figure out an easy way, in a figwheel setup, to chnage that system property and do a rebuild. Thanks -- Note that posts from new members are moderated - please be patient with your first post. --- You received this message because you are subscribed to the Google Groups "ClojureScript" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojurescript+unsubscr...@googlegroups.com. To post to this group, send email to clojurescript@googlegroups.com. Visit this group at https://groups.google.com/group/clojurescript.
[ClojureScript] Pressure towards ever larger namespace/file
I'm working on a library, for which I would like to expose a single namespace to users. I don't want users (including myself!) to have to remember this function comes from foo-lib, this one comes from foo-lib.utils etc. Internally, however, I would very much like to split my code up into separate files. This is not just for convenience (although I do find smaller files much more convenient), but has a material impact on my productivity. A single long file takes a few seconds to compile (usually in figwheel). These pauses really add up and make the overall experience feel sluggish. In Clojure this is a non-issue -- a namespace can be split into multiple files using load and in-ns. We don't have those in ClojureScript. I have tried various approaches to breaking my library up into multiple namespaces, while keeping the single namespace API, but none are satisfactory. I can expose symbols just by def-ing them in the main namespace, e.g. (def foo my-utils/foo). This is inconvenient for editing (e.g. go to definition), but the real stumbling block is namespaced keywords, which I use a lot. As users of the library must use the keywords also, I need them to be in the main namespace. This means my utility namespaces (which cannot require the main namespace due to circular dependencies) would have to use the long-hand keyword syntax (i.e. no :: ). This is too high a price and I am back to everything in a single namespace. Is this issue affecting others? My guess is people just impose multiple namespaces on the consumers of libraries, or are stuck with cumbersome, large namespaces. I came across this old thread, which is related. It didn't get very far: https://groups.google.com/forum/#!topic/clojure/MwGV6GDN9p8 Thanks very much Tom P.S. I have seen people mentioning "sub second compiles" in figwheel. I am seeing, e.g. more than 3 seconds to compile a 1,700 file. Does that sound typical? (2012 MacBook Pro) -- Note that posts from new members are moderated - please be patient with your first post. --- You received this message because you are subscribed to the Google Groups "ClojureScript" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojurescript+unsubscr...@googlegroups.com. To post to this group, send email to clojurescript@googlegroups.com. Visit this group at https://groups.google.com/group/clojurescript.
[ClojureScript] Re: Pressure towards ever larger namespace/file
> Dynamic load is simply not possible due to the restrictions of the browser (all IO is async). A static load could be possible but I'm not convinced that it would actually change much. It seems to me this is a static problem that could have a static solution. Even just a static in-ns (essentially a compiler directive) would, I think, provide a solution. The three second compile time is with :compile-dependents false, :optimizations :none and :parallel-build true. I would love to know if that is atypical and what I might have set up wrong. > A more Clojure-esque REPL driven approach via `load-file` can also be a whole lot faster than automatic file-watch + hot-reload. `load-file` seems to be just as slow as recompiling, but one thing that is super fast is send-form-to-repl (I'm using Cursive). The only downside is I have to remember to do that for every top-level form I change. If I've jumped around a bit and made a few changes it's much easier to hit save. > Splitting the code into multiple impl namespaces and only exposing actual public API selectively seems like a pretty good strategy apart from the keyword issue? Yes it's really just the keyword issue making me decide against that route. The library in question is all about manipulating a bunch of nested maps, which are full of name spaced keyword keys. I find the pain of the large namespace preferable to the pain of super long keywords. Thanks very much for the advice, and also for pointing me to the jira issue. I've voted for that. Seems like it has a long way to go though - it's not much more than "this is a problem" right now. Tom -- Note that posts from new members are moderated - please be patient with your first post. --- You received this message because you are subscribed to the Google Groups "ClojureScript" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojurescript+unsubscr...@googlegroups.com. To post to this group, send email to clojurescript@googlegroups.com. Visit this group at https://groups.google.com/group/clojurescript.
[ClojureScript] Re: Bridging core.async / callbacks
I don't think this addresses the issue. I'll try to state the problem more simply: Write a function that does not return until some channel event occurs. (The difficulty being that go, put! and take! all return immediately) I would argue the ability to do so is: - fundamentally important for interfacing with JS libraries - not possible with the existing core.async API - not difficult to implement, but needs to coordinate with the scheduler -- Note that posts from new members are moderated - please be patient with your first post. --- You received this message because you are subscribed to the Google Groups "ClojureScript" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojurescript+unsubscr...@googlegroups.com. To post to this group, send email to clojurescript@googlegroups.com. Visit this group at https://groups.google.com/group/clojurescript.
[ClojureScript] Bridging core.async / callbacks
In the early core.async presentation, Rich argues that we should avoid putting application logic in callback handlers, and instead build the "machine like" parts of our code in the core.async model. To bridge from callback world to core.async we have put! and take! which we should call as soon as possible. But what do we do if the library we are interfacing with relies on some effect having happened *before* the callback returns, but our application architecture dictates that effect should come from some other process? (go) (put!) and (take!) all return immediately. According to my (hopefully incorrect!) understanding, it's not possible. It seems to me we need something like (https://groups.google.com/group/clojurescript.