How to re-export #%module-begin etc from scribble/text? - racket

I want a language like scribble/text but with some additional functions offered. This is what I've tried:
#lang racket/base
(require scribble/text)
(provide (all-from-out scribble/text)
hello)
(define (hello name)
(format "Hello ~a!" name))
When I try to run a module written in this language, I get a message saying that there is no #%module-begin binding in the module's language.
I assume that scribble/text has a binding for #%module-begin, else how does it work when I use it as a #lang?
Maybe scribble/text knows that I am importing it using 'require' rather than as a #lang, and so I don't automatically get the #% macros? If that's the case, then how would I get them and re-export them?
Or is something else happening here?

The language for #lang scribble/text and the library for (require scribble/text) are different modules. The library version doesn't provide #%module-begin or the other bindings from racket:
When scribble/text is used via require instead of #lang, then .... it does not include the bindings of racket/base ....
The module-language #lang scribble/text actually uses is scribble/text/lang. So you can fix your module-language like this:
#lang racket/base
(require scribble/text/lang)
(provide (all-from-out scribble/text/lang)
hello)
(define (hello name)
(format "Hello ~a!" name))
However, the module scribble/text/lang is undocumented, so use at your own risk.

Related

How do I set the meta-language in the Racket REPL?

I have a program that uses the at-exp meta-language:
#lang at-exp racket
(define v '#f{str})
(displayln v)
I want to manually type it line-by-line into the Racket REPL. Unfortunately, #lang at-exp racket is not valid in the REPL:
$ racket
Welcome to Racket v6.11.
> #lang at-exp racket
; readline-input:1:0: read: #lang not enabled in the current context [,bt for
; context]
; at-exp: undefined;
; cannot reference undefined identifier
; [,bt for context]
; racket: undefined;
; cannot reference undefined identifier
; [,bt for context]
>
How do I set the meta-language in the Racket REPL?
For the beginners who have ended up here, the short answer is no. The #lang shorthand should only be used in files. If you want to run your example program in the REPL, you could load it using this command.
racket --repl --eval '(enter! (file "your-file.rkt"))'
The more detailed answer is that the #lang shorthand gets re-written behind the scenes into module form.
So for example something like this...
#lang racket
(define v "Hello!")
(displayln v))
Is re-written to what you see below and you could copy and paste this into the repl and then require the module, e.g. in the repl type...
> (module the-hello-module racket
(define v "Hello!")
(displayln v))
> (require 'the-hello-module)
Hello!
But from what I can tell, that re-write is dependent on the languages you're using, so the rewrite is probably not something you want to do manually and I don't think the at-exp metalanguage is something you would be add manually to module form.
I don't know why they're different, but the REPL inside DrRacket can use the #lang shorthand:
Unlike the command-line REPL, the DrRacket REPL adopts the language spec­i­fied by the #lang line at the top of the defi­n­i­tions panel. DrRacket also uses the REPL itself to print output from the program.
https://beautifulracket.com/explainer/repl.html#a_Rv5YS
So if you have #lang at-exp racket/base in the definitions panel and click "Run" the bottom REPL panel will show Language: at-exp racket/base, etc., and this will work:
> #string-append{this is a test}
"this is a test"
That page also says:
More intri­cate REPL hacking is possible. For instance, the REPL can be config­ured to use a custom reader (other than Racket’s default S-expres­sion reader).
https://beautifulracket.com/basic-3/the-repl.html
However, the steps described there are much more involved than I care to get into. I don't know what DrRacket is doing in the background to make #lang at-exp work.

Why can't I customize the application of a struct-id construction function?

I would like to build a custom language in Racket that requires redefining the implicit form #%app. However, using the macro stepper I noticed that unlike regular "proc-id" function application, struct-id application does not get replaced with the custom #%app form. Why is this the case?
My guess is that what you are seeing in the macro stepper is a result of the fact that (unless you specify otherwise with keyword options) struct binds the struct name to a macro to communicate static information about the struct type, which is used by match, shared, struct-out, and other macros. When used as an expression, this macro expands to the constructor function, which is bound to an otherwise-inaccessible name. If that doesn't seem to explain what you're seeing, perhaps you could give a code example.
In any case, if you disable macro hiding, you will see that direct application of the constructor function does use the correct #%app form. For example, this program:
#lang racket
(module language racket
(provide (rename-out [my-app #%app])
(except-out (all-from-out racket)
#%app))
(define-syntax-rule (my-app rator rand ...)
(let ()
(print-app-form '(rator rand ...))
(rator rand ...)))
(define (print-app-form quoted)
(printf "; ~a\n" quoted)))
(module main (submod ".." language)
(struct bag (contents)
#:transparent)
(define groceries
'(oranges milk salsa))
(bag groceries))
prints the following output, where bag1 is an artifact of #%app being expanded after the bag macro:
; (bag1 groceries)
(bag '(oranges milk salsa))

How to 'require' a Racket module that doesn't have a #lang header line?

As just one of many possible examples, break-example.rkt would be a perfectly valid Java program, except for the #lang mini-java header that Racket requires.
So e.g. if I've written a Java interpreter/compiler in Racket as a Racket module language, how can I say, "require this file Main.java which is written in module language mini-java but doesn't have any Racket-specific header"?
(Note that I have almost non-zero practical experience with Racket. I'm evaluating this for a specific use case I have for Racket + DrRacket, which has nothing to do with Java by the way. I searched the documentation but couldn't find any way to achieve this.)
I can’t run or test this right now, but maybe you can start from here and experiment with it. The main thing it uses is include/reader:
#lang racket
(require racket/include
syntax/parse/define
(for-syntax racket/syntax
racket/port
syntax/modread))
(define-simple-macro (require/mini-java path)
#:with modname (generate-temporary #'path)
(begin
(include/reader path (mini-java-reader 'modname))
(require 'modname)))
(begin-for-syntax
;; Symbol -> [Any InputPort -> Syntax]
(define ((mini-java-reader modname) src input)
(cond
[(port-closed? input) eof]
[else
(define stx
(with-module-reading-parameterization
(lambda ()
(read-syntax src
(input-port-append #t
(open-input-string "#lang mini-java\n")
input)))))
(close-input-port input)
(syntax-parse stx
[(module _ l . b)
#`(module #,modname l . b)])])))

Racket, include, require and provide don't work

I have a file with the name “functions.rkt”, where I have some functions.
And I am working in another file, let’s name it “working.rkt”
I have tried the following (one by one) at “working.rkt” to use the function defined at “functions.rkt”:
(require “functions.rkt”)
(include “functions.rkt”)
(provide “functions.rkt”)
And anyone of them hasn’t worked, any help?
They are in the same path.
In the file "functions.rkt:
#lang racket
(provide my-function)
(define (my-function x) (* 2 x))
In the file "working.rkt":
#lang racket
(require "functions.rkt")
(my-function 21)

Chaining file inclusions

I have a file, configuration.rkt:
(define file-path "path/to/file.rkt")
Then I have the 'main' file program.rkt, in which I would like to include the file specified by file-path. I tried this way, but it does not work:
(include "configuration.rkt")
(include file-path)
What can I do?
Use require instead of include.
http://docs.racket-lang.org/guide/module-require.html
As #soegaard said, you want to use Racket's module system via require, instead of textually including source files. It will save you a ton of grief.
I noticed that you seem to want the choice of source file to be determined at runtime?
If so, two options:
You could use units and signatures.
You could use dynamic-require. For example:
config.rkt:
#lang racket
(provide to-be-required)
(define to-be-required "foo.rkt")
foo.rkt:
#lang racket
(provide foo-value
foo-proc)
(define foo-value "I am from foo.rkt and I was dynamic-required!")
(define (foo-proc)
"I am foo-proc.")
main.rkt
#lang racket
(require "config.rkt")
(printf "Let's dynamic-require ~a, as config.rkt said.\n" to-be-required)
(define foo-value (dynamic-require to-be-required 'foo-value))
(define foo-proc (dynamic-require to-be-required 'foo-proc))
foo-value
(foo-proc)
Output:
Let's dynamic-require foo.rkt, as config.rkt said.
"I am from foo.rkt and I was dynamic-required!"
"I am foo-proc."