* this is a translation of an article with DailyJSIntroduction
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))
(console.log "2 + 2 = %d" (+ 2 2))
console.log("2 + 2 = %d", (2 + 2));
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:
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