ClojureScript

Google Closure Class interop form (genclass)

Details

  • Type: Enhancement Enhancement
  • Status: Open Open
  • Priority: Minor Minor
  • Resolution: Unresolved
  • Affects Version/s: None
  • Fix Version/s: None
  • Component/s: None
  • Labels:
    None

Description

Currently it's not really possible to use to the existing deftype/record to construct "classes" that interop well with Google Closure. It seems odd to ship Closure and then provide no tools for writing ClojureScript against it, especially the UI component parts. Several people have asked for this now so perhaps we really should offer the ClojureScript equivalent of genclass.

Activity

Hide
Tyler Tallman added a comment - - edited

What do you think of this approach based on
based on http://www.50ply.com/blog/2012/07/08/extending-closure-from-clojurescript/

While it may not preserve enough of gen-class's semantics. This would be enough for us to start gradually porting our large GClosure code base to Clojurescript. The code size reduction would be enormous.

sample_use
(ns com.example
  (:require [goog.ui.tree.TreeControl :as TreeControl]))
(gen-class
  :name DemoTree
  :extends goog/ui.tree.TreeControl
  :constructor ([name config]
                 (goog/base (js* "this") name config))
  :methods [[handleKeyEvent [e]
              (goog/base (js* "this") "handleKeyEvent" e)
              ;; my special code to handle the key event
    ]])

here is a untested mock implementation modified from http://www.50ply.com/blog/2012/07/08/extending-closure-from-clojurescript/

I changed constructors to constructor because there can be only one in js

This unfortunately has different semantics from gen-class because the original did not include the definition of the methods and constructor inline. It tried to read the Clojure gen-class source,but I still do not yet understand how the :prefix grabbing of functions from the current namespace works from within a macro.

For Google Closure interop each class should have its own provide

dryrun_for_gen-class
(defmacro gen-class [{new-type :name base-type :extends ctor :constructor methods :methods}]
  `(do
     ;(goog/provide ~@(str *ns* "." new-type)) 
     (defn ~new-type ~@ctor)

     (goog/inherits ~type ~base-type)

     ~@(map
        (fn [method]
          `(set! (.. ~type -prototype ~(to-property (first method)))
                 (fn ~@(rest method))))
        methods)))
Show
Tyler Tallman added a comment - - edited What do you think of this approach based on based on http://www.50ply.com/blog/2012/07/08/extending-closure-from-clojurescript/ While it may not preserve enough of gen-class's semantics. This would be enough for us to start gradually porting our large GClosure code base to Clojurescript. The code size reduction would be enormous.
sample_use
(ns com.example
  (:require [goog.ui.tree.TreeControl :as TreeControl]))
(gen-class
  :name DemoTree
  :extends goog/ui.tree.TreeControl
  :constructor ([name config]
                 (goog/base (js* "this") name config))
  :methods [[handleKeyEvent [e]
              (goog/base (js* "this") "handleKeyEvent" e)
              ;; my special code to handle the key event
    ]])
here is a untested mock implementation modified from http://www.50ply.com/blog/2012/07/08/extending-closure-from-clojurescript/ I changed constructors to constructor because there can be only one in js This unfortunately has different semantics from gen-class because the original did not include the definition of the methods and constructor inline. It tried to read the Clojure gen-class source,but I still do not yet understand how the :prefix grabbing of functions from the current namespace works from within a macro. For Google Closure interop each class should have its own provide
dryrun_for_gen-class
(defmacro gen-class [{new-type :name base-type :extends ctor :constructor methods :methods}]
  `(do
     ;(goog/provide ~@(str *ns* "." new-type)) 
     (defn ~new-type ~@ctor)

     (goog/inherits ~type ~base-type)

     ~@(map
        (fn [method]
          `(set! (.. ~type -prototype ~(to-property (first method)))
                 (fn ~@(rest method))))
        methods)))

People

Vote (3)
Watch (4)

Dates

  • Created:
    Updated: