Nex

Three Ways to Express the Same Computation

The same normalize algorithm written three ways — functional (fuses to one loop), explicit-loop with a local var, and slice assignment for partial in-place updates.

// 1) Functional: fresh array, fusion-friendly. The expression `v / mag`
//    lowers to a single fused loop with no intermediate.
def normalize(v: [real]) =
  val mag = sqrt(sum(v * v))
  if mag == 0.0 then v
  else v / mag

// 2) Explicit-loop with a local `var`: same machine code as (1), useful
//    when the loop body is more complex than a single element-wise
//    expression can capture. `out` is unique inside the function, so
//    indexed writes are in-place; the return value moves the buffer out.
def normalize_loop(v: [real]) =
  val n = length(v)
  val mag = sqrt(sum(v * v))
  if mag == 0.0 then v
  else
    var out = fill(n, 0.0)
    for i in 0..n do
      out[i] = v[i] / mag
    end for
    out

// 3) Slice assignment: overwrite a sub-extent of an existing var array
//    in place. The assignment mutates the underlying buffer in the
//    binding's own scope — no clone, no reallocation, no new identity.

def main() =
  // 1) Functional:
  val a = [3.0, 4.0]
  val b = normalize(a)
  print(b)                          // [0.6, 0.8]

  // 2) Explicit loop — same answer, same machine code (per design promise):
  val c = normalize_loop([3.0, 4.0])
  print(c)                          // [0.6, 0.8]

  // 3) Slice assignment: replace the first two elements in place.
  //    This is the idiom for partial in-place updates on a var array.
  var d = [9.0, 9.0, 9.0, 9.0]
  d[..2] = [0.6, 0.8]               // open lo: writes positions 0 and 1
  print(d)                          // [0.6, 0.8, 9.0, 9.0]

Search

Esc
to navigate to open Esc to close