relateby-pattern 0.2.8

Core pattern data structures
Documentation
# Python API Changes - Pattern Construction

**Date**: 2026-01-27  
**Version**: 0.2.0 (Breaking Changes)

## Summary

This document describes breaking changes made to the Python pattern-core API to improve clarity and follow functional programming conventions.

## Changes

### 1. Removed: `Pattern.from_list(value, values)`

**Old API (Removed):**
```python
# Confusing: takes both a root value and a list of values
pattern = Pattern.from_list("root", [1, 2, 3])
```

**Why Removed:**
- Confusing signature: name implies it takes only a list
- Hidden nesting: the `value` parameter wasn't obvious
- Not intuitive for users expecting a simple "list → pattern" conversion

### 2. Added: `Pattern.from_values(values) → List[Pattern]`

**New API:**
```python
# Clear: converts values to a list of atomic patterns
patterns = Pattern.from_values([1, 2, 3])
# Returns: [Pattern.point(1), Pattern.point(2), Pattern.point(3)]

# For nested structures, be explicit:
root = Pattern.pattern("root", Pattern.from_values([1, 2, 3]))
```

**Benefits:**
- ✅ Does ONE thing: converts values → patterns
- ✅ Name matches behavior: "from values" returns patterns
- ✅ Explicit nesting via `Pattern.pattern()`
- ✅ No hidden parameters
- ✅ Return type is clear (list of patterns)

**Type Signature:**
```python
@staticmethod
def from_values(values: List[Any]) -> List[Pattern]:
    """Convert a list of values into a list of atomic patterns."""
```

### 3. Added: `Pattern.of(value) → Pattern`

**New API:**
```python
# Alias for Pattern.point()
p1 = Pattern.point(42)
p2 = Pattern.of(42)
# Both create identical atomic patterns
```

**Benefits:**
- ✅ Follows functional programming convention
- ✅ Familiar to developers from other FP languages
-`of` typically lifts a value into a functor/applicative
- ✅ Zero runtime overhead (inlined alias)

**Type Signature:**
```python
@staticmethod
def of(value: Any) -> Pattern:
    """Alias for point(). Lift a value into a Pattern."""
```

## Migration Guide

### Migrating from `from_list`

**Before:**
```python
# Old API
pattern = Pattern.from_list("root", [1, 2, 3, 4, 5])
```

**After (Option 1 - Explicit structure):**
```python
# New API: explicit decoration
elements = Pattern.from_values([1, 2, 3, 4, 5])
pattern = Pattern.pattern("root", elements)
```

**After (Option 2 - Manual construction):**
```python
# Alternative: manual construction
pattern = Pattern.pattern("root", [
    Pattern.point(1),
    Pattern.point(2),
    Pattern.point(3),
    Pattern.point(4),
    Pattern.point(5)
])
```

**After (Option 3 - Just the list):**
```python
# If you don't need a root, just use the list
patterns = Pattern.from_values([1, 2, 3, 4, 5])
# Use patterns directly
```

### Using `Pattern.of()`

**New (preferred for FP style):**
```python
# Functional programming style
pattern = Pattern.of(42)
```

**Still works (original API):**
```python
# Original style still available
pattern = Pattern.point(42)
```

## Examples

### Creating a decorated pattern

```python
import pattern_core as pc

# Old way (removed):
# root = pc.Pattern.from_list("root", ["a", "b", "c"])

# New way (explicit decoration):
# The value decorates/describes the pattern represented by the elements
elements = pc.Pattern.from_values(["a", "b", "c"])
decorated = pc.Pattern.pattern("decoration", elements)

print(f"Decoration: {decorated.value}")
print(f"Elements: {decorated.length()}")
```

### Functional style

```python
import pattern_core as pc

# Using Pattern.of() for functor/applicative style
data = [1, 2, 3, 4, 5]

# Create patterns functionally
patterns = [pc.Pattern.of(x) for x in data]

# Or use the convenience method
patterns = pc.Pattern.from_values(data)

# Build tree
tree = pc.Pattern.pattern("numbers", patterns)
```

### Converting existing code

```python
import pattern_core as pc

# Before (BROKEN):
# def build_graph(decoration, values):
#     return pc.Pattern.from_list(decoration, values)

# After (FIXED):
def build_graph(decoration, values):
    elements = pc.Pattern.from_values(values)
    return pc.Pattern.pattern(decoration, elements)

# Usage remains similar:
graph = build_graph("users", [1, 2, 3, 4, 5])
```

## Rationale

### Why break compatibility?

1. **Clarity**: The old API was confusing to users
2. **Single Responsibility**: `from_values` does one thing well
3. **Explicit > Implicit**: Nesting is now explicit via `Pattern.pattern()`
4. **Standards**: `Pattern.of()` follows FP conventions
5. **Clean**: Better to break once than carry confusion forever

### Design Principles

The new API follows these principles:

1. **Names match behavior**: `from_values` returns patterns (plural)
2. **One function, one job**: No hidden structure creation
3. **Explicit decoration**: Use `Pattern.pattern()` to decorate elements with a value
4. **FP conventions**: `of` for lifting values
5. **Type clarity**: Return types match names

## Testing

All existing tests have been updated. Key test changes:

```python
# Before:
p = Pattern.from_list("root", [1, 2, 3])

# After:
p = Pattern.pattern("root", Pattern.from_values([1, 2, 3]))
```

## Documentation Updates

- ✅ Type stubs updated (`__init__.pyi`)
- ✅ Examples updated (`basic_usage.py`, `operations.py`)
- ✅ API documentation updated
- ✅ This migration guide created

## Questions?

For questions or issues with the migration:
1. Check examples in `examples/pattern-core-python/`
2. Review type stubs in `pattern_core/__init__.pyi`
3. See tests in `crates/pattern-core/tests/python/`

## Version History

- **v0.1.0**: Original API with `from_list(value, values)`
- **v0.2.0**: Breaking change - removed `from_list`, added `from_values` and `of`