Variables
Levython uses the <- operator for variable assignment, providing clear visual
distinction between assignment and comparison operations.
Assignment Syntax#
Levython uses the <- (left arrow) operator for variable assignment. This distinctive
syntax provides visual clarity by showing the direction of data flow and eliminates confusion between
assignment and equality comparison.
# Variable assignment
name <- "Levython"
version <- 1.0
is_fast <- true
# Variables are dynamically typed
x <- 42 # x is a number
x <- "text" # x is now a string (reassignment)
# Reassignment and mutation
counter <- 0
counter <- counter + 1
counter <- counter + 1
say(name) # Output: Levython
say(str(version)) # Output: 1.0
say(str(counter)) # Output: 2
Variable Naming Rules
- Must start with a letter (a-z, A-Z) or underscore (_)
- Can contain letters, digits (0-9), and underscores
- Case-sensitive:
myVarandmyvarare different - Cannot use reserved keywords (act, if, for, while, etc.)
# Valid variable names
user_name <- "Alice"
total_count <- 100
_private <- "hidden"
MAX_SIZE <- 1000
# Invalid variable names (will cause errors)
# 123abc <- "nope" # Cannot start with digit
# my-var <- "nope" # Cannot contain hyphens
# if <- "nope" # Cannot use keywords
Compound Assignment Operators
Levython supports compound assignment operators for convenience:
# Compound assignment operators
x <- 10
x <- x + 5 # Standard form
x += 5 # Compound form (equivalent)
# Available operators
counter <- 0
counter += 1 # Addition: counter = counter + 1
counter -= 1 # Subtraction: counter = counter - 1
counter *= 2 # Multiplication: counter = counter * 2
counter /= 2 # Division: counter = counter / 2
<- arrow operator was chosen for several reasons:
- Visual Clarity: Shows data flowing from right (value) to left (variable)
- No Confusion: Eliminates mix-ups between assignment (
<-) and comparison (==) - Consistency: Pairs with return operator (
->) which shows data flowing out - Readability: Makes variable assignments stand out in code
Data Types#
Levython supports the following data types:
| Type | Description | Example |
|---|---|---|
string |
Text data | "Hello" |
number |
Integer or float | 42, 3.14 |
boolean |
True or false | true, false |
list |
Ordered collection | [1, 2, 3] |
null |
No value | null |
Strings#
Strings are sequences of characters enclosed in double quotes:
# String literals
greeting <- "Hello, World!"
empty <- ""
# String concatenation
first <- "Levy"
last <- "thon"
full <- first + last
say(full) # Output: Levython
# String length
say(str(len(greeting))) # Output: 13
Numbers#
Levython supports both integers and floating-point numbers (doubles) with automatic type handling. All numeric values are internally represented using NaN-boxing for efficient 8-byte storage.
# Integer literals
count <- 42
negative <- -10
large <- 1000000
# Floating-point literals
pi <- 3.14159
temperature <- -40.5
scientific <- 1.5e-10
# Arithmetic operations
sum <- 10 + 5 # Addition: 15
diff <- 10 - 5 # Subtraction: 5
product <- 10 * 5 # Multiplication: 50
quotient <- 10 / 5 # Division: 2.0
remainder <- 10 % 3 # Modulo: 1
power <- 2 ** 8 # Exponentiation: 256
say(str(sum)) # Output: 15
say(str(product)) # Output: 50
say(str(power)) # Output: 256
Operator Precedence
Levython follows standard mathematical precedence rules:
**(Exponentiation) - highest precedence*,/,%(Multiplication, Division, Modulo)+,-(Addition, Subtraction) - lowest precedence
# Precedence examples
result <- 2 + 3 * 4 # 14 (not 20)
result <- (2 + 3) * 4 # 20 (parentheses override)
result <- 2 ** 3 ** 2 # 512 (right-associative)
result <- 10 / 2 * 3 # 15 (left-to-right)
Type Conversion
Convert between numeric types and strings:
# String to number
text <- "42"
num <- int(text) # 42 (integer)
num <- float(text) # 42.0 (float)
# Number to string
value <- 123
text <- str(value) # "123"
# For display (str() is required)
x <- 100
say("Value: " + str(x)) # Correct
# say("Value: " + x) # Error: cannot concatenate number
Special Numeric Values
Levython handles special IEEE 754 floating-point values:
- Infinity: Result of overflow (e.g.,
1.0 / 0.0) - NaN (Not a Number): Result of undefined operations (e.g.,
0.0 / 0.0)
Booleans#
Boolean values represent true or false:
# Boolean literals
is_active <- true
is_complete <- false
# Comparison results
x <- 10
is_greater <- x > 5 # true
is_equal <- x == 10 # true
is_not_equal <- x != 5 # true
if is_active {
say("Active!")
}
Lists#
Lists are ordered, mutable collections:
# List creation
numbers <- [1, 2, 3, 4, 5]
mixed <- ["hello", 42, true]
empty_list <- []
# Accessing elements (0-indexed)
first <- numbers[0] # 1
second <- numbers[1] # 2
# Adding elements
append(numbers, 6)
# List length
say(str(len(numbers))) # Output: 6
See Lists for more details.
Null#
The null value represents the absence of a value:
value <- null
if value == null {
say("No value set")
}
Type Conversion#
Levython provides built-in functions for converting between different data types:
Available Conversion Functions
| Function | Description | Example | Result |
|---|---|---|---|
str(value) |
Convert to string | str(42) |
"42" |
int(value) |
Convert to integer | int("42") |
42 |
float(value) |
Convert to float | float("3.14") |
3.14 |
type(value) |
Get type name | type(42) |
"integer" |
# String conversion (required for output)
number <- 42
boolean <- true
list <- [1, 2, 3]
say("Number: " + str(number)) # Number: 42
say("Boolean: " + str(boolean)) # Boolean: true
say("List: " + str(list)) # List: [1, 2, 3]
# Numeric conversion
text <- "123"
num <- int(text) # 123
decimal <- float(text) # 123.0
# Type checking
value <- 42
say("Type: " + type(value)) # Type: integer
# Conversion in expressions
user_input <- "10"
doubled <- int(user_input) * 2
say("Result: " + str(doubled)) # Result: 20
Type Introspection
Use the type() function to inspect value types at runtime:
say(type(42)) # "integer"
say(type(3.14)) # "float"
say(type("hello")) # "string"
say(type(true)) # "boolean"
say(type([1, 2])) # "list"
say(type(null)) # "null"
str() function must be used when concatenating
non-string values with strings. Attempting to concatenate without conversion will result in a
runtime type error.
Common Patterns
# Pattern: User input conversion
age_str <- ask("Enter your age: ")
age <- int(age_str)
if age >= 18 {
say("You are an adult")
} else {
say("You are " + str(18 - age) + " years away from adulthood")
}
# Pattern: Numeric calculations
price_str <- "29.99"
quantity_str <- "3"
total <- float(price_str) * int(quantity_str)
say("Total: $" + str(total)) # Total: $89.97
# Pattern: Dynamic type handling
values <- [42, "hello", 3.14, true]
for val in values {
say("Value: " + str(val) + ", Type: " + type(val))
}
# Output:
# Value: 42, Type: integer
# Value: hello, Type: string
# Value: 3.14, Type: float
# Value: true, Type: boolean