NOTE: Documentation for Beta version can be found at LIPS wiki.
(define x 10)
(define square (lambda (x) (* x x)))
(define (square x) (* x x))
(define-macro (foo x) `(1 2 ,@(car x) 3 4))
lips have no problems in evaluating factorial of thousand, and it's fast.
(define (! n) (reduce * (map 1+ (range n))))
(print (! 1000))
(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))
(print (cadaddr lst)))
all functions that match this regex `c[ad]{1,5}r` are defined.
(let ((l '((foo . "lorem") (bar "ipsum"))))
(set-cdr! (assoc l 'foo) "hello")
(set-cdr! (assoc l 'bar) "world")
(print l))
(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)
(print "newer printed"))
(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 (read "(print \"hello\")"))
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)))
(eval (read))
then type S-Expression like (print 10)
. If function return Promise
the execution is paused and restored when Promise is resolved
((. window "alert") "hello")
((. 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)))
;; todo
(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))
(let* ((res (fetch "https://terminal.jcubic.pl"))
(text ((. res "text"))))
(. ((. text "match") "<title>([^<]+)") 1))
(define (add a b) (+ a b))
(define add10 (curry add 10))
(print (add10 20))
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;
}
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: {
read: function() {
return new Promise(function(resolve) {
term.read('', function(command) {
resolve(command);
});
});
}
}
});
< > => >= 1+ 1- ++ -- + - * / % and or not
| & ~ << >>
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()
.