3

New to Clojure and wondering how to use it to make other languages I program in easier.

One thing I would like to be able to do is use Clojure for code generation.

For example, given the input from a data file (EDN format) how should I (1) walk this structure or (2) push the data into an existing templating mechanism?

Data below would be for defining simple REST API so that you could generate Clients from it. Generate clients in multiple languages by using different templates.

(:restcall "GetAccountBalance" 
  {:method "GET" :path "account/balance"}
  {:id int})

(:restcall "GetLastTransactions" 
  {:method "GET" :path "account/transactions"}
  {:page int})

resulting code would be something like

public void GetAccountBalance(int id) 
{
    var input = new { id = id };
    callIntoRestLibrary("GET", "account/balance", input);
}

public void GetLastTransactions(int page) 
{
    var input = new { page = page };
    callIntoRestLibrary("GET", "account/transactions", input);
}

Note: my end goal would having these as System.Net.Http.HttpClient calls via C#, but also be able to translate these into JavaScript/Ajax calls also

BuddyJoe
  • 69,735
  • 114
  • 291
  • 466
  • Can you give an example of what output you want to get and probably we can give an example how to achieve it. – Mikita Belahlazau Apr 28 '14 at 20:05
  • I'm unsure I got you message correctly, but what you do looks very much alike to [this](https://github.com/Prismatic/schema#transformations-and-coercion) – 0rca Apr 28 '14 at 20:38
  • I simplified the problem a little. So for now, assume I'm not returning any data (my methods will return void for now). Updated question. – BuddyJoe Apr 28 '14 at 20:57
  • Which are you asking: (A) how to use Clojure to create textual representation of code in another language? (B) how use Clojure to compile code with Java / CLR interop? (C) how to do REST in Clojure, e.g. with Compojure? (D) None of the above – A. Webb Apr 28 '14 at 21:20
  • A. Webb, I'm trying to do (A). Trying to find the idiomatic way of string concatenation/building/templating in Clojure while navigating over a data structure. Or is there a built-in XSLT-like approach. – BuddyJoe Apr 29 '14 at 01:43

1 Answers1

3

You have several choices for templating with Clojure. One place to look is the Clojure Toolbox.

Here is an example with clostache, a small library (358 loc) implementation of mustache.

(ns so.core
  (:require [clostache.parser :refer (render)]))

(def template "
public void {{restcall}}({{id}} id) 
{
    var input = new { id = id };
    callIntoRestLibrary(\"{{method}}\", \"{{path}}\", input);
}")

(def data 
  {:restcall "GetAccountBalance" 
   :method "GET" :path "account/balance" :id "int"})


(print (render template data))

Output:

public void GetAccountBalance(int id)
{
    var input = new { id = id };
    callIntoRestLibrary("GET", "account/balance", input);
}

To clear up confusion about what it means to read EDN.

(spit "foo.txt" (prn-str data))

Now the file foo.txt contains a textual representation of data, presumably your starting point.

(def data2 (with-open [r (java.io.PushbackReader. (java.io.FileReader. "foo.txt"))] 
             (clojure.edn/read r)))

(= data data2) ;=> true

So, read doesn't just pull in text, but also parses it into its data representation.

A. Webb
  • 26,227
  • 1
  • 63
  • 95
  • Thanks. For the EDN part of my question... How do I read in the data var from a file and have it treated as s-expressions and not a string? Eventually I would like to be able to point the Clojure code at a template file and a data file. – BuddyJoe Apr 29 '14 at 19:32
  • @BuddyJoe When you read EDN from a file with `clojure.edn/read`, for example, it _is_ read, and "read" here also means parsed into the data representation. – A. Webb Apr 29 '14 at 20:07
  • Awesome. That does clear up my understanding of using EDN. Thanks. +1 and answer. – BuddyJoe Apr 29 '14 at 21:33