2
votes

In clojure, read-string followed by str will not return the original string, but the string for which the reader macros have been expanded:

(str (read-string "(def foo [] #(bar))"))
;"(def foo [] (fn* [] (bar)))"

This is problematic if we want to manipulate a small part of the code, far away from any reader macros, and get back a string representation that preserves the reader macros. Is there a work around?

1

1 Answers

0
votes

The purpose of read is to build an AST of the code and as such the function does not preserve all the properties of the original text. Otherwise, it should keep track of the original code-layout (e.g. location of parenthesis, newlines, indentation (tabs/spaces), comments, and so on). If you have a look at LispReader.java, you can see that the reader macros are unconditionally applied (*read-eval* does not influence all reader macros).

Here is what I would recommend:

  • You can take inspiration of the existing LispReader and implement your own reader. Maybe it is sufficient to change the dispatch-table so that macro characters are directed to you own reader. You would also need to build runtime representations of the quoted forms and provide adequate printer functions for those objects.
  • You can process your original file with Emacs lisp, which can easily navigate the structure of your code and edit it as you wish.

Remark: you must know that what you are trying to achieve smells fishy. You might have a good reason to want to do this, but this looks needlessly complex without knowing why you want to work at the syntax level. It would help if you could provide more details.