What do the $ and #? operators mean in EK9?

← Operators and Expressions · Ref: Q897

EK9 has dedicated operator symbols for string conversion and hashcode. These are NOT what you might expect from other languages.

$ OPERATOR — STRING CONVERSION (NOT interpolation)
The $ operator calls the _string() method to convert any value to its String representation:

  age <- 25
  ageText <- $age         converts Integer 25 to String "25"
  point <- Point(3.0, 4.0)
  pointText <- $point     calls point._string()

IMPORTANT: $ is NOT string interpolation. For interpolation, EK9 uses backtick strings with ${...}:

  greeting <- `Hello ${name}`   interpolation inside backtick string
  nameStr <- $name               standalone string conversion

Inside backtick strings, ${$variable} uses $ to convert to string:

  stdout.println(`Age is ${$age}`)   ${...} is the interpolation, $ inside converts

#? OPERATOR — HASHCODE (lowercase 'c')
The #? operator calls _hashcode() and returns an Integer hash value:

  hashValue <- #? myObject    calls myObject._hashcode()

Note: it is _hashcode (lowercase c), not _hashCode (Java style).

#^ OPERATOR — PROMOTE (type conversion)
The #^ operator calls _promote() to convert to a wider type:

  anInteger <- 42
  asFloat <- #^ anInteger   promotes Integer to Float

IMPORTANT: #^ is NOT Python list comprehension. It is type PROMOTION only.

OPERATOR METHOD NAMES

- $ calls _string()
- #? calls _hashcode()
- #^ calls _promote()
- ? calls _isSet()
- <=> calls _cmp()
- == calls _eq()
- <> calls _neq()

See Q96 for all operators. See Q238 for operator enforcement. See Q245 for implementing operators.

Example

defines module qa.operators.stringhash

  defines record

    Coordinate
      xPos as Float: 0.0
      yPos as Float: 0.0

      Coordinate()
        ->
          initialX as Float
          initialY as Float
        this.xPos :=: initialX
        this.yPos :=: initialY

      default operator

  defines function

    showConversions() as pure
      ->
        label as String
        coordinate as Coordinate
      <-
        rtn as String: String()

      // $ operator converts to String via _string()
      coordText <- $coordinate
      hashVal <- #? coordinate
      rtn := `${label}: text=${coordText}, hash=${hashVal}`

  defines program

    StringAndHashDemo()
      stdout <- Stdout()

      // $ operator — string CONVERSION (not interpolation)
      age <- 25
      ageText <- $age
      stdout.println(`Age as string: ${ageText}`)

      // Inside backtick strings: ${variable} for conversion
      price <- 19.99
      stdout.println(`Price: ${price}`)

      // #? operator — hashcode
      greeting <- "Hello"
      greetingHash <- #? greeting
      stdout.println(`Hash of greeting: ${greetingHash}`)

      // #^ operator — promote (type conversion)
      wholeNumber <- 42
      promoted <- #^ wholeNumber
      stdout.println(`Promoted: ${promoted}`)

      // Custom type with operators
      origin <- Coordinate()
      target <- Coordinate(3.0, 4.0)
      stdout.println(showConversions("Origin", origin))
      stdout.println(showConversions("Target", target))

Common mistakes

E07620 — Use $ to convert an Integer to String before concatenation — "Age: " + age has no defined + operator for a String and an Integer. See ek9 -h E07620 for details.

Incorrect:

ageText <- "Age: " + age

Correct:

ageText <- $age
Other ways to ask this
  • What is the $ operator in EK9?
  • What is the #? operator in EK9?
  • How does string conversion work in EK9?
  • How does hashcode work in EK9?

Coming from another language?

Java: toString() and hashCode() are method calls. Python: str() and hash() are built-in functions, $ has no meaning. Rust: Display trait for string, Hash trait for hashing. Go: String() method convention. Kotlin: toString() and hashCode() like Java. EK9: $ for _string() conversion, #? for _hashcode(), #^ for _promote() — these are operator symbols, not method calls.

Keywords: conversion, operator, backtick, interpolation, string, promote, dollar, hashcode