recursive types
Translation status: العربية reader-locale proof. Term names and code fences follow the ar pack; supporting prose may still be English.
A تمايز or صنف may name itself in its own fields; every backend gives it a finite carrier.
Syntax: تمايز <name> { <Variant> { <name> <field> } } · صنف <name> { <name> ∪ نوع_لاشيء <field> }
Category#
type
Related#
Examples#
radix/corpus/recursio/expressio-arbor.fab (canonical · feature)#
A تمايز or صنف may name itself in its own fields; every backend gives it a finite carrier.
# =============================================================================
# recursive types — a type may refer to itself in its own fields.
# =============================================================================
#
# What this teaches:
# • Recursive تمايز — `Expr` variants hold `Expr` operands, so a value
# is a whole expression tree. `طابق` walks it recursively.
# • Recursive صنف — `Nodus` holds a nullable `Nodus` link, so a value is a
# linked list ending in `نوع_لاشيء`.
# • No keyword, no box type — Faber values alias by reference, so the
# indirection is implied. Backends that store fields inline (Rust) insert
# the pointer themselves on the fields that close the cycle.
#
# Common mistakes:
# • A non-nullable self field on a صنف (`Nodus next`) — no value can ever
# be built, because every node needs another node. End the chain with
# `∪ نوع_لاشيء`, or recurse through a تمايز with a leaf variant.
#
# See also: تمايز, صنف, طابق, أنشئ, نوع_لاشيء
# =============================================================================
#
# EXPECTED OUTPUT:
# 14
# (2 + (3 * 4))
# -9
# 6
# 3
# 2
# 15
union Expr {
Numerus {
int قيمة
},
Nega {
Expr interior
},
Adde {
Expr sinister
Expr dexter
},
Multiplica {
Expr sinister
Expr dexter
}
}
fn evalua(Expr e) → int {
match e {
case Numerus const قيمة {
return قيمة
}
case Nega const interior {
return 0 - evalua(interior)
}
case Adde const sinister, dexter {
return evalua(sinister) + evalua(dexter)
}
case Multiplica const sinister, dexter {
return evalua(sinister) * evalua(dexter)
}
}
}
fn depinge(Expr e) → string {
match e {
case Numerus const قيمة {
return "§"(قيمة)
}
case Nega const interior {
return "-§"(depinge(interior))
}
case Adde const sinister, dexter {
return "(§ + §)"(depinge(sinister), depinge(dexter))
}
case Multiplica const sinister, dexter {
return "(§ * §)"(depinge(sinister), depinge(dexter))
}
}
}
class Nodus {
var int قيمة
var Nodus ∪ none sequens
}
fn المجموع(Nodus ∪ none n) → int {
if n is none {
return 0
}
return n.valor + المجموع(n.sequens)
}
fn longitudo(Nodus ∪ none n) → int {
if n is none {
return 0
}
return 1 + longitudo(n.sequens)
}
main {
const Expr tres ← variant Numerus { قيمة = 3 }
const Expr productum ← variant Multiplica { sinister = tres, dexter = variant Numerus { قيمة = 4 } }
const Expr arbor ← variant Adde { sinister = variant Numerus { قيمة = 2 }, dexter = productum }
print evalua(arbor)
print depinge(arbor)
print evalua(variant Nega { interior = variant Adde { sinister = tres, dexter = variant Numerus { قيمة = 6 } } })
var Nodus caput ← Nodus { قيمة = 1, sequens = Nodus { قيمة = 2, sequens = Nodus { قيمة = 3, sequens = null } } }
print المجموع(caput)
print longitudo(caput)
print caput?.sequens?.valor
caput.sequens ← Nodus { قيمة = 14, sequens = null }
print المجموع(caput)
}Expected output:
14
(2 + (3 * 4))
-9
6
3
2
15