05 — Casts, Try und Fallible Boundaries¶
Status: Konsolidierungsentwurf
1. CastTo bleibt ein Protocol¶
Konversion ist weiterhin eine gerichtete Relation zwischen Source und Target über CastTo[T].
provide CastTo[UserResponse] for User {
def castTo(self) -> UserResponse = UserResponse {
id: self.id
name: self.name
email: self.email
}
}
2. Cast-Modus gehört zur Relation¶
Ein Cast hat genau einen Modus:
Lossless
total, verlustfrei, implizit zulässig
Narrowing
total, aber verlustbehaftet, nur explizit
Try[E]
fallibel, liefert Result[T, E]
Empfohlene neue Schreibweise:
provide CastTo[UserSummary] for User
:> CastMode(Narrowing)
{
def castTo(self) -> UserSummary = UserSummary {
name: self.name
}
}
provide CastTo[UserId] for User
:> CastMode(Try[ConvError])
{
def castTo(self) -> Result[UserId, ConvError] =
if self.id.value.isEmpty() then
Err(ConvError.InvalidId)
else
Ok(self.id)
}
Alternativ kann CastMode als Associated Meta im provide-Block normalisiert werden. Wichtig ist nicht die Oberflächensyntax, sondern die Semantik:
3. try als fallible Scope¶
try erzeugt einen fallible Boundary-Scope.
parsed hat den Typ:
abhängig von den Fehlern im Block.
4. =? propagiert zur nächsten Boundary¶
=? bedeutet nicht mehr hart „return aus Funktion“.
Regel:
Propagation Boundaries:
ASCII:
def f(...) -> Result[T, E] {
val r = try {
val x =? op1()
val y =? op2(x)
y
}
val z =? r
Ok(z)
}
inneres =? -> verlässt try-Block
äußeres =? -> verlässt Funktion
5. Kein redundantes try bei sofortiger Propagation¶
Nicht nötig:
Wenn der Ausdruck sofort mit =? konsumiert wird, reicht:
Innerhalb eines try-Blocks propagiert =? nur bis zum Block.
6. Fallible Ergebnis behalten¶
Wenn das fallible Ergebnis als Wert behalten werden soll, wird try verwendet.
oder als Kurzform, falls später zugelassen:
MVP-Empfehlung:
7. Weak -> Strong¶
Weak-Upgrades passen in dieselbe Kategorie.
Wenn upgrade() Option[Strong[Node]] liefert, endet der try-Block bei None mit None, nicht mit einem Funktions-Return.
8. Normative Regeln¶
F-1: `try { ... }` ist ein Ausdruck.
F-2: Ein try-Block erzeugt eine Propagation Boundary.
F-3: `=?` propagiert immer nur zur nächsten Boundary.
F-4: Innerhalb einer Funktion ohne try-Block ist die Funktion die nächste Boundary.
F-5: `try` selbst führt keinen Runtime-Return aus der umgebenden Funktion aus.
F-6: `=?` darf nur auf propagierbare Container angewendet werden.
F-7: Fallible Casts liefern Result[T, E].
F-8: Weak-Upgrades liefern Option[T] und können über try-Boundaries lokal behandelt werden.