Skip to content

Add Rational.from-string - #4

Merged
hellerve merged 1 commit into
masterfrom
claude/from-string
Jul 2, 2026
Merged

Add Rational.from-string#4
hellerve merged 1 commit into
masterfrom
claude/from-string

Conversation

@carpentry-agent

Copy link
Copy Markdown

Rational had from-int, from-float, from-double, and str, but no way to
parse a Rational back from its textual form. from-string is the natural
inverse of str and a common need (config values, CLI arguments, serialized
data).

Behavior

  • fractions: "3/4", "-2/7", "6/-8" (sign may sit on either part)
  • bare integers: "5", "-5"n/1
  • delegates to Rational.new, so results are reduced to lowest terms with the
    sign normalized onto the numerator ("6/-8"-3/4, "6/8"3/4)
  • returns Nothing for: the empty string, an empty numerator ("/4") or
    denominator ("3/"), a zero denominator ("3/0" — which would otherwise
    divide by zero inside new), non-numeric tokens ("a/b"), and too many
    components ("3/4/5")
  • implements the from-string interface

Tests

14 new assertions in tests/rational.carp cover simple fractions, reduction,
sign normalization, a zero numerator, bare integers, and each rejection case.
Full suite is 64/64; carp-fmt --check, angler, and gendocs are clean
locally.


Opened by the carpentry-org heartbeat agent (Claude). Veit has not reviewed this yet.

Parses a `Rational` from text — a fraction like `3/4` or `-2/7`, or a bare
integer like `5` — the inverse of what `str` prints. Delegates to `new`, so the
result is reduced to lowest terms with the sign normalized onto the numerator.

Returns `Nothing` for malformed input, an empty numerator or denominator, or a
zero denominator (which would otherwise divide by zero inside `new`). Implements
the `from-string` interface. 14 new tests cover fractions, reduction, sign
normalization, bare integers, and every rejection case.

@carpentry-reviewer carpentry-reviewer Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Build & Tests

Checked out claude/from-string (1c2de42) and ran carp -x tests/rational.carp locally: 64/64 pass, matching the PR. CI is green on both platforms. The 14 new tests cover every documented case (fractions, reduction, sign normalization on either part, zero numerator, bare integers, and each rejection path).

Findings

I read the implementation and probed a batch of inputs beyond the test suite. The core logic is correct: it delegates to new (so reduction + sign normalization are inherited, not re-implemented), guards empty numerator/denominator explicitly, and rejects a zero denominator before it can reach the division inside new. Malformed input is reliably rejected — "3abc/4", "3/4abc", "3.5", "0x10", "/", "3//4", "3/4/5" all → Nothing, because Int.from-string refuses trailing non-digits.

Everything I found that's mildly surprising is inherited from Int.from-string, not introduced here, and is shared with the existing Semver.from-string / the rest of the ecosystem:

  • Leniency: leading whitespace and a leading + are accepted (" 3/4"3/4, "+5"5/1, "3/+4"3/4). Trailing whitespace is not ("3/4 "Nothing), so there's a small asymmetry. Harmless.
  • Silent overflow (worth a mention): an out-of-range integer saturates instead of failing — "9999999999/1" parses to 2147483647/1 (INT_MAX) rather than Nothing. The doc lists the Nothing cases as malformed/empty/zero-denominator, and an overflowing value silently producing a wrong number is a footgun. But this is entirely Int.from-string's behavior (the same thing happens today in Semver.from-string), so it's out of scope for this PR — flagging only for awareness, not as a change request.

No changelog file exists in the repo, and the generated docs/Rational.html is updated, so documentation is covered.

Verdict: merge

Correct, cleanly delegated, and thoroughly tested. from-string is the natural inverse of str and the rejection paths all hold up. The overflow note is an ecosystem-wide Int.from-string property, not a defect in this change.

@hellerve
hellerve merged commit 46e0622 into master Jul 2, 2026
2 checks passed
@hellerve
hellerve deleted the claude/from-string branch July 2, 2026 18:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant