01_Function_Calls

Function Calls

What is Juxtaposition?

In Baba Yaga you call functions by putting them next to each other.

/* 
   JavaScript: f(x, y)
    Baba Yaga: f x y
*/

Basic Examples

/* Simple function calls */
add 5 3;           /* Instead of add(5, 3) */
multiply 4 7;      /* Instead of multiply(4, 7) */
subtract 10 3;     /* Instead of subtract(10, 3) */

/* Function calls with tables */
/* ...we'll talk more about @ in a bit */ 
map @double {1, 2, 3, 4, 5};
filter @is_even {1, 2, 3, 4, 5, 6};
reduce @add 0 {1, 2, 3, 4, 5};

How It Works

The parser automatically translates juxtaposition into nested calls to apply, so that

/* f x y becomes: apply(apply(f, x), y) */
/* map double {1, 2, 3} becomes: apply(apply(map, double), {1, 2, 3}) */

Precedence Rules

Juxtaposition has lower precedence than operators,

result : add 5 multiply 3 4;
/* Parsed as: add 5 (multiply 3 4) */
/* Result: 5 + (3 * 4) = 17 */
/* Not as: (add 5 multiply) 3 4 */

With Baba Yaga you'll use juxtaposition when you

  • call functions with arguments
  • build function composition chains
  • work with combinators like map, filter, reduce

You won't use it, exactly, when you are

  • defining functions (use : and ->)
  • assigning values (use :)
  • using operators (use +, -, *, etc.)

Common Patterns

/* Data processing pipeline */
data : {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
is_even : x -> x % 2 = 0;
double : x -> x * 2;
sum : x -> reduce add 0 x;

/* Pipeline using juxtaposition */
result : sum map double filter is_even data;
/* Reads: sum (map double (filter is_even data)) */
/* Result: 60 */

Using Parentheses for Control

Juxtaposition eliminates the need for parentheses in most cases, parentheses are available for when you need explicit control over precedence or grouping.

/* Without parentheses - left-associative */
result1 : add 5 multiply 3 4;
/* Parsed as: add 5 (multiply 3 4) */
/* Result: 5 + (3 * 4) = 17 */

/* With parentheses - explicit grouping */
result2 : add (add 1 2) (multiply 3 4);
/* Explicitly: (1 + 2) + (3 * 4) = 3 + 12 = 15 */

/* Complex nested operations */
result3 : map double (filter is_even (map increment {1, 2, 3, 4, 5}));
/* Step by step:
   1. map increment {1, 2, 3, 4, 5} → {2, 3, 4, 5, 6}
   2. filter is_even {2, 3, 4, 5, 6} → {2, 4, 6}
   3. map double {2, 4, 6} → {4, 8, 12}
*/

/* Hard to read without parentheses */
complex : map double filter is_even map increment {1, 2, 3, 4, 5};

/* Much clearer with parentheses */
complex : map double (filter is_even (map increment {1, 2, 3, 4, 5}));

/* Or break it into steps for maximum clarity */
step1 : map increment {1, 2, 3, 4, 5};
step2 : filter is_even step1;
step3 : map double step2;

Parentheses are also helpful for debugging because they let you isolate specific pieces of a program or chain.

data : {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

/* Test each step separately */
filtered : filter @is_even data;
doubled : map @double filtered;
final : reduce @add 0 doubled;

/* Or use parentheses to test intermediate results */
test1 : filter is_even data;               /* {2, 4, 6, 8, 10} */
test2 : map double (filter is_even data);  /* {4, 8, 12, 16, 20} */

Spacing Rules

Baba Yaga uses spacing to distinguish between unary and binary operators...mostly just minus.

  • Unary minus: -5 (no leading space) → negate(5)
  • Binary minus: 5 - 3 (spaces required) → subtract(5, 3)
  • Legacy fallback: 5-3subtract(5, 3) (but spaces are recommended)

The parser distinguishes between these scenarios based off of spaces, and kinda best guess heuristics. It should work as expected in most cases.

  • Unary minus (negative numbers): -5negate(5)
  • Binary minus (subtraction): 5 - 3subtract(5, 3)

Spacing makes expressions less ambiguous.

Common Patterns

/* Function calls with negative numbers */
double : x -> x * 2;
result : double -5;      /* unary minus */
result2 : double (-5);   /* explicit grouping */

/* Comparisons with negative numbers */
is_negative : x -> x < 0;
test1 : is_negative -5;  /* unary minus */

/* Complex expressions with negative numbers */
validate_age : age -> (age >= 0) and (age <= 120);
test2 : validate_age -5; /* unary minus */

/* Arithmetic with proper spacing */
result3 : -5 + 3;        /* unary minus + binary plus */
result4 : 5 - 3;         /* binary minus with spaces */
result5 : (-5) + 3;      /* explicit grouping */

Best Practices

  • Use spaces around binary operators: 5 - 3, 5 + 3, 5 * 3
  • Unary minus works without parentheses: -5, f -5
  • Legacy syntax still works: (-5), 5-3 (but spaces are recommended)
  • When in doubt, use spaces: It makes code more readable and follows conventions

When You Might Encounter This

  • Arithmetic operations: -5 + 3, 5 - 3, (-5) + 3
  • Comparisons: -5 >= 0, 5 - 3 >= 0
  • Function calls: f -5, f (-5), map double -3
  • Logical expressions: (-5 >= 0) and (-5 <= 120)
  • Pattern matching: when x is -5 then "negative five"

To make everyone's life easier, use spaces around binary operators.