Skip to content

Latest commit

 

History

History
135 lines (87 loc) · 3.28 KB

INTRODUCTION.md

File metadata and controls

135 lines (87 loc) · 3.28 KB

Brief Yal Introduction

Yal is a typical toy lisp with support for numbers, strings, characters, hashes and structures.

Primitive Types

Primitive types work as you would expect:

  • Numbers can be written as integers in decimal, binary, or hex:
    • (print 3)
    • (print 0xff)
    • (print 0b1010)
  • Floating point numbers are also supported:
    • (print 3.4)
  • Strings are just encoded literally, and escaped characters are honored:
    • (print "Hello, world\n")
  • Characters are written with a #\ prefix:
    • (print #\*)
  • Lists are written using parenthesis to group them:
    • (print (list 1 2 3))

Other Types

We support hashes, which are key/value pairs, written between { and } pairs:

(print { name "Steve" age (- 2022 1976) } )

Functions exist for getting/setting fields by name, and for iterating over the keys, values, or key/value pairs, contained in a given hash.

We also support structures, which are syntactical sugar for hashes, along with the autogeneration of some simple helper methods.

To define a "person" with three fields you'd write:

(struct person name age address)

Once this struct has been defined it can be populated via the constructor:

(person "Steve" "18" "123 Fake Street")

Values which are not supplied will default to nil:

(person "Steve" "18")

The structure's fields can be accessed, and updated via generated methods, named after the type of the object, and the field involved:

; Set the variable "me" to be a new instance of the person-structure.
(set! me (person "Steve" "18" "123 Fake Street"))

; Change the adddress
(person.address me "999 Fake Lane")

; Confirm it worked
(print (person.address me))

Variables

To set the contents of a variable use set! which we saw above:

(set! foo "bar")

To start a new scope, with local variables, use let*:

(let* (foo "bar"
       baz  "bart")
  (print "foo is %s" foo)
  (print "baz is %s" baz)
  ;...
)

Inside a let* block, or a function, you'll only set the values of local variables. If you wish to affect something globally use the three-argument form of set!:

(let* (foo "bar"
       baz  "bart")
  (set! global "updated" true)
  ;..
)

Functions

To define a function use set! with fn*:

(set! fact (fn* (n)
  (if (<= n 1)
    1
      (* n (fact (- n 1))))))

Optionally you may write some help/usage information in your definition:

(def! gcd (fn* (m n)
  "Return the greatest common divisor between the two arguments."
  (if (= (% m n) 0) n (gcd n (% m n)))))

Help information can be retrieved at runtime, for usage:

(print (help print))

To define a macro use defmacro!:

(defmacro! debug (fn* (x) `(print "Variable '%s' has value %s" '~x ~x)))

You might use this macro like so:

(set! foo "steve")
(debug foo)

That concludes the brief overview, note that lambda can be used as a synonym for fn*, and other synonyms exist. In the interests of simplicity they're not covered here.

See Also

  • README.md
    • More details of the project.
  • PRIMITIVES.md
    • The list of built-in functions, whether implemented in Golang or YAL.