Schm-tutorial

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-range

(for i (range 1 6) (
    (print i)
  )
)

Result:

> 1
> 2
> 3
> 4
> 5
> 6

comments

; comment

defining-functions

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"

if-statement

(print
  (if (> 4 6)
    (string "first")
    (string "second")
  )
)

recursive-functions

(fn f (i) (
    (if (> i 0)
      ( (print i)
        (f (-- i))
      )
      (print (string "end"))
    )
  )
)
(f 6)
> 6
> 5
> 4
> 3
> 2
> 1
> "end"

lists-and-arrays

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

arrays-update-and-access

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-operations

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

map-iter

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)

switch-structure

(define a 30)
(print
  (switch (+ a 10)
    (30 (s "hello"))
    (40 (s "morning"))
    (50 (s "afternoon"))
    (_  (s "noon")) ; default
  )
)

Result:

> "morning"

predefined-functions

(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



try-the-playground

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.


extending-schm

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")
  )

extended-playground

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)
      )
    )
  )
)

load-sprite-and-rand

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.


init-and-animate-loop

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