Requiring another file
use :base # .zr is assumed
use :base, :extensions, :extensions-optional # if no file is found, but folder is present, loads all .zr files from the folder
use-all # loads all .zr files in current folder
use "core/base.zr" # direct filename
Scope
if a==1
# this is 4 spaced intendation
if a==1
{
# this is scope limited by {}
}
if a == 1 {b=3} #just another case of scope
if a == 1 {b=3;c=3} #dotcomma saparates operations in single line
Constants is case insensitive
true == True # actually same
true == TRUE # actually same
FalsE== FaLsE# warning: nonrecommended constant usage
Nan == NAN # actually false due float compare logic
Constants is very flexible
123456789
123_456_789 # equal to 123456789
123 456 789 # equal to 123456789
123456789i # defining imaginary part of complex number
# oct/hex
256
0400 # oct numbers begin from '0'
0xFF # hex numbers begin from '0x' or 'OX'
0XFF
#float
#2. banned format!
2.0
2.12321321
# exponential form
2.12321321e+01
2.12321321E+01
2.12321321E+1 # leading zeros in exp can be omitted
2.12321321E1 # + in exp can be omitted
2.12321321E1i # now it's imaginary
if
if expr
#if expr == true
if expr
#if expr == true
else
#otherwise
if expr
#if expr == true
elseif expr
#if expr == true
else if expr
#if expr == true
elif expr
#if expr == true
else
#optional
# inlined
a=5 if b==1
switch
case expr
1 ? #space strongly is required
2 ? #break is automatically added by default
'1' ?
1..10 ? #range is valid value
1,2,3 ? #list is valid value
:else ? #
#experimental
case expr manual_nreak
1 ? #here break is not automatically added by default
2 ? #all this cases will execute from start line up to end line
'1' ? break #but here we dropped
:else ? #
while
while expr
# body
do
# body
while expr
loop #equivalent to while true
# body
for range
for i in 1..10
# body
for classic (experimental)
for(i=0;i<n;i++)
# body
for each constructor
fore_kv arr k v
# k - key
# v - value
fore_vk arr k v
# v - key
# k - value
fore_cv arr k v
# k - ordinal number
# v - value
fore_ckv arr c k v
# c - ordinal number
# v - key
# v - value
for/for each cycle management
for i in 1..10
next # cycle increment and go to begin
continue # synonym to next
break # exit cycle
prev # cycle decrement and go to begin
retry # go to begin and no cycle increment
# php-styled modifications
break 2 # exit from 2 cycles
next 2 # exit from 1 cycle and continue from new current cycle
# iterator manipulations
retry +2 # increment+2 and retry
retry -2 # increment+2 and retry
move +2 # increment+2
move -2 # increment+2
retry rewind # move pointer to begin and retry
rewind # move pointer to begin but continue from next line
Variable assigning
a = b
a, b = b, a # swapping
a, b, c = d, e, f # mass assignment
first, second, third = a # list decomposed into elements
a = :first, :second, :third # a is a list
Get the type of variable
a = 2.14
type a #=> :float
typeof a #=> :float
float? a #=> true. type? function is defined for every type and struct, including user-defined
“Or equals”
a = 5 if foo
a ?= 3 # if a is not set, 3, else, no change
logic operations
a &&= b && c
a and= b and c
a ||= b || c
a or= b or c
a ^^= b ^^ c
a xor= b xor c
a = !a
a = not a
in fact in most cases there is no difference between logic and logic operations
a &= b & c
a and= b and c
a |= b | c
a or= b or c
a ^= b ^ c
a xor= b xor c
a <<= b >> c
a = ^a # Go lang syntax
a = not a
math operations
a += b + c
a -= b - c
a *= b * c
a /= b / c
a %= b % c # modulo
a **= b ** c # power
a--
a++
--a
++a
a = -a
# yep you can still write in c++ style
Special math functions (experimental)
ln a
ln2 a
log2 a # equal to ln2
exp a # equal e ** a
# in fact you can use "method call" operations
a.ln, a.ln2, a.exp
# but there is no postfix operation aliases due bad formula readability
a ln # is invalid
String interpolation
apples = '33 tasty apples'
oranges = '6 juicy oranges'
output = "I had $apples and $oranges" # note double quotes
output = "I paid \$34 for them" # uninterpolated dollar sign
output = 'I paid $34 for them' # WILL NOT WORK similar to PHP
output = "I paid #{34} for them" # ruby compatibility
#special chars
output = "\a\e\b\f\n\r\t\v" # escape sequence with char
output = "\'\"\\" # other escapes
output = "\007" # octal escape sequence
output = "\xfF" # hex escape sequence case incensitive
output = "\u12e4" # unicode escape sequence
output = "\U00101234" # another unicode escape sequence
# special constant policy for single quotes and single char
char = 'a' # this is not string but char type! In fact can be used as string anywhere, but string can't be used as char
char = "a" # this is string
char = 'aa' # this is also string
char = '\n' # this is char! escape sequence works
char = '\n\n' # here escape sequence also
Convert anything to string
a = 5
`a #=> '5'
`5 #=> '5'
a to_s # another way
struct name = :first-name, :last-name
john-smith = *name 'john' 'smith'
`john-smith #=> "first-name:john, last-name:smith" - default to_s for structs
f `name
f, l = (first-name, last-name) @@ capitalize
"$f $l"
`john-smith #=> "John Smith"
some methods
a='123'
strlen a # strlen as function
a.length # length as method
a length # length as postfix operation
a count # count as postfix operation. return 3
a size # count as postfix operation
# most methods have their postfix operations aliases
Different array initialization methods
apples = 1,2,3
apples =
1
2
3
apples =
1,
2,
3
apples = [
1,
2,
3
]
apples = [
1
2
3
]
apples = [1,2,3]
some methods
apples = [1,2,3]
apples count # count as postfix operation. returns 3
count apples # count as function. returns 3
hash = field: 'a', other-field: 'b', yet-another: 'c' # :field, :other-field and :yet-another are symbols
var = :new-var
hash << ($var: 'd') # hash :new-var == 'd'
hash.$var = 'd' # alternative
hash.field # => a
struct phone-number = :area-code, :number
larrys-number = *phone-number # * is new prefix operator
larrys-number = new phone-number # this syntax is also valid
larrys-number.area-code = 303
larrys-number.number = 5053819
definition
f do-stuff arg1, arg2
do-more-complex-stuff arg1, arg2, 5 # Basic function declaration
f inline-function = 'Hello world' # one-line version
f zircon? (arg1, arg2='zircon') = true if arg1 == arg2 # default parameters defined only when () is used
f zircon? arg1, (arg2,'zircon') = true if arg1 == arg2 # another way default parameters
# Warning: for every struct defined, struct-name? is reserved.
# Types of functions are normally inferred. Manual type declaration:
f real-part x :complex
x.real
f real-part-equal? x:complex, y:numeric
x.real == y
# Full type signature
f imaginary-part-equal? x:complex, y:numeric -> boolean
x.imaginary == y
Return values
f add x, y
x + y #=> last statement is returned by default
f divide x, y
return NAN if y == 0 #=> preemptive return
x / y
f add x:complex, y :numeric # space between variable name and type is possible
y-real, y-imaginary = complex? y ? (y.real, y.imaginary) : (y, 0)
*complex x.real + y-real, x.imaginary + y-imaginary #=> struct is returned
f add x:complex, y:numeric :complex # strict return type. You can't define return variable type but not define type of last argument
y-real, y-imaginary = complex? y ? (y.real, y.imaginary) : (y, 0)
*complex x.real + y-real, x.imaginary + y-imaginary
f add x, y -> :complex # You can define return variable type but not define type of last argument. Just add ->. -> is optional
y-real, y-imaginary = complex? y ? (y.real, y.imaginary) : (y, 0)
*complex x.real + y-real, x.imaginary + y-imaginary
struct phone-number
:area-code
:number
f method arg
@number = 1 # @ is #this-> operator
static :s_var
static f s_method arg
self:s_var = 1
larrys-number = *phone-number
larrys-number.area-code = 303
larrys-number.method # this is method call
phone-number.s_method # this is static method call
f check-twitter username
stream = open "http://twitter.com/$username" # http/ftp streams, files can used as argument
err :no-connection unless stream
err :twitter-troubles if err? stream
stream
f twitter-status
true unless err? check-twitter 'zircon'
# Exception handling
try
#code
catch
#code
try
#code
catch exception_variable
#code
try
#code
catch exception_variable :expression_type1
#code
catch exception_variable :expression_type2
#code
try
#code
catch exception_variable :expression_type1
#code
catch exception_variable :expression_type2
#code
catch exception_variable
#code
try
#code
catch :expression_type
#code
Testing
f multiply x, y
inlinetest 5, 2 -> 10 # multiply 5, 2 should be equal to 10
inlinetest 8, x -> (x << 3) # basic support for fuzzing
inlinetest 133, 14 -> 1862
inlinetest x * y
Map reduce
array = 1,2,3
array2 = array @@ to_s # map
array2 = array map to_s # map
array = 1,2,3
p array >> sum # reduce. prints 6
p array reduce sum # reduce. prints 6
a = 3, 5, 9
`a #=> "3, 5, 9" - default to_s for lists
`a ' - ' #=> "3 - 5 - 9" - an argument specifies join string
Usage
use :animals-core #=> loads animals-core.zr, no namespace defined
use :pigs, Pig #=> define Pig namespace for functions in pigs.zr
Pig:oink #=> a function called which is defined in pigs.zr
f oink
'Oink!'
p oink #=> local implementation
p Pig:oink #=> external implementation
Definition
namespace Pig
f oink
'Oink!'