-
-
Notifications
You must be signed in to change notification settings - Fork 2
Home
- Introduction
- Installation
- Getting Started
- Language Fundamentals
- Data Types
- Control Flow
- Functions and Methods
- Object-Oriented Programming
- Advanced Features
Sidef is a modern, high-level programming language designed for versatile general-purpose applications, drawing inspiration from Ruby, Raku, and Julia.
** ** **** * ********* *********
* * ** * * **** ** ** ** ** ** ** **
** ** **** *** ********* * * *
** ** ** **** * * ****** ******
* * * * * * * * * **** ** ** ** ** ** **
** ** ** **** ****** ****** * *
** ** **** * * * ********* ***
* * ** * * **** ** ** ** ** ** ** **
** ** **** ********* ********* *
Resources:
IMPORTANT: Sidef requires the following C libraries:
- GMP - GNU Multiple Precision Arithmetic Library
- MPFR - Multiple Precision Floating-Point Reliable Library
- MPC - Multiple Precision Complex Library
Download the portable 32-bit executable:
Arch Linux:
trizen -S sidefDebian/Ubuntu/Linux Mint:
sudo apt install libgmp-dev libmpfr-dev libmpc-dev libc-dev cpanminus
cpanm --sudo -n SidefFrom MetaCPAN:
cpan Sidef
# Or without testing (faster):
cpan -T SidefFrom Git Source:
wget 'https://github.com/trizen/sidef/archive/master.zip' -O 'master.zip'
unzip 'master.zip'
cd 'sidef-master'
perl Build.PL
sudo ./Build installdeps
sudo ./Build installpkg install perl make clang libgmp libmpfr libmpc
cpan -T SidefAfter installation, verify Sidef is working:
sidef -h
sidef -vCreate a file hello.sf with:
#!/usr/bin/sidef
say "Hello, 世界"Run it:
sidef hello.sfBy convention, Sidef scripts use the .sf extension.
Sidef handles operator precedence uniquely—whitespace controls precedence:
1+2 * 3+4 # means: (1+2) * (3+4) = 21
1 + 2 * 3 # means: ((1 + 2) * 3) = 9
1+2*3 # means: (1 + (2 * 3)) = 7Best practices:
var n = 1 + 2 # WRONG: parsed as (var n = 1) + 2
var n = 1+2 # correct
var n = (1 + 2) # better - explicit groupingUse backslash (\) or dot prefix (.) to control precedence:
1 + 2 \* 3 # means: (1 + (2 * 3))
1 + 2 .* 3 # same as aboveMulti-line method chaining:
say "abc".uc \
.reverse \
.chars
# Equivalent to:
say "abc".uc.reverse.charsCore language keywords:
Declaration:
-
var- lexical variable -
local- local dynamic variable -
func- function -
class- class -
module- module -
subset- subset type -
struct- structure -
const- runtime dynamic constant -
static- runtime static variable -
define- compile-time static constant -
enum- enumeration
Control Flow:
-
if,elsif,else -
with,orwith -
while,loop,for -
try,catch -
given,when,case -
gather,take -
return,break,next,continue
I/O and Utilities:
-
say,print -
read,warn,die -
eval,del -
assert,assert_eq,assert_ne -
include,import
Special Values:
-
nil- undefined value -
true,false- boolean values
> # alias for 'say'
>> # alias for 'print'
+ # scalar context
- # negative value
++, -- # increment/decrement
~ # logical not
\ # reference
* # dereference
: # hash initializer
! # boolean negation
^ # exclusive range (0 to n-1)
@ # array context
@| # list context
√ # square root++, -- # post-increment/decrement
! # factorial
!! # double-factorial
... # unpack to listCore types in Sidef:
Numeric:
-
Number(Num) - rational/integer/floating-point -
Complex- complex numbers -
Fraction- generic fractions -
Gauss- Gaussian integers -
Quadratic- quadratic integers -
Quaternion- quaternions -
Polynomial(Poly) - polynomials -
PolynomialMod(PolyMod) - modular polynomials -
Mod- modular arithmetic
Collections:
-
Array(Arr) - ordered list -
Hash- key-value pairs -
Set- unique elements -
Bag- multiset -
Pair- two-element tuple -
Vector,Matrix- mathematical vectors/matrices -
Range,RangeNum,RangeStr- ranges
Text:
-
String(Str) - text strings -
Regex(Regexp) - regular expressions
I/O:
-
File,FileHandle -
Dir,DirHandle -
Pipe,Socket
Other:
-
Bool- boolean -
Block- code block -
Ref- reference -
Time,Date- temporal types -
Sys,Sig- system interaction -
Math- mathematical functions
255 # decimal
0xff # hexadecimal
0377 # octal
0b1111_1111 # binary (underscores for readability)Decimals are stored as rational numbers:
1.234 # stored as 617/500
.1234 # 0.1234
1234e-5 # 0.01234
12.34e5 # 1234000
say (0.1 + 0.2 == 0.3) #=> true (exact rational arithmetic)Create floating-point values with f suffix:
12345f # floating-point
12.34f # floating-point
1.5e9f # floating-point
var f = 12.345.float # convert to floatDefault precision is 192 bits. Change with -P flag:
sidef -P100 script.sf # 100 decimal placesOr dynamically:
say sqrt(2) #=> 1.41421...
local Num!PREC = 42.numify # 42 bits precision
say sqrt(2) #=> 1.4142135623:4 # 3+4i
3+4i # 3+4i
3+4.i # 3+4i
Complex(3,4) # 3+4i
sqrt(-1) # 1i
log(-1) # πi
(3+4i)**2 # -7+24iModular Arithmetic:
var a = Mod(13, 19)
a += 15 # Mod(9, 19)
a *= 99 # Mod(17, 19)
say a**42 # Mod(11, 19)Gaussian Integers:
var a = Gauss(3,4)
var b = Gauss(17,19)
say a*b #=> Gauss(-1112, 2466)Polynomials:
var p = Poly([1,2,3]) # x^2 + 2x + 3
var q = Poly("2*x^2 + 3*x - 5")
say p*q # polynomial multiplicationDouble-quoted strings support interpolation and escapes:
var name = "World"
say "Hello, #{name}!" # interpolation
say "Line 1\nLine 2" # escape sequencesSingle-quoted strings are literal:
say 'No interpolation: #{name}'
say 'Literal backslash: \n'Unicode quotes:
var dstr = „double quoted"
var sstr = ‚single quoted'Symbol notation:
:word == 'word'
:foo == 'foo'%q{single {} quoted} # single-quoted
%Q«double «» quoted» # double-quoted
%w(word1 word2) # word array
%W(interpolated words) # double-quoted words
<single words> # word array
«double «quoted» words» # double-quoted words
%r/regex/ # regex
%f"filename.txt" # File object
%d'/directory' # Dir object
%p(command) # Pipe object
%x(shell command) # backticksvar str = <<'EOF'
literal text
no interpolation
EOF
var str = <<-"EOT"
indented heredoc
with interpolation: #{1+2}
EOT"hello".uc # uppercase → "HELLO"
"HELLO".lc # lowercase → "hello"
"hello world".tc # titlecase → "Hello world"
"hello world".wc # wordcase → "Hello World"
" text ".trim # remove whitespace → "text"
"hello".reverse # → "olleh"
"hello".length # → 5
"hello".contains("ll") # true
"hello".begins_with("he") # true
"hello".ends_with("lo") # true
"hello".index("ll") # 2
"a,b,c".split(',') # ["a", "b", "c"]
"hello".chars # ["h", "e", "l", "l", "o"]var arr = [1, 2, 3, 4, 5]
var arr = Array(1, 2, 3, 4, 5)arr[0] = 6 # assignment
arr[3][4] = "hi" # autovivification
arr[-1] # last element
arr[0, 2] # slice: first and third elements
# Methods
arr.push(6) # append
arr.pop # remove last
arr.shift # remove first
arr.unshift(0) # prepend
arr.length # size
arr.reverse # reversed copy
arr.sort # sorted copy[1,2,3,4,5].grep { _ > 2 } # [3,4,5]
[1,2,3].map { _**2 } # [1,4,9]
[3,1,2].sort # [1,2,3]
[1,2,3].reduce { |a,b| a + b } # 6
[1,2,3].each { |n| say n } # iterationUnroll (element-wise):
[1,2,3] »+« [4,5,6] # [5,7,9]Map:
[1,2,3] »*» 4 # [4,8,12]Reduce:
[1,2,3]«+» # 6Cross product:
[1,2] ~X+ [3,4] # [4,5,5,6]Zip:
[1,2] ~Z+ [3,4] # [4,6]var hash = Hash(
name => 'John',
age => 42,
)
var hash = :(name => 'John', age => 42)hash{:name} # get value
hash{:name} = 'Jane' # set value
hash{:a, :b, :c} # multiple valueshash.keys # all keys
hash.values # all values
hash.has(:name) # check key exists
hash.delete(:age) # remove key
hash.sort_by { |k,v| v } # sort by value1..10 # 1 to 10 (inclusive)
1..^10 # 1 to 9 (exclusive end)
10^..1 # 10 to 1 (exclusive start)(1..10) + 2 # 3..12 (shift)
(1..10) * 2 # 2..20 (stretch)
(1..10).reverse # 10..1
(1..10).by(0.5) # step by 0.5
# Iteration
for i in (1..5) {
say i
}var s1 = Set('a', 'b', 'c')
var s2 = Set('b', 'c', 'd')
s1 & s2 # intersection
s1 | s2 # union
s1 - s2 # difference
s1 ^ s2 # symmetric differencevar b1 = Bag('a', 'b', 'b', 'c')
b1.count('b') # 2if (condition) {
# code
}
elsif (other_condition) {
# code
}
else {
# code
}Tests for defined (non-nil) values:
with (some_value) { |val|
say "Got: #{val}"
}
orwith (other_value) { |val|
say "Or: #{val}"
}
else {
say "Nothing defined"
}var result = (condition ? true_value : false_value)Pattern matching with smartmatch:
given (value) {
when (1) { say "one" }
when (2) { say "two" }
when (/^\d+$/) { say "number" }
else { say "other" }
}Boolean expression testing:
given (x) {
case (x < 0) { say "negative" }
case (x == 0) { say "zero" }
case (x > 0) { say "positive" }
}while (condition) {
# code
}do {
# code
} while (condition)# Traditional
for (var i = 0; i < 10; i++) {
say i
}
# For-in
for item in collection {
say item
}
# With block variable
for (1..10) { |i|
say i
}loop {
# infinite loop
break if condition
}5.times { |i|
say i # 0,1,2,3,4
}
5.of { |i| i**2 } # [0,1,4,9,16]
5.by { .is_prime } # [2,3,5,7,11]break # exit loop
next # skip to next iteration
continue # fall through (in given/when)func greet(name) {
say "Hello, #{name}!"
}
greet("World")func greet(name="World") {
say "Hello, #{name}!"
}
greet() # Hello, World!
greet("Alice") # Hello, Alice!func sum(*args) {
args.reduce('+')
}
say sum(1,2,3,4) # 10func div(a, b) {
a / b
}
say div(b: 5, a: 35) # 7func concat(String a, String b) {
a + b
}
concat("hello", "world") # OK
concat(1, 2) # runtime errorfunc add(a, b) -> Number {
a + b
}func factorial(n) {
return 1 if (n <= 1)
n * factorial(n - 1)
}
say factorial(5) # 120Anonymous recursion:
func fib(n) {
n < 2 ? n : (__FUNC__(n-1) + __FUNC__(n-2))
}func make_counter(start=0) {
var count = start
func {
++count
}
}
var counter = make_counter(10)
say counter() # 11
say counter() # 12func fib ((0)) { 0 }
func fib ((1)) { 1 }
func fib (n) { fib(n-1) + fib(n-2) }
say fib(10) # 55With blocks:
func fib(Number n {_ <= 1} = 0) { n }
func fib(Number n) { fib(n-1) + fib(n-2) }func test(String s) {
say "Got string: #{s}"
}
func test(Number n) {
say "Got number: #{n}"
}
test("hello") # Got string: hello
test(42) # Got number: 42func fib(n) is cached {
return n if (n <= 1)
fib(n-1) + fib(n-2)
}
say fib(100) # Fast with memoizationclass Person(name, age) {
method greet {
say "Hello, I'm #{name} and I'm #{age} years old"
}
method birthday {
self.age++
}
}
var person = Person(name: "Alice", age: 30)
person.greet()
person.birthday()
say person.age # 31class Example(a, b) {
has c = 3
has d = (a + c)
method sum {
a + b + c + d
}
}class Example(value) {
has processed
method init {
processed = (value * 2)
}
}class Person(String name, Number age) {
# name must be String, age must be Number
}Lightweight data containers:
struct Point {
Number x,
Number y,
}
var p = Point(x: 10, y: 20)
say p.x # 10Type refinement:
subset Integer < Number { |n| n.is_int }
subset Positive < Integer { |n| n.is_pos }
func square_root(Positive n) {
n.sqrt
}if ("hello world" =~ /world/) {
say "Match!"
}
# Capture groups
var match = "hello world".match(/(\w+) (\w+)/)
say match[0] # hello
say match[1] # worldvar text = "a cat, a dog and a fox"
while (var m = text.match(/\ba\h+(\w+)/g)) {
say m[0]
}
# Output: cat, dog, fox"hello" ~~ /^h/ # true
"oo" ~~ "foobar" # false
"a" ~~ %w(a b c) # true
/^b/ ~~ %w(foo bar) # truesay (^Inf -> lazy.grep{.is_prime}.first(10))
# First 10 primes without memory overheadPartial application:
var add10 = 10.method('+')
say [1,2,3].map(add10) # [11, 12, 13]25 |> :sqrt |> :say # 5
42 |> {_*3} |> {_*2} |> {_+1} # 253try {
die "Error!" if condition
}
catch { |msg|
say "Caught: #{msg}"
}var file = File('/tmp/data.txt')
# Read
var content = file.read
var lines = file.lines
# Write
file.write(text)
file.append(more_text)
# Edit in place
file.edit { |line|
line.gsub(/old/, 'new')
}module math::utils {
func double(n) { n * 2 }
func triple(n) { n * 3 }
}
say math::utils::double(21) # 42Lazy list building:
var list = gather {
for i in (1..10) {
take(i) if i.is_prime
}
}
say list # [2, 3, 5, 7]- Use explicit parentheses for complex expressions
- Prefer meaningful names over abbreviations
- Use type constraints where appropriate
- Leverage functional methods (map, grep, reduce)
- Cache expensive recursive functions
- Use
definefor compile-time constants - Cache recursive functions with
is cached - Prefer lazy evaluation for large datasets
- Use appropriate numeric types (Int vs Float vs Rational)
- Profile with
-rflag to see parsed structure
Hash with Array values creation:
var hash = Hash()
hash{:key} := [] << 1
hash{:key} := [] << 2
say hash{:key} #=> [1, 2]Conditional assignment:
var x = nil
x := some_func1()
x := some_func2() # calls some_func2() if x == nil- Official Documentation: https://trizen.gitbook.io/sidef-lang/
- Source Code: https://github.com/trizen/sidef
- Example Scripts: https://github.com/trizen/sidef-scripts
- MetaCPAN: https://metacpan.org/pod/Sidef
This tutorial covers the essentials of Sidef. For complete documentation, refer to the official book and POD documentation.
Rosettacode: http://rosettacode.org/wiki/Category:Sidef