Language Features#

Core language features demonstrated through examples.

language/link_operator.bark View on GitLab
// Basic link - passing output from fn1 to fn2
fn fn1(){
  return("hello")
}(string)

fn fn2(str string){
  str > str.concat(" world") > return()
}(string)

// Execute all functions
println("=== Link Operator ===")

fn1() > result1
println("fn1() returns: {result1}") // Outputs: "fn1() returns: hello"

fn1() > fn2() > result2
println("fn1() > fn2() returns: {result2}") // Outputs: "fn1() > fn2() returns: hello world"

Functions#

language/functions.bark View on GitLab
// Basic function examples from README

// Simple function with no parameters
fn hello_world(){
  println("hello world")
}

// Function that returns a string
fn name(){
  return("bark")
}(string)

// Function returns two strings
fn name_and_semver(){
  return("bark", "0.0.1")
}(string, string)

// Function with parameter that returns bool
fn positive?(num int){
  num > gt?(0) > return()
}(bool)

// Constants as functions
fn pi(){
  return(3.14159)
}(float)

fn weekdays(){
  return(["monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"])
}(array)

// Execute and display results
println("=== Basic Functions ===")

name() > n1
println("name() returns: {n1}") // Outputs: "name() returns: bark"

println("name_and_semver() returns:")
name_and_semver() > (name_val string, ver string) {
  println("{name_val} {ver}")
  return(name_val, ver)
}(string, string) > (n, v)
// n and v now hold "bark" and "0.0.1"

5 > positive?() > p1
println("5 > positive?() returns: {p1}") // Outputs: "5 > positive?() returns: true"

-3 > positive?() > p2
println("-3 > positive?() returns: {p2}") // Outputs: "-3 > positive?() returns: false"

pi() > pi_val
println("pi() returns: {pi_val}") // Outputs: "pi() returns: 3.14159"

weekdays() > days
println("weekdays() returns: {days}") // Outputs: "weekdays() returns: [monday, tuesday, wednesday, thursday, friday, saturday, sunday]"

Anonymous Functions#

language/anonymous_functions.bark View on GitLab
// Anonymous Functions
//
// Anonymous functions in bark are inline functions that behave exactly like
// named functions. They require explicit parameter types and return type annotations.
//
// Use Cases:
// 1. Switch/case style pattern matching
// 2. Recursive iteration with repeat?()
// 3. One-time transformations in a chain
// 4. Callback-style operations

// Example 1: Simple anonymous function called via link operator
// The value on the left of > becomes the first parameter
fn example_simple() {
  // 5 is passed as 'n' to the anonymous function
  5 > (n int) {
    n > add(10) > return()
  }(int) > result

  result > println()
}()
// Outputs: 15

// Example 2: Anonymous function with multiple parameters
// When calling via link operator, only the first parameter is provided
// Additional parameters must be provided differently (implementation detail)
fn example_multi_param() {
  // This shows an anonymous function that could take multiple params
  // In practice, multi-param anonymous functions are used with repeat?()
  10 > (x int) {
    x > mul(2) > return()
  }(int) > doubled

  doubled > println() // Outputs: 20
}()

// Example 3: Anonymous function with no return type
fn example_no_return() {
  42 > (n int) {
    n > println() // Outputs: 42
  }()
}()

// Example 4: Anonymous function for transformation
fn transform_value(val int) {
  val > (x int) {
    x > mul(2) > add(5) > return()
  }(int) > result

  return(result)
}(int)
// transform_value(7) returns 19

// Example 5: Anonymous function in switch/case pattern
fn grade_letter(score int) {
  score > (s int) {
    s > gte?(90) > return?("A")
    s > gte?(80) > return?("B")
    s > gte?(70) > return?("C")
    s > gte?(60) > return?("D")
    return("F")
  }(string) > letter

  return(letter)
}(string)
// grade_letter(85) returns "B"

// Example 6: Chaining anonymous functions
fn example_chain() {
  5 > (n int) {
    n > add(3) > return()
  }(int) > (m int) {
    m > mul(2) > return()
  }(int) > result

  result > println() // Outputs: 16
}()

// Example 7: Anonymous function with variable binding inside
fn example_binding() {
  100 > (amount int) {
    amount > mul(2) > doubled
    doubled > add(50) > total
    total > println()
    total > return()
  }(int) > final_result

  return(final_result)
}(int)
// example_binding() returns 250

// Example 8: Anonymous function for conditional logic
fn is_adult(age int) {
  age > (a int) {
    a > gte?(18) > return()
  }(bool) > result

  return(result)
}(bool)
// is_adult(21) returns true
// is_adult(16) returns false

// Example 9: Anonymous function with early exit
fn find_positive(nums array) {
  nums > head() > (arr array, idx int) {
    idx > lt?(0) > break?(0)  // Empty array, return 0

    arr > get(idx) > n > gt?(0) > return?(n)  // Found positive, return it

    arr > next(idx) > nextIdx // if idx >= length of array, next(idx) returns -1
    repeat(arr, nextIdx)
  }() > value

  return(value)
}(int)
// find_positive([-1, -2, 3]) returns 3
// find_positive([-1, -2, -3]) returns 0


// Example 10: Nested anonymous functions (edge case)
fn example_nested() {
  10 > (outer int) {
    outer > add(5) > (inner int) {
      inner > mul(2) > return()
    }(int) > return()
  }(int) > result

  result > println() // Outputs: 30
}()

// Example 11: Tuples for multi-parameter initialization
//
// When an anonymous function needs multiple parameters, use a tuple
// to provide all initial values at once.
fn example_tuple_init() {
  // Tuple (10, 5) unpacks to x=10, y=5
  (10, 5) > (x int, y int) {
    x > add(y) > return()
  }(int) > result

  result > println() // Outputs: 15
}()

// Example 12: Tuple with recursive anonymous function
//
// Tuples are essential for recursive patterns where you need
// to initialize an accumulator or counter.
fn sum_1_to_n(n int) {
  // Initialize with (current=1, total=0)
  (1, 0) > (current int, total int) {
    total > add(current) > new_total
    current > add(1) > next

    next > gt?(n) > return?(new_total)

    repeat(next, new_total)
  }(int) > result

  return(result)
}(int)
// sum_1_to_n(5) returns 15 (1+2+3+4+5)

// Example 13: Three-element tuple
fn example_three_params() {
  // All three values are passed to the anonymous function
  (1, 2, 3) > (a int, b int, c int) {
    a > add(b) > add(c) > return()
  }(int) > result

  result > println() // Outputs: 6
}()

// Example 14: Tuple with named function
fn calculate(a int, b int, c int) {
  a > mul(b) > add(c) > return()
}(int)

fn example_tuple_named() {
  // Tuples also work with named functions
  (2, 3, 4) > calculate() > println() // Outputs: 10 (2*3+4)
}()

// Key Points:
// - Anonymous functions require explicit parameter types: (param type)
// - Return type annotation is required: }(return_type) or }() for no return
// - Values are passed via link operator: value > (param type) { ... }
// - Use tuples (a, b, c) to initialize multi-parameter anonymous functions
// - Tuples unpack in order: first element -> first param, etc.
// - Use return() to exit and return a value
// - Use return?() for conditional early exit
// - Anonymous functions behave exactly like named functions
// - They can be chained: result > (x) { } > (y) { } > final

// =============================================================================
// Execute Functions
// =============================================================================

println("=== Anonymous Functions ===")

println("example_simple(): ")
example_simple()

println("example_multi_param(): ")
example_multi_param()

println("example_no_return(): ")
example_no_return()

transform_value(7) > r1
println("transform_value(7): {r1}")

grade_letter(85) > r2
println("grade_letter(85): {r2}")

grade_letter(72) > r3
println("grade_letter(72): {r3}")

grade_letter(55) > r4
println("grade_letter(55): {r4}")

println("example_chain(): ")
example_chain()

example_binding() > r5
println("example_binding(): {r5}")

is_adult(21) > r6
println("is_adult(21): {r6}")

is_adult(16) > r7
println("is_adult(16): {r7}")

find_positive([-1, -2, 3]) > r8
find_positive([-1, -2, -3]) > r8_1
println("find_positive([-1, -2, 3]): {r8}")
println("find_positive([-1, -2, -3]): {r8_1}")

println("example_nested(): ")
example_nested()

println("example_tuple_init(): ")
example_tuple_init()

sum_1_to_n(5) > r9
println("sum_1_to_n(5): {r9}")

println("example_three_params(): ")
example_three_params()

calculate(2, 3, 4) > r10
println("calculate(2, 3, 4): {r10}")

println("example_tuple_named(): ")
example_tuple_named()

String Interpolation#

language/string_interpolation.bark View on GitLab
// String Interpolation Examples
// Demonstrates variable interpolation in strings

println("=== Basic String Interpolation ===")

// Simple variable interpolation
"Alice" > name
30 > age
println("{name} is {age} years old")

// Multiple variables in one string
"Seattle" > city
"Engineer" > job
println("{name} works as an {job} in {city}")

println()
println("=== Map Field Access ===")

// Map field interpolation
{"name": "Bob", "email": "bob@example.com", "role": "Admin"} > user
println("User: {user.name}")
println("Email: {user.email}")
println("Role: {user.role}")

// Nested data (requires extraction first)
{"user": {"name": "Charlie", "age": 25}} > data
data > get("user") > innerUser
println("Inner user: {innerUser.name}")

println()
println("=== Different Types ===")

// Integers
42 > answer
println("The answer is {answer}")

// Floats
3.14159 > pi
println("Pi is approximately {pi}")

// Booleans
true > active
println("Active: {active}")

// Arrays
[1, 2, 3] > numbers
println("Numbers: {numbers}")

println()
println("=== Escaping Braces ===")

// Use \{ and \} for literal braces
println("Use \{name\} syntax for interpolation")
println("JSON example: \{\"key\": \"value\"\}")

println()
println("=== Mixing with Positional Arguments ===")

// Both variable names and positional work together
"world" > greeting
42 > num
println("Hello {greeting}! The number is {num}")

println()
println("=== Complete! ===")

Switch/Case#

language/switch_case.bark View on GitLab
// Anonymous function - case/switch style example
//
// Anonymous functions can implement case/switch logic using return?().
// The function receives input and tests conditions, returning early on matches.
fn full_day_name(abbr string) {
  // The value returned by str.lower() is passed to the anonymous function.
  // Each condition is checked and return?() exits early if true.
  //
  // Example flow for input "WED":
  //    "WED" > str.lower() -> "wed"
  //    Anonymous function receives "wed"
  //    Check 1: "wed" > eq?("mon") -> false > return?("monday") -> no exit, continue
  //    Check 2: "wed" > eq?("tue") -> false > return?("tuesday") -> no exit, continue
  //    Check 3: "wed" > eq?("wed") -> true > return?("wednesday") -> exits function!
  //    Function returns "wednesday"
  //    "wednesday" > day_name -> variable binding
  //
  // The return?() function takes a boolean (from eq?) and a value.
  // If the boolean is true, it exits the function and returns that value.

  abbr > str.lower() > (day string) {
    day > eq?("mon") > return?("monday")
    day > eq?("tue") > return?("tuesday")
    day > eq?("wed") > return?("wednesday")
    day > eq?("thu") > return?("thursday")
    day > eq?("thur") > return?("thursday")
    day > eq?("fri") > return?("friday")
    day > eq?("sat") > return?("saturday")
    day > eq?("sun") > return?("sunday")
    return("unknown day abbreviation")  // Default case
  }(string) > day_name

  return(day_name)
}(string)


full_day_name("WED") > day_name
println("Full day name for 'WED' is: {day_name}") // Outputs: "Full day name for 'WED' is: wednesday"

full_day_name("fri") > day_name
println("Full day name for 'fri' is: {day_name}") // Outputs: "Full day name for 'fri' is: friday"

full_day_name("Sun") > day_name
println("Full day name for 'Sun' is: {day_name}") // Outputs: "Full day name for 'Sun' is: sunday"

full_day_name("xyz") > day_name
println("Full day name for 'xyz' is: {day_name}") // Outputs: "Full day name for 'xyz' is: unknown day abbreviation"