Commit2b96acb1Recorded4 Jul 2026Repositorysigil-fp

Re-export threading macros from core

Message

chain.sgl re-exports ->/chain/some-> from (sigil core) instead of defining them locally, following the 2026-07-04 decision to return the threading macros to core. Dual-import (core + fp) verified conflict-free. Rebased onto v0.9.2; the manifest modernization from v0.9.2 is kept as-is (no version bump here).

Changed
 README.md              |  10 ++++++++++
 src/sigil/fp.sgl       |  25 ++++++++++++++++---------
 src/sigil/fp/chain.sgl | 131 ++++++++++++++++++-----------------------------------------------------------------------------------------------------------------
 3 files changed, 44 insertions(+), 122 deletions(-)
Diff
README.mdmodified
@@ -91,7 +91,17 @@ Apply multiple functions to the same arguments, returning a list of results:
91
92
Thread values through sequences of expressions, similar to Clojure's threading macros and SRFI-197.
93
+94
> **These macros live in `(sigil core)` now.** `chain`, `->`, and `some->` are
+95
> part of core, which is auto-imported into every module, so every program
+96
> already has them in scope without importing anything. `(sigil fp chain)`
+97
> re-exports them from core purely for backward compatibility, so existing
+98
> `(import (sigil fp chain))` / `(import (sigil fp))` code keeps working.
+99
100
```scheme
+101
;; No import needed — these come from core:
+102
(-> 5 (+ 3) (* 2))
+103
+104
;; Or, for backward compatibility:
105
(import (sigil fp chain))
106
```
107
src/sigil/fp.sglmodified
@@ -1,10 +1,13 @@
1
;;; (sigil fp) - Functional Programming Utilities for Sigil
2
;;;
−3
;;; This package provides function composition, partial application,
−4
;;; and threading macros for Sigil programs.
+3
;;; This package provides function composition and partial application
+4
;;; combinators. Import the aggregate module to get everything:
5
;;;
−6
;;; Due to Sigil's module system not supporting re-exports, import
−7
;;; the specific sub-modules you need:
+6
;;; ```scheme
+7
;;; (import (sigil fp))
+8
;;; ```
+9
;;;
+10
;;; Or import a specific sub-module:
11
;;;
12
;;; ```scheme
13
;;; ;; Function composition and partial application
@@ -12,17 +15,21 @@
15
;;;
16
;;; ;; Threading macros (chain, ->, some->)
17
;;; (import (sigil fp chain))
−15
;;;
−16
;;; ;; Or import both
−17
;;; (import (sigil fp fn)
−18
;;; (sigil fp chain))
18
;;; ```
19
;;;
+20
;;; ## Threading macros live in core
+21
;;;
+22
;;; The threading macros `chain`, `->`, and `some->` now live in
+23
;;; `(sigil core)`, which is auto-imported into every module, so every
+24
;;; program already has them in scope without importing anything. The
+25
;;; `(sigil fp chain)` sub-module re-exports them from core purely for
+26
;;; backward compatibility with existing `(import (sigil fp ...))` code.
+27
;;;
28
;;; ## Sub-modules
29
;;;
30
;;; - **(sigil fp fn)** - compose, pipe, partial, partial-right,
31
;;; const, flip, complement, juxt
−25
;;; - **(sigil fp chain)** - chain, ->, some->
+32
;;; - **(sigil fp chain)** - chain, ->, some-> (re-exported from core)
33
34
(define-library (sigil fp)
35
(import (sigil fp fn)
src/sigil/fp/chain.sglmodified
@@ -1,13 +1,24 @@
−1
;;; (sigil fp chain) - Threading Macros
+1
;;; (sigil fp chain) - Threading Macros (re-exported from core)
2
;;;
−3
;;; Thread values through sequences of expressions, similar to
−4
;;; Clojure's threading macros and SRFI-197.
+3
;;; The threading macros `chain`, `->`, and `some->` now live in
+4
;;; `(sigil core)`, where they were before the 2026-03-31 FP extraction.
+5
;;; They are structural control-flow syntax used throughout idiomatic Sigil,
+6
;;; not optional combinators, so they belong in core. Since `(sigil core)` is
+7
;;; auto-imported into every module, any program already has these macros in
+8
;;; scope without importing anything.
+9
;;;
+10
;;; This module re-exports them so existing `(import (sigil fp chain))` and
+11
;;; `(import (sigil fp))` consumers keep working unchanged. Because the
+12
;;; re-exported bindings ARE core's bindings (not fresh definitions), a program
+13
;;; importing both `(sigil core)` and `(sigil fp)` sees no duplicate-binding
+14
;;; conflict.
+15
;;;
+16
;;; The optional combinators (`compose`, `pipe`, `partial`, `partial-right`,
+17
;;; `flip`, `complement`, `juxt`, `const`) remain in `(sigil fp fn)`.
18
;;;
19
;;; ## Basic Threading
20
;;;
21
;;; ```scheme
−9
;;; (import (sigil fp chain))
−10
;;;
22
;;; ;; Thread-first (no placeholder needed)
23
;;; (chain 5 (+ 3) (* 2))
24
;;; ; => 16 (same as (* (+ 5 3) 2))
@@ -30,111 +41,5 @@
41
;;; ```
42
43
(define-library (sigil fp chain)
−33
(export chain -> some->)
−34
−35
(begin
−36
−37
;;; Thread a value through a sequence of expressions.
−38
;;;
−39
;;; Similar to SRFI-197's `chain`. Uses `_` as the placeholder symbol.
−40
;;; When a step contains `_`, the threaded value is substituted there.
−41
;;; When no `_` is present, the value is inserted as the first argument.
−42
;;;
−43
;;; ```scheme
−44
;;; ;; Thread-first (no placeholder)
−45
;;; (chain 5 (+ 3) (* 2))
−46
;;; ; => 16 (same as (* (+ 5 3) 2))
−47
;;;
−48
;;; ;; Explicit placeholder
−49
;;; (chain '(1 2 3)
−50
;;; (map (lambda (x) (* x 2)) _)
−51
;;; (apply + _))
−52
;;; ; => 12
−53
;;;
−54
;;; ;; Placeholder in various positions
−55
;;; (chain 10 (- 20 _)) ; => 10 (= 20 - 10)
−56
;;; (chain 5 (list 1 2 _ 4)) ; => (1 2 5 4)
−57
;;; ```
−58
(define-syntax chain
−59
(syntax-rules (_ %step)
−60
;; Base case: just the value
−61
((chain expr)
−62
expr)
−63
−64
;; Internal: process step result and continue
−65
((chain %step result)
−66
result)
−67
((chain %step result next-step rest ...)
−68
(chain result next-step rest ...))
−69
−70
;; Step patterns: _ as entire step (identity)
−71
((chain expr _ rest ...)
−72
(chain %step expr rest ...))
−73
−74
;; Step patterns: _ in first position (function position)
−75
((chain expr (_ arg ...) rest ...)
−76
(chain %step (expr arg ...) rest ...))
−77
−78
;; Step patterns: _ in second position (first arg)
−79
((chain expr (f _ arg ...) rest ...)
−80
(chain %step (f expr arg ...) rest ...))
−81
−82
;; Step patterns: _ in third position (second arg)
−83
((chain expr (f a _ arg ...) rest ...)
−84
(chain %step (f a expr arg ...) rest ...))
−85
−86
;; Step patterns: _ in fourth position (third arg)
−87
((chain expr (f a b _ arg ...) rest ...)
−88
(chain %step (f a b expr arg ...) rest ...))
−89
−90
;; Step patterns: _ in fifth position (fourth arg)
−91
((chain expr (f a b c _ arg ...) rest ...)
−92
(chain %step (f a b c expr arg ...) rest ...))
−93
−94
;; Default for lists: no _ found, insert as first arg (thread-first)
−95
((chain expr (f arg ...) rest ...)
−96
(chain %step (f expr arg ...) rest ...))
−97
−98
;; Bare identifier - call with expr as arg (must come last)
−99
((chain expr f rest ...)
−100
(chain %step (f expr) rest ...))))
−101
−102
;;; Alias for `chain` (Clojure-style threading operator).
−103
;;;
−104
;;; ```scheme
−105
;;; (-> 5 (+ 3) (* 2)) ; => 16
−106
;;; ```
−107
(define-syntax ->
−108
(syntax-rules ()
−109
((-> . args)
−110
(chain . args))))
−111
−112
;;; Thread value through steps, short-circuiting on #f.
−113
;;;
−114
;;; Like `->`, but stops and returns `#f` if any step produces `#f`.
−115
;;; Useful for optional/nullable value pipelines.
−116
;;;
−117
;;; ```scheme
−118
;;; ;; Returns #f if any step fails
−119
;;; (some-> user
−120
;;; (dict-ref _ name:)
−121
;;; (string-split " " _)
−122
;;; car)
−123
;;;
−124
;;; ;; Short-circuits on #f
−125
;;; (some-> #f (+ 1 _)) ; => #f (doesn't call +)
−126
;;;
−127
;;; ;; Continues while truthy
−128
;;; (some-> 5 (+ 1 _) (* 2 _)) ; => 12
−129
;;; ```
−130
(define-syntax some->
−131
(syntax-rules ()
−132
;; Base case: just the value
−133
((some-> expr)
−134
expr)
−135
;; One or more steps: evaluate expr, check for #f, then continue
−136
((some-> expr step rest ...)
−137
(let ((%v expr))
−138
(if %v
−139
(some-> (-> %v step) rest ...)
−140
#f)))))))
+44
(import (sigil core))
+45
(export chain -> some->))