Skip to content

darkleaf/polyglot.groovy

Repository files navigation

polyglot.groovy

Spice you code with Groovy!

Integrates Groovy into Clojure tooling. Works like regular deftype.

  • Write fast imperative code for special cases
  • Reload your groovy code dynamically with REPL
  • Dynamically define an Exception classes hierarcy
  • Dynamically implement abstract classes faster then proxy
  • Compile groovy code with the regualr compile

Installation

Beta stage.

{:deps {io.github.darkleaf/polyglot.groovy {:git/sha "%SHA%"}}
clj -T:build prep-lib

Why Groovy?

First. Groovy was designed as embeddable language. So its compiler has good enough compiler API to integrate it with Clojure.

Second. Groovy compiler can link with dynamically loaderd classes. So you can implement an interface of a Clojure protocol in Groovy. It is possible to dynamically compile and load Java or Kotlin code but it will be linked only with AOT compiled classes.

Third. It is much easier to write Groovy code without an IDE than Java code.

Groovy flavors

Actually there are to flavors of the Groovy language. One is a regular dynamic Groovy. It call methods indirectly and employs both runtime and compile-time metaprogramming Second is a staticaly compiled and type checked Groovy. It uses only compile-time metaprogramming.

In case of Clojure we usually don't need of slow indirect method invocation, so instead of regular Groovy this library compiles .groovy files statically.

If you have to use dynamic features like methodMissing or can't specify types you should use .dgroovy file extension or annotate a class or a method with @CompileDynamic.

.groovy, .gvy, .gy, .sgroovy, .sg and .java are compiled with @CompileStatic.

.dgroovy and .dg are compiled dynamically as a regular Groovy does.

Also you can use @CompileDynamic and @CompileStatic annotations to tune single class or method.

See config.

Java compatibility

In most cases Static Groovy is a superset of Java, so you can even use .java file extension! With dynamically class (re)loading!

It is usefull when you need to load generated Java files.

Use cases

Imperative algorithms

Use g/defobject just like def or defn.

;; src/my/project/core.clj
(ns my.project.core
  (:require
   [darkleaf.polyglot.groovy.core :as g]))

(g/defobject imperative-algorithm)

(comment
  (imperative-algorithm 42))
// src/my/project/core/imperative_algorithm.groovy
package my.project.core

class imperative_algorithm extends AFunction {
  def invoke(x) {
    // ...
  }
}

Java interop

gen-class proxy exceptions

API

Extensions

  • with
  • rwith
  • tap

Compilation

When a clojure ns compiles it also compile all defined groovy classes just like deftype. It integrates with *compile-files*. No configuration is required.

(compile 'my.project.core)

Other

var('clojure.core', 'prn')(42)

println and flushing

Inspiration

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published