# Coming from Ruby or C#

> Understand which familiar ideas transfer and where Alice has different rules.

Canonical: https://alice-lang.org/documentation/learn/from-ruby/

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

## From Ruby and Crystal

The syntax is familiar: `def`, `end`, blocks, symbols, implicit returns, predicate names ending in `?`, and `case` patterns. The execution model is statically compiled .NET.

| Familiar form        | Alice rule                                                                                        |
| -------------------- | ------------------------------------------------------------------------------------------------- |
| `x = 1`              | A statically inferred local; it is not an unconstrained Ruby object slot.                         |
| `def length(x)`      | Parameters specialize for call-site types when possible. Use `Any` to request dynamic binding.    |
| `nil`                | Nullable types must be explicit when inference cannot determine the underlying type.              |
| `class String`       | Adds extension methods to the .NET type; it does not mutate a running Ruby VM.                    |
| `include M`          | Rebinds mixin methods into the receiving class.                                                   |
| `define_method`      | Static forms create real compiled methods; runtime-generated names need dynamic dispatch.         |
| `require "./helper"` | A compile-time file dependency resolved once, relative to the requiring file.                     |
| `xs << value`        | Append to a growable collection such as `List(T)`; ordinary array literals are fixed .NET arrays. |

Not every Ruby library or metaprogramming trick is available. Use Alice's [dynamic and DSL chapter](https://alice-lang.org/documentation/language/dynamic.md) for supported forms, and NuGet for .NET libraries.

## From C\#

Alice types become CLR types, and .NET methods keep their declared case. `StringBuilder.new` corresponds to constructing a `StringBuilder`; `List(Int32)` is generic type application. `::` qualifies constants and nested names.

| C# concept                           | Alice form                                |
| ------------------------------------ | ----------------------------------------- |
| `int`, `double`, `string`, `bool`    | `Int32`, `Float64`, `String`, `Bool`      |
| `int[]`                              | `Array(Int32)` or an inferred `[1, 2, 3]` |
| `List<int>`                          | `List(Int32)`                             |
| method returning its last expression | `def square(x : Int32) : Int32 = x * x`   |
| get-only / read-write property       | `getter` / `property`                     |
| `new Point(1, 2)`                    | `Point.new(1, 2)`                         |
| lambda                               | `->(x : Int32) { x * x }`                 |
| `Task<T>` method                     | `async def` with `await`                  |

Use [interop](https://alice-lang.org/documentation/guides/dotnet.md) for mixed Alice/C# projects. A local project is described by `alice.toml`; the CLI generates its MSBuild project.

## Three differences to remember

**Integer division stays integer.** `7 / 2` is `3`; use a floating operand for `3.5`.

**Reassignment and mutation differ.** `val` freezes the binding, not every object reachable through it.

**Parallelism has a compile-time gate.** A captured list cannot be mutated from concurrent work without synchronization, even though equivalent C# could compile. See [AL0202](https://alice-lang.org/documentation/concurrency/race-safety.md).

## Continue reading

- Previous: [Your first project](https://alice-lang.org/documentation/learn/first-project.md)
- Next: [Programs, files, and names](https://alice-lang.org/documentation/language/programs.md)
