Looking for new language (recommendation) for specific problem


#1

I have a setup for code generation that I love, but is now moribund. I will describe the aspects that are great and I would like to know what clojure might offer for solving this problem.

My current solution uses the Dart programming language. With dart there are now a few implementations of the language - one for web, one for flutter and another vm for console work. My stuff is all console vm. I say my setup is moribund because all my code is written in Dart 1 and the recent move to Dart 2 has killed it for me. While the language is still awesome IMHO, my m.o. for using it no longer works because version two of the language moved to an ahead of time compilation approach.

I made a decision early on to model items I want to generate code for in the Dart language itself - rather than in json, xml or some data language. My thinking was so often I want to transform models that it did not make sense to even deal with json to dart every time I want to make a change. Plus, by modeling my data in the language I get the intellisense. So, if I’m targeting c++ I model classes, templates, members, statics, consts etc and then at a higher levels of abstraction implementation files, header files, build scripts - etc. The libraries supporting those models, once written don’t change too frequently. The issue with Dart 2 is startup time went from under 1 second to over 8 seconds which killed the workflow. So prior to 2 I could generate 20 files in less than a couple seconds and now its over 10 seconds. Similar issue for testing. The language has support for snapshots which is great for scripts run repeatedly, but does not help my situation because I create my models in the language directly and therefore every change is a “recompile”. Currently there is no real support for “incremental” compilation with the snapshots (e.g. no way to just compile the one script that has changed and patch it in to preexisting snapshot(s)).

Some features I love in current (Dart 1) setup is:

  • Fast turnaround since language was in scripting space - make change, save and less than two seconds all files updated
  • Great support for string interpolation “class ${className} …”. I’ve used template libraries in other languages and I’m ok with them but have no strong attraction to them and don’t mind piecing together all text in code. String interpolation makes it easy.
  • They have this nice syntax called cascades that turns any set of chained method calls into a kind of fluid API automatically. So - a small sample:
        class_('change_tracker')
        ..descr = '''
  Tracks current/previous values of the given type of data. For some
  algorithms it is useful to be able to examine/perform logic on
  current value and compare or evalutate how it has changed since
  previous value.'''
        ..template = [ 'typename T' ]
        ..customBlocks = [clsPublic]
        ..members = [
          member('current')..type = 'T'..access = ro,
          member('previous')..type = 'T'..access = ro,
        ],
  • Excellent libraries for xml, json, yaml etc. One use case is to read xml from protocol schema definitions and generate library support.
  • Excellent error identification (type related) from the IDE before even running the code.

I don’t know much about clojure yet and am willing to learn new paradigms if they are good for this problem. I’m used to OO, modeling data and then adding behavior. I’ve seen a couple talks by Rich Hickey and admit I don’t get it yet - but if it is a good tool for this task I’d like to know and then pursue. What are your thoughts on clojure for this problem? Are there any killer features? Note: I’ve posted the same question to elixir forum and if there are other languages good/better for this task would appreciate the suggestions.


#2

Well, if I understand correctly Ebisu (the link you provided at the beginning) you basically want a project scaffolder ? You could create a Leiningen template for it. You script the template in Clojure, which gives you really good support for XML, json out of the box (don’t know for YAML but a good library surely exists). You have a REPL for interactive development, so you could regenerate the template easily from it I guess.

You could also try Yeoman (in Javascript/Node.js).

Hope this helps !


#3

Thanks. I will explore Leiningen. I do want a language with features that are embraced as positive for quality code - so for me that does eliminate javascript. Kotlin, for example, looks like a great language and it has scripting in a sense. The hello world script runs in about 3 seconds on my mac after any update. Thereafter, running it is sub-second. The issue is some piece of code will change frequently as part of the development cycle. The Dart 1, Ruby, Python type languages are not the fastest for many jobs, but for this type job in particular, in which the code has changed, they are fast because the parse/run cycle is fast. For clojure I’m curious if the modification of one file, requiring its recompilation and patching it into maybe something already running waiting to emit code is quick. I have done some lisp in emacs and that aspect was nice - you can reevaluate a function or data and it is almost instantly replaced.


#4

Yes, once you have a REPL going, you couldn’t wish for a faster turn-around.
You don’t really have a parse/run-cycle. You have a continuous interaction cycle with your app.
Adding new functions you can try out and run instantly.
Clojure encourages you to write small, pure functions that are trivial to test and you build apps by composing functions, often using a bottom-up approach.

So if iteration-speed is important to you, Clojure and to a bigger extent ClojureScript are a great choice.


#5

The killer feature for Clojure are the immutable data structures.

Clojure has great libraries for XML, JSON, CSV, etc.

Clojure does not have string interpolation, but there are templating libraries.

The JVM startup time may cost a little bit. A simple hello world application takes 1 second on my machine, and I hear it gets longer as dependencies are added. Do your own research though–it depends on the size of the dependency.

Lumo starts faster. It’s a ClojureScript runner. You can use any JS library from npm.

What @beders said is true. If you’re concerned mostly about development flow, Clojure is great. Once the JVM is started and Clojure is loaded, recompiling and running is super fast.

I hope that helps.

Rock on!
Eric


#6

What do you make of cl-format ? I use it a lot, it’s very powerful, but I can see how people are afraid of it at first sight. It would be fun to modernize by adding support for maps and named key access instead of just lists. That’s mostly the only thing making it stranger looking than other string templating libs.


#7

We run REPLs in several of our production processes so we can attach to them (from a terminal or an editor) and we can evaluate updated functions into the running image on the fly in a fraction of a second with zero downtime.

Well, zero downtime unless we mess up the new definition of course :slight_smile:

The ability to inspect, run, and modify production code – while your application is running – is amazingly powerful, and you have the same “instant” response via that REPL as in any other situation with Clojure. That’s because the Clojure compiler and the REPL work the exact same way: read a form, compile it (and, in the REPL, run it).