Language Basics
Core syntax and fundamental concepts of Strada.
Program Structure
A Strada program consists of function definitions. Execution begins at the main function:
# Comments start with #
func helper() {
say("I'm a helper function");
}
func main() int {
helper();
say("Hello from main!");
return 0;
}
Variables
Variables use Perl-style sigils. Type annotations are optional — the sigil determines the default type:
my $name = "Strada"; # scalar (any value)
my $count = 42; # scalar
my $pi = 3.14159; # scalar
my @colors = ("red", "green", "blue"); # array
my %config = ("debug" => 1, "port" => 8080); # hash
# You can add explicit types for documentation:
my int $count = 42;
my str $name = "Strada";
my num $pi = 3.14159;
Functions
Functions are defined with func (or fn). Types are optional:
# Simple function — no type annotations needed
func greet($name) {
say("Hello, " . $name . "!");
}
func add($a, $b) {
return $a + $b;
}
# No-parens form — args available as @_ (like Perl subs)
func log_msg {
my $level = $_[0];
my $msg = $_[1];
say("[" . $level . "] " . $msg);
}
# With explicit types (for APIs, libraries, documentation)
func distance(num $x1, num $y1, num $x2, num $y2) num {
return math::sqrt(($x2 - $x1) ** 2 + ($y2 - $y1) ** 2);
}
See the Functions page for closures, variadic functions, default parameters, and more.
Statements
Statements end with semicolons:
my $x = 10;
my $y = 20;
say($x + $y);
$x = $x + 1;
Comments
# This is a single-line comment
my int $x = 42; # Inline comment
Operators
Arithmetic Operators
| Operator | Description | Example |
|---|---|---|
+ | Addition | $a + $b |
- | Subtraction | $a - $b |
* | Multiplication | $a * $b |
/ | Division | $a / $b |
% | Modulo | $a % $b |
** | Exponentiation | $a ** $b |
Comparison Operators
| Numeric | String | Description |
|---|---|---|
== | eq | Equal |
!= | ne | Not equal |
< | lt | Less than |
> | gt | Greater than |
<= | le | Less than or equal |
>= | ge | Greater than or equal |
<=> | cmp | Spaceship (returns -1, 0, or 1) |
<=> for numeric sort and cmp for string sort:
sort { $a <=> $b; } @nums or sort { $a cmp $b; } @strings
eq/ne for string comparison, not ==/!=.
Using numeric operators on strings compares them numerically.
Logical Operators
| Operator | Description | Example |
|---|---|---|
&& | Logical AND (returns boolean) | $a && $b |
|| | Logical OR (returns value) | $h{"key"} || "default" |
// | Defined-or | $h{"key"} // "default" |
! | Logical NOT | !$a |
and | Low-precedence AND | $a and $b |
or | Low-precedence OR | $a or $b |
not | Low-precedence NOT | not $a |
|| operator returns its left operand if truthy, otherwise its right operand (like Perl/JavaScript). The // operator returns its left operand if defined (not undef), otherwise its right operand. Use // when you want empty strings or zero to be considered valid values.
String Operators
| Operator | Description | Example |
|---|---|---|
. | Concatenation | "Hello" . " World" |
x | Repetition | "ab" x 3 → "ababab" |
Bitwise Operators
| Operator | Description | Example |
|---|---|---|
& | Bitwise AND | $a & $b |
| | Bitwise OR | $a | $b |
^ | Bitwise XOR | $a ^ $b |
~ | Bitwise NOT | ~$a |
<< | Left shift | $a << 2 |
>> | Right shift | $a >> 2 |
Increment/Decrement
my int $i = 0;
$i++; # Postfix increment (returns old value)
$i--; # Postfix decrement
++$i; # Prefix increment (returns new value)
--$i; # Prefix decrement
Assignment Operators
$x = 10; # Assignment
$x += 5; # Add and assign ($x = $x + 5)
$x -= 3; # Subtract and assign
$x *= 2; # Multiply and assign
$x /= 4; # Divide and assign
$x .= "!"; # Concatenate and assign
Ternary and Other Operators
# Ternary conditional
my str $result = $x > 0 ? "positive" : "non-positive";
# Range operator (creates array)
my array @nums = (1..10);
# Reference operator
my int $x = 42;
my scalar $ref = \$x; # Reference to $x
# Function reference
my scalar $fn = &my_function;
Blocks
Blocks are delimited by curly braces and create a new scope:
{
my int $x = 10; # $x only visible in this block
say($x);
}
# $x is not accessible here
Truthiness
Values are considered "false" if they are:
- The number
0 - The empty string
"" undef
Everything else is "true".
if ($value) {
say("Value is true");
} else {
say("Value is false");
}
Magic Namespaces
Built-in functions are organized into namespaces:
Core Functions (No Namespace)
Common functions like say(), print(), push(), pop(), len(), etc.
math:: Namespace
math::sin(3.14)
math::cos(0)
math::sqrt(16)
math::pow(2, 10)
math::abs(-5)
math::floor(3.7)
math::ceil(3.2)
core:: Namespace
core:: is the preferred namespace for system functions. (sys:: also works for backwards compatibility.)
core::open("file.txt", "r")
core::read($fd, 1024)
core::write($fd, $data)
core::close($fd)
core::fork()
core::exec("ls", ["-la"])
core::getenv("PATH")
core::time()
Regex Operations
Pattern Matching
my str $s = "Hello World";
# Match
if ($s =~ /World/) {
say("Found it!");
}
# Negated match
if ($s !~ /Goodbye/) {
say("Not found");
}
Substitution
my str $s = "Hello World";
# Replace first occurrence
$s =~ s/World/Strada/;
# Replace all occurrences (g flag)
$s =~ s/l/L/g;
# Case-insensitive (i flag)
$s =~ s/hello/Hi/i;
Input/Output
Console Output
say("With newline"); # Prints with newline
print("No newline"); # Prints without newline
Heredocs
Multi-line string literals using heredoc syntax:
my str $text = <<EOT;
This is a multi-line
string literal.
EOT
# Single-quoted: no escape sequences
my str $raw = <<'EOT';
Backslash-n stays literal: \n
EOT
<<EOT; line. Supports bare <<EOT, single-quoted <<'EOT', and double-quoted <<"EOT".
chomp
chomp() strips trailing \n (or \r\n) from a variable in-place and returns the modified string:
my str $line = "hello\n";
chomp($line); # $line is now "hello"
File I/O
# Read entire file
my str $content = slurp("file.txt");
# Write to file
spew("output.txt", $content);
# Low-level file operations
my scalar $fh = core::open("file.txt", "r");
my str $data = core::readline($fh);
core::close($fh);
# Perl-style open modes
my scalar $fh = core::open("file.txt", "<"); # read
my scalar $fh = core::open("file.txt", ">"); # write
my scalar $fh = core::open("file.txt", ">>"); # append
# STDIN, STDOUT, STDERR barewords
say(STDOUT, "to stdout");
say(STDERR, "error output");
my str $line = <STDIN>;
# File test operators
if (-e $path) { say("exists"); }
if (-f $path) { say("is a file"); }
if (-d $path) { say("is a directory"); }
Diamond Operator <$fh>
Read lines from filehandles using the Perl-style diamond operator:
# Scalar context: read one line at a time
my scalar $fh = core::open("input.txt", "r");
my str $line = <$fh>;
while (defined($line)) {
say($line);
$line = <$fh>;
}
core::close($fh);
# Array context: read ALL lines at once
$fh = core::open("input.txt", "r");
my array @lines = <$fh>; # Reads entire file!
core::close($fh);
foreach (@lines) { # Implicit $_ loop variable
say($_);
}
Print/Say to Filehandle
Write to files or sockets using say/print with a filehandle as the first argument:
# Write to file
my scalar $out = core::open("output.txt", "w");
say($out, "Line with newline"); # Adds \n
print($out, "No newline"); # No \n
core::close($out);
# Also works with sockets!
my scalar $sock = core::socket_client("localhost", 80);
say($sock, "GET / HTTP/1.0");
my str $response = <$sock>; # Read response
core::socket_close($sock);