Schm provides a scheme-like minimalist-script syntax with no-deps, and no c-stubs, written in ocaml, that can be embed into a web-page, with javascript and html5.
Defining vars:
(define a 20) (define b 30)
Basic operations:
(define c (+ a b)) (print c)
(for i (range 1 6) ( (print i) ) )
Result:
> 1 > 2 > 3 > 4 > 5 > 6
; comment
Defining a function called f, which concatenates 2 strings together, and print it.
(fn f (s) (print (^ (string "hello:") s))) (f (string "a")) (f (string "b")) (f (string "c"))
Result:
> "hello:a" > "hello:b" > "hello:c"
(print (if (> 4 6) (string "first") (string "second") ) )
(fn f (i) ( (if (> i 0) ( (print i) (f (-- i)) ) (print (string "end")) ) ) ) (f 6)
> 6 > 5 > 4 > 3 > 2 > 1 > "end"
List:
(define lst (1 2 3 4 5))
(print lst)
> 1, 2, 3, 4, 5
Array:
(define arr (# 1 2 3 4 5)) (print arr)
> 1; 2; 3; 4; 5
Array update:
(define arr (# 1 2 3 4 5)) (arrset arr 3 40) (print arr)
> 1; 2; 3; 40; 5
Array cell access:
(define arr (# 1 2 3 4 5)) (print (arrget arr 2))
> 3
List head and tail:
(define lst (1 2 3 4 5))
(print (tail lst))
(print (head lst))
> 2, 3, 4, 5 > 1
List length:
(define lst (1 2 3 4 5))
(print (len lst))
> 5
List cons:
(define lst (1 2 3 4 5 6))
(print (cons 0 lst))
> 0, 1, 2, 3, 4, 5, 6
The iter key-word, can be used for both iter and map, on lists and arrays.
(fn f (s) (strlen (^ (string "s:") s))) (define lst (iter f ( (string "hello") (string "world") (string "!") ) ) ) (iter print lst)
(define a 30) (print (switch (+ a 10) (30 (s "hello")) (40 (s "morning")) (50 (s "afternoon")) (_ (s "noon")) ; default ) )
Result:
> "morning"
(strlen (string "hello")) ; string-length (^ (string "hello") (string "-world")) ; cat strings (^ (string "hi") (string "-wrl") (string "!")) (^ ((string "hi") (string "-wrl") (string "!"))) (^ (# (string "hi") (string "-wrl") (string "!"))) (print (cat (s "hi") (s "-wrl"))) ; alias: cat, s (define s1 (string "a b c")) (define s2 (string " d e f")) (print (substr (^ s1 s2) 2 5)) ; substr: "b c d" (print 2.3) ; floats (print (+. 2.2 1.6)) ; prints: 3.8 ; float-operations: +. -. *. /. ; sqrt, cos, sin (print (strmake 3 (char "$"))) ; "$$$" (c "$") ; char-alias (len (1 2 3 4 5)) (len (# 1 2 3 4 5)) ; converting to/from array (print (to_array (1 2 3 4 5))) (print (of_array (# 1 2 3 4 5))) ; same than (range), but returns an array, in stead of a list (print (#range 1 6)) ; accessing the n-th element of a list (define lst (1 2 3 4 5)) (print (lstget lst 3)) ; returns 4 ; boolean types: ; #t / #f ; functions to check the type of an element: ; is_int, is_float, ; is_str, is_chr, ; is_lst, is_arr, ; is_bool, is_unit, ; is_fun, is_err, ; objects, list of pairs: (field-name, value) (define e (obj ( (c (20 20)) (r 12) ) ) ) (print (objget e r)) ; 12 (objset e r 16) ; update a field (objadd e v 20) ; add a new field (objrem e c) ; remove a field (print (objhas e r)) ; tells if the obj has this field ; mutable elements (define r (ref 3)) (print (refget r)) ; prints 3 (refset r 4) (print (refget r)) ; prints 4
You can try it in the interactive playground.
It has been transpiled to javascript, and embed into an html web-page, so that you can try it without compiling and installing anything, just from your web-browser.
Schm can easily be extended with new functions, here is an example:
let f_draw_rect = "draw_rect", Ari4 (function (v1, v2, v3, v4) -> match (v1, v2, v3, v4) with | Int x, Int y, Int w, Int h -> begin let color = "rgb(220, 220, 240)" in Canvas.fillStyle ctx color; Canvas.fillRect ctx x y w h; end; (Unit) | _ -> Err("invalid-arg:draw_rect") )
You can try this extended playground (schm-demo), which has been extended with 3 new functions:
(draw_rect x y w h)
(draw_circ cx cy r)
(draw_text x y (s "hello"))
You can try these examples:
(for i (range 0 3) ( (define x (* i 40)) (draw_rect (+ x 80) 60 20 20) (draw_circ (+ x 90) 100 10) (print i x) ) ) (draw_text 80 140 (s "hello"))
And:
(for i (range 0 4) ( (for j (range 0 2) ( (define x (* i 40)) (define y (* j 40)) (draw_circ (+ x 90) (+ y 100) 10) ) ) ) )
We can also extend our playground with
random-numbers (rand_int n), you can try this expression:
(for i (range 1 6)
(draw_circ
(rand_int 460)
(rand_int 300)
(+ 3 (rand_int 16)))
)
You can also try to draw sprites with
the expression (draw_sprite x y (s "sprite-name")):
(define sp (# (s "abs-12a") (s "abs-12b") (s "abs-12c") (s "abs-12d") (s "abs-12e") (s "abs-12f") (s "abs-12g") (s "abs-12h") (s "abs-12i") (s "abs-12j") ) ) (for _sp (sp) ( (draw_sprite (rand_int 460) (rand_int 270) _sp) ) )
The sp-define above, contains the exhaustive list of the
available sprites in this demo.
You can display each of them near each-other with:
(for i (range 0 (- (arrlen sp) 1)) ( (define x (* i 35)) (draw_sprite (+ x 25) (60) (arrget sp i)) ) )
And with the same sp-define, you can also try:
(for i (range 1 6) (
(draw_sprite
(rand_int 460)
(rand_int 270)
(arrget sp (rand_int (arrlen sp))))
)
)
Which demonstrate, how to select a random element, from an array.
Another extended playground with 2 textareas.
The first one is for the init() stage of a game or a demo, and the
second one which will be executed at each step of the animate-loop.
You can try this small example:
(define r (ref 10))
(refset r (+ 20 (refget r))) (refset r (if (> (refget r) 460) (0) (refget r))) (draw_sprite (refget r) 100 (s "abs-12i"))
© 2025 fccm — license: cc-by-sa_2.5