Expressions, comparison and evaluation order¶
Choose output shape from the required behavior. Tuple comparison evaluates its operands differently from a sequence of short-circuit field comparisons. A passing integer equality example does not establish callback or raw-result semantics.
For a field-wise short-circuit algorithm, the intended Python sketch is:
result = left.first == right.first
if not result:
return result
return left.last == right.last
This sketch preserves a falsey non-bool intermediate object and returns the final comparison result without an additional truth conversion. Actual resources must bind direct read paths, preserve deliberate cross-scope locals and order the contributions. Empty operands require an explicit consumer policy. Python minor versions can change the dataclass reference algorithm; do not assume one shape matches every minor.
Status of the recorded nested chain¶
The inventory's nested indexed expression arrangement failed with term_path,
next_term and native-materialization symptoms. Its general cause remains
unresolved. A flat ordered alternative passed a bounded Dataclass differential
corpus; this does not prove the nested mechanism broken or the alternative
universally equivalent. No new nested-chain support is claimed here.
Bare statement-form astichi_ref is value-only and was rejected in the recorded
case. The consumer's static expression carrier (read if True else None) is a
bounded observed alternative. Its precise backend and overhead properties must
be qualified separately; astichi_funcargs is not automatically a scalar tuple
carrier.
Use collection/port ordering and explicit build indices; do not rely on fact insertion for semantic evaluation order. Before promoting a new expression recipe, check falsey non-bool results, the final raw object, nonreflexive/shared operands, getter traces and callback counts. Consumer excerpts link the qualified comparison authority. Compatibility keeps unresolved cases visible.
Executable flat three-operand recipe¶
This new standalone recipe assembles two guarded intermediate comparisons and one final direct return. It checks falsey non-bool identity, callback order, truth-conversion counts, a shared/nonreflexive input and zero operands. It is a bounded algorithm of its own, not an assertion of dataclass equivalence across Python minors. It does not explain or fix the original D17 nested chain.
Source authority: example/documentation/comparison.py.
"""A bounded three-operand short-circuit recipe; not a general dataclass algorithm."""
from __future__ import annotations
import ast
from dataclasses import dataclass
from yidl.concept_parser import compile_yidl_files
from yidl.generation.data_def_sys import emit_concept_runtime_source
SOURCE = """
concept Comparison {
property Name: str
property Order: int
property Last: bool
record Operand { Name Order Last }
collection Operands: Operand identity Name many
resource Root = code $[
def compare(left, right):
astichi_hole(steps)
return True
]$ { keep compare }
resource Step = template $[
result = astichi_pass(left, outer_bind=True).astichi_ref(external=path) == astichi_pass(right, outer_bind=True).astichi_ref(external=path)
if not result:
return result
]$
resource Final = template $[
return astichi_pass(left, outer_bind=True).astichi_ref(external=path) == astichi_pass(right, outer_bind=True).astichi_ref(external=path)
]$
resource Empty = template `pass`
contribution Next = Step {
as Operand index Order order Order target steps { build /Root }
external path = Name
}
contribution LastOperand = Final {
as Operand index Order order Order target steps { build /Root }
external path = Name
}
contribution EmptyOperand = Empty {
as Empty target steps { build /Root }
}
matcher EmptySelection() -> contribution { default -> EmptyOperand }
matcher Select(operand: Operands) -> contribution {
default -> Next
rule final when Last == True -> LastOperand
}
production RootProduction -> composable {
root Root = Root
apply empty using EmptySelection
apply steps from operand: Operands using Select
}
assembly Module = RootProduction
}
"""
@dataclass
class Raw:
truth: bool
conversions: list[bool]
def __bool__(self) -> bool:
self.conversions.append(self.truth)
return self.truth
@dataclass(frozen=True, eq=False)
class Value:
name: str
result: Raw
events: list[str]
def __eq__(self, other: object) -> object:
self.events.append(self.name)
return self.result
@dataclass
class Pair:
first: object
middle: object
last: object
def run() -> str:
concept = compile_yidl_files(
{"comparison.yidl": SOURCE}, "comparison.yidl"
).concepts["Comparison"]
runtime = emit_concept_runtime_source(
concept.plan.build_data_definition(),
resources=concept.resources,
assembly_plan=concept,
)
schema: dict[str, object] = {}
exec(runtime, schema)
builder = schema["new_builder"]()
for name, order, last in (
("last", 30, True),
("first", 10, False),
("middle", 20, False),
):
builder.add(
schema["OperandsCollection"],
schema["Operand"](name=name, order=order, last=last),
)
tree = schema["build_Module"](builder.freeze()).to_executable_ast()
namespace: dict[str, object] = {}
exec(compile(tree, "comparison_model.py", "exec"), namespace)
compare = namespace["compare"]
events: list[str] = []
yes, no, final = Raw(True, []), Raw(False, []), Raw(False, [])
left = Pair(
Value("first", no, events),
Value("middle", yes, events),
Value("last", final, events),
)
right = Pair(object(), object(), object())
assert compare(left, right) is no
assert events == ["first"] and no.conversions == [False]
events.clear()
left.first = Value("first", yes, events)
assert compare(left, right) is final
assert events == ["first", "middle", "last"]
assert yes.conversions == [True, True] and final.conversions == []
events.clear()
# There is no implicit identity shortcut for shared/nonreflexive values.
assert compare(left, left) is final
assert events == ["first", "middle", "last"]
empty_tree = schema["build_Module"](
schema["new_builder"]().freeze()
).to_executable_ast()
empty_namespace: dict[str, object] = {}
exec(compile(empty_tree, "empty_comparison.py", "exec"), empty_namespace)
assert empty_namespace["compare"](left, right) is True
return ast.unparse(tree) + "\n"
if __name__ == "__main__":
print(run(), end="")
Source authority: tests/data/goldens/materialized/documentation_classes/comparison_model.py.
def compare(left, right):
pass
result = left.first == right.first
if not result:
return result
result__astichi_scoped_1 = left.middle == right.middle
if not result__astichi_scoped_1:
return result__astichi_scoped_1
return left.last == right.last
return True