# Variables

## Variables

* [Values](#values)
* [Scope](#scope)
* [Assignment](#assignment)
* [Variable Types](#variable-types)
  * [Variables](#variables-1)
  * [Constants](#constants)
  * [Typed Variables](#typed-variables)
* [Type Declarations](#type-declarations)

### Values

_Variables_ are named slots for storing values. You define a new variable in Jingle using a `var` statement, like so:

```
var a = 1 + 2
```

&#x20;This _declares_ a new variable `a` in the current _scope_ and initializes it with the result of the expression following the `=`. Once a variable has been defined, it can be accessed by name as you would expect.

```
var animal = "Dog"
echo animal # "Dog"
```

### Scope

Jingle has _block scope_: a variable only exists from where it is define to the end of the block.

```
    echo a # Error: 'a' hasn't been declared yet
    var a = 50 # Declares variable 'a' and assigns value '50'
    echo a # Prints 50
end
echo a # Error: 'a' doesn't exist anymore because it is out of the block
```

&#x20;Variables defined at the top level of a script are _top-level_ and are visible to the module system. All other variables are _local_. Declaring a variable in an inner scope with the same name as an outer one is called _shadowing_ and is not an error (although it’s not something you likely intend to do much).

```
var a = "outer"
: # block opener for example
    var a = "inner"
    echo a # Prints "inner"
end
echo a # Prints "outer"
```

However, _declaring_ multiple variables of the same name in the same _scope_ is an error.

### Assignment

After a variable has been declared, the value can be reassigned using `=`:

```
var a = 5
a = 6
```

It’s an error to assign to a variable that isn’t defined. This can only be done with variables and binds.

### Variable Types

#### Variables

Variables are dynamically-typed, inferred and mutable. This means you do not have to give it a type, and it can change along with the value of the variable. They are declared with the `var` keyword.

```
# Valid Statements:
var a = 1243
a = 3421

var b = "b"
b = "c"

var c = 2.4
c = 9.9

var d = True
d = False

var e = 50
e = 49.9

var f = "6"
f = 6

var g = True
g = 9 
```

#### Constants

Constants are statically-typed, inferred and immutable. This means you do not have to give it a type, but it cannot change. The value of the variable cannot change. They are declared with the `const` keyword.

```
# Valid Statements:
const GRAVITY = 9.807
const PI = 3.14
const VERSION = 0.1.0

# Invalid Statements:
const MOON = "Moon"
moon = "Sun"
```

#### Typed Variables

Typed Variables are statically-typed, inferred and mutable. This means you do not have to give it a type, but it cannot change. The value of the variable cannot change. They are declared with the `let` keyword.

```
# Valid Statements:
let pizza = 2.99
pizza = 4.99

let fruit = "Apple"
word = "Orange"

# Invalid Statements:
let chicken = "Leg"
chicken = 10

let vegetable = "Cucumber"
vegetable = False
```

### Type Declarations

Types can be deliberately declared using type declarations. They are done like this:

```
var age::int = 20
age = 2.5 # Error, declared as int not float
```

You can declare the type of a variable multiple times:

```
var height::int = 160
height = 180

height::float = 167.5
height = 192.75

height::string = "200"
height = "50" 
```

These can be used for variables if you plan on changing the type of a variable rarely, but still multiple times. If you don't plan on changing the type than just use a typed variable. You can use `bool`,`int`,`float/flt`,`string/str`,`any` in type declarations.
