diff options
Diffstat (limited to 'js/scripting-lang/design/HISTORY/FUNCTION_COMPOSITION_PLAN.md')
-rw-r--r-- | js/scripting-lang/design/HISTORY/FUNCTION_COMPOSITION_PLAN.md | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/js/scripting-lang/design/HISTORY/FUNCTION_COMPOSITION_PLAN.md b/js/scripting-lang/design/HISTORY/FUNCTION_COMPOSITION_PLAN.md new file mode 100644 index 0000000..34ee728 --- /dev/null +++ b/js/scripting-lang/design/HISTORY/FUNCTION_COMPOSITION_PLAN.md @@ -0,0 +1,192 @@ +# Function Composition & Currying Design Plan - REVISED + +## Current Issue Analysis + +### Problem Statement +The current function application implementation has a fundamental flaw for function composition: + +```javascript +f g x // Currently parsed as: apply(apply(f, g), x) + // This fails because: apply(f, g) = NaN (f expects a number, not a function) + // Then: apply(NaN, x) = Error +``` + +### Root Cause +1. **Left-associative parsing**: `f g x` → `(f g) x` → `apply(apply(f, g), x)` +2. **Non-curried functions**: Functions expect specific argument types, not other functions +3. **Missing composition semantics**: No built-in understanding of function composition + +## Design Decision: Simplified Approach + +### Option 1: Full Currying (Haskell-style) ❌ +**Why not**: Major architectural change, breaks existing code, complex implementation + +### Option 2: Explicit Composition Only ✅ **RECOMMENDED** +**Why this is better**: +- **No ambiguity**: `f via g x` is always composition, `f g x` is always left-associative application +- **Backward compatible**: All existing code works unchanged +- **Clear intent**: Explicit composition makes code more readable +- **No complex detection**: No need for runtime type checking +- **Natural language**: `via` reads like English and is self-documenting + +### Option 3: Hybrid Approach ❌ +**Why not**: Overcomplicated, introduces ambiguity, harder to understand + +## Recommended Solution: Explicit Composition Only + +### 1. Keep Current Function Application +- `f x` → `apply(f, x)` (immediate application) +- `f g x` → `apply(apply(f, g), x)` (left-associative, as currently implemented) +- Functions remain non-curried by default +- Maintains current behavior for simple cases + +### 2. Add Explicit Composition Keyword +- `f via g` → `compose(f, g)` (explicit composition) +- `f via g via h` → `compose(f, compose(g, h))` (right-associative) +- `f via g x` → `apply(compose(f, g), x)` (composition then application) +- Clear and explicit about intent + +### 3. Fix and Enhance @ Operator +- `@f` → function reference (fix current parsing issues) +- `map(@f, [1,2,3])` → pass function as argument +- `when x is @f then ...` → pattern matching on functions +- Essential for higher-order programming + +### 4. Enhanced Standard Library +- Improve `compose` function to handle multiple arguments +- Add `pipe` for left-to-right composition +- Add `curry` and `uncurry` utilities for when needed + +## Implementation Plan + +### Phase 1: Lexer Enhancement +- Add composition keyword (`via`) +- Fix `@` operator parsing issues +- Update token precedence + +### Phase 2: Parser Enhancement +- Add `parseComposition()` function +- Fix `parsePrimary()` to handle `@` operator correctly +- Implement explicit composition parsing + +### Phase 3: Standard Library Enhancement +- Improve `compose` function +- Add `pipe` function +- Add `curry`/`uncurry` utilities + +### Phase 4: Testing & Validation +- Test all composition scenarios +- Ensure backward compatibility +- Performance testing + +## Syntax Examples + +### Current (Working) +```javascript +f : x -> x * 2; +g : x -> x + 1; + +result1 : f x; // apply(f, x) = 10 +result2 : f (g x); // apply(f, apply(g, x)) = 12 +``` + +### Proposed (Enhanced) +```javascript +f : x -> x * 2; +g : x -> x + 1; + +result1 : f x; // apply(f, x) = 10 +result2 : f via g x; // apply(compose(f, g), x) = 12 +result3 : pipe(f, g) x; // apply(pipe(f, g), x) = 12 +result4 : @f; // function reference to f +result5 : map(@f, [1,2,3]); // [2, 4, 6] + +// Natural language examples +data : [1, 2, 3, 4, 5]; +result6 : data via filter via map via reduce; // Pipeline example +result7 : x via abs via double via add(10); // Mathematical pipeline +``` + +## Why `via` is Better Than `.` + +### 1. **Natural Language** +- `f via g x` reads like "f via g applied to x" +- `data via filter via map` reads like "data via filter via map" +- More intuitive for non-FP developers + +### 2. **No Conflicts** +- No confusion with decimal numbers +- No conflict with object property access +- Won't interfere with existing syntax + +### 3. **Clear Intent** +- Explicitly indicates composition +- Self-documenting code +- No ambiguity about what's happening + +### 4. **Better Error Messages** +- "Expected function after 'via'" is clearer than "Expected function after '.'" +- More natural error reporting + +### 5. **Accessibility** +- Lower learning curve +- No prior FP knowledge needed +- Intuitive for beginners + +## Backward Compatibility + +### Guaranteed to Work +- All existing function calls: `f x` +- All existing operator expressions: `x + y` +- All existing function definitions +- All existing when expressions +- All existing table operations + +### New Features (Optional) +- Explicit composition: `f via g` +- Fixed function references: `@f` +- Enhanced standard library functions + +## Why This Approach is Better + +### 1. Simplicity +- No complex detection logic +- No runtime type checking +- Clear, predictable behavior + +### 2. Clarity +- `f g x` always means `(f g) x` +- `f via g x` always means `f(g(x))` +- No ambiguity about intent + +### 3. Familiarity +- `via` is intuitive and self-explanatory +- No mathematical notation to learn +- Easy to understand and teach + +### 4. Flexibility +- Users can choose when to use composition +- No forced architectural changes +- Easy to extend later if needed + +## Next Steps + +1. **Implement Phase 1**: Add composition keyword to lexer, fix @ operator +2. **Implement Phase 2**: Add composition parsing to parser +3. **Implement Phase 3**: Enhance standard library +4. **Test thoroughly**: Ensure all existing code still works +5. **Document**: Update language documentation +6. **Examples**: Create comprehensive examples + +## Success Criteria + +- [ ] `f via g x` works correctly for function composition +- [ ] `@f` works correctly for function references +- [ ] All existing code continues to work unchanged +- [ ] Performance impact is minimal +- [ ] Error messages are clear and helpful +- [ ] Documentation is comprehensive + +## Conclusion + +The explicit composition approach using `via` is simpler, clearer, and more maintainable than the hybrid approach. It provides the functionality we need without the complexity and potential ambiguity of automatic detection. The `via` keyword makes the language more accessible and self-documenting, while maintaining all the power of functional composition. Combined with fixing the `@` operator, this gives us a powerful and clear functional programming language. \ No newline at end of file |