I'm writing an ADT in r5rs and I'm using DrRacket. I put #lang r5rs at the top of my file and chose Determine Language from Source from DrRacket, but it tells me my ADT is undefined. I'm using DrRacket version 6.0. It's the first time I've had this and can't understand what I'm doing wrong.
My ADT
#lang r5rs
(#%require "queue.rkt") ;A required file
(#%provide (all-defined))
(define (my-ADT)
(let ((val1 '())
(val2 '()))
(define (foo) ...)
(define (bar) ...)
(define (dispatch msg)
(case msg
((foo) foo)
((bar) bar)
(else "Unknown message")))
dispatch))
When I try to create an instance of my-ADT I get the following output: my-ADT: undefined; cannot reference an identifier before its definition
When I remove #lang r5rs from the top and choose R5RS as language in DrRacket, it seems to work. But then my queue.rkt file still has #lang r5rs at the top and Determine Language from Source. When I remote #lang r5rs and choose R5RS as language in that file also, I get the following in the my-ADT file:
default-load-handler: expected a `module' declaration
found: something else
in: #<path:/Users/path/path/path/queue.rkt>
The error
my-ADT: undefined; cannot reference an identifier before its definition
normally indicates that the function my-ADT was used before it was defined.
That is, one must place all definitions on top of the file and place the expressions below.
Your example above has no uses of my-ADT so if you get this error, the problem might be in "queue.rkt". Can you run "queue.rkt" without errors?
Related
I'm learning racket and as a way to consolidate my knowledge I'm trying to build a library for parser expression grammars (PEG). My intention is to build a language to express PEGs and the module should export a function parser that receives a string and tries to parse it using the grammar defined in the language. However, I'm struggling with building this module using the following read function:
(define (peg-read-syntax path port)
(define grammar (parse port))
(datum->syntax
#f
`(module peg-mod racket
(provide parser
pretty
(all-from-out "tree.rkt"))
(define (parser s)
(peg-parse ,grammar s))
(define (pretty t)
(peg-pretty ,grammar t))))))
and racket returns the following error whenever I try to process a program in #lang peg language:
default-load-handler: expected a `module' declaration, but found something else
Can someone help me with this mistake? The complete project is at the following github repo:
https://github.com/lives-group/peg-parsing
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 specified by the #lang line at the top of the definitions 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 intricate REPL hacking is possible. For instance, the REPL can be configured to use a custom reader (other than Racket’s default S-expression 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.
I don't know how to explain the following behavior in DrRacket's interactions window. I think the output should be only one "hello", since the module m should be instantiated once in this case. But actually "hello" is printed 3 times.
> (module m racket
(printf "hello\n"))
> (module n racket
(require (for-syntax 'm)))
hello
hello
hello
>
The same behavior also exists if I write this example in DrRacket's definitions window and run it.
#lang racket
(module m racket
(printf "hello\n"))
(module n racket
(require (for-syntax (submod ".." m))))
hello
hello
hello
>
This example is a simplified version of one from Racket's guide (https://docs.racket-lang.org/guide/macro-module.html) -- the first example in 16.3.2. The behavior shown in that document
is intuitive (printing the string one time), but when I execute that code in DrRacket's interactions window, it also prints the string 3 times.
I'm using DrRacket version 7.7.
See also https://github.com/greghendershott/racket-mode/issues/379 and https://github.com/racket/drracket/issues/278.
The latter in particular indicates that one of the extra ones is from errortrace instrumentation, which is on by default in DrRacket.
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.
I have sample code like this:
#!/usr/bin/guile -s
!#
(define (process body)
(list 'list (map (lambda (lst)
(list 'quote (car lst)))
body)))
(defmacro macro (body)
(list 'quote (process body)))
(display (macro ((foo bar) (bar baz))))
(newline)
it run but I've got error from compiler
ERROR: Unbound variable: process
functions inside macros should be allowed, why I got this error?
Functions inside macros are allowed in Guile and in most other Scheme dialects.
However, the crucial question is: Which functions are available for a macro to call out during the expansion process?
Think of it this way: When the compiler is processing your code, it is first focused on turning your source code into something that can be run at some point in the future. But the compiler might not necessarily be able to execute those same functions right now while it is compiling them, at the same time that your macro is running and expanding the source code in general.
Why wouldn't such a function be available? Well, one example would be: What if the function's body used the macro you are in the midst of defining? Then you would have a little chicken/egg problem. The function would need to run the macro to be compiled (since the macro use in the body needs to be expanded, at compile-time) ... But the macro would need the compiled function available in order to even run!
(Furthermore, there might be some functions that you only want to be available at compile-time, as a helper for your macros, but that you do not want to be available at run-time, so that it will not be included in your program executable when you deploy it, as that would waste space in the deployed binary.)
One of my favorite papers describing this problem, and the particular solution adopted by MzScheme (now known as Racket), is the "You Want It When" paper by Matthew Flatt.
So, this is a problem that any Scheme dialect with a procedural macro system has to deal with in some way, and Guile is no exception.
In Guile's case, one fix that is directly documented in the Guile manual is to use the eval-when special form, which allows you to specify at what phases a particular definition is meant to be available.
(The "You Want It When" paper referenced above describes some problems with eval-when, but since it is what the Guile manual documents, I'm going to stick with it for now. I do recommend that after you understand eval-when, that you then look into Racket's solution, and see if Guile offers anything similar.)
So in your case, since you want the process function to be available at compile-time (for use in the macro definition), you could write:
#!/usr/bin/guile -s
!#
(eval-when (expand)
(define (process body)
(list 'list (map (lambda (lst)
(list 'quote (car lst)))
body))))
(defmacro macro (body)
(list 'quote (process body)))
(display (macro ((foo bar) (bar baz))))
(newline)