- If the two values are `vec`s, `true` is returned if each of their `number` components is equal to each other using the rules above.
- Likewise with `rgba`s.
- All other types of values use _reference_ equality - `true` is returned only if `a` and `b` are located in the same place in memory.
This more or less means that the values are considered equal if they are produced by the same call to a system function, in time.
`<>` returns `(not (= a b))`.
```haku
(<
(a *)
(b *)
boolean)
(<=
(a *)
(b *)
boolean)
(>
(a *)
(b *)
boolean)
(>=
(a *)
(b *)
boolean)
```
`<` returns `true` if `a` is less than `b`, and `<=` returns `true` if `a` is less than _or_ equal to `b`.
Order is only well-defined for numbers.
Other types may assume an arbitrary but consistent ordering - `()` may be less than `true`, or it may not be less than `true`, but this will not change between executions of the program.
`(> a b)` is the same as `(< b a)`.
`(>= a b)` is the same as `(<= b a)`.
---
Note that `and` and `or` are currently missing from this list.
You can implement them using regular functions as a replacement.
```haku
(def and
(fn (a b)
(if a (if b true false) false)))
(def or
(fn (a b)
(if a true (if b true false))))
```
## Vectors
```haku
(vec
vec)
(vec
(x number)
vec)
(vec
(x number)
(y number)
vec)
(vec
(x number)
(y number)
(z number)
vec)
(vec
(x number)
(y number)
(z number)
(w number)
vec)
```
Creates a new `vec` from zero to four number values.
A `vec` always has four dimensions.
If any of the arguments are omitted, its corresponding dimension is initialized to zero.
```haku
(.x
(v vec)
number)
(.y
(v vec)
number)
(.z
(v vec)
number)
(.w
(v vec)
number)
```
`.x`, `.y`, `.z`, and `.w` extract the individual components of a `vec`.
---
Note that mathematical operations are currently not defined for vectors.
You may define your own vector operations like so:
```haku
(def +v ; Vector addition
(fn (a b)
(vec
(+ (.x a) (.x b))
(+ (.y a) (.y b))
(+ (.z a) (.z b))
(+ (.w a) (.w b)))))
; Likewise for subtraction, multiplication, and division.
```
Note that haku-defined vector operations like these are more costly the more components they operate on.
Therefore, it's recommended to only define them for two dimensions, unless you really need more.
```haku
(def +v2 ; 2D vector addition
(fn (a b)
(vec
(+ (.x a) (.x b))
(+ (.y a) (.y b)))))
```
## Colors
```haku
(rgba
(r number)
(g number)
(b number)
(a number)
rgba)
```
Creates a new `rgba` with the given color channels.
Note that unlike `vec`, all color channels have to be provided to form an `rgba`.
```haku
(.r
(color rgba)
number)
(.g
(color rgba)
number)
(.b
(color rgba)
number)
(.a
(color rgba)
number)
```
`.r`, `.g`, `.b`, and `.a` extract color channels out of an `rgba`.
---
haku uses RGBA values in a normalized `0` to `1` range rather than `0` to `255`, which may be unfamiliar if you're coming from other image editing software.
This is because it's easier to do math on normalized colors.
For example, consider multiplicatively blending two colors.
```haku
; This is how you can multiply two colors together.
(def *rgba
(fn (a b)
(rgba
(* (.r a) (.r b))
(* (.g a) (.g b))
(* (.b a) (.b b))
(* (.a a) (.a b)))))
```
If haku represented colors using an 8-bit `0` to `255` range instead, to multiply two colors together, you would have to divide them by `255` to get them back into the correct range.
```haku
; NOTE: This example does NOT work correctly.
(def *rgba
(fn (a b)
(rgba
(/ (* (.r a) (.r b)) 255)
(/ (* (.g a) (.g b)) 255)
(/ (* (.b a) (.b b)) 255)
(/ (* (.a a) (.a b)) 255))))
```
Note that haku does not clamp colors to the `0` to `1` range.
It is perfectly valid to have a color that is out of range or even `NaN`, but when drawing scribbles:
- `∞` is clamped back to `1`.
- `-∞` is clamped back to `0`.
- any scribble with a `NaN` color is ignored.
Note that just like vectors, arithmetic operations on colors are currently not defined.
Before scribbles are drawn to the wall, colors are converted to 8-bit integers for more efficient rasterization and storage.
This means some loss of precision will happen, which may cause issues with brushes like this one:
```haku
(stroke
128
(rgba 0 0 0 0.1)
(vec))
```
If you try to to use this brush to fill up a single spot with black, you will notice that despite all the math suggesting so, the color will end up gray instead.
## Data structures
```haku
(list
(... *)
list)
```
`list` is used to construct a new list.
Currently, lists do not have any operations defined on them.
However, lists made up solely of scribbles are scribbles themselves, which allows for combining scribbles together.
## Shapes
```haku
(to-shape
(value *)
(() shape))
```
Converts the given value to a shape.
- For `shape`, clones the shape that was passed in.
- For `vec`, returns a point `shape`.
- For anything else, returns `()`.
```haku
(line
(start vec)
(end vec)
shape)
```
Creates a line segment shape with the provided `start` and `end` points.
```haku
(rect
(position vec)
(size vec)
shape)
(rect
(x number)
(y number)
(width number)
(height number)
shape)
```
Creates a rectangle shape with its top-left corner at `position`, with a given `size` stretching from the top-left corner.
The alternative 4-argument version takes in the rectangle's X/Y coordinates, width, and height as separate arguments instead of aggregating them into a `vec`.
```haku
(circle
(center vec)
(radius number)
shape)
(circle
(x number)
(y number)
(radius number)
shape)
```
Creates a circle shape, with its center at `center`, with the provided radius.
The alternative 3-argument version takes in the circle's center X/Y coordinates as separate arguments instead of aggregating them into a `vec`.
## Scribbles
```haku
(stroke
(thickness number)
(color rgba)
(shape shape-like)
scribble)
```
Creates a stroke scribble, which outlines the provided shape with a stroke of the given thickness and color.
Point shapes are drawn as squares, and `line` shapes have square caps at the line's endpoints.
```haku
(fill
(color rgba)
(shape shape-like)
scribble)
```
Creates a fill scribble, which fills in the entire area of the provided shape with a solid color.
Since this requires the shape to have a surface area, this does not do anything when point and `line` shapes are passed in.