Scope

A scope is akin to a dictionary, where values are associated with keys.

Definition

Scopes are defined using curly brackets {}, as shown below:

myCoolScope = {
  place = 'here'
  when = 'now'
}

Scopes store entries in alphabetical order, a characteristic that becomes apparent when mapping over a scope.

Access

There are three ways you can directly access entries inside a scope.

Dot syntax

myCoolScope.place  # output: 'here'

Get syntax

# assuming prop = 'place'
myCoolScope(prop)  # output: 'here'

In both methods, if the property is not present, null is returned. If the outer scope is not found, an error is raised.

Optional chaining syntax

Use the question-dot ?. operator to safely chain potentially non-existent outer scopes:

nonExisting?.prop  # returns null

The optional chaining syntax does not raise an error when the outer scope is null.

Operations

  • == equal
  • != not equal
  • + addition (merge effect)
  • - subtraction (difference effect)
  • & logical AND
  • | logical OR

logical AND/OR evaluate empty scopes as false, otherwise true

Scope addition (merge)

The second operand acts as a patch for the first operand:

x = { a = 1, b = 3 }
y = { b = 2 }

x + y  # results in { a = 1, b = 2 }
y + x  # results in { a = 1, b = 3 }

values from the second operand replace those from the first

Scope subtraction (difference)

Subtraction removes elements from the first operand that are identical to those in the second operand:

x = { a = 1, b = 3 }
y = { a = 1 }

x - y  # results in { b = 3 }

only values that are exactly identical are removed

Scoped Blocks

Scoped Blocks in FatScript allow for executing statements within the context of a specific scope:

object.{
  # Statements executed in the context of 'object'
}

Here, object is the target scope. Within the block, you can directly access and modify object's properties.

Features

  • Isolation: entries declared within a Scoped Block are local to that scope and do not affect the outer scope
  • Outer Scope Access: Scoped Blocks can access entries from the outer scope

Example

x = {}

x.{
  a = 5      # 'a' is now a property of 'x'
  b = a + 3  # 'b' is also a property of 'x'
}

Scope interactions

FatScript uses sophisticated mechanisms for managing variables across different scopes, leveraging concepts of lexical scoping and shadowing to provide powerful programming capabilities. This section explores these mechanisms, including assignment nuances, increment/decrement behaviors, and the innovative use of the += operator for boolean toggling.

Assignment

The assignment operator (=) copies values from outer scopes into current scope, defining a new value:

~ n = 1
x = {}
x.{ ~ n = n }  # now x.n == 1, and x.n is independent from root.n
x.{ c = n }    # has similar effect, however 'c' is immutable

the same concept applies to code running on a method scope

Caveat

Using ~ n = n + 1 inside a block or method adds a new 'n' in the current scope, initialized with the value of n + 1 from the nearest enclosing scope, without altering the outer n.

Incrementing and decrementing

Increment (+=) and decrement (-=) operations, interact with variable scoping in a different way. These operations search for the nearest instance of a variable, starting from the current scope and moving outward recursively, and then modify that instance directly.

~ outerN = 1
fn = -> {
  outerN += 1  # targets and increments 'outerN' in the outer scope
}

Auto-initialization with +=

FatScript also provides a special behavior regarding increment operator (+=). If the entry doesn't exist, increment works as a regular assignment as if you had written the following for n += 1:

n == Void ? n = 1 : n += 1

The auto-initialization feature can be particularly useful when used in combination with dynamic entries for dynamic programming.

this feature is exclusively available for increment operator, decrement can't initialize non-existent values

Boolean toggling with +=

Generally, booleans don't allow addition operations. FatScript, however, extends the += operator's functionality to boolean types, allowing for an intuitive toggle mechanism within inner scopes.

The expression flag += !flag effectively toggles the boolean value, even when flag is defined in an outer scope.

in the particular case of booleans, the only distinction between = and += is scoping

Other compound assignment operators

Similarly, other compound assignment operations such as *=, /=, %=, and **= are supported by numeric types and respect the same scoping rules that apply to increment and decrement operations.

See also

results matching ""

    No results matching ""