0.45+9.2.0.3

8.4 Imports: import🔗ℹ

The import form imports from another module. An import form can appear within a module, in which case it introduces bindings from the specified module into the importing module. An import form can also appear at the top level (in a REPL), in which case it both imports bindings and instantiates the specified module; that is, it evaluates the body definitions and expressions of the specified module, if they have not been evaluated already.

A single import form can specify multiple imports at once using a block of import_clauses:

import:

  import_clause

  ....

Specifying multiple import_clauses in a single import is essentially the same as using multiple import forms, each with a single import_clause.

The simplest import_clause is just a module path. By default, an import clause that names a module binds a prefix derived from the last element of the module path; imports are then accessed using that prefix, ., and the imported name.

module m ~lang rhombus:

  export:

    color

  def color = "blue"

module n ~lang rhombus:

  export:

    size

  def size = 17

import:

  self!m

  self!n

[m.color, n.size]

The import_clause shape can be adjusted by attaching modifiers to it.

import

module_path as id

The as modifier changes the prefix that is bound for the import, instead of using the prefix derived from the module path.

import:

  "f2c.rhm" as convert

convert.fahrenheit_to_celsius(convert.fahrenheit_freezing)

Using as ~none suppresses the prefix entirely, so that only exposed names are bound.

import

module_path open

The open modifier imports without a prefix, so each imported binding can be referenced by its bare name.

import:

  "f2c.rhm" open

fahrenheit_to_celsius(fahrenheit_freezing)

Opening an import is sometimes called “namespace dumping” and is discouraged in some cases. When module_path provides macros or a sublanguage, however, it may be intended for use with open. The documentation for each Rhombus module either shows open to suggest that the module is imported that way, or it is documented without open.

import

module_path expose:

  id_or_rename_as

  ...

 

id_or_rename_as

 = 

id

 | 

id as local_id

The expose modifier exposes specific names without a prefix, while leaving other imported bindings accessible only through the prefix. The exposed bindings are imported with the prefix as well as without.

import:

  "f2c.rhm" expose:

    fahrenheit_to_celsius

fahrenheit_to_celsius(f2c.fahrenheit_freezing)

Combining as ~none and expose is similar to Racket’s only-in, where only the listed names are bound.

import

module_path rename:

  id as local_id

  ...

The rename modifier supports renaming individual imports. The renamed bindings are still imported through the same prefix (or no prefix, if open is also applied), but under a new name.

module m ~lang rhombus:

  export:

    tastes_great

    less_filling

  def tastes_great = #true

  def less_filling = #true

import:

  self!m rename:

    less_filling as lite

[m.tastes_great, m.lite]

import

module_path only:

  id_or_rename_as

  ...

 

id_or_rename_as

 = 

id

 | 

id as local_id

The only modifier limits the imports to a specified set of names, optionally renaming.

import:

  self!m only:

    tastes_great

m.tastes_great

import

module_path except:

  id ...

  ...

The except modifier is the complement of only: it excludes specific bindings from the import.

import:

  self!m except:

    tastes_great

m.less_filling

The as, open, expose, rename, only, and except modifiers can be combined within a single import clause to implement more complex manipulations of imported bindings. For example,

import:

  self!m as my_m except:

    tastes_great

imports all bindings that m exports, except for tastes_great, and with local names accessed through the prefix my_m.