📜 ⬆️ ⬇️

LispyScript - Lisp JavaScript

* this is a translation of an article with DailyJS

Introduction


LispyScript is a tree-like programming language that compiles to javascript. As a matter of fact, this is something between javascript and lisp.
The script on Lispy consists of similar expressions:
(<function> arg1 arg2 arg3 ...) 


This expression calls a function (generally speaking, this is not quite true, but more on that later).
The first element indicates the function. The rest - on the arguments.
 (console.log "abc") 

Yes, I almost forgot: you can play around here .

For example, a function can be called like this:
  (console.log "2 + 2 = %d" (+ 2 2)) 

Well, in JS it looks like this:
  console.log("2 + 2 = %d", (2 + 2)); 


We all know the structure of HTML:
 <html lang="en"> <head> <title>My Home Page</title> </head> <body> <h1>Welcome to LispyScript</h1> </body> </html> 

')
In Lispy templates, it looks a little different:
 (html {lang: "en"} (head (title "My Home Page")) (body (h1 "Welcome to LispyScript"))) 


But about the templates later, it is now important to see the tree structure.

Macros


One of the most important parts of Lispy. Macros are not compiled in JS, but they can extend the compiler. For example, let's write a print macro:
 (macro print (str rest...) (console.log ~str ~rest...)) (print "Hello print macro!") (print "2 + 2 = %d" (+ 2 2)) 

 console.log("Hello print macro!") console.log("2 + 2 = %d", (2 + 2)); 


The above macro expands Lispy. The macro expression takes the macro name as the first parameter, then the parameters in brackets, then the code into which the macro call is compiled.
Operator ~ dereferences parameters. The variable rest ... contains all parameters passed after str.

The compiler works in 2 stages: first, the macros are converted into code. Those. of
  (print "Hello print macro!") 

He creates:
  (console.log "Hello print macro!") 

Well, then already compiles to JS. Similarly:
  (print "2 + 2 = %d" (+ 2 2)) ; lispy 

 (console.log "2 + 2 = %d" (+ 2 2)) ; lispy 

  console.log("2 + 2 = %d", (2 + 2)); // js 


One may ask, why not use a function instead of a macro? Let's try:
 (var print (function (data value) (console.log data value))) 


Now compare the resulting code:
 //  console.log("2 + 2 = %d", (2 + 2)); //  var print = function(data,value) { return console.log(data,value); }; print("2 + 2 = %d",(2 + 2)); 


Macro is not a function!

You should not expect a macro to behave like a function. It is often better to use a function rather than a macro.
Example: write a macro to calculate the square of a number:
 (macro square (x) (* ~x ~x)) (console.log (square 2)) 

And this code will work fine, output 4. In JS, this is how it is:
 console.log((2 * 2)); 


And now we try:
 (var i 2) (console.log (square i++)) 

And we return the number 6 instead of 9. Why this is so, it becomes clear if you look at the compiled code:
 var i = 2; console.log((i++ * i++)); 


In the case of a function, the value is calculated in advance, but in the case of a macro, it is not. It is necessary to understand and remember.

Conclusion


In general, Lispy provides an alternative way to write scripts. Macros are a very powerful tool, but they are best used with caution.

PS


There is also a javathcript . True, he without macros.
UPD. More ClojureScript , thanks for the help monolithed

Source: https://habr.com/ru/post/152119/


All Articles