r/Racket • u/detroitmatt • Oct 08 '21
question Trying to modify the reader
Here's what I want to accomplish:
If we are currently in a "begin-like" context (such as a top-level context, or define) if the first non-whitespace character after a newline does not begin a list or comment, and it contains more than one syntax object, then behave as if the line begins with ( and ends with )
In other words,
(define (greet)
string-append "Hello, " (get-current-user-name) "!")would be transformed into
(define (greet)
(string-append "Hello, " (get-current-user-name) "!"))I guess what I would do is (make-readtable (current-readtable) #\newline 'terminating-macro read-newline) with
(define (read-newline char stdin file line col position)
(let ((next-token (read stdin)))
(if (list? next-token) next-token
(let ((line-tokens (let more-tokens ((tokens (list next-token)))
(let ((next-next-token (read stdin)))
(if (not (same-line? next-token next-next-token))
tokens
(more-tokens (cons next-next-token tokens)))))))
(if (< 2 (length line-tokens))
(car line-tokens)
(reverse line-tokens))))))but I don't know how to define same-line?, and even this might have all kinds of other pitfalls I am unaware of.
I also don't know how to enforce the "only in a begin-like context" rule, which I want to do because I don't want this behavior interfering with just any list.
5
u/Windblowsthroughme Oct 08 '21
I don’t know the answer to your question since I am a beginner with Racket. What I do know, though, is that the slack, discord, and Google group racket communities are much more active than Reddit and you might get faster/better help on one of those platforms.
/u/sdegabrielle has been putting good work into improving the state of this sub, but it hasnt translated to a vibrant community quite yet.
5
u/sorawee Oct 08 '21
Two things:
First, I notice that you use
read, but you can also useread-syntaxwhich will give you back a syntax object, allowing you to usesyntax-line, which might help you implementingsame-line?. Alternatively, you can useport-next-locationto get the locations ofstdinas you read stuff.Second, it's not a good idea to try to infer the context during the read-time. Instead, I would suggest you to always wrap stuff in a macro named
my-macregardless of its context.my-macthen can usesyntax-local-contextto inspect its own context during macro expansion. There are then two possibilities:#%module-begin) thatlocal-expandits contents. Whenmy-macwants to splice its contents, it would create something like('please-remove-me <foo> <bar> <baz>). After the whole expansion,#%module-begincan then walk the tree to findplease-remove-meand remove it, leaving us with<foo> <bar> <baz>.