Is there an apply-able new?

173 views
Skip to first unread message

hiskennyness

unread,
May 27, 2016, 1:24:12 PM5/27/16
to Clojure
qooxdoo lets us supply oft-used widget parameters to the constructor. For example, a button can specify its label and icon at new time. And this works fine from cljs:

   (new qx.ui.mobile.form.Button "Go!") ;; label is the first arg

But I am wrapping qooxdoo in something more concise and want to be able to code:

   (qxia/make (::Button "Go!")
      ..other init params to be "set"

Unfortunately I cannot even

   (new (qx-class qia-type)) ;; computed class

Let alone

   (apply new (qx-class qxia-type) make-inits)

Not that I thought I would get away with it. :) I grok new is special.

I can fall back on the qooxdoo API and use setLabel and setIcon, but I like learning so I thought I would ask if there were some way to:
  1. compute a class (preferably by first constructing a name) and/or
  2. do the moral equivalent of applying new to parameters
-hk

Gary Trakhman

unread,
May 27, 2016, 1:25:55 PM5/27/16
to Clojure
Yes, you'll have to use the reflection API to create a class dynamically.


--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@googlegroups.com
Note that posts from new members are moderated - please be patient with your first post.
To unsubscribe from this group, send email to
clojure+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
---
You received this message because you are subscribed to the Google Groups "Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clojure+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Gary Trakhman

unread,
May 27, 2016, 1:30:26 PM5/27/16
to Clojure
Here's a complex example using clojure.reflect, the intent of which was to create a macro that emits type-hints for the actual constructors that are available, to resolve ambiguity when there are multiple constructors with the same number of arguments that differ in type.

Kenneth Tilton

unread,
May 27, 2016, 1:47:06 PM5/27/16
to clo...@googlegroups.com
Thanks but... Ugh. I guess I should have mentioned this is Clojure/Javascript. Guessing clojure.reflect does not apply to JS.

Sorry for the trouble.

-kt


You received this message because you are subscribed to a topic in the Google Groups "Clojure" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/clojure/4HWF7725JvM/unsubscribe.
To unsubscribe from this group and all its topics, send an email to clojure+u...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.



--
Kenneth Tilton
54 Isle of Venice Dr, Apt 5
Fort Lauderdale, FL 33301

Brandon Bloom

unread,
May 27, 2016, 10:57:05 PM5/27/16
to Clojure
The new operation intentionally demands a statically knowable type to construct. While this is true of Java as well, it's not true of JavaScript. However, it is true of the Google Closure compiler's "type system" for advanced compilation. That said, if the library you're using isn't going to be optimized with advanced, you can do any typical dynamic metaprogramming you'd want to do in JavaScript and call in to that.

mynamespace.make = function(cls) {
 
return new (Function.prototype.bind.apply(cls, arguments));
};

Then from ClojureScript:

(apply mynamespace/make qx.ui.mobile.form.Button ["Go!"])

hiskennyness

unread,
May 31, 2016, 8:28:01 AM5/31/16
to Clojure


On Friday, May 27, 2016 at 10:57:05 PM UTC-4, Brandon Bloom wrote:
The new operation intentionally demands a statically knowable type to construct. While this is true of Java as well, it's not true of JavaScript. However, it is true of the Google Closure compiler's "type system" for advanced compilation. That said, if the library you're using isn't going to be optimized with advanced, you can do any typical dynamic metaprogramming you'd want to do in JavaScript and call in to that.

mynamespace.make = function(cls) {
 
return new (Function.prototype.bind.apply(cls, arguments));
};

Then from ClojureScript:

(apply mynamespace/make qx.ui.mobile.form.Button ["Go!"])


Looking at this for the third time I am not sure what held me back the first two times. 

Thx, I'll give it a shot. This keeps coming up where qooxdoo decides some things should be constructor params instead of properties.

 -kt

Kenneth Tilton

unread,
May 31, 2016, 2:26:40 PM5/31/16
to clo...@googlegroups.com
It woiks! 

This game never gets old. I am going to be unreasonably happy for the rest of the day.

For noobs like me that stumble across this...

1. I added a script element to my index.html:

  <script type="text/javascript">
    var MyTerop = {};
    MyTerop.make = function(cls) {
        return new (Function.prototype.bind.apply(cls, arguments));
    };
  </script>

2. Leveraging a function I have that translates isomorphically from cljs types to qooxdoo types:

    (apply MyTerop/make
           (qxia-type-to-qx-class type)
           ["It Woiks!", "identica/mmedia/games.png"])
 
[This is temporarily in the spot normally dedicated to the Button type, whose constructor takes optional args for the label and an icon reference, which will soon -- well, more below.]

3. Put the tools in the truck. Well, one more minor thing: can these be suppressed? 

WARNING: No such namespace: MyTerop, could not locate MyTerop.cljs, MyTerop.cljc, or Closure namespace "" at line 81 src/tiltontec/qxia/base.cljs
WARNING: Use of undeclared Var MyTerop/make at line 81 src/tiltontec/qxia/base.cljs
 
I tried this in externs.js to no avail:

MyTerop = {};
MyTerop.make = function () {};
 
This is way cool because we are getting close to the point where a Qxia user can just look at the excellent qx.Mobile doc and code up a qxia/make call:

   :qx-class -- the actual qooxdoo class name
   :constructor-args -- as above
   ...and then any properties they see in the qooxdoo doc for that class. The qx.Class API lets me ask the properties so I can cull the initargs meant for qooxdoo and bundle them up in a map and set them all in one go. Other purely application properties get left behind automatically (not that I think they would bother qx, but still.)

In the Common Lisp version I whittled away at their very big library piecemeal supporting classes/properties as I needed them, which would not make a very attractive library for general use.

Ya gotta love dynamic.

Thanks again.

-kt


--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@googlegroups.com
Note that posts from new members are moderated - please be patient with your first post.
To unsubscribe from this group, send email to
clojure+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
---
You received this message because you are subscribed to a topic in the Google Groups "Clojure" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/clojure/4HWF7725JvM/unsubscribe.
To unsubscribe from this group and all its topics, send an email to clojure+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Reply all
Reply to author
Forward
0 new messages