What is the difference between <-, :=, and :=: in EK9?

← Getting Started · Ref: Q879

Three operators, three purposes:

  other <- String()
  name <- "Steve"        // DECLARE: creates new variable, type inferred
  other :=: name          // COPY: copies the value of name into the existing object other
  name := "Different"    // ASSIGN: changes existing variable

Think of it this way:
- '<-' is for BIRTH — the variable didn't exist before this line
- ':=' is for CHANGE — the variable already exists, you're updating it
- ':=:' is for COPYING — copy the contents into an existing object, not the reference. Each type copies at its own level: a List copies its element references (the elements are shared), and the generated default :=: is shallow - each field then refers to the source's object; write your own :=: for a deeper copy (Q2100).

There are also conditional variants:

  config <- String()
  config :=? "default"   // assign only if config is currently UNSET
  if value <- getValue()  // guard that DECLARES: the block runs only if the result is SET
    stdout.println(value)
  current <- String()
  if current := getValue() then current?  // EXISTING variable: assign, then run the block only if SET
    stdout.println(current)

Common mistake from Java/Python developers: using '<-' to reassign. A second '<-' on a name that already exists, in the same scope or a nested block, is compile error E50050 (Variable/Constant duplicated) - nothing is shadowed. Use ':=' to change an existing variable.

See Q22 for variable declaration. See Q29 for unset variables. See Q75 for guards.

Example

defines module qa.getting.started.three.operators

  defines program

    ThreeOperators()
      stdout <- Stdout()

      //DECLARE with <-
      counter <- 0
      stdout.println(`Created counter: ${counter}`)

      //ASSIGN with :=
      counter := 10
      stdout.println(`Changed counter: ${counter}`)

      //COPY with :=:
      backup <- 0
      backup :=: counter
      counter := 99
      stdout.println(`Counter now: ${counter}`)
      stdout.println(`Backup is still: ${backup}`)

      //CONDITIONAL with :=?
      serverName <- String()
      serverName :=? "localhost"
      stdout.println(`Server: ${serverName}`)

Common mistakes

E50050 — counter already exists, so a second '<-' is E50050 (Variable/Constant duplicated) - EK9 does not shadow. Use ':=' to change an existing variable. See ek9 -h E50050 for details.

Incorrect:

      counter <- 10

Correct:

      counter := 10
Other ways to ask this
  • EK9 has too many assignment operators — which one do I use?
  • When do I use := vs :=: vs <- in EK9?
  • Explain the arrow and colon operators in EK9

Coming from another language?

Java: single '=' for everything. Python: single '=' for everything. Rust: 'let' for declare, '=' for assign. EK9: '<-' declare, ':=' assign, ':=:' copy into an existing object (each type at its own level) — each has distinct semantics. Re-declaring with '<-' is an error (E50050), never shadowing.

Keywords: colon, assign, operator, copy, arrow, declare, variable, difference