What does the #^ operator mean in EK9?

← Operators and Expressions · Ref: Q912

The #^ operator in EK9 calls _promote() for type widening. It converts a value to a wider or more general type. It is NOT list comprehension and NOT reflection.

#^ IS _promote()
The #^ operator promotes a value to a wider type:

  anInteger <- 42
  asFloat <- #^ anInteger

This converts Integer 42 to Float 42.0 via the _promote() method.

IMPORTANT DISTINCTIONS

- In Python, [x**2 for x in list] is list comprehension. EK9 has NO list comprehension.
- In some languages, ^ is XOR or power. In EK9, #^ is specifically the promote operator.
- The # and ^ characters together form this specific operator. Neither has meaning alone as an operator.

TYPE WIDENING EXAMPLES

- Integer to Float (narrower numeric to wider numeric)
- Character to String (single char to string)
- Any type with a defined #^ operator to its target type

RETURN TYPE RULE

The #^ operator MUST return a DIFFERENT type from the source. If you define #^ on a class, the return type cannot be the same class. This is enforced by the compiler.

IMPLEMENTING #^ ON CUSTOM TYPES

  operator #^ as pure
    <- rtn as Float: Float(internalValue)

Must be pure, takes no parameters, returns the wider type.

AUTOMATIC PROMOTION

The compiler uses #^ automatically when a narrower type is used where a wider type is expected, such as passing an Integer to a function expecting Float.

See Q911 for the #? hashcode operator. See Q839 for promote return type rules. See Q242 for all conversion operators.

Example

defines module qa.operators.hashcaretpromote

  defines class

    Measurement
      amount as Integer: 0

      Measurement() as pure
        -> amount as Integer
        this.amount :=: amount

      operator #^ as pure
        <- rtn as Float: Float(amount)

      operator $ as pure
        <- rtn as String: `Measurement(${amount})`

      override operator ? as pure
        <- rtn as Boolean: amount?

  defines program

    PromoteDemo()
      stdout <- Stdout()

      // === #^ on Integer — promotes to Float ===

      wholeNumber <- 42
      promoted <- #^ wholeNumber
      stdout.println(`Integer ${wholeNumber} promoted to Float: ${promoted}`)

      // === #^ on custom class ===

      measurement <- Measurement(100)
      asFloat <- #^ measurement
      stdout.println(`Measurement promoted: ${asFloat}`)

      // === Promotion preserves value ===

      small <- 1
      smallFloat <- #^ small
      stdout.println(`Small promoted: ${smallFloat}`)

      large <- 999999
      largeFloat <- #^ large
      stdout.println(`Large promoted: ${largeFloat}`)

Common mistakes

E07420 — The #^ promote operator must return a DIFFERENT type from the class it is defined on. Returning the same type (Measurement) defeats the purpose of promotion and triggers E07420. See ek9 -h E07420 for details.

Incorrect:

operator #^ as pure
        <- rtn as Measurement: Measurement(amount)

Correct:

operator #^ as pure
        <- rtn as Float: Float(amount)
Other ways to ask this
  • How does type promotion work in EK9?
  • What is the promote operator in EK9?
  • How do I widen a type in EK9?

Coming from another language?

Java: implicit widening (int to double). Python: implicit numeric promotion. Rust: explicit 'as' casting (i32 as f64). Go: explicit conversion float64(intVal). Kotlin: toDouble() method. JavaScript: implicit coercion. EK9: #^ operator calls _promote(), explicit and type-safe, must return different type.

Keywords: integer, hash, float, widening, type, promote, operator, caret, conversion