Skip to content

Types and Values

lash is dynamically typed. Variables do not carry type annotations; their type is determined at runtime by the value they hold.

TypeExample
stringlet greeting = "hello"
intlet count = 42
floatlet ratio = 3.14
boollet verbose = true
listlet files = ["a.txt", "b.txt"]
objectlet config = { editor: "vim", tabs: 4 }
semverlet ver = semver("1.2.3")

Every type defines .min and .max properties:

Type.min.max
int-92233720368547758089223372036854775807
float-1.7976931348623157e+3081.7976931348623157e+308
string"" (empty string)undefined
boolfalsetrue
list[] (empty list)undefined
object{} (empty object)undefined

The semver() constructor parses a semantic version string and returns a tagged object:

let ver = semver("1.2.3-beta+build.42")
FieldTypeDescription
majorintMajor version number
minorintMinor version number
patchintPatch version number
prereleasestringPre-release identifier (may be "")
buildstringBuild metadata (may be "")

The object carries a hidden __type entry (value "semver") excluded from keys() output. Comparison operators follow semver 2.0 precedence rules. String representation: MAJOR.MINOR.PATCH[-PRERELEASE][+BUILD].

These properties are available on all value types:

  • .isSuccess — Returns true if the value is “successful”. For command capture results, checks exit code == 0. For other values, returns truthiness.
  • .isFailure — The inverse of .isSuccess.
let items = [1, 2, 3]
let mixed = ["hello", 42, true]

Lists can hold values of any type, including mixed types.

let config = { host: "localhost", port: 8080 }

Bracket syntax and dot syntax are both supported:

config["host"] # bracket access
config.host # dot access (when key is a valid identifier)

Dot access on objects resolves the key name as a property lookup. It must not collide with built-in method names — use bracket syntax when a key matches a method name.

let nums = 1..10 # produces [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Ranges produce integer lists and are usable anywhere a list is expected.