Skip to content

Language Reference ​

This page contains a language reference with a complete overview of all language syntax available in hop.

Types ​

There are eight built-in types available in hop.

Bool ​

The Bool type represents booleans.

Boolean literals are constructed via the keywords true and false.

OperationReturns
!xBool
x && yBool
x || yBool
x != yBool
x == yBool

Int ​

The Int type represents a 64-bit signed integer.

Integer literals are constructed by writing a literal number without a decimal point.

OperationReturns
-xInt
x + yInt
x - yInt
x < yBool
x > yBool
x <= yBool
x >= yBool
x == yBool
x != yBool
x.to_float()Float
x.to_string()String

Float ​

The Float type represents a 64-bit floating point number.

Floating point literals are constructed by writing a literal number containing a decimal point.

OperationReturns
-xFloat
x + yFloat
x - yFloat
x < yBool
x > yBool
x <= yBool
x >= yBool
x == yBool
x != yBool
x.to_int()Int

String ​

The String type represents a string of characters.

String literals are constructed by writing a string using "" as delimiters.

OperationReturns
s1 + s2String
s1 == s2Bool
s1 != s2Bool
s1.is_empty()Bool

Array ​

The Array type represents an array of a given type.

OperationReturns
arr.len()Int
arr.is_empty()Bool

Option ​

The Option type represents a container that either holds a value or not.

OperationReturns
x.is_some()Bool
x.is_none()Bool

Record ​

The Record types represent a collection of named fields.

hop
record User {
  name: String,
}

view Main {
  <let {
    user = User {name: "Tobi"},
  }>
    The name of the user is {user.name}
  </let>
}
Open in playground

Enum ​

The Enum types represent a value that can hold exactly one value of a given set of types.

hop
enum LaundryRoomState {
  Free,
  Occupied {
    available_at: String,
  },
}

view Main {
  <let {state = LaundryRoomState::Free}>
    <match {state}>
      <case {LaundryRoomState::Free}>
        <p>
          The laundry room is available.
        </p>
        <button>
          Book now
        </button>
      </case>
      <case {LaundryRoomState::Occupied {available_at}}>
        <p>
          The laundry room is occupied.
        </p>
        <p>
          It becomes available at {available_at}.
        </p>
      </case>
    </match>
  </let>
}
Open in playground

Expressions ​

Apart from the methods and operators available on values there is only one type of primitive expression available in hop. The match expression.

match ​

The match expression in hop is similar to the match expression in Rust and is used to destructure a value into different cases.

The match expression works on the Bool, Option and Enum type. Support for matching on other types is in progress.

hop
record User {
  name: String,
  email: String,
}

enum Visibility {
  Visible,
  Hidden,
}

view Main {
  <!-- Matching on Enum -->
  <let {
    input = Visibility::Visible,
    current_user = Some(
      User {name: "Loki", email: "loki@example.com"}
    ),
  }>
    <!-- Matching on the Visibility enum -->
    {match input {
      Visibility::Visible => "It is visible",
      Visibility::Hidden => "It is invisible",
    }}
    <!-- Matching on Option[User] -->
    {match current_user {
      Some(User {
        name,
        email: _,
      }) => "The current user is " + name,
      None => "There is no current user",
    }}
  </let>
}
Open in playground

Macros ​

join! ​

The join! macro concatenates strings, adding a space between each string while filtering out empty strings. The idiomatic use case for the macro is to split long class strings into separate strings.

hop
view Main {
  <div class={
    join!(
      "px-2",
      "py-3",
      "border",
    )
  }>
  </div>
}
Open in playground

asset! ​

The asset! macro registers an asset and returns the string for its production url.

hop
view Main {
  <div>
    <img src={asset!("/tutorial/2012_2017.jpg")}>
  </div>
}
Open in playground

Tags ​

<let> ​

The <let> tag binds one or more variables to the value of the given expression.

hop
view Main {
  <let {
    x = 20,
    y = 5,
    result = (x + y).to_string(),
  }>
    The result is {result}
  </let>
}
Open in playground

<match> ​

The <match> tag is the cousin of the match expression. The <match> tag works just like the match expression but can be used when the purpose of matching is not to produce a value, but instead render different markup depending on which case is matched.

hop
component LoggedInContent {
  <div>
    Welcome to the area for authenticated users.
  </div>
}

component MustSignInMessage {
  <div>
    You need to sign in to view this content.
  </div>
}

view Main {
  <let {logged_in = true}>
    <match {logged_in}>
      <case {true}>
        <LoggedInContent/>
      </case>
      <case {false}>
        <MustSignInMessage/>
      </case>
    </match>
  </let>
}
Open in playground

<for> ​

The <for> tag loops over the items of an array, rendering its contents once for each item of the array.

hop
view Main {
  <for {x in ["foo", "bar", "baz"]}>
    <div>
      {x}
    </div>
  </for>
}
Open in playground

<if> ​

The <if> tag renders its contents when a given condition evaluates to true. It is a shorthand for a match tag on a Bool with an empty false case.

hop
view Main {
  <let {x = 5, y = 10}>
    <if {x + y == 15}>
      <div>
        the math is mathing
      </div>
    </if>
  </let>
}
Open in playground