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->))