[ClojureScript] core.async - restriction on macros inside go block?

2014-07-21 Thread Tom Locke
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?

2014-07-22 Thread Tom Locke
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?

2014-07-23 Thread Tom Locke
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

2014-11-07 Thread Tom Locke
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

2015-01-04 Thread Tom Locke
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?

2015-02-20 Thread Tom Locke
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

2015-10-01 Thread Tom Locke
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

2015-10-01 Thread Tom Locke
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

2016-12-02 Thread Tom Locke
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

2016-12-03 Thread Tom Locke
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

2016-12-02 Thread Tom Locke
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)

2018-03-02 Thread Tom Locke
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

2018-10-10 Thread Tom Locke
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

2018-10-11 Thread Tom Locke
> 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

2019-05-04 Thread Tom Locke
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

2019-05-03 Thread Tom Locke
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.