Skip to content

Add lift/unlift functions for seqseq dimension conversion - #2

Merged
namingbe merged 3 commits into
masterfrom
claude/implement-ensv-lift-unlift-804ci
Feb 22, 2026
Merged

Add lift/unlift functions for seqseq dimension conversion#2
namingbe merged 3 commits into
masterfrom
claude/implement-ensv-lift-unlift-804ci

Conversation

@namingbe

Copy link
Copy Markdown
Collaborator

Summary

This PR adds lift and unlift functions to convert between 2D sequences of strings (seqseq) and 1D sequences, enabling dimension reduction/recovery while preserving structural information through escape sequences and empty string delimiters.

Key Changes

  • New module nsv/ensv.py: Implements lift() and unlift() functions

    • lift(seqseq): Converts a 2D sequence into a 1D sequence by escaping special characters (backslashes, newlines, empty cells) and using empty strings as row delimiters
    • unlift(seq): Recovers the original 2D structure from a lifted sequence by unescaping and splitting on empty string delimiters
    • Both functions integrate with existing Reader.unescape() and Writer.escape() utilities
  • Updated nsv/__init__.py: Exports lift and unlift functions for public API access

  • Comprehensive test suite tests/test_ensv.py:

    • 194 lines of unit tests covering edge cases (empty rows, ragged rows, special characters)
    • Roundtrip tests verifying unlift(lift(x)) == x and lift(unlift(y)) == y
    • Escape invariant tests ensuring lifted sequences contain no newlines

Implementation Details

  • lift() requires non-empty input (raises ValueError for empty seqseq since [] is irrepresentable)
  • Escaping rules: backslashes → \\, newlines → \n, empty cells → \
  • Row boundaries are marked by empty strings in the lifted sequence
  • The final terminator is discarded to preserve line numbers in the original structure

https://claude.ai/code/session_01PuxiBkVsjVDzcSopK3kNRg

Add nsv/ensv.py with lift and unlift functions as defined in the ENSV
spec. lift collapses a seqseq into a single row using separator
semantics (init ∘ spill[String, ''] ∘ map(map(escape))), and unlift
recovers the original structure by unescaping and splitting on empty
strings. Includes 31 tests covering escaping, empty rows, ragged data,
and bidirectional roundtrip properties.

https://claude.ai/code/session_01PuxiBkVsjVDzcSopK3kNRg
Rewrite lift to use separator semantics directly instead of going
through spill+init. Remove ValueError for empty input (caller's
responsibility). Remove lift/unlift from top-level namespace. Add
decomposition equivalence test.

https://claude.ai/code/session_01PuxiBkVsjVDzcSopK3kNRg
Use existing SAMPLES_DATA from test_utils for roundtrip and
decomposition equivalence tests instead of maintaining a separate
set of cases. Trim redundant unit tests that are covered by samples.

https://claude.ai/code/session_01PuxiBkVsjVDzcSopK3kNRg
@namingbe
namingbe merged commit 57e4f09 into master Feb 22, 2026
10 checks passed
@namingbe
namingbe deleted the claude/implement-ensv-lift-unlift-804ci branch March 14, 2026 19:08
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.

2 participants