Skip to main content

Fundamentals

Here, we describe the first little pieces of Quarrel. Can you feel the montage music coming?!

Comments#

Comments begin with a #

# Here is a comment
NonComment

Comments can also be sectional or short mid-line circumfix style

###
This is a comment section
It can contain lots of informatoin
###
NotAComment #[This is a comment]# ThisIsNotAgain

Assignment#

In Quarrel, you assign using either := or .=. The first one will make a copy at that new location (disconnecting it from the origin). The latter will just give you a symbolic link to the origin.

resources/fundamentals/assignment.qvr
foo .= 12 # reference assignment
bar := foo # copy assignment
'foo bar' .= 15 # you can include spaces in container names with single quotes

To create a constant immutable container, utilize the $ prefix operator.

$baz := 24 # baz can never change
$baz := 0 # this will throw an error
$'qux' := "cool!"

Equality Operators#

Create a file at src/pages/my-markdown-page.md:

resources/fundamentals/eqops.qvr
f == g # equal?
f <> g # not equal?

Unlike some languages that use !=, Quarrel opts for another popular choice, the diamond operator.

Text Data#

resources/fundamentals/text.qvr
s .= "wow!"
t .= "Cheese"
o .= "!" # This is a Symbol, a single character Text datum
p .= "String {{t+o}}" #= "String Cheese!"

Remember, single quotes are not for strings

Truth Values#

Also called "booleans", Quarrel has the usual cast of true and false, however, we've also opted for a new intuitive convention yes and no.

classic .= true
boring := false
# Quarrel also offers new (equivalent) truth values
wild .= no
hungry := yes

Math Operators#

In addition to the usual math operators, there are some other operators that represent what would normally be provided as method calls in other languages.

f + g # addition
f ++ g # ceiling
f +++ g # greatest common divisor
f - g # subtraction
f -- g # floor
f --- g # least common multiple
f / g # division
f // g # log base g of f
f /// g # radication (nth root# equiv: f ** 1/g)
f % g # modulus
f %% g # divisilibity (equiv to f % g == 0)
f %%% g # divmod (returns [quotient, remainder])
f * g # multiplication
f ** g # power
f *** g # random (picks from a list, within a range, or up to a single number)

And there are some even weirder ones:

|val| # absolute value
val.. # truncate everything after the decimal
..val # truncate everything before the decimal

Comparison Operators#

To allow for using < and > for another syntax (dictionaries), we've added an extra operator for the usual suspects. This has the inadvertent effect of aligning the character count for all comparison operators.

f >> g # greater than
f << g # less than
f >= g # greater than or equal
f <= g # less than or equal
f <> g # not equal (fits perfectly here!)

Logical Operators#

In some languages, programmers cheat the control flow game with "short-circuit" logical operators. In Quarrel, you are provided conditional operators that already act like these "short-circuit" versions which we will discuss shortly. To help eliminate extraneous syntax, the logical operators in Quarrel do not "short-circuit" and are in fact much more traditional propositional logic operators.

p /\ q # conjunction
p \/ q # disjunction
# "implies" operator
p ==> q
# if p is false, then q can be true or false
# if p is true, then q must be true
# "if and only if" operator
p <=> q
# if p is false, then q must be false
# if p is true, then q must be true

Conditional Operators#

As mentioned, Quarrel does not provide traditional logical operators in any way. Instead, logic is done with something like the ternary operators of some c-like languages. Of course, Quarrel takes it a step further by giving you a few additional forms that make it even easier to write control flows.

p @@ if_true_then_this!
q ~@ if_false_then_this!
# can also be combined
p @@ if_true_then_this! ~@ if_false_then_this!
~p # negation
maybe_empty ?@ if_empty_then_this!

Routines#

# identifier .= parameter pattern => sequence
name .= {arg} => ("My name is " + arg)

The curly braces are optional around the parameter pattern and the parentheses around the sequence are optional too. If there is ambiguity, use a , to separate expressions and a ; to terminate the sequence.

Invoke a routine with the list postcircumfix operator.

name("Jake") #= "My name is Jake"

Parentheses are also optional in invocation with ; being used to terminate ambiguous sequence expressions as well.

name "Michelle" #= "My name is Michelle"
add .= x, y => x + y
add 10, 20; + 30 #= 60

A routine without any arguments is called a sequence. Sequences can be invoked by using the ! postfix operator.

hours .= 2
minutes .= => 60 * hours
minutes!

The ! operator used on an empty sequence provides a null result, useful for creating empty containers and arguments

nothing .= ()!

Parameter patterns can be variadic with the ... operator.

first .= x, xs... => x
last .= xs..., xn => xn

No containing name means the remaining parameters are discarded.

second .= x, y, ... => y
edges .= x, ..., xn => [x, xn] # this is a list literal result

Optional parameters are specified by using a ?@ operator inside of a pattern.

optSecondParam .= {x, y ?@ "Unknown"}

If y is ()! (empty), then it will set y to "Unknown".


Routines are really just a binary operation from a pattern to a sequence. The pattern provides the layout of the context, the sequence provides a series of expressions given that context. Patterns and sequences are examples of aggregate data which is explained in the next section.