How does $ work on different types in EK9?

← Operators and Expressions · Ref: Q913

The $ operator calls _string() on ANY type that implements it. Every built-in type has a $ operator, and custom classes can define their own. The result is always a String.

$ ON BUILT-IN TYPES

  $25           returns "25" (Integer to String)
  $19.99        returns "19.99" (Float to String)
  $true         returns "true" (Boolean to String)
  $"hello"      returns "hello" (String to String, identity)
  $'A'          returns "A" (Character to String)

$ ON COLLECTIONS

List and other collections implement $ to produce a string representation:

  names <- ["Alice", "Bob"]
  namesText <- $names

The exact format depends on the type's _string() implementation.

$ ON CUSTOM CLASSES

Any class with 'operator $ as pure' can be converted:

  colour <- Colour(255, 0, 0)
  colourText <- $colour     calls Colour's $ operator

CONSISTENCY

$ ALWAYS means _string(). There are no exceptions, no special cases, no context-dependent behavior. It is the single, universal way to get a String representation of any value.

IN BACKTICK STRINGS

Inside backtick interpolation ${...}, the $ conversion is called implicitly for non-String types. But as a standalone prefix operator, $ must be written explicitly.

See Q908 for $ basics. See Q909 for $ in backtick strings. See Q910 for implementing $ on custom types.

Example

defines module qa.operators.dollarvaried

  defines class

    Score
      points as Integer: 0
      label as String: String()

      Score() as pure
        ->
          points as Integer
          label as String
        this.points :=: points
        this.label :=: label

      operator $ as pure
        <- rtn as String: `${label}=${points}`

      override operator ? as pure
        <- rtn as Boolean: points? and label?

  defines program

    DollarVariedDemo()
      stdout <- Stdout()

      // === $ on Integer ===

      count <- 42
      countText <- $count
      stdout.println(`Integer: ${countText}`)

      // === $ on Float ===

      ratio <- 3.14
      ratioText <- $ratio
      stdout.println(`Float: ${ratioText}`)

      // === $ on Boolean ===

      isActive <- true
      activeText <- $isActive
      stdout.println(`Boolean: ${activeText}`)

      // === $ on String (identity) ===

      name <- "Steve"
      nameText <- $name
      stdout.println(`String: ${nameText}`)

      // === $ on Character ===

      letter <- 'A'
      letterText <- $letter
      stdout.println(`Character: ${letterText}`)

      // === $ on custom class ===

      score <- Score(95, "Math")
      scoreText <- $score
      stdout.println(`Custom: ${scoreText}`)

      // === $ on List ===

      items <- ["one", "two", "three"]
      itemsText <- $items
      stdout.println(`List: ${itemsText}`)

Common mistakes

E50060 — EK9 does not have a toString() method like Java. Use the $ prefix operator ($count) to convert any value to String. The $ calls the _string() method. See ek9 -h E50060 for details.

Incorrect:

countText <- count.toString()

Correct:

countText <- $count
Other ways to ask this
  • Can I use $ on any type in EK9?
  • What does $ return for Integer, Float, Boolean?
  • Does $ always call _string()?

Coming from another language?

Java: toString() on all objects. Python: str() works on all types. Rust: Display trait must be implemented. Go: Stringer interface optional. JavaScript: String() or toString(). EK9: $ operator universal, calls _string(), every built-in type supports it.

Keywords: integer, types, float, dollar, universal, conversion, string, boolean, list