Clojurescript: Create New Object from Namespace - clojurescript

I'm relatively new to ClojureScript and having never worked in a lisp-like language before, I must say that the documentation is rather... lacking. I just want to transform the following JavaScript statement into ClojureScript:
var obj = new namespace1.namespace2.SomeObject();
I know that you can create new instances of an object in cljs by writing something like
(SomeObject.)
but trying
(def obj (namespace1/namespace2/SomeObject.))
didn't compile. What should I be doing instead?

Have a look at this answer, it is exactly the same question:
https://stackoverflow.com/a/23653459/1400662
Pasted here:
Using js/a.b.c.d is a bad practice and is likely to break in future versions of the compiler (because it is not a clojure compatible version of interop from what I know)
The good way would be:
(def LatLng (.. js/google -maps -LatLng))
(LatLng. 100 100)

Related

what is the clojurescript equivalent to 'var'?

In clojure, (var some-function) and #'some-function are equivalent.
What is the clojurescript equivalent of var?
ClojureScript also has var as a special form. And, in ClojureScript (var foo) and #'foo are equivalent.
Having said that, ClojureScript's var is a bit limited compared to Clojure:
Vars are not reified at runtime. When the compiler encounters the var special form it emits a Var instance reflecting compile time metadata. (This satisfies many common static use cases.)
(Taken from Differences from Clojure.)

Clojurescript Add an Event Listener

(defn domready [handler]
(.addEventListener js/window "DOMContentLoaded" handler))
I borrowed this code from here. The problem is I don't totally understand what's going on. JS interop is still a bit of a mystery to me.
.addEventListener
So this is clearly a procedure call, but it's kind of generic. It's like Clojurescript took everything that was inside an object, took it out, and you use it to call that method on "objects". As long as that "object" has the ".addEventListener" property it will call this. Is that what it's doing? Why not use a keyword instead? like (:addEventListener domElement) that seems more logical to me.
js/window
What is this? Is it a namespace or an object? Are they the same thing?
"DOMContentLoaded"
A string, that's familiar.
handler
Also familiar, but does it have a notion of this? Not that I'm really going to miss this.
.addEventListener
So this is clearly a procedure call, but it's kind
of generic. It's like Clojurescript took everything that was inside an
object, took it out, and you use it to call that method on "objects".
As long as that "object" has the ".addEventListener" property it will
call this. Is that what it's doing? Why not use a keyword instead?
like (:addEventListener domElement) that seems more logical to me.
Your mental model about how this works is mostly fine. What it does when it compiles is move the function name to be run as a method on the first argument.
(.method obj ...args) get's transformed to obj.method(...args)
This type of interop comes from the parent language Clojure.
On why do we have an explicit version of calling the function that's not Clojure idiomatic, I think the idea is to have clear separation between what is native Clojure code with Clojure semantics (immutability, friendly to CLJ data structures, etc) and what is interoperating with the host environment (mutable, not friendly to CLJ data structures, etc).
In my opinion it is better to have clear separation between those two given how different the semantics of CLJS and the host platforms are. For me explicitness is better than implicit in this case (it is easy to spot looking at the code what is JS code in CLJS, and what is pure CLJS).
js/window
What is this? Is it a namespace or an object? Are they the same thing?
Both, js/ is accessing the namespace js, which is where CLJS puts the JS namespace (since there is only one and global). window is just grabbing the window variable from the js namespace.
This is no different from how you access variables in other namespaces in CLJS. If you (def a 1) in (ns cljs.test) and then run cljs.test/a that will give you 1. Same form, ns/something-in-that-ns.
"DOMContentLoaded"
A string, that's familiar.
\o/
handler
Also familiar, but does it have a notion of this? Not that I'm really going to miss this.
Not sure what this has to do with handler. It is just a higher order function passed into domready as a parameter, like you would do in JS: function domready (onReady) { window.addEventListener("DOMContentLoaded", onReady) }
I hope this helps, if you want to try it out live and learn some more, maybe visit the Talking with JS on the Diving into ClojureScript tutorial, or maybe check this section of the lt-cljs-tutorial.
I'm just learning clojurescript so I don't really know if it is the correct answer but I've done it in the following way:
(defn handler [] (js/console.log "ready"))
(js/document.addEventListener "DOMContentLoaded" handler)
which is then translated to
cljs.user.handler = (function cljs$user$handler(){
return console.log("ready");
});
document.addEventListener("DOMContentLoaded",cljs.user.handler);
to check how clojurescript translate code I've used KLIMPSE http://app.klipse.tech/
.addEventListener is a method call on the global Javascript object js/window. This method call takes two parameters: "DOMContentLoaded" and handler.
When you are doing interop (either Java or Javascript) you really are calling methods on objects. There are macros behind what is happening here. What is straight after the ( is a verb, which I usually think of as a function call (although it might also be a macro or a special form). When doing interop what comes after the verb is the instance, and after that the parameters.
If it were straight Javascript it would look like this:
function domready(handler){
window.addEventListener("DOMContentLoaded" handler);
}

Instantiate namespaced javascript class

I want to use google maps api v3, and it needs me to instantiate google.maps.LatLng. Using clojurescript this is what I do:
(ns foocljs.core)
(LatLng. (.-maps js/google) 100 100)
I got an error undefined is not a function, this is the culprit:
new foocljs.core.LatLng(foocljs.core.google.maps, // ... another args
I'm guessing this is because the compiler think that LatLng. is clojure namespaced class. How to deal with this? Thanks.
Using js/a.b.c.d is a bad practice and is likely to break in future versions of the compiler (because it is not a clojure compatible version of interop from what I know)
The good way would be:
(def LatLng (.. js/google -maps -LatLng))
(LatLng. 100 100)
Silly me, I can just do this:
(js/google.maps.LatLng. 100 100)

Is there an Actionscript to ABC Bytecode parser?

So, I have an app where users should define ActionScript functions.
What do I need to get the string whritten by the user and convert it to bytecode so that I can use it with as3-commons-bytecode?
Edit
I don't think I was clear enough. I need to turn: if(!myValue) {...}
Into this:
...
findpropstrict private::myValue
getproperty private::myValue
not
iffalse L1
...
Because with this ^^^^ code, I can use as3-commons-bytecode to do what I need.
I took a look at this app's source code. It's very confusing, the project is old and the code is a mess, but it works. I need to find "where the magic happens". Can you show me the way?
You should use part of this project :
eval.hurlant.com/demo/#app=da4a&757d-selectedIndex=0
Check source , there is parser to ABC .
I'm not aware of any libraries that do this for you, but to achieve this functionality you should parse user's input into function names.
For example, you can call a function just by having it's name as a String like so:
var functionName:String = "myMethod";
function myMethod():void
{
trace("myMethod");
}
this[functionName](); //traces "myMethod"
Of course, if you wish to interpret advanced strings with getting/setting objects and their properties and any other user defined statements, that would require to write quite a sophisticated string-to-bytecode converter.
UPDATE:
There's also AS3Eval library that might do the job. Take a look at http://eval.hurlant.com/
There is a library for Haxe which makes it possible to compile Actionscript assembly language into ABC at runtime, but this is still lower-level than the Actionscript you normally write.
http://haxe.org/com/libs/format/abc
The most likely solution is a server or other process which can compile and return SWF content for you. Haxe has a very fast and straightforward compiler, but it may also be possible to use Tamarin or another solution for compiling AS3 on the server.
Actually, there is a runtime library for executing Haxe code, which again, is very similar to Actionscript. Might be worth looking into:
http://code.google.com/p/hscript/
What exactly want to do? To compile "string" the string must be something meanfull for the compiler such as package not a simply string ( like 'asdas ' ). If you don't wont to use flash/flex compiler you may compile AS to ABC with Ant or Haxe. But ther is a problem - how you will start this ABC?

AS3 - evaluating at runtime - D.eval vs hurlant

I need to pass in a string that gets evaluated at runtime. So I can write this:
var foo = someEvalMethod ( "dataObject.someValue" )
instead of:
if ( argIn == "dataObject.someValue")
var foo = dataObject.someValue
}
Does anyone have an opinion on the following evaluate libraries, or better ones for AS3? Thanks:
AS3 eval by hurlant:
http://eval.hurlant.com/
D.eval by RIA 1:
http://www.riaone.com/products/deval/
As far as I know AS3 eval by hurlant is a "real" compiler. It parses code, generates bytecode and injects it to the Flash Player instance in use (through loadBytes() I guess).
D.eval has the same purpose but it does not generate bytecode, it parses expressions and execute them dynamically through its own API.
I see D.eval as a good candidate for what you are trying to achieve. It's not a full featured compiler, but it has enough APIs that cover many simple operations. Other than that it is a product that has a company behind, which is always a good guaranty.
Cheers!