Every value in SCUA is one of a handful of kinds. This page names them, shows how to ask a value what it is, and covers the two things newcomers trip on most: integers and floats are separate, and only two values count as false.
You write SCUA without type annotations and it behaves like a dynamic language. The kinds below are what values are at runtime, whether or not you annotate anything. Annotations add compile-time checks on top; see Records and gradual types.
#The kinds
There are eight value kinds you'll meet right away. The
type() builtin returns the kind of a value as a string:
print(type(nil))
print(type(true))
print(type(42))
print(type(3.14))
print(type("hi"))
print(type([1, 2, 3]))
print(type({ x = 1 }))
print(type(fn(n) return n end))
Run it:
$ scua kinds.scua
nil
bool
int
float
string
array
table
fn
So the kinds are nil, bool,
int, float, string,
array, table, and fn. A few
notes:
- nil is the absence of a value. A missing table
field reads as
nil, and a function with noreturngives backnil. - bool is
trueorfalse. - int and float are both 64-bit numbers, and they are not the same kind. More on that below.
- string is text. See Strings and interpolation.
- array is an ordered, 0-based sequence written with square brackets. table is a string-keyed map written with braces. Both are covered in Collections.
- fn is a function value. See Functions and closures.
There are a few more kinds you'll meet later:
decimal for exact base-10 numbers like money and
big for huge-magnitude idle-game numbers (both on the
Numbers page), vectors, matrices, and
quaternions for math (see Math), and the
Ok/Error values that represent results of
operations that can fail (see Errors and
faults).
#Numbers in depth
int and float are different kinds and never
mix silently — / always gives a float, //
stays an int — and SCUA adds two specialist number kinds:
decimal (exact base-10, for money) and
big (unbounded magnitude, for idle games).
How each is stored, the rules for mixing them, and when to use which are
their own page: Numbers.
#Truthiness
In a condition, only nil and false are
false. Everything else is true, including 0, the empty
string, and an empty array.
fn check(v)
if v then return "truthy" else return "falsy" end
end
print(check(nil))
print(check(false))
print(check(0))
print(check(""))
print(check([]))
Run it:
$ scua truthy.scua
falsy
falsy
truthy
truthy
truthy
If you're used to languages where 0 or an empty
collection is false, watch this one. To test for an empty array, compare
its length: if len(xs) == 0 then ....
#Equality
== compares values, and != is its negation.
Numbers compare by value across int and float, so 1 == 1.0
is true. Strings compare by their contents.
print(1 == 1.0)
print("ed" == "ed")
print("ed" == "Ed")
print(1 == "1")
print([1, 2] == [1, 2])
let a = [1, 2]
let b = a
print(a == b)
print(3 != 4)
Run it:
$ scua equality.scua
true
true
false
false
true
true
true
Two things to know:
- Values of different kinds are never equal.
1 == "1"is false; the int and the string are not compared after any conversion. (Akeyis its own kind too, so$"hp" == "hp"is false.) - Arrays, tables, and records compare by value —
their contents, compared element by element (and recursively for nested
ones). Two separately built arrays with the same elements are
equal:
[1, 2] == [1, 2]istrue, and{ x = 1 } == { x = 1 }istrue. Two names for the same value are equal too. (Comparing two different kinds, or two records with different fields, isfalse.)