Skip to content

Latest commit

 

History

History
188 lines (137 loc) · 2.97 KB

02-variables.md

File metadata and controls

188 lines (137 loc) · 2.97 KB

Variables

Variables are dynamically typed. No declarations needed.

name = "Rugo"
age = 1
pi = 3.14
cool = true
nothing = nil

Reassignment works freely:

x = 10
x = "now a string"

Compound Assignment

x = 10
x += 5   # 15
x -= 3   # 12
x *= 2   # 24
x /= 4   # 6
x %= 4   # 2

Works with strings too:

msg = "Hello"
msg += ", World!"
puts msg

Constants

Names starting with an uppercase letter are constants — they can only be assigned once:

PI = 3.14
MAX_RETRIES = 5
AppName = "MyApp"

PI = 99   # compile error: cannot reassign constant PI

Lowercase names remain freely reassignable. This follows Ruby convention.

Scoping

Different blocks have different scoping rules:

Functions have their own scope

Functions can read top-level variables and constants, but cannot modify them — assigning inside a function creates a local variable:

name = "Rugo"

def greet()
  name = "World"     # this is a separate, local variable
  return name
end

puts greet()   # World
puts name      # Rugo (unchanged)

Top-level state like configuration hashes is accessible:

config = {host: "localhost", port: 8080}

def show_host()
  puts config["host"]
end

show_host()   # localhost

Function parameters are also local:

def add(a, b)
  return a + b
end

puts add(1, 2)  # 3
# puts a         # compile error: undefined: a

if blocks share the parent scope

Variables created or modified inside if/elsif/else are visible after the block:

if true
  msg = "hello"
end
puts msg  # hello

x = "before"
if true
  x = "after"
end
puts x  # after

Loops create their own scope

while and for loops can read and modify outer variables, but new variables defined inside the loop stay local:

total = 0
for x in [1, 2, 3]
  total += x
end
puts total  # 6
# puts x    # compile error: undefined: x

count = 0
while count < 3
  count += 1
end
puts count  # 3

Lambdas capture the outer scope

Unlike functions, lambdas can see variables from the surrounding scope:

prefix = "Hello"
greet = fn(name) prefix + ", " + name end
puts greet("Rugo")  # Hello, Rugo

But variables defined inside a lambda don't leak out:

maker = fn()
  secret = "hidden"
  return secret
end
puts maker()  # hidden
# puts secret # compile error: undefined: secret

Constants are scoped per function

A constant in a function is independent from one with the same name at the top level:

PI = 3.14

def show()
  PI = 99
  puts PI
end

show()    # 99
puts PI   # 3.14

rats blocks are fully isolated

Test blocks (rats) cannot see top-level variables or constants. Use environment variables to share state between setup_file and test blocks:

import "os" as go_os
use "test"

def setup_file()
  go_os.setenv("TEST_PORT", "8080")
end

rats "port is set"
  port = go_os.getenv("TEST_PORT")
  test.assert_eq(port, "8080")
end

Next: Strings