[ClojureScript] Re: Best practice to prepare a state for cljs.js/eval?

2017-09-28 Thread Timothy Pratley
also, regarding 
> Most of my use cases are doing refers of namespaces.

I generate a user.cljs file that does all the refers so that the symbols 
can be used without fully qualifying them.
That way when you start up in the user.cljs namespace, all your refers are 
ready to go! :)


-- 
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: Best practice to prepare a state for cljs.js/eval?

2017-09-28 Thread Timothy Pratley
Hi Tiago,

The compiler produces files ending in .cache.json
You can collect these and merge them together.

I've been doing this (thanks to Mike for suggesting) 
in http://github.com/timothypratley/power-turtle
if you wanted to do the same thing...
Here is how I am doing it:

I define a clojure task that collects the caches into a single file

(ns power-turtle.collect-caches
  (:require
[clojure.java.io :as io]
[clojure.string :as string]
[cognitect.transit :as transit])
  (:import (java.io File)))

(defn collect-caches [caches-dir]
  (into {}
(for [^File f (file-seq (io/file caches-dir))
  :when (.isFile f)
  :let [filename (.getName f)]
  :when (string/ends-with? filename ".cache.json")
  :let [cache (with-open [in (io/input-stream f)]
(transit/read
  (transit/reader in :json)))]]
  [(symbol (:name cache)) cache])))

(defn -main [caches-dir output-cache-file]
  (println "Collect caches: Started")
  (let [mega-cache (collect-caches caches-dir)]
(with-open [out (io/output-stream output-cache-file)]
  (transit/write
(transit/writer out :json)
mega-cache))
(println "Collect caches: Done" (count mega-cache) "namespaces")))



Then I load that into the state:

(io/fetch-file!
  "aot/cache.json"
  (fn fetched [txt]
(let [cache (transit/read (transit/reader :json) txt)]
  (swap! replumb-repl/st update :cljs.analyzer/namespaces merge cache)


and now you can call stuff.

I hope that helps.


Regards,
Timothy

On Sunday, July 23, 2017 at 5:31:58 AM UTC-7, Tiago Antão wrote:
>
> Hi,
>
> I am trying to prepare a state to be used under cljs.js/eval. Mostly of 
> what I want to do could be achieved with a loader, but I was wondering if 
> there is any documentation or example on how to prepare a state before 
> usage with eval? The only thing available is empty-state and I was not able 
> to find any documentation on how to change empty-state to add more stuff to 
> it.
>
> Most of my use cases are doing refers of namespaces.
>
> I would prefer to change the start state as in my case using the loader to 
> achieve what I need is actually a hack (I know from the very start all that 
> I want to add).
>
> Thanks,
> Tiago
>

-- 
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.


Re: [ClojureScript] clojurescript compiler loads twice macro in .cljc for require-macros?

2017-09-28 Thread Timothy Pratley
Hi 박상규,

The trick with ClojureScript defmacro is that it behaves differently in 
different circumstances.

If you call defmacro in a cljs file, it actually defines a function, not a 
macro, instead of throwing an error.
I find that pretty confusing. The function will produce the form instead of 
expanding the form like a macro would.
There is no error reported.

A cljc file can be loaded in response to either :require-macros,  
:require,  or being in your compilation directory.
If it gets loaded by :require-macros, it will define the macro correctly.
If it gets loaded by :require, it will define the macro incorrectly.
In your example, you never :require the file, but the file is compiled 
never the less, because it is in the src directory.
What this does is produces the incorrect function.
However because you ALSO :require-macros, it also correctly creates the 
macro.
Now there is a weird situation where if you refer to the macro using the 
fully qualified namespace,
it will call the incorrect function,
but if you just call the macro as you have, it works.

So to answer your question, yes in your example the (defmacro) happened 
twice:
Once in the correct context of defining the macro in clj,
and a second time in the incorrect context of defining a function in cljs.
It is confusing and bad to have (defmacro) called in both contexts.

You can avoid this however by wrapping your macro in #?(:clj  (defmacro 
...))
Now it will only get defined once, in the correct context.

You can find more detailed examples here:

http://blog.fikesfarm.com/posts/2015-06-19-portable-macro-musing.html
https://stackoverflow.com/questions/29914967/can-cljc-single-file-macro-definitions-to-work-with-clojurescript

But the easiest thing to do to avoid confusion is to only put your macros 
in a clj file, not a cljc file.


Regards,
Timothy





On Friday, September 15, 2017 at 11:27:24 AM UTC-7, 박상규 wrote:
>
> oh, sorry for my unclear questions.
>
> In my thought, the following steps might be expected when ClojureScript 
> compiler compiles core.cljs above.
>
> 1) It meets `ns` form at line 1 in core.cljs, handles `:require-macros`, 
> and it tries to load macro.cljc as Clojure code because what is required is 
> macros as the keyword `:require-macros` means
>
> 2) Loading macro.cljc, as expected, it makes a namespace named 'macro' and 
> registers symbols and vars to use for compile time, not for runtime.
>
> 3) At line 6 in core.cljs it meets `log` form and it tries to macro-expand 
> the `log` macro.
>
> 4) It finds the `log` macro var in macro namespace which is registered 
> just before, call the `log` macro var to expand the `log` form, and is 
> returned the expanded form which includes `now` symbol.
>
> 5) At this time ClojureScript compiler starts to resolve the symbols in 
> the expanded form.
>
> 6) And It meets symbol `now` and searches in all namespaces to resolve the 
> symbol to use for runtime.
>
> 7) When the modified macro.cljc above is used, ClojureScript compiler 
> can't resolve the symbol `now` for runtime, because the `now` function is a 
> macro helper function to be used for compile time. Hence the warning.
>
> 8) But when the unmodified macro.cljc above is used, ClojureScript 
> compiler emited no warning. This means ClojureScript compiler resolved the 
> symbol `now` for runtime, which I thought must be registered by loading 
> macro.cljc as ClojureScript code.
>
> So, this makes me have a doubt that ClojureScript compiler load macro.cljc 
> twice, one time as ClojureScript code, next time as Clojure code.
>
>
> 2017년 9월 15일 금요일 오후 9시 40분 19초 UTC+9, David Nolen 님의 말:
>>
>> You cannot define macros in .cljs files or .cljc files you intend to load 
>> as ClojureScript. So it's not clear to me what you are trying to 
>> demonstrate.
>>
>> HTH,
>> David
>>
>> On Thu, Sep 14, 2017 at 4:37 AM, 박상규  wrote:
>>
>>> I have wondered how clojurescript compiler processes macros.
>>> So I tested as following:
>>>
>>> I made dirs and files as below.
>>>
>>> guruma@mac cljs $ tree .
>>> .
>>> ├── build.clj
>>> ├── cljs.jar
>>> └── src
>>> └── foo
>>> ├── core.cljs
>>> └── macro.cljc
>>>
>>> 2 directories, 4 files
>>>
>>> I downloaded cljs.jar using curl.
>>>
>>> guruma@mac cljs $ curl -LOk 
>>> https://github.com/clojure/clojurescript/releases/download/r1.9.908/cljs.jar
>>>
>>> And I made build.clj, core.cljs and macro.cljc as below.
>>>
>>> build.clj
>>> (require 'cljs.build.api)
>>>
>>> (cljs.build.api/build
>>>   "./src"
>>>   {:main 'core
>>>:output-to "out/main.js"})
>>>
>>> core.cljs
>>> (ns foo.core
>>>   (:require-macros [macro :refer [log]]))
>>>
>>> (enable-console-print!)
>>>
>>> (log "hello, world")
>>>
>>> core.cljs require macro.cljc and use a macro 'log'.
>>>
>>> macro.cljc
>>> (ns foo.macro)
>>>
>>> (defn now []
>>>   #?(:clj (System/currentTimeMillis)
>>>  :cljs (js/Date.now)))
>>>
>>> (defmacro log [x]
>>>   `(println "log[" (now) "]: " ~x))
>>>
>>> 

[ClojureScript] [bug report] :rename-macros is inaccessible do to overly restrictive spec

2017-09-28 Thread Timothy Pratley
The ClojureScript compiler has code to handle :rename-macros, but it is 
inaccessible due to an overly restrictive spec:

(ns cljs.user
  (:require [n.m :refer-macros [a] :rename-macros {a b}]))

Could not Analyze src/cljs/user.cljs
Only :as, :refer and :rename options supported in :require / 
:require-macros; offending spec: (power-turtle.m :rename-macros {all all2}) 
at line 1 src/cljs/user.cljs

I believe that this form is valid and the intention is to support it.
If so please let me know and I can raise an issue in Jira.


The alternative form works fine:

(ns cljs.user
  (:require-macros [n.m :refer [a] :rename {a b}]))


Regards,
Timothy

-- 
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: “Seamless interaction with NPM” not so seamless

2017-09-28 Thread Thomas Heller
*“Seamless interaction with NPM” not so seamless*

This has been exactly my experience as well which is why I wrote an 
entirely new implementation for JS dependencies.

The detailed article can be found here
https://code.thheller.com/blog/shadow-cljs/2017/09/15/js-dependencies-going-forward.html

In short the implementation is much less aggressive and sacrifices some 
potential byte savings for greater compatibility with the JS ecosystem.

I added js-nacl to my demo here:
https://github.com/thheller/shadow-cljs-examples/blob/bb29828917080b143030ff557590c7c94b806ed7/browser/src/demo/app.cljs#L25-L29

The relevant bits from the config are
https://github.com/thheller/shadow-cljs-examples/blob/bb29828917080b143030ff557590c7c94b806ed7/browser/shadow-cljs.edn#L26-L28

which basically just tell the compiler to use the window.crypto property 
when require("crypto") is used.

I don't know if everything works since I know nothing about js-nacl. The 
Basic example from their README seems to work.

This is still in pre-release mode but I could some more testers with 
"troublesome" JS dependencies.



On Saturday, September 23, 2017 at 8:26:43 PM UTC+2, António Monteiro wrote:
>
> You also need to pass the `:install-deps true` compiler option from 
> 1.9.854 onwards.
>
> Some libraries are not consumable by Google Closure if they use constructs 
> like dynamic exporting and such.
>
> In any case, it looks like your problem is even another one: you're trying 
> to use a Node.js library in the browser. Obviously, `fs`, `path` and 
> `crypto` (which are Node.js builtins) are not going to be available in any 
> browser.
>
> On Friday, September 22, 2017 at 3:50:45 PM UTC-7, Krzysztof Jurewicz 
> wrote:
>>
>> Hello, 
>>
>> I want to write a simple proof-of-concept (which may eventually evolve 
>> into something more serious) GUI wallet for a cryptocurrency that I’ve been 
>> writing. As desktop libraries/languages are either not very functional or 
>> not very portable, ClojureScript plus local storage in browser as a 
>> database looks like a good choice. To make it work, I need support for 
>> Ed25519 (a public-key signature system). 
>>
>> Fortunately, there are implementations of Ed25519 compiled to JavaScript. 
>> js-nacl is a “pure-Javascript High-level API to Emscripten-compiled 
>> libsodium routines”, available also as a NPM package, and post at 
>> https://clojurescript.org/news/2017-07-12-clojurescript-is-not-an-island-integrating-node-modules
>>  
>> advertises “Seamless interaction with NPM dependencies”. I tried to use it, 
>> roughly in the following way: 
>>
>> ⒈ lein new reagent-frontend ercoin-wallet 
>> ⒉ Added :npm-deps {:js-nacl "1.2.2"} to :cljsbuild ⇨ :builds ⇨ app ⇨ 
>> :compiler in project.clj. 
>> ⒊ Added [js-nacl :as nacl] to :require in core.cljs 
>>
>> However :npm-deps seemed to be ignored. Fixed this by downgrading 
>> ClojureScript from 1.9.908 to 1.9.671 (BTW, these versions are not tagged 
>> in the Git repository), but then there are warnings: 
>>
>> WARNING: JSC_JS_MODULE_LOAD_WARNING. Failed to load module […] at […] 
>>
>> , where modules are “fs”, “path” and “crypto”. 
>>
>> spinningtopsofdo on IRC said that “From a quick skim for js-nacl it looks 
>> like it's using emscripten and doing some unique module loading that Google 
>> Closure isn't aware of (
>> https://github.com/tonyg/js-nacl/blob/master/lib/nacl_factory.js#L30-L39).” 
>> and “I think it's more the way js-nacl is using ASM / Emscripten and 
>> creating JavaScript Modules. :npm-deps covers the common JavaScript module 
>> patterns (e.g. CommonJs, Node, UMD) but there is still many edge cases out 
>> there”. 
>>
>> I’ve tried also tweetnacl-js, but similarly there is a warning: 
>>
>> “WARNING: JSC_JS_MODULE_LOAD_WARNING. Failed to load module "crypto" at 
>> […]”. 
>>
>> What is the status of NPM interoperability then? Is it supposed to work 
>> as plug & play or does it require hacky knowledge in some cases? 
>>
>

-- 
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.