> For the complete documentation index, see [llms.txt](https://craftscript.kenzie.mx/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://craftscript.kenzie.mx/tutorials/environments-and-contexts.md).

# Environments and Contexts

Introduction

An **environment** is the space that code runs in.

This space contains all of the functions, scripts, variables, libraries and other resources that the code can interact with.

<details>

<summary>Graphic</summary>

![](/files/NCEgThMUf602SgAsA3fY)

This is a depiction of the environment.

Any process is allowed to access resources from a box it is inside, but not those from another box.

E.g. a function in `my` script cannot access variables from something in `other` script.

</details>

The **context** is a map of where we are in the environment.

It contains information such as:

* The variables available here
* The current line of the script (for printing an error)
* The current script
* Where this script started from
* A link to the script manager

## Environment Sanitation

CraftScript attempts to keep the environment as clean as possible, in order to avoid pollution.

Pollution occurs when data belonging to a process is altered by a different process in an unexpected or unintended way.

<details>

<summary>Example of Pollution</summary>

Imagine a script `my.script`.

{% code title="my.script" lineNumbers="true" %}

```java
number = 10
// wait 5 seconds
if number > 0 /print yes
```

{% endcode %}

Having set `number` to `10` in line 1, we can be certain that `number` is `10` (and so greater than zero) in line 3.

An example of environment pollution would be if another script, `other.script`, changed or deleted the value of the `number` variable between lines 1 and 3, so our if-statement would fail.

</details>

Pollution is unhealthy for development because it can affect how a program will run in a way that a developer cannot expect or account for.

### Variable Locality

The most common offender of environment pollution is through variables.

Variable pollution occurs when two separate domains want to access the same variable at the same time.

<table><thead><tr><th>Process #1</th><th>Process #2</th></tr></thead><tbody><tr><td><pre class="language-log"><code class="lang-log">set number to 10

read number </code></pre></td><td><pre><code>

set number to 5

</code></pre></td></tr></tbody></table>

In the above example, `Process #1` will read the `number` variable, expecting it to be `10` but `Process #2` has polluted it by changing its value to 5 between the initial write and the final read.

If, for example, process 2 comes from a third-party program that the creator of the process 1 program does not know about, the creator of process 1 has no way to anticipate or to prevent this error.

<details>

<summary>Variable Pollution in Browser JavaScript</summary>

Non-modular JavaScript files running in the browser share a global variable context.

This makes it easy to pass data between two scripts, since a variable `foo` can be written to in one script and then read from in another.

However, it also means that one script can unintentionally change or break the variable structure of another, e.g. by overwriting a value.

</details>

CraftScript avoids variable pollution by keeping variables local to their context.

When a script is run it starts with its own variable container. When the script finishes running the container is discarded for the garbage collector to tidy up.

<details>

<summary>Example</summary>

When each of the scripts below is run it will have its own `number` variable.

One script cannot change the other's `number` variable value.

<pre class="language-java" data-title="other.script"><code class="lang-java"><strong>/print {number} // null
</strong>number = 10
/print {number} // 10
</code></pre>

{% code title="my.script" %}

```java
/print {number} // null
number = 5
/print {number} // 5
run other.script
/print {number} // 5
```

{% endcode %}

</details>

The same is also true of functions.

A function inside a script has its own variable container, so it cannot read or write variables outside the function in the rest of the script.

{% hint style="info" %}
Functions need to have their own variable container since they can be run anywhere, including in a different script from where they were created.
{% endhint %}

<details>

<summary>Example</summary>

The function in the script below has its own variable container. Changing the `number` variable inside the function does not affect the `number` variable in the outer script.

{% code title="my.script" %}

```java
number = 10
func = function {
    /print {number} // null
    number = 5
    /print {number} // 5
}
/print {number} // 10
run func
/print {number} // 10
```

{% endcode %}

The function object can be stored and run later or from a different script and will not be affected by changes to the environment.

</details>

## Passing Data

While it is important to keep variable containers separate for environment hygeine, scripts also need a way to share important data between them.

CraftScript has a fairly atypical approach to this, since the standard parameter/argument setup does not exist in the language.

### #1: Initial Variables

When a script or function is run from within another script, variables may be assigned in the `run` statement.

#### Initial Map

This can be done by providing a key<->value map object as data.

```java
greet = function {
    /print hello, {name}
}

run greet [name="Jeremy"]
```

In the above example, a new variable container is allocated for the `greet` function and a `name` variable is set to `Jeremy` before the function is run.

While this allows fairly granular control of what data is passed to the function, it does not indicate to the user that a `name` variable should be passed -- and if it is not, the function would print `hello, null`.

We have two approaches to fixing this.

The simplest is to **require** the user to provide that name variable using a `require` statement.

This makes sure that a `name` variable was provided or, if not, terminates the script.

```java
greet = function {
    require [name]
    /print hello, {name}
}

run greet [name="Jeremy"] // good, we gave it a name
run greet // errors, we forgot our name
```

By terminating the script and printing an error we alert the developer that they haven't met the conditions for this function to run and that they must correct their script in order to use it properly.

However, a developer could still run the function with an explicit `null` name.

```java
greet = function {
    require [name]
    /print hello, {name}
}

run greet [name=null] // uh oh
```

The `require` statement makes sure the `name` variable exists but permits an empty `null` value.

As an alternative, we could simply check that the `name` variable is what we expect it to be.

```java
greet = function {
    if name == null {
        /print hello
    } else {
        /print hello, {name}
    }
}

run greet [name="Jeremy"] // good
run greet [name=null] // good
run greet // good
```

#### Initial List

As the anonymous map syntax is cumbersome a list of objects may also be provided.

```java
greet = function {
    require [name]
    /print hello, {name}
}

run greet ["Jeremy"]
```

This makes use of the `require` statement's second feature: automatic assignment.

The objects passed in the list are **anonymous** variables - they have no name and so cannot be directly referenced in code.

If a `require [x]` statement can find no variable named `x`, it will assign the next anonymous variable to the label `x`.

In the example above, the anonymous variable `"Jeremy"` is being assigned to `name` since no `name` variable exists.

If a single object is provided instead of a list it will be treated as a single-element list.

{% hint style="warning" %}
The initial list is less precise than a map, since the variables must be provided in a specific order to function correctly.
{% endhint %}

### #2: Structured Environments

A structure can be used in the place of a map when running a function or script.

```java
greet = function {
    /print hello, {name}
}

person = struct {
    name = "Jeremy"
}

run greet person
```

Unlike the map, the structure **itself** is used as the variable context.

This means that any changes to variables in the function or script being run will be reflected in the structure.

```java
rename = function {
    name = "Bearimy"
}

person = struct {
    name = "Jeremy"
}

assert person[name] == "Jeremy"
run rename person
assert person[name] == "Bearimy"
```

In the above example the `name` variable in the function directly references the `name` property of `person`. Any changes to one are reflected in the other.

{% hint style="info" %}
Structures have a **fixed** property set.

You cannot assign a new property that was not created to begin with.
{% endhint %}

Since the structure has a fixed set of properties this means the script will have a fixed set of variables.

This can lead to some unexpected behaviour.

```java
rename = function {
    name = "Bearimy"
    number = 10 // we can't set `number`
    assert number == null // the variable does not exist
}

person = struct {
    name = "Jeremy"
}

run rename person
assert person[number] == null // we can't add a new property to a struct
```

{% hint style="danger" %}
Using a structure as an environment for a third-party script or function is not advised, since it cannot assign new variables and will fail silently or unexpectedly.
{% endhint %}

### #3: Global Variables

The global variable library allows us to set variables that are visible and mutable from anywhere in the runtime environment -- including completely unrelated script processes we did not start.

```java
import [global]

greet = function {
    import [global]
    /print hello, {global[name]}
}

global[name="Jeremy"]

run greet
```

The `global` object we import in our function is the same as the global object we imported in our script. Any changes to one are immediately present in the other.

{% hint style="danger" %}
Any script can access the global variable map at any time.

Another script could alter your variable between your write and read, changing its value unexpectedly.
{% endhint %}

As the global variable container is a variable container it can be used as the variable container for a function or script.

```java
import [global]

greet = function {
    /print hello, {name}
    test = 5
}

global[name="Jeremy"]

run greet global
assert global[test] == 5
```

While this is not recommended (given the large risk of variable pollution) it may be useful (and/or necessary) in rare cases.

{% hint style="info" %}
The global variable container has a special safety feature that makes it constant between all programs and background tasks.

Two scripts can be run simultaneously using the global variable container and see each others' changes in real time.
{% endhint %}

### #4: Reflection

The built-in reflection library allows the user to obtain a copy of the current variable container.

This can be used as the container for a function or another script, meaning all variables and changes from one will be seen by the other.

```java
import [reflection]

greet = function {
    /print hello, {name}
    test = 5
}

name="Jeremy"

variables = run reflection[variables]
run greet variables

assert test == 5
```

This is inherently dangerous since it guarantees variable pollution, so it should only be used for functions and scripts the user knows the contents of.

{% hint style="danger" %}
The context must **not** be transferred to a background process, since it has no safety features.
{% endhint %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://craftscript.kenzie.mx/tutorials/environments-and-contexts.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
