Reading unknown symbols as strings in at-exp languages - racket

I have created a module which provides various functions, including #%module-begin. I want to use it with at-exp syntax, which I can do using the following #lang line:
#lang at-exp s-exp "my-library.rkt"
However, this does not read unknown symbols as strings, as would happen for example when using the scribble/text language. How can I provide this functionality from my library, to save me writing quote marks around all my strings?
I think it may have something to do with the #%top function. Perhaps I can require it somehow from scribble/text and then provide it from my library?

What scribble/text does, is it starts reading the file in "text" mode, whereas at-exp starts reading the file in "racket" mode. Messing with #%top is not what you want here. To do the same thing as scribble/text, you would need a version of at-exp that starts in text mode. That doesn't exist (yet) though.
The function read-syntax-inside from scribble/reader does this. However, you will have to define your own #lang language that uses it. For that, you might find this documentation helpful, but there's no quick answer.
Update:
I looked at the implementation of scribble/text, and the answer seems a lot quicker than I thought it would be. Something like this should work:
my-library/lang/reader.rkt:
#lang s-exp syntax/module-reader
my-library/main
#:read scribble:read-inside
#:read-syntax scribble:read-syntax-inside
#:whole-body-readers? #t
#:info (scribble-base-reader-info)
(require (prefix-in scribble: scribble/reader)
(only-in scribble/base/reader scribble-base-reader-info))
Testing it:
#lang my-library
This is text
#(list 'but 'this 'is 'not)
I tested this with my-library/main.rkt re-providing everything from racket/base.

Related

Racket: enable scribble language in sub module

#lang racket/base
(module x scribble/text
#(display 123))
It seems like #lang statements are not valid in nested sub-modules, and the expanded module version above is missing something:
error: module: no #%module-begin binding in the module's language
update:
looks like this more or less works, but is there a better way? does scribble do something with output ports that isn't being handled?
#lang racket/base
(module x scribble/text/lang
(#%module-begin
#reader scribble/reader #list{
hi
#(+ 1 456)
}))
First, your code has a redundant #%module-begin which can be removed.
#lang does several things -- one is control the semantics of the file
by determining the set of initially imported bindings, and that's
something that the module form has done before #lang came up. With
submodules, it became possible to use module for parts of a file too.
However, #lang can also determine the reader that parses the file, and
that's not possible to do with submodules, so you're stuck with only one
toplevel #lang to set the parser for the whole file.
(Sidenote: There is a technical reason for that. A #lang reader reads
the rest of the file until it reaches an eof value, so a nested
#lang would require getting an eof value before getting the end of
the file, or adding a new kind of eof-like value. That means that it's
a change that should be done carefully -- it's possible to do, of
course, but the need didn't come up often enough. Hopefully it will, in
the future.)
But in your case you don't want a completely new concrete syntax, just
an extension for s-expressions -- and an extension that was chosen to
have a minimal impact on regular code. So in almost all cases it's fine
to just enable the #-form syntax for the whole file, and then use
#-forms where you want it. Since it's just an alternative way for
reading sexprs, you can even use that with module, leading to this
code that doesn't need to use #reader:
#lang at-exp racket/base
#module[x scribble/text/lang]{
hi
#(+ 1 456)
}
(require 'x)
One thing that is a bit strange here is using scribble/text/lang and
not just scribble/text. Usually, #lang foo is exactly the same as
(module x foo ...) after reading the code with foos reader. But in
the case of the scribble/text language there is another difference:
using it as a #lang makes the semantics of the module body be "output
each thing". The idea is that as a language you'll want to spit out
mostly-text files, but as a library you'll want to write code in it
and do the printout yourself.
Since this code uses module, using scribble/text means that you're
not getting the spit-all-out functionality, which is why you need to
explicitly switch to scribble/text/lang. But you could have instead
just do the spitting yourself using the language's output, which would
give you this code:
#lang at-exp racket/base
(module x racket/base
(require scribble/text)
(output #list{
hi
#(+ 1 456)}))
(require 'x)
Note that scribble/text is not used as a language here, since it
doesn't provide enough stuff to be one when used (outside of a #lang).
(Which you've found out, leading to that redundant #%module-begin...)
This version is slightly more verbose, but I'm guessing that it makes
more sense in your case, since using it for some part of the code means
that you want to use it as a library.
Finally, if you really don't want to read the whole file with the #
syntax, only some parts, then the #reader that you've found is
perfectly fine. (And this is made simple with scribble/text that
treats lists as concatenated outputs, so you need just one wrapper for
each chunk of text.)

Selecting student language in Racket source code

I am trying to write a source file for DrRacket that specifies one of the languages from How to Design Programs Teaching Languages (see the Racket documentation). I know I can select such a language in the DrRacket menu, but I would like to specify it using a #lang directive and have DrRacket recognize the language automatically.
I cannot find any documentation about the strings that I need to use instead of racket in the initial line
#lang racket
Where can I find the documentation on this? Or can these languages only be selected from DrRacket's menu?
You should be able to use
#lang htdp/bsl
(or htdp/bsl+, htdp/isl, htdp/isl+, or htdp/asl) but it's "not in a complete shape, yet".

Why is clojure adding namespace qualifiers to names inside a backquote?

I am trying to build datalog queries programmatically, but keep running into the problem that I will illustrate with an example function:
(defn test-expr [attribute]
`[?entity ~attribute ?value]])
When I run (test-expr 3), I would expect the output:
[?entity 3 ?value]
But instead, I get
[mynamespace/?entity 3 mynamespace/?value]
Which obviously is not what I want. Is there a way to tell clojure "please just quote the list and expand variables I tell you to?"
Yes, there is.
(defn test-expr [attribute]
`[~'?entity ~attribute ~'?value])
Here you first unquote the syntax quotation and then immediately quote the symbol (~' construct) again. The result is namespace-less symbol.
It is equivalent to the following, which explains how it works:
(defn test-expr [attribute]
`[~(quote ?entity) ~attribute ~(quote ?value)])
What you're looking for is the backtick library by Brandon Bloom https://github.com/brandonbloom/backtick
It was built for the exact problem you describe. It supplies a command named 'template' that works like the backtick but without the namespacing stuff.
In Clojure, quasiquotation and namespace resolution are mixed together in a single feature. This has great benefits for writing macros in a language like Clojure, which is a "Lisp-1" (as opposed to Common Lisp, which is a "Lisp-2", with separate namespaces for functions and variables.)
I also agree that it might have been better not to conflate these features, but it would have made the writing of macros in Clojure less elegant, so I can see why it works the way it does.

Should macros have side effects?

Can (or should) a macro expansion have side effects? For example, here is a macro which actually goes and grabs the contents of a webpage at compile time:
#lang racket
(require (for-syntax net/url))
(require (for-syntax racket/port))
(define-syntax foo
(lambda (syntx)
(datum->syntax #'lex
(port->string
(get-pure-port
(string->url
(car (cdr (syntax->datum syntx)))))))))
Then, I can do (foo "http://www.pointlesssites.com/") and it will be replaced with "\r\n<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\"\r\n\t <and so on>"
Is this good practice, or not? Am I garunteed that Racket will only run this code once? If I add a (display "running...") line to the macro, it only prints once, but I would hate to generalize from one example ...
PS - the reason I'm asking is because I actually think this could be really useful sometimes. For example this is a library which allows you to load (at compile-time) a discovery document from the Google API Discovery service and automatically create wrappers for it. I think it would be really cool if the library actually fetched the discovery document from the web, instead of from a local file.
Also, to give an example of a macro with a different kind of side effects: I once built a macro which translated a small subset of Racket into (eta-expanded) lambda calculus (which is, of course, still runnable in Racket). Whenever the macro finished translating a function, it would store the result in a dictionary so that later invocations of the macro could make use of that function definition in their own translations.
The short answer
It's fine for macros to have side effects, but you should make sure that your program doesn't change behavior when it's compiled ahead of time.
The longer answer
Macros with side effects are a powerful tool, and can let you do things that make programs much easier to write, or enable things that wouldn't be possible at all. But there are pitfalls to be aware of when you use side effects in macros. Fortunately, Racket provides all the tools to make sure that you can do this correctly.
The simplest kind of macro side effect is where you use some external state to find the code you want to generate. The examples you list in the question (reading Google API description) are of this kind. An even simpler example is the include macro:
#lang racket
(include "my-file.rktl")
This reads the contents of myfile.rktl and drops it in place right where the include form is used.
Now, include isn't a good way to structure your program, but this is a quite benign sort of side effect in the macro. It works the same if you compile the file ahead of time as if you don't, since the result of the include is part of the file.
Another simple example that's not good is something like this:
#lang racket
(define-syntax (show-file stx)
(printf "using file ~a\n" (syntax-source stx))
#'(void))
(show-file)
That's because the printf gets executed only at compile time, so if you compile your program that uses show-file ahead of time (as with raco make) then the printf will happen then, and won't happen when the program is run, which probably isn't the intention.
Fortunately, Racket has a technique for letting you write macros like show-file effectively. The basic idea is to leave residual code that actually performs the side effect. In particular, you can use Racket's begin-for-syntax form for this purpose. Here's how I would write show-file:
#lang racket
(define-syntax (show-file stx)
#`(begin-for-syntax
(printf "using file ~a\n" #,(syntax-source stx))))
(show-file)
Now, instead of happening when the show-file macro is expanded, the printf happens in the code that show-file generates, with the source embedded in the expanded syntax. That way your program keeps working correctly in the presence of ahead-of-time compilation.
There are other uses of macros with side effects, too. One of the most prominent in Racket is for inter-module communication -- because require doesn't produce values that the requiring module can get, to communicate between modules the most effective way is to use side effects. To make this work in the presence of compilation requires almost exactly the same trick with begin-for-syntax.
This is a topic that the Racket community, and I in particular, have thought a lot about, and there are several academic papers talking about how this works:
Composable and Compilable Macros: You want it when?, Matthew Flatt, ICFP 2002
Advanced Macrology and the Implementation of Typed Scheme, Ryan Culpepper, Sam Tobin-Hochstadt, and Matthew Flatt, Scheme Workshop 2007
Languages as Libraries, Sam Tobin-Hochstadt, Ryan Culpepper, Vincent St-Amour, Matthew Flatt, and Matthias Felleisen, PLDI 2011
In common Lisp the function eval-when allows you to decide when the macro will be expanded.

Best way to customize auto-formatting/auto-indenting in vim for Common Lisp

I would like to know the best way to customize auto-formatting/auto-indenting in vim for Common Lisp.
Auto-formatting (I usually do this by typing '==' in command mode per line) works very well for the base lisp language in vim (e.g., defmacro, defun, lambda, if, with-output-to-string), but any time that new language constructs are defined (e.g., using macros), I find that the formatting for the new construct is often not what I'd like it to be.
For example, here's how vim formats 'when (standard lisp construct) and 'awhen (commonly-used anaphoric version of 'when; not part of lisp standard)
(when 'this
(process 'this))
(awhen 'this
(process it))
I would like 'awhen to auto-format like 'when. Any ideas how I can do this?
Edit: Thanks Gilligan and Tamas for the Slimv recommendation. As a test, I downloaded MacVim (will need this working with terminal vim, but that's a different problem) and slimv, rsynched the slimv download into ~/.vim, launched MacVim, and loaded a .lisp file.
I then started up the lisp server (done through a GUI with MacVim), which loaded up my default lisp executable and core file.
And* since my core file is already loaded with the language extensions that I commonly use (awhen being one of them), awhen formatted correctly right out of the box.
I really like this solution. Instead of [1] having to learn how to tell vim to indent particular functions properly, and [2] writing the code that does this explicitly for each language extension that I define, and [3] updating that code every time I add a new language construct. Instead I leverage slimv to do the formatting for me. And slimv can 'learn' new language extensions, as long as those macros are already loaded into the lisp core that the server session is using. Pretty slick!
I have found that this works well for a particular class of language extensions. Usually ones defined as a macro, using the &body keyword. This seems to 'do the right thing' most of the time, but there are macros I use that still don't properly auto-format. Although I'd say that this is more likely to be an issue with how the macro is written (non-standard language extension) than anything else.
So, this solution works well for me for most cases, and I didn't have to code (and maintain) anything. Great stuff!
This might not be a direct answer to your question but I strongly suggest that you install
the slimv plugin: http://www.vim.org/scripts/script.php?script_id=2531
Its a great plugin which integrates SLIME functionality into vim and besides many other things it also comes with an improved indentation for clisp&clojure. It won't indent awhen the way you want though.
For those who are looking for this topic and don't want to run Slimv, because they aren't working with Common Lisp or other reasons, here is the scoop.
Vim's Lisp indentation is not like that for other languages; it has a special "Lisp mode". This mode is turned on by
:set lisp
which is done automatically for .lisp files. Lisp mode isn't a Vim invention; classic Vi implementations have a Lisp mode turned on with :set lisp. (It's not described by POSIX, unfortunately).
Vim's Lisp mode has a simple mechanism for recognizing forms that require operator-style indentation: namely, there is a parameter called lispwords which holds a comma-separated list of identifiers.
You can prove to yourself that this is the identifier list which is used, even when you're editing a Common Lisp .lisp file with syntax highlighting and all. Simply do :set listwords[TAB] and edit the list to remove something from it, such as defun. Then try to reindent a defun: you will see the function-style indentation now instead of the operator-style.
The syntax highlighting support for Common Lisp is separate from Lisp mode's lispwords parameter; it has its own list of identifiers. For example, in Vim 7.3 if you enter this:
(symbol-macrolet ((foo bar))
you get indented out to here!)
This is in spite of the fact that symbol-macrolet is recognized and colored. Why? It's because symbol-macrolet does not appear in the rather scanty lispwords list, whereas it does appear in the lisp.vim syntax highlighting definition file.
The upshot is that you can cob together some script which scans your directory of .lisp files for macros and generates a set lispwords=... command that is placed into a directory .vimrc.
Or if you are working on a custom Lisp dialect, you can just make its Vim syntax highlighting file customize lispwords when it loads.
Here is an implementation oversight: the lispwords option has no local value; you cannot use setlocal lispwords ... to give it a buffer-specific value. In other words, it appears that (at least in the Vim 7.3 I'm using under Ubuntu) you can't have two or more buffers open holding different dialects of Lisp with different identifiers for indentation. The default contents of lispwords contains a smattering of Lisp and Scheme symbols to try to be a kind of "one size almost fits all" solution.
If you filetype is 'lisp' then I think you need to add indenting rules for your special case in the 'lisp.vim' file in the '/vim7x/indent' directory. You can find a bit more info in help at :h indent-expr and :h indentexpr.
Someone may be able to tell you better, but I believe the default lisp.vim indent file basically does nothing because the built-in function lispindent() is used to get indent values. You will want to:
(1) set function used to get indent values (i.e., indentexpr) to a function in your own indent/lisp.vim file, e.g., GetLispIndent().
(2) in your your GetLispIndent() function you will use lispindent() to get indent values to return for all lines except your special case. See other languages' indent files and read the docs to get an idea for how indentexpr works, e.g, java.vim.
#Kaz's answer is completely correct, but they don't go all the way to answering the original question. Vim's lispwords config string is a comma-delimited list of words; when any of the words in lispwords is found at the beginning of an S-expression, Vim will change the way that S-expression is indented. In other words, it defines the "standard lisp constructs" to which the OP refers. If you view your current lispwords config with :set lispwords, you'll see "when" is included, but "awhen" is not, resulting in the following indentation:
(when 'this
(process 'this))
(awhen 'this
(process it))
To fix this, simply add "awhen" to the config string somewhere in your config, like so:
set lispwords+=awhen,
The trailing comma isn't strictly necessary, but the default value includes it, and is probably wise in case you or a plugin modifier elsewhere. That would turn the original formatting into this:
(when 'this
(process 'this))
(awhen 'this
(process it))
(Tested on my current installation of Vim 9.0)
Note that, as #Kaz points out, this config string is universal, so if you have different dialects of lisp their indentation will all be controlled by this setting. Vim is pretty good about auto-detecting lisps, but you may need so :set lisp if it doesn't recognize your filetype or dialect.