Basic Syntax
Sema is a Lisp, meaning it has a very simple and uniform syntax based on S-expressions (symbolic expressions). If you have used Scheme or Clojure, you will feel right at home. If you are new to Lisp, this guide will introduce you to the core rules of the syntax.
1. S-Expressions and Prefix Notation
All code and data in Sema are represented as S-expressions. An expression is either a single value (like a number or string) or a list of expressions enclosed in parentheses.
In Sema, operators and functions always come first. This is called prefix notation:
(+ 1 2) ; => 3
(* 10 (+ 2 3)) ; => 50 (10 * (2 + 3))Here is how to read (+ 1 2):
- The opening parenthesis
(starts a list. - The first element
+is the function or operator to call. - The remaining elements
1and2are the arguments passed to it. - The closing parenthesis
)ends the call.
2. Comments
Comments in Sema start with a semicolon ; and run to the end of the line:
; This is a single-line comment
(+ 1 2) ; This is an inline commentBy convention:
- A single semicolon
;is used for inline comments. - A double semicolon
;;is used for comments on their own line.
3. Basic Types
Sema supports standard scalar types:
- Numbers: Integers (
42) and floats (3.14). - Strings: Double-quoted text (
"hello world"). - F-Strings: Interpolated strings prefixed with
f(f"Hello ${name}"). - Booleans:
#t(true) and#f(false). - Nil: The null/empty value (
nil). - Keywords: Colon-prefixed identifiers (
:name,:status) commonly used as map keys or identifiers.
4. Variable Bindings
There are two primary ways to declare variables: globally and locally.
Global Bindings (define)
Use define to bind a name to a value globally:
(define pi 3.14159)
(define radius 10)
(* pi (* radius radius)) ; => 314.159Local Bindings (let)
Use let to bind variables within a specific scope. The syntax uses a list of (variable value) pairs:
(let ((width 10)
(height 5))
(* width height)) ; => 50
;; 'width' and 'height' are not visible here5. Core Collections
Sema supports three main collection types: Lists, Vectors, and Maps.
Lists
Lists are ordered, linked collections. Since parentheses denote code execution, you create a literal list using the list function or by quoting it with ':
(list 1 2 3) ; => (1 2 3)
'(1 2 3) ; => (1 2 3)Vectors
Vectors are array-like collections with fast index-based access. They are defined using square brackets []:
(define my-vector [10 20 30])
(nth my-vector 1) ; => 20 (0-indexed)Maps
Maps are key-value structures. They are defined using curly braces {} and typically use keywords as keys:
(define user {:name "Ada" :age 36})Keyword Accessors
In Sema, keywords act as accessor functions. You can look up a value in a map by calling the keyword with the map as an argument:
(:name user) ; => "Ada"
(:age user) ; => 36Next Steps
Now that you know how to represent data and variables, let's learn how to organize code into functions: