# Tuples, delegates, and reflection

> Return multiple values, deconstruct tuples, adapt .NET delegates, and inspect CLR types.

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

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

## Return several values

A tuple is a fixed group of values. Use `{T1, T2}` for its type and `{value1, value2}` for a value. Assignment can deconstruct the tuple into locals.

```alice
def pair : {Int32, String}
  {1, "one"}
end
number, label = pair
puts "#{number}=#{label}"
puts pair.Item2
```

Expected output:

```text
1=one
one
```

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

The tuple also exposes CLR members such as `Item1` and `Item2`. Use a [record](https://alice-lang.org/documentation/language/records.md) when field names make the meaning clearer or the shape belongs in a public domain API. A tuple is useful for a small local result without introducing another named type.

A tuple literal is not a hash: a hash uses `key => value` pairs. Deconstructed locals follow the same scope and definite-assignment rules as other locals.

## Delegates

A lambda is assignable to a compatible .NET `Func` or `Action`:

```alice
f : Func(Int32, Int32) = ->(x : Int32) { x * 3 }
puts f.Invoke(2)
```

`Func(Input, Output)` returns a result, while `Action(Input)` has no result. More argument types can precede a Func's result type. An annotation helps choose a .NET overload or event-handler signature.

## Ref and out

```alice
number = 0
ok = Int32.TryParse("42", out number)
puts ok ? number : -1
```

`out` lets the callee assign a result and `ref` passes a variable by reference. These are the CLR API's contracts, not ownership transfers. A concurrent write through a reference still needs synchronization.

## Type inspection

```alice
type = typeof(String)
puts type.Name
puts typeof(List(Int32)).IsGenericType
```

`typeof` yields a .NET `Type`. Reflection APIs then expose metadata about constructors, members, and generic arguments. Prefer direct typed calls for routine program logic; reflection can complicate trimming and NativeAOT.

Runtime helpers also expose supported `methods`, `is_a?`, `instance_variables`, `instance_variable_get`, and `instance_variable_set` forms. These are dynamic inspection tools, not a substitute for a stable typed API. Read [dynamic features](https://alice-lang.org/documentation/language/dynamic.md) and [security](https://alice-lang.org/documentation/advanced/security.md#dynamic-and-native-boundaries) before dispatching based on external names.

## Asynchronous sequences

Inside an async method, `for await item in sequence` consumes an `IAsyncEnumerable(T)`. This lets .NET APIs yield values over time without blocking between elements. The sequence's cancellation and disposal behavior still follows its .NET contract. Keep synchronous spans out of suspended lifetimes; use an appropriate memory owner when async code must retain a buffer.

## Continue reading

- Previous: [Attributes and native interop](https://alice-lang.org/documentation/language/attributes.md)
- Next: [Arrays, lists, and iterators](https://alice-lang.org/documentation/library/collections.md)
