 # Powerful Scheme lisp in JavaScript

NOTE: Documentation for Beta version can be found at LIPS wiki.

### Variables and functions

``````
(define x 10)
(define square (lambda (x) (* x x)))
(define (square x) (* x x))
``````

### Lisp Macros

``````
(define-macro (foo x) `(1 2 ,@(car x) 3 4))
``````

### BigInt

lips have no problems in evaluating factorial of thousand, and it's fast.

``````
(define (! n) (reduce * (map 1+ (range n))))

(print (! 1000))
``````

### List operations

``````
(cons 1 2)
(cons 1 (cons 2 nil))
(list 1 2 3 4)
'(1 2 3 4)

(let ((lst '(1 2 (3 4 5 6))))
(print (car lst))
``````

all functions that match this regex `c[ad]{1,5}r` are defined.

### ALists

``````
(let ((l '((foo . "lorem") (bar "ipsum"))))
(set-cdr! (assoc l 'foo) "hello")
(set-cdr! (assoc l 'bar) "world")
(print l))
``````

### Flow constructs

``````
(let ((x 5))
(while (> (-- x) 0) (print x)))
``````

Operator `==` work as == in javascript but it should only be used on number or values that can be converted to numbers like string "10".

To compare strings or any values use `eq?`

``````
(if (== "10" 10)

(if (eq? "foo" "bar")
(print "equal")
(print "not equal"))

(let ((x 10))
(if (and (> x 1) (< x 20))
(begin
(print "this is x > 1")
(print "and x < 20"))))
``````

### Eval

``````
``````

### Apply

Apply function the same as the one from javascript invoke a function with arguments taken from list

``````
(let ((strings '("foo" "bar" "baz")))
(print (apply concat strings)))
``````

### Async code

``````
``````

then type S-Expression like `(print 10)`. If function return Promise the execution is paused and restored when Promise is resolved

### Access JavaScript functions and objects

``````
((. console "log") "hello")
``````

If object is not found in environment, then window object is tested for presense of the element.

You can execute jQuery functions

``````
(let* ((term (\$ ".terminal")))
((.  term "css") "background" "red"))
``````

function `\$` is available because it's in window object.

or operate on strings

``````
((. "foo bar baz" "replace") /^[a-z]+/g "baz")

(let ((match (. "foo bar baz" "match")))
(array->list (match /([a-z]+)/g)))
``````

### String operations

``````
;; todo
``````

### Mapping, filtering and reducing

``````
(map car (list
(cons "a" 2)
(cons "b" 3)))

(filter odd (list 1 2 3 4 5))

(filter (lambda (x)
(== (% x 2) 0))
(list 1 2 3 4 5))

(define (reverse list)
(reduce (lambda (list x) (cons x list)) list nil))

(reverse '(1 2 3 4))

(define (sum . list) (reduce (lambda (a b) (+ a b)) list))
;; or
(define (sum . list) (reduce + list))

(print (sum 1 2 3 4 5))
``````

### Auto resolving promises

``````
(let* ((res (fetch "https://terminal.jcubic.pl"))
(text ((. res "text"))))
(. ((. text "match") "<title>([^<]+)") 1))
``````

### Currying

``````
(define (add a b) (+ a b))
``````

### Working with arrays

You can modify array with `set!` function and to get the value of the array you can use `.` dot function.

``````
(let ((arr (list->array '(1 2 3 4))))
(set! (. x 1) 10)
(print (array->list arr)))

(let* ((div ((. document "querySelectorAll") ".terminal .cmd-prompt"))
(len (. div "length"))
(i 0))
(while (< i len)
(print (. (. div i) "innerHTML"))
(++ i)))
``````

this equivalent of JavaScript code:

``````
var div = document.querySelectorAll(".terminal .cmd-prompt");
var len = div.length;
var i = 0;
while (i < len) {
console.log(div[i].innerHTML);
++i;
}
``````

### Stdin and stdout

If you're using `print` function to display values or using `read` to get values from users, you can provide your own handlers in environment, jQuery Terminal based implementation look like this:

By default stdout prints to console and stdin use browser `prompt` function.

``````
var env = lips.env.inherit('name', {
stdout: {
write: function(...args) {
args.forEach((arg) => {
term.echo(arg, {keepWords: true});
});
}
},
stdin: {
return new Promise(function(resolve) {
resolve(command);
});
});
}
}
});
``````

### Math and boolean operators (functions and macros)

`< > => <= 1+ 1- ++ -- + - * / % and or not`

### Bit operation

`| & ~ << >>`

### Extending LIPS

to create new function from JavaScript you can use:

``````
env.set('greeter', function(user) {
return "hello " + user;
});
``````

then you can use it in LIPS:

``````
(greeter "john")
``````

To define a macro in javascript you can use Macro constructor that accept single function argument, that should return lisp code (instance of Pair).

``````
var {Macro, Pair, Symbol, nil} = lips;

env.set('quote-car', new Macro('quote-car', function(code) {
return Pair.fromArray([new Symbol('quote'), code.car.car]);
}));
``````

and you can execute this macro in LIPS:

``````
(quote-car (foo bar baz))
``````

it will return first symbol and not execute it as function foo.

you can also use eval here to execute code

``````
env.set('async', new Macro('async', function(code, {dynamic_scope, error}) {
var args = {error, env: this};
if (dynamic_scope) {
args.dynamic_scope = this;
}
return new Promise(function(resolve) {
setTimeout(function() {
resolve(evaluate(code.car, args));
}, 0);
});
}));
``````

This function will invoke code in next iteration of event loop

if you want to create macro like quasiquote, the returned code need to be wrapped with function quote

When creating macros in JavaScript you can use helper `Pair.fromArray()` and `code.toArray()`.