Add full string interpolation as syntax extension
- Dominant language
- JavaScript
- Stars
- 507
- Forks
- 45
- Avg merge
- 11h 22m
- Merged PRs (30d)
- 4
Description
This is an implementation that works right now
```scheme
(set-special! "$" 'interpolate)
(define (interpolate str)
(typecheck "interpolate" str "string")
(let* ((re #/(\$\{[^\}]+\})/)
(parts (--> str (split re) (filter Boolean))))
`(string-append ,@(map (lambda (part)
(if (not (null? (part.match re)))
(let* ((expr (part.replace #/(^\$\{)|(\}$)/g ""))
(port (open-input-string expr))
(value (with-input-from-port port read)))
`(repr ,value))
part))
(vector->list parts)))))
(pprint (macroexpand-1 (let ((x 10)) $"x = ${(+ x 2)}")))
;; ==> (let ((x 10))
;; ==> (string-append "x = " (repr (+ x 2))))
(let ((x 10))
$"x = ${(+ x 2)}")
;; ==> "x = 12"
```
But it has limitations you can't put strings as an interpolated value, because it will break the parser, to be fully working as expected you should be able to use something like this:
```scheme
(print $"x = ${(+ 1 2)}; y = ${(+ 2 3)}; s = ${(string-append "{" "hello" "}")}")
```
But this will not work because the parser doesn't know that it should process `${...}` differently. So interpolation would need to be built into the parser but I don't want that.
The alternative is to wait to have `(read)` inside syntax extensions. So this will need to wait for https://github.com/jcubic/lips/issues/150
For better regex that will work with strings inside quoted expressions, see [How to match everything except single character but not inside double quoted string](https://stackoverflow.com/a/78062063/387194) on StackOverflow.
- [ ] document the feature
- [ ] add a note about performance
Contributor guide
Assessment
This issue has not been assessed yet.