Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Appendix B: Operator Reference

BioLang operators are listed below from highest precedence (binds tightest) to lowest. Within the same precedence level, operators are left-associative unless noted otherwise.


Precedence Table

1. Access and Call (highest)

SymbolNameDescriptionExample
.Field accessAccess a record field or methodvariant.chrom
()CallInvoke a function or builtingc_content(seq)
[]IndexIndex into a list, string, or sequencereads[0]

2. Exponentiation

SymbolNameDescriptionExample
**PowerRaise to a power (right-associative)2 ** 10 gives 1024

3. Unary

SymbolNameDescriptionExample
-NegateArithmetic negation-log2(fc)
!Logical NOTBoolean negation!is_snp(v)
notLogical NOT (word)Same as !, reads more naturally in predicatesnot is_indel(v)
~Bitwise NOTBitwise complement~flags

4. Multiplicative

SymbolNameDescriptionExample
*MultiplyArithmetic multiplicationcoverage * depth
/DivideArithmetic divisiongc_count / len(seq)
%ModuloRemainder after division; useful for reading frame mathpos % 3

5. Additive

SymbolNameDescriptionExample
+AddArithmetic addition; also concatenates stringsstart + kb(1)
-SubtractArithmetic subtractionend - start

6. Type Cast

SymbolNameDescriptionExample
asCastConvert between compatible typesqual as Int

7. Ranges

SymbolNameDescriptionExample
..Range (exclusive)Half-open range; useful for genomic coordinates0..len(seq)
..=Range (inclusive)Closed range1..=22 for autosomal chromosomes

8. Bit Shifts

SymbolNameDescriptionExample
<<Left shiftShift bits left1 << 4
>>Right shiftShift bits right; useful for SAM flag decodingflags >> 8

9. Bitwise AND

SymbolNameDescriptionExample
&Bitwise ANDTest individual flag bits in BAM flagsflags & 0x4 to check unmapped

10. Bitwise XOR

SymbolNameDescriptionExample
^Bitwise XORExclusive ora ^ b

11. Comparison

SymbolNameDescriptionExample
==EqualStructural equalityvariant_type(v) == "snp"
!=Not equalStructural inequalityv.chrom != "chrM"
<Less thanNumeric or lexicographic comparisonv.qual < 30
>Greater thangc_content(seq) > 0.6
<=Less or equallen(seq) <= kb(1)
>=Greater or equaldepth >= 10
~Regex matchTrue if the left string matches the right patternheader ~ "^>chr[0-9]+"

12. Logical AND

SymbolNameDescriptionExample
&&ANDShort-circuiting logical andis_snp(v) && v.qual > 30
andAND (word)Same as &&, reads naturally in filtersis_snp(v) and v.qual > 30

13. Logical OR

SymbolNameDescriptionExample
||ORShort-circuiting logical oris_het(v) || is_hom_alt(v)
orOR (word)Same as ||is_het(v) or is_hom_alt(v)

14. Null Coalesce

SymbolNameDescriptionExample
??Null coalesceUse the right-hand value when the left is nilv.info["AF"] ?? 0.0

15. Pipe

SymbolNameDescriptionExample
|>PipePass the left-hand value as the first argument to the right-hand functionreads |> filter(|r| mean_phred(r.quality) > 30)
|>>Tap pipeLike pipe, but passes the value through unchanged; used for side effectsreads |>> print |> len()
|> intoPipe bindEvaluate the left side, bind the result to a name, and return itdata |> filter(|x| x > 0) |> into clean

The pipe operators are the idiomatic way to build multi-step analysis pipelines in BioLang. The |> into variant lets you capture an intermediate result without breaking left-to-right reading order — expr |> into name is equivalent to let name = expr:

read_fastq("sample.fq")
  |> filter(|r| mean_phred(r.quality) > 25)
  |>> |reads| print("After QC: " + str(len(reads)) + " reads")
  |> map(|r| {id: r.id, gc: gc_content(r.seq)})
  |> write_csv("gc_report.csv")

16. Assignment (lowest)

SymbolNameDescriptionExample
=AssignBind a value to a namelet gc = gc_content(seq)
+=Add-assignIncrement in placecount += 1
-=Subtract-assignDecrement in placeremaining -= 1
*=Multiply-assignMultiply in placescore *= weight
/=Divide-assignDivide in placetotal /= n
?=Nil-assignAssign only if the target is currently nilcache ?= compute()

17. Structural (not expression operators)

These symbols appear in specific syntactic positions and do not participate in general expression precedence.

SymbolNameDescriptionExample
=>Fat arrowSeparates patterns from bodies in match and given armsmatch v { "snp" => handle_snp() }
->ArrowReturn type annotation in function signaturesfn gc(seq: Dna) -> Float

Newlines and Statement Termination

BioLang uses newlines as statement terminators – there are no semicolons. A newline ends the current expression unless it is suppressed.

Newline Suppression Rules

A newline does not terminate a statement when it appears:

  1. After a binary operator. The expression continues on the next line.

    let total = a +
        b +
        c
    
  2. After an opening delimiter ((, [, {). The expression continues until the matching closing delimiter.

    let record = {
        chrom: "chr1",
        start: 1000,
        end: 2000
    }
    
  3. After a pipe operator (|> or |>>). The pipeline continues on the next line.

    reads
      |> filter(|r| mean_phred(r.quality) > 30)
      |> map(|r| r.seq)
    
  4. After a comma inside argument lists, list literals, and record literals.

    let xs = [
        1,
        2,
        3
    ]
    
  5. After keywords that expect a continuation: then, else, do, and, or.

These rules mean that multi-line pipelines and data structures work naturally without any explicit continuation characters.

Blank Lines

Blank lines (lines containing only whitespace) are ignored between statements. Use them freely to organize code into logical sections.


Comments

SyntaxNameDescription
#Line commentEverything from # to end of line is ignored
##Doc commentAttached to the following declaration; extractable by documentation tools
# This is a regular comment

## Compute GC content for a DNA sequence.
## Returns a float between 0.0 and 1.0.
fn gc(seq: Dna) -> Float
  gc_content(seq)
end

Doc comments (##) attach to the immediately following fn, let, or type declaration and are preserved in the AST for tooling and auto-generated documentation.