You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Stringize drops a node's Codomain, so domain(x, ZZ) prints as x and does not round trip #1022
Stringize prints no node's Codomain, so a node that carries one prints as though it did not, and
parsing the result gives a different node back. Same shape as #873, which was the Rational/Divf
case, and the last one I can find.
vard=MathS.FromString("domain(x, ZZ)");d.GetType()// Entity.Variabled.Codomain// Integerd.Stringize()// "x"
MathS.FromString(d.Stringize()).Codomain// Any
d ==MathS.FromString(d.Stringize())// False
The parser has the syntax already — domain(expr, SET) maps straight onto WithCodomain, and it
works for every node, not only variables:
It is not confined to a node somebody wrote domain(...) around, because the codomain travels with
the subnode:
vare=MathS.Sin(MathS.Var("x").WithCodomain(Domain.Integer))+MathS.Var("y").WithCodomain(Domain.Real);e.Stringize()// "sin(x) + y" -- both annotations gone
Codomain is not decoration: it decides evaluation. sqrt(-1) is i, and the same expression with Codomain = Real is NaN — the example in Domains.Definition.cs says exactly this, and prints the
same string for both.
Why it matters beyond the round trip: the printed form is the library's exchange format, so anything
that writes an expression out — a file, a database column, EntityJsonConverter (#323) — loses the
annotation silently, and a caller who narrowed a domain gets it back widened with no error anywhere.
StringizeRoundTripsToTheSameNode in EveryNodeSurvivesEveryPipelineTest does not catch it because
the samples it builds all carry the default codomain for their type. A node with a narrowed one is
worth adding there whichever way this is fixed.
Two ways to fix, and they are not equivalent:
print domain(<inner>, SET) wherever a node's codomain is not the one the parser would give the
same text. Round trip becomes an identity; output for the ordinary case is unchanged, since the
ordinary case has the default.
decide that Codomain is not part of a node's identity and take it out of record equality — which
is roughly Unify Codomain with a "provided ... in RR" condition #721's direction, where the constraint becomes a provided ... in RR condition that is printed.
The first is the smaller fix and does not prejudge #721.
Stringizeprints no node'sCodomain, so a node that carries one prints as though it did not, andparsing the result gives a different node back. Same shape as #873, which was the
Rational/Divfcase, and the last one I can find.
Measured on
v2.3.0(6b93b40):The parser has the syntax already —
domain(expr, SET)maps straight ontoWithCodomain, and itworks for every node, not only variables:
so this is only the printing half being absent.
It is not confined to a node somebody wrote
domain(...)around, because the codomain travels withthe subnode:
Codomainis not decoration: it decides evaluation.sqrt(-1)isi, and the same expression withCodomain = RealisNaN— the example inDomains.Definition.cssays exactly this, and prints thesame string for both.
Why it matters beyond the round trip: the printed form is the library's exchange format, so anything
that writes an expression out — a file, a database column,
EntityJsonConverter(#323) — loses theannotation silently, and a caller who narrowed a domain gets it back widened with no error anywhere.
StringizeRoundTripsToTheSameNodeinEveryNodeSurvivesEveryPipelineTestdoes not catch it becausethe samples it builds all carry the default codomain for their type. A node with a narrowed one is
worth adding there whichever way this is fixed.
Two ways to fix, and they are not equivalent:
domain(<inner>, SET)wherever a node's codomain is not the one the parser would give thesame text. Round trip becomes an identity; output for the ordinary case is unchanged, since the
ordinary case has the default.
Codomainis not part of a node's identity and take it out of record equality — whichis roughly Unify Codomain with a "provided ... in RR" condition #721's direction, where the constraint becomes a
provided ... in RRcondition thatis printed.
The first is the smaller fix and does not prejudge #721.