Skip to content

Syntax for Piecewise? #326

Description

@WhiteBlackGoose

What would be a good syntax for piecewise-defined function? Currently, it's

  • Piecewise(a provided b, c provided d) without the otherwise case
  • Piecewise(a provided b, c provided d, e) with the otherwise case.

By this time, multiple ideas have been considered:

  • a if b else c (but how to expand for more than two cases?)
  • (a if b, c if d, ..., e) (but will there be no conflicts in the future?)
  • (a if b else c if d else ..., e) (is it readable enough?)
  • piecewise((a, b), (c, d), ..., e) (sympy's way)
  • if a then b elif c then d ... else e (is it convenient?)

Your ideas are welcomed

Activity

  1. unpinned this issue on Jun 12, 2024
  2. Rafael-SOWNet commented on Aug 16, 2026

    @Rafael-SOWNet
    Member

    Two measured things for the syntax discussion, on master at a45a7256.

    1. The syntax in the issue body does not parse. Piecewise(...) capitalised is an UnhandledParseException; only lowercase piecewise(...) works.

    written result
    Piecewise(a provided b, c provided d) UnhandledParseException
    piecewise(a provided b, c provided d) parses
    piecewise(a provided b, c provided d, e) parses, prints as piecewise(a provided b, c provided d, e provided True)
    a provided b parses on its own

    Worth fixing in the issue text either way, since anyone evaluating alternatives will try the incumbent first.

    2. The incumbent round-trips, and that is a criterion the alternatives should have to meet. Every form above satisfies expr.Stringize().ToEntity() == expr, including the otherwise case and a Piecewise built through MathS.Piecewise rather than parsed.

    That is not free — it is exactly what Rational and Complex fail (#873): they print as an operator and parse back as the operator, so the round trip is not an identity. EveryNodeSurvivesEveryPipelineTest holds the tree to this property and carries those two as its only known exclusions.

    So of the candidates listed:

    • piecewise((a, b), (c, d), ..., e) — sympy's — keeps a function-call shape and would round-trip as easily as the current one.
    • a if b else c and (a if b, c if d, ..., e) introduce infix forms, and an infix form is where round-tripping usually breaks: the printer has to reproduce precedence and the parser has to recover the same tree. Worth prototyping the printer alongside the grammar rather than after it.
    • if a then b elif c then d ... else e reads well but is a statement shape in an expression grammar, and else would need to bind unambiguously against the surrounding expression.

    I have no strong preference on which reads best — that is taste and it is yours. What I would suggest is making "prints and parses back to the same tree" an explicit requirement of whichever wins, because the library already has two node types that do not, and it costs real work to live with.

  3. Happypig375 commented on Sep 18, 2026

    @Happypig375
    Member

    We use the "for" keyword in LaTeX round-tripping today. Using provided keyword here will fail to round-trip provided nodes at the last arm back as provided nodes, which will be a problem for #323. So I'd say we use something like for here, with piecewise(...) outside. Part of v3 redesign

  4. added this to the 3.0 milestone on Sep 18, 2026
  5. Happypig375 commented on Sep 27, 2026

    @Happypig375
    Member

    If there are no oppositions to using for like this for v3 (we don't have "for loops" in a math language... right??? we use summation, product etc) then this would be a triaged feature

  6. Rafael-SOWNet commented on Sep 27, 2026

    @Rafael-SOWNet
    Member

    No objection from me. for is how cases are written in text (x^2 for x >= 0), and it leaves provided free to round-trip as the node it is. The one use it would rule out is a comprehension, { x^2 for x in ZZ }, and the library writes that as image(...) already, so nothing collides.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions