Entries
Entries are key-value pairs that exist in the scope where they are declared.
Naming
Entry names (keys) cannot start with an uppercase letter, which is the distinction compared to types. Identifiers are case-sensitive, so "frenchfries" and "frenchFries" would be considered different entries.
The recommended convention is to use camelCase
for entries.
you may use an arbitrary name as key by using dynamic nomination
Declaration and assignment
In FatScript, you can declare entries by simply assigning a value:
isOnline: Boolean = true
age: Number = 25
name: Text = 'John'
Types can also be inferred from assignment:
isOnline = true # Boolean
age = 25 # Number
name = 'John' # Text
Immutable entries
When an entry is declared in FatScript, it is immutable by default. This means that once you assign a value to it, you can't change it:
fruit = 'banana'
fruit = 'apple' # raises an AssignError because fruit is immutable
Immutable entries are useful when you want to ensure that a value remains constant throughout your program's execution.
Exception to the rule
It's worth mentioning that immutability only applies to the entry itself, but not to its content when it comes to a scope.
In FatScript, a paradox arises because all of the following statements are true:
- An immutable entry cannot be changed after being defined.
- A scope can always accept new entries.
- An entry can store a scope.
See:
s = { a = 1, b = 2 }
s.c = 3 # even though s is immutable it accepts the new value of c
s # now { a = 1, b = 2, c = 3 }
this is not a bug, it is a feature
This is because scopes are passed by reference and can always be "mutated" by appending new entries, even if the entry holding the scope is immutable. So, in this case, it is the same, but it's not quite the same.
On the other hand, lists declared as immutable behave more consistently with the rule, as new entries cannot be appended to them.
Mutable entries
Yes, you can declare mutable entries, also known as variables. To declare a mutable entry, use the tilde ~
character:
~ fruit = 'banana'
fruit = 'apple' # ok
Note that even a mutable entry cannot immediately change its type, unless it's erased from the scope. To erase an entry, assign null
to it, and then redeclare it with a new type. Changing types is discouraged by the syntax and not recommended, but it is possible:
~ color = 32 # creates color as a mutable Number entry
color = 'blue' # raises a TypeError because color is a Number
color = null # entry is erased
color = 'blue' # redefines color with a different type (Text)
you have to declare the entry as mutable again using tilde
~
when redefining after erasure if you want the next value to be mutable
Dynamic entries
You can create entries with dynamic names using square brackets [ ref ]
:
ref = 'popCorn' # text will be the name of the entry
options = { [ ref ] = 'is tasty' }
options.[ref] # dynamic syntax: yields 'is tasty', with read and write access
options(ref) # get syntax: yields 'is tasty', but value is read-only
options.popCorn # dot syntax: yields 'is tasty', but has to follow naming rules
all dynamic declarations are mutable entries
This feature allows to dynamically define the names inside a scope and create entries with names that otherwise would not be accepted by FatScript.
Dynamic entries can also use numeric references, however the reference is converted into text automatically, e.g.:
[ 5 ] = 'text stored in entry 5'
$self.['5'] # yields 'text stored in entry 5'
$self.[5] # yields 'text stored in entry 5'
in a different context, not followed by assignment
=
or preceded by dot notation.
, dynamic syntax will be interpreted as a list declaration
Special entries
Entries with names starting with underscore _
are completely free and dynamic, they don't require tilde ~
and can also change type without the need of erasure, like variables in JavaScript or Python.
Destructuring assignment
You can copy values of a scope into another scope like so:
_ <- fat.math
distance = (position: Scope): Number -> {
{ x, y } = position # destructuring assignment into method scope
sqrt(x ** 2 + y ** 2) # calculates distance between origin and (x, y)
}
distance({ x = 3, y = 5 }) # 5.83095189485
You can also use destructuring assignment to expose a certain method or property from a named import:
console <- fat.console
{ log } = console
log('Hello World')
using this syntax with imports, you can choose to bring to the current scope only the elements of the library that you are interested in using, thus avoiding polluting the namespace with names that would otherwise have no use or could clash with those of your own writing
JSON-like syntax
FatScript also supports JSON-like syntax for declaring entries:
"nothing": null, # Void entry - distinct behavior, see bellow
"isOnline": true, # Boolean entry
"age": 25, # Number entry
"name": "John", # Text entry
"tags": [ "a", "b" ], # List entry
"options": { "prop": "other" } # Scope entry
However it might appear that declaring "nothing" creates a "nothing" value of null
, it's important to note that the "resulting entry" doesn't actually exist in the scope. When you try to access that "nothing", FatScript does return null
, but if you attempt to map over the scope, the name of that entry will be missing since it was never truly created.
It's important to note that JSON-like declarations always create immutable entries, so you can't prepend them with the tilde ~
character to make them mutable.