On this page

Expressions, contracts and patterns

Look up evaluation, scoped results, successful-exit checks and branch-local values. The linked specification rules are authoritative; the guide teaches these constructs through programs.

Operators, conditionals and assignment

Form Behavior Rules
a / b Fractional division; integer operands promote to Double before calculation CS-ARITH-001
a div b Quotient truncated toward zero; fractional/compatible mixed inputs produce Long via CLR quotient conversion CS-ARITH-002/006
a mod b .NET-like remainder, not Euclidean modulo CS-ARITH-002
not age >= 18 Negates the comparison CS-EXPR-004
age >= 18 and <= 65 Reuses the once-evaluated subject with short-circuiting CS-EXPR-005
if(c, a, b) Evaluates only the selected result CS-EXPR-006
if(c, a) / ifnot(c, b) Returns nothing when its branch is unselected CS-EXPR-006–CS-EXPR-007
value ?? fallback Lazy fallback only on actual absence CS-EXPR-008
value ?? throw Check at expression execution only; no persistent assignment policy. Direct parameter uses ArgumentNullException, other expressions NullReferenceException CS-EXPR-009
target ??= expression Lazy null fill; once-only target evaluation; writable target required CS-ASSIGN-001–CS-ASSIGN-002
a = b = Load() One final RHS evaluation; rightmost local assigned first CS-ASSIGN-003
checked(...) / unchecked(...) Ordinary C# overflow context for applicable expressions CS-OVERFLOW-001–CS-OVERFLOW-003

Block overflow forms use matching end checked / end unchecked. A context does not suppress unrelated exceptions or change arithmetic inside imported methods. mod= is supported; div= is not inferred from the existence of div.

Operands execute once in source order; grouping is a separate concern. Unselected conditional/fallback operands do not execute. Default substitution applies locally to supported authored arithmetic, preserving stored absence and imported operator contracts. The old persistent ?? nothing policy is superseded.

See chapter 6 for diagnostics and reference lowerings, and appendix B for confirmed grouping relationships. Use parentheses when combining unfamiliar operators. Imported operators retain their declared CLR behavior.

Expression select and take

let fee = select customer.Type
    case .Vip
        take 0
    else
        take 20
end select

First matching case wins, without fall-through. Every normally completing selected path has a final take; an exceptional path needs no manufactured value. An else is required unless selection is provably complete. Results need a common/contextual type. return still exits the action. Missing cases do not synthesize nothing or default.

CS-SELECT-001–CS-SELECT-006, invalid paths and reference switch lowering: chapter 7. take is limited to approved supporting scopes; it does not make arbitrary blocks expressions.

require, ensure and old_value_of

Construct Evaluation Failure/constraint
require condition Immediately when executed Fail-fast, ordinary .NET exception
ensure condition On normal completion, after required finally blocks Failure prevents successful return
result Captured return value No repeated return-expression evaluation
old_value_of(source) Capture before body/require; constructors first complete generated initialization Once per eligible source in first-written-occurrence order; captured outer locals allowed, body locals/calls/arithmetic excluded

Default failures: absent required action parameter → ArgumentNullException with parameter name; attributable parameter constraint → ArgumentException/appropriate subclass; state or unclear attribution → InvalidOperationException; every ensure failure → InvalidOperationException.

Exceptional exits skip postconditions. Do not lower ensure into finally. Conditions must not be reevaluated for error messages, which identify source expressions without including runtime values.

CS-CONTRACT-001–CS-CONTRACT-010 and the synchronous C# example: chapter 12. Use otherwise to supply a message or exception expression. It does not introduce a control-flow branch.

Pattern and regex captures

is like uses wildcards: * means zero or more, ? exactly one. Sequence patterns require suitable ordered, indexable targets and permit at most one variable-length wildcard per nesting level. Exact = does not interpret wildcard syntax.

if fileName is like "report-{{let name = *}}.csv" then
    Print(name)
end if

Regex uses ordinary .NET named groups, not wildcard capture syntax:

Known regex group Promoted local / value
Non-repeat-capable, participating String; may be empty
Non-repeat-capable, nonparticipating nothing
Repeat-capable List of all captured strings, in capture order
Repeat-capable with zero captures Empty list
Name outside DirectSharp ASCII identifier grammar No promoted local; regex remains valid
Dynamic pattern No invented locals

Captures exist in the successful branch. Keyword names use @; case-colliding promotable names are compile-time errors. Repeatability depends on regex structure, not a particular match. Ordinary matching is case-insensitive; is match_case_sensitive is explicit.

CS-PATTERN-001–CS-PATTERN-005 and CS-REGEX-001–CS-REGEX-006: chapter 16, including capture typing and diagnostics.

Lazy values

let customer = lazy LoadCustomer(id)

The entire initializer waits for first ordinary value use; captured mutable values are read then. One initializer executes even under concurrent first reads. Successful values, including nothing, and exceptions are cached. There is no retry. The source binding is assign-once and transparently has the computed value's type.

Predicate True when Forces initialization?
is initialized Successfully completed, including nothing No
is not initialized Not started, working or faulted No
is working Initializer executing No
is faulted Cached initialization failure No

The optional report index shows a complete ordinary class example, force-time captures, resource lifetime and a C# state/publication pattern.

Recursive forcing fails clearly. Safe publication does not make the computed object's mutation thread-safe. CS-LAZY-001–CS-LAZY-008 and the limits of System.Lazy lowering: chapter 18.