On this page:
#%dynamism
use_  static
use_  dynamic
dynamic
8.17.0.6

2.2 Static and Dynamic Lookup🔗ℹ

expression

#%dynamism

Initially indicates dynamic mode, but intended to be redefined by use_static or use_dynamic.

This binding is not exported by rhombus/static, and a binding to indicate static mode is exported, instead.

definition

use_static

(Re-)defines #%dynamism to require certain static information and consistency with static information:

  • A static . accesses a component of a target only when the access can be resolved statically, otherwise the . form is a syntax error.

  • A static #%index looks up a value only when the lookup operator can be specialized statically (e.g., to a list or map lookup), otherwise the lookup form is an error.

  • A static in performs a membership test only when the test can be specialized statically (e.g., to a set or list lookup), otherwise the membership test is an error.

  • A static ++ works only when the append operation can be specialized statically (e.g., to a list or map append), otherwise the operator use is an error.

  • A static #%call does not require static information about functions and methods for calls, but it reports an error when the number of supplied arguments is inconsistent with static information that is available for the called function or method. Similarly, := assignment to a property is rejected if static information does not declare the property as supporting assignment.

  • A static with requires static information for a class on the left-hand side of with (i.e., the object to be functionally updated). An error is reported if a field name supplied on the right-hand side of with does not correspond to the field of the class.

  • A static for requires static information for each sequence on the right-hand side of an each form to specialize the iteration statically.

For each of these forms, static mode is detected by checking the binding of #%dynamism using the scopes of form’s operator or identifier.

Other forms not provided by rhombus might also be sensitive to dynamic mode versus static mode. Macro implementations can use syntax_meta.is_static to determine a mode.

See also Static by Default.

> class Posn(x, y)

> fun ok_lookup(ps :~ List.of(Posn)):

    use_static

    ps[0].x

> fun bad_lookup(ps):

    use_static

    ps[0].x

[]: specialization not known (based on static information)

> fun still_bad_lookup(ps :~ List):

    use_static

    ps[0].x

x: no such field or method (based on static information)

> block:

    use_static

    Posn(1, 2, 3)

Posn: wrong number of arguments in function call (based on static information)

definition

use_dynamic

(Re-)defines #%dynamism to not require certain static information and consistency with static information. See use_static.

> class Posn(x, y)

> fun (ps):

    use_dynamic

    ps[0].x

#<function:fun>

function

fun dynamic(v :: Any) :: Any

The identity function.

A call to dynamic has no static information, even if its argument has static information, so wrapping a call to dynamic around an expression has the effect of discarding any static information available for the expression.

> class Posn(x, y)

> fun bad_lookup(ps :~ List.of(Posn)):

    use_static

    dynamic(ps)[0].x

[]: specialization not known (based on static information)

> fun still_bad_lookup(ps :~ List.of(Posn)):

    use_static

    dynamic(ps[0]).x

x: no such field or method (based on static information)

> fun (ps :~ List.of(Posn)):

    dynamic(dynamic(ps)[0]).x

#<function:fun>