Clojurscript: extend a Javascript class - clojurescript

I'm trying to use a particular JavaScript framework which requires extending a base class to use it for application.
Basically I want to do the following as idiomatic ClojureScript.
class Foo extends Bar {
constructor() { super("data") }
method1(args) { /* do stuff */ }
}
I tried
(defn foo
[]
(reify
js/Bar
(constructor [this] (super this "data"))
(method1 [this args] )))
Which would work if I'd create a new class from Object, but as shadow-cljs correctly complains, "Symbol js/Bar is not a protocol". Also, I don't want to add methods but create a subclass that inherits somemethods and overloads others.
I thought about using proxy, but "core/proxy is not defined".
Of course I could create an instance of Bar and set! new methods, but that feels like giving up and using an inferior language.

Please see answer below for more current solution!
CLJS has no built-in support for class ... extends ....
You can hack it together yourself with a bit of boilerplate, which you could generate via a macro to make it look pretty.
(ns your.app
(:require
[goog.object :as gobj]
["something" :refer (Bar)]))
(defn Foo
{:jsdoc ["#constructor"]}
[]
(this-as this
(.call Bar this "data")
;; other constructor work
this))
(gobj/extend
(.-prototype Foo)
(.-prototype Bar)
;; defining x.foo(arg) method
#js {:foo (fn [arg]
(this-as this
;; this is Foo instance
))})

CLJS (still) has no built-in support for class ... extends ....
However in recent shadow-cljs versions I added support for class as well as extends. This will emit a standard JS class and does not require any hacky workarounds to get it working.
Translating this example
class Foo extends Bar {
constructor() { super("data") }
method1(args) { /* do stuff */ }
}
would be
(ns your.app
(:require [shadow.cljs.modern :refer (defclass)]))
(defclass Foo
;; extends takes a symbol argument, referencing the super class
;; could be a local symbol such as Bar
;; a namespaced symbol such as alias/Bar
;; or just a global via js/Bar
(extends Bar)
(constructor [this]
(super "data"))
;; adds regular method, protocols similar to deftype/defrecord also supported
Object
(method1 [this args]
;; do stuff
))
More complex examples of defclass can be found here and here.
Currently this only ships with shadow-cljs but technically you can take the modern.cljc and modern.cljs files from here and put them into your project. It should work with all build tools then.

Related

Referencing overloaded top-level Kotlin functions reflectively

In brief, how can one reference / iterate reflectively over overloaded top-level functions in Kotlin, such as kotlin.io.println?
Given the following:
object Bar {
fun foo(x: Int) = Unit
fun foo(x: Byte) = Unit
fun foo(x: Float) = Unit
}
I can iterate over the various overloads of foo by doing:
fun main() {
Bar::class.memberFunctions
.filter { kFunction -> kFunction.name == "foo" }
.forEach { kFunction -> println(kFunction) }
}
Which produces:
fun com.example.Bar.foo(kotlin.Byte): kotlin.Unit
fun com.example.Bar.foo(kotlin.Float): kotlin.Unit
fun com.example.Bar.foo(kotlin.Int): kotlin.Unit
However, if the various overloads of foo are defined top-level (outside of a class or object definition) such as simply:
fun foo(x: Int) = Unit
fun foo(x: Byte) = Unit
fun foo(x: Float) = Unit
Then there doesn't seem to be a way to reference them.
I tried being tricky using a top-level function in my example (such as main) to access the synthetic class:
::main::class.memberFunctions
.filter { kFunction -> kFunction.name == "foo" }
.forEach { kFunction -> println(kFunction) }
But it pukes on the fact that it's synthetic:
Exception in thread "main" java.lang.UnsupportedOperationException: This class is an internal synthetic class generated by the Kotlin compiler, such as an anonymous class for a lambda, a SAM wrapper, a callable reference, etc. It's not a Kotlin class or interface, so the reflection library has no idea what declarations does it have. Please use Java reflection to inspect this class.
How can I reference top-level overloaded functions in Kotlin?
More specifically, top-level overloaded functions defined in other packages / modules such as kotlin.io.println?
Top level functions by definition don't have a declaring class.
::println.javaClass.declaringClass //will return null
so you don't have a class to use reflection on, and consequently, you can't enumerate the top level members of a package.(Some magic can be done though, if you are willing to trade your soul)
The only way you can reference ambiguous top level functions is by helping the compiler to resolve the ambiguity like this:
val functionReference: (Int)->Unit = ::foo
and then you can call functionReference()

how to override/extend chisel signal naming

It seems not an easy thing to do or even impossible, but we are using a naming convention that prefix or postfix signals with "i_" or "o_" for inputs/outputs in verilog.
Is there some method to mess with or override inside the chisel library to to that?
I saw that except for clock and reset, all signals have "io" prefix.
Is is possible to use just "i" for input and "o" for output?
The easiest way to do this is to probably use a MultiIOModule. However, you can also do it with suggestName. Both approaches are shown below.
MultiIOModule
This a more flexible Module that lets you call the IO method to add ports to a module more than once. (Module requires that you define an io member and only allows you to call IO once.)
Because MultiIOModule frees you from the constraints of val io = ... you can use the prefix/postfix naming that you want with the names of your vals. Reflective naming will then get these right in the generated Verilog.
Consider the following Chisel code:
import chisel3._
import chisel3.stage.{ChiselStage, ChiselGeneratorAnnotation}
class Foo extends MultiIOModule {
val i_bar = IO(Input(Bool()))
val o_baz = IO(Output(Bool()))
o_baz := ~i_bar
}
(new ChiselStage).execute(Array.empty, Seq(ChiselGeneratorAnnotation(() => new Foo)))
This produces the following Verilog:
module Foo(
input clock,
input reset,
input i_bar,
output o_baz
);
assign o_baz = ~ i_bar;
endmodule
SuggestName
As an alternative, you can use the suggestName method to change the name to be different from what reflective naming (getting the name from the name of the val) would use.
Using suggestName you can coerce the names to be whatever you want. The following Chisel produces the same Verilog as above:
class Foo extends MultiIOModule {
val a = IO(Input(Bool())).suggestName("i_bar")
val b = IO(Output(Bool())).suggestName("o_baz")
b := ~a
}

Compile ClojureScript in Java application

I'm trying to compile String that contains Clojure Script code in Java/Groovy. I'm not really happy with using "java -jar ...".execute().
Is there any way to invoke clojurescript library (version 1.8.51) to compile code?
Edit:
So combining these two links I got this code (Groovy):
IFn require = Clojure.var("clojure.core", "require");
require.invoke(Clojure.read("cljs.analyzer.api"))
require.invoke(Clojure.read("cljs.compiler.api"))
IFn emptyEnv = Clojure.var("cljs.analyzer.api", "empty-env")
IFn analyze = Clojure.var("cljs.analyzer.api", "analyze")
IFn emit = Clojure.var("cljs.compiler", "emit-str")
final inputText = "(defn plus [a b] (+ a b))"
emit.invoke(
analyze.invoke(emptyEnv.invoke(), "'$inputText"
)
)
My problem is that emit function return empty string :/. Is there anything I'm doing wrong?
Edit2: The analyze method return this:
{
:op :constant,
:env {:ns {:name cljs.user},
:context :statement,
:locals {},
:fn-scope [],
:js-globals ...removed...,
:form #object[org.codehaus.groovy.runtime.GStringImpl 0x37816ea6 "'(defn plus [a b] (+ a b))"],
:tag any
}
It should be very easy to call ClojureScript Compiler API from Clojure, for example as presented in answers to a similar question on how to do it from Clojure.
But as you want to do it from Java or Groovy, you will have to use some Clojure Java API for calling Clojure from Java.

debugging functions in the clojurescript repl

Does anybody know a good way to debug functions in the clojureScript REPL?
The default, behavior is that the generated JS code of the function is printed.
midi.lib=> (defn f [] (println "hello"))
#'midi.lib/f
midi.lib=> f
#object[midi$lib$f "function midi$lib$f(){
return cljs.core.println.call(null,"hello");
}"]
With longer functions this gets annoying. For many debugging cases, simply the name of the function would be sufficient..
There is currently no support for controlling how function values print in ClojureScript.
But, if you are OK with extending the JavaScript function type, you can evaluate the following in a REPL
(extend-type js/Function
IPrintWithWriter
(-pr-writer [obj writer _]
(let [name (.-name obj)
name (if (empty? name)
"Function"
name)]
(write-all writer "#object[" name "]"))))
and then your example function value would print as #object[midi$lib$f].
Try using the Figwheel REPL, it doesn't print out the generated JS, and behaves similarly to a Clojure REPL.

Reagent: How to get new props from component-will-receive-props?

So signature for component-will-receive-props is such:
https://github.com/reagent-project/reagent/blob/master/src/reagent/core.cljs#L114
:component-will-receive-props (fn [this new-argv])
But new-args seems like it's function or js object. I was expecting it to be map of props. How do I get map of props from new-argv? I can get old props from this by (reagent/props this), but it's old props, not newly received.
Ok I finally found out it's reagent.impl.util/extract-props.
So (reagent.impl.util/extract-props new-argv) will return new props.
https://github.com/reagent-project/reagent/blob/v0.5.1-rc3/src/reagent/impl/util.cljs#L11
I think the correct way to do this is through the props function. An example here shows this.
;; assuming you have reagent required :as reagent
(reagent/create-class
{
...
:should-component-update
(fn [this]
(println "next-props" (reagent/props this))
...
})