What does the #? operator mean in EK9?

← Operators and Expressions · Ref: Q911

The #? operator in EK9 calls _hashcode() and returns an Integer hash value. It is NOT a Python-style comment and NOT a Ruby-style method reference.

#? IS _hashcode()
The #? operator is read as 'hash-query' and calls the _hashcode() method:

  hashVal <- #? myObject

This returns an Integer suitable for use as a Dict key or equality checking.

IMPORTANT DISTINCTIONS

- In Python, # starts a comment. In EK9, // starts a comment.
- In Ruby, #method is an unbound method reference. EK9 has no such syntax.
- In EK9, # is part of TWO operator symbols: #? (hashcode) and #^ (promote).
- The # character has NO meaning on its own in EK9.

RETURN TYPE

#? always returns Integer. The method signature is:

  operator #? as pure
    <- rtn as Integer: ...

NOTE THE LOWERCASE 'c'
The method is _hashcode (lowercase c), NOT _hashCode (Java style camelCase). This is a common mistake.

IMPLEMENTING #? ON CUSTOM TYPES

  operator #? as pure
    <- rtn as Integer: #?field1 + #?field2

Combine hash values of fields using arithmetic.

DEFAULT OPERATOR

Using 'default operator' generates a #? implementation that combines all fields.

See Q897 for $ and #? together. See Q912 for the #^ promote operator. See Q242 for all conversion operators.

Example

defines module qa.operators.hashqhashcode

  defines record

    Tag
      name as String: String()
      priority as Integer: 0

      Tag()
        ->
          name as String
          priority as Integer
        this.name :=: name
        this.priority :=: priority

      default operator

  defines program

    HashcodeDemo()
      stdout <- Stdout()

      // === #? on String ===

      greeting <- "Hello"
      greetingHash <- #? greeting
      stdout.println(`String hash: ${greetingHash}`)

      // === #? on Integer ===

      number <- 42
      numberHash <- #? number
      stdout.println(`Integer hash: ${numberHash}`)

      // === #? on Float ===

      price <- 19.99
      priceHash <- #? price
      stdout.println(`Float hash: ${priceHash}`)

      // === #? on custom record ===

      versionTag <- Tag("version", 1)
      versionHash <- #? versionTag
      stdout.println(`Tag hash: ${versionHash}`)

      // === Different values produce different hashes ===

      buildTag <- Tag("build", 2)
      buildHash <- #? buildTag
      stdout.println(`Build hash: ${buildHash}`)

Common mistakes

E07550 — The #? operator must return Integer, not String. Defining #? to return String triggers E07550 because hashcode must always return an Integer value. See ek9 -h E07550 for details.

Incorrect:

      operator #? as pure
        <- rtn as String: name

Correct:

      default operator
Other ways to ask this
  • Is # a comment in EK9?
  • How does hashcode work in EK9?
  • What does #? return in EK9?

Coming from another language?

Java: hashCode() method (camelCase). Python: hash() built-in, # is comment. Ruby: hash method, # is interpolation in strings. Rust: Hash trait derive. Go: no built-in hash interface. Kotlin: hashCode() like Java. EK9: #? operator calls _hashcode() (lowercase c), returns Integer.

Keywords: integer, hash, dict, key, hashcode, equality, comment, python, operator