# Dynamic features and DSLs

> Use supported reflection, dynamic methods, receiver blocks, and Ruby-style DSL construction.

Canonical: https://alice-lang.org/documentation/language/dynamic/

[Documentation index](https://alice-lang.org/documentation/llms.txt) · [Complete book](https://alice-lang.org/llms-full.txt)

## Reflection-backed calls

`send` calls a named method, and `respond_to?` checks for it. These forms are implemented through Alice runtime helpers and reflection rather than a Ruby VM.

```alice
class Ghost
  def method_missing(name : String, args : Array(Object)) : String
    "#{name}(#{args.size})"
  end
end
puts Ghost.new.hello("Alice")
puts "alice".send(:ToUpper)
puts "alice".respond_to?(:ToUpper)
```

Expected output:

```text
hello(1)
ALICE
true
```

[Edit and run in the Alice playground](https://playground.alice-lang.org/#code=u.Y2xhc3MgR2hvc3QKICBkZWYgbWV0aG9kX21pc3NpbmcobmFtZSA6IFN0cmluZywgYXJncyA6IEFycmF5KE9iamVjdCkpIDogU3RyaW5nCiAgICAiI3tuYW1lfSgje2FyZ3Muc2l6ZX0pIgogIGVuZAplbmQKcHV0cyBHaG9zdC5uZXcuaGVsbG8oIkFsaWNlIikKcHV0cyAiYWxpY2UiLnNlbmQoOlRvVXBwZXIpCnB1dHMgImFsaWNlIi5yZXNwb25kX3RvPyg6VG9VcHBlcik)

Use the declared CLR spelling for .NET methods, as in `:ToUpper` or `:Replace`. `public_send` is also available for supported runtime-defined methods.

## Define methods

A static `define_method` declaration can create a real compiled method:

```alice
class Greeter
  define_method :hello do |name|
    "Hello, #{name}!"
  end
end
puts Greeter.new.hello("Alice")
```

When a method's name is generated at runtime, the method is stored in a runtime registry. Call it through `send` or `public_send`; the compiler cannot turn an unknown runtime name into an ordinary static call. `respond_to?` sees registered names.

## Method missing

`def method_missing(name : String, args : Array(Object))` can receive calls not declared on an Alice class. Direct unresolved calls are routed at compile time, and dynamic sends can fall back to it. Keep return types predictable and give failures a clear message.

`Point = Struct.new(:x, :y)` creates a record-like type with dynamically typed fields. Prefer a typed `record` when the schema is known.

## Receiver blocks

`obj.instance_eval { ... }` evaluates receiverless calls against `obj`. `instance_exec` also passes arguments into the block. These forms are inlined when the receiver's static type is known. Instance variables refer to the receiver, using an accessor where available and reflection otherwise.

This supports builder-style APIs in which a block configures an object. Keep the receiver explicit at the outer call so the scope of the DSL is understandable.

## Class-body DSLs

Statements inside a class body are collected into a static class-body method and run by a module initializer in declaration order. This enables forms such as `field "name"`. Class registries can use `@@registry ||= []`.

Class-body execution and runtime-generated methods have effects and ordering. They are not automatically pure code eligible for parallelization.

## Events

`obj.Event += handler` adapts a compatible block or lambda to the CLR delegate type. Store the handler when you will need to remove it with `-=`; removing a different delegate instance does not unsubscribe the original subscription.

## Boundaries

These are specific supported forms, not unrestricted Ruby metaprogramming. Use ordinary methods, modules, records, and generics when they express the same design clearly. Dynamic APIs trade some static checking for flexibility and can fail at runtime.

## Continue reading

- Previous: [Exceptions and cleanup](https://alice-lang.org/documentation/language/exceptions.md)
- Next: [Attributes and native interop](https://alice-lang.org/documentation/language/attributes.md)
