jcubic / jcubic/lips

Add full string interpolation as syntax extension

Open
#321 2 comments 0 reactions 0 assignees View on GitHub
documentation enhancement
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.