I wonder why this doesn't work:
(module testModule (sayHello)
(import chicken scheme)
(define (sayHello)
(format #t "Hello\n")))
When I launch this file with csi it say:
Warning: reference to possibly unbound identifier `format' in:
But here is written that the srfi-28 (where format is) is builtin. Indeed if I try this...
(module testModule (sayHello)
(import chicken scheme)
(use srfi-28)
(define (sayHello)
(format #t "Hello\n")))
...it says:
Error: (import) during expansion of (import ...) - cannot import from undefined module: srfi-28
Why? What can I do to create a module which use the SRFI 28?
I also tried to install the srfi-28 via chicken-install but rightly the egg does not exist.
Mea culpa, the problem is that doesn't exist the unit srfi-28.
I simply solved importing extras unit which implements the format function.
(module testModule (sayHello)
(import chicken scheme)
(use extras)
(define (sayHello)
(format #t "ciao")))
Related
I've just installed guile-lib-0.2.7.tar.gz, and checking post-install, found it
at /usr/share/guile/site—which I believe is correct given:
scheme#(guile-user)> (list (%library-dir) (%site-dir) (%global-site-dir) (%package-data-dir))
$1 = ("/usr/share/guile/3.0" "/usr/share/guile/site/3.0" "/usr/share/guile/site" "/usr/share/guile")
That said, the following bread crumbs my problem:
scheme#(guile-user)> (use-modules (guile-lib))
While compiling expression:
no code for module (guile-lib)
scheme#(guile-user)> (use-modules (math))
While compiling expression:
no code for module (math)
scheme#(guile-user)> (add-to-load-path "/usr/share/guile/site")
scheme#(guile-user)> (use-modules (math))
While compiling expression:
no code for module (math)
scheme#(guile-user)> (use-modules (primes.scm))
While compiling expression:
no code for module (primes.scm)
I next tried brute force:
scheme#(guile-user)> (primitive-load-path "/usr/share/guile/site/math/primes.scm")
;;; note: auto-compilation is enabled, set GUILE_AUTO_COMPILE=0
;;; or pass the --no-auto-compile argument to disable.
;;; compiling /usr/share/guile/site/math/primes.scm
;;; compiled /home/hsmyers/.cache/guile/ccache/3.0-LE-8-4.2/usr/share/guile/site/math/primes.scm.go
scheme#(math primes)> (prime? 3)
$2 = #t
While it's nice that this approach works, it doesn't seem like the correct way to do things.
Obviously, I'm doing something wrong here, but I'm (as usual) completely clueless
as to what is wrong. My question is—what do I need to fix the connection between
Guile and Library location?
If I want to optionally require a module at runtime, I can use [dynamic-require'1. This works great if I want to require a package that has been installed, for example:
(dynamic-require 'racket/match 'match)
This will (provided I have racket/match installed), require racket/match and evaluate to the match binding in that library.
However, I run into trouble when I want to require a local, non installed module. Let's say I have some module called eat.rkt, which provides one function: bite:
#lang racket ;; eat.rkt
(provide bite)
(define (bite) "Nom nom")
Now lets say we want to make a lunch.rkt module that requires eat.rkt, and calls the function. Furthermore, lets suppose I put them in the same directory:
#lang racket ;; lunch.rkt
(require "eat.rkt")
(bite) ; => Nom Nom
This is fine because I used static require, but this falls apart when I want to do a dynamic-require:
#lang racket ;; lunch2.rkt
(define bite (dynamic-require "eat.rkt" 'bite)
(bite) ; => Nom Nom
While this appears to be fine, it turns out that the module required by dynamic-require is NOT required based on the module's path, but on current-directory. So, if I run the program in the directory the module is defined, that's fine, but if I'm in another directory, everything breaks:
$ racket lunch2.rkt
"Nom Nom"
$ cd snacks/
$ racket ../lunch2.rkt
; default-load-handler: cannot open module file
Obviously I could just change the current-directory to this module's directory if I know where it is. But if I don't know this module's path, is there any way to get it? Or, more directly, is it possible to dynamic-require a module relative to the requiring's module path?
The define-runtime-path form defines a path that will be available at runtime and is independent of the current-directory. Use it to define the path to the module you want to require dynamically, for example:
#lang racket
(require racket/runtime-path)
(define-runtime-path eat "eat.rkt")
(dynamic-require eat 'bite)
The easiest way to dynamic-require a module relative to the current module path (which is to say the path where the module is saved), is to get that module path and append it your relative module.
You can do this with #%variable-reference and variable-reference->module-path-index. (You may also want to use variable-reference->resolved-module-path for other situations, but we will not do it here.) Composing these two functions gives us a module-path-index? to the module being defined. (Or in general, the module that the #%variable-reference came from.)
So, we can a variable like:
(define here (variable-reference->module-path-index (#%variable-reference)))
Now all that is left is to compose this here path with the relative path to the module we want to require. We are looking for the module path analogy of build-path, if you will.
It turns out that the function we are looking for is: module-path-index-join, which takes a base path and a relative path and appends them together. The result will look something like:
(module-path-index-join "eat.rkt" here)
(Yes, it is backwards of what you would expect from build-path, but the base path comes second for this function.)
The resulting module, lunch3.rkt looks like:
#lang racket
(define here (variable-reference->module-path-index (#%variable-reference)))
(define bite (dynamic-require (module-path-index-join "eat.rkt" here) 'bite))
And now lunch3.rkt will require eat.rkt relative to where its defined, not based on the current-directory:
$ racket lunch3.rkt
"Nom Nom"
$ cd snacks/
$ racket ../lunch3.rkt
"Nom Nom"
Thank you to Matthew Flatt for helping with this answer.
General question:
Can I invoke the current racket executable from within a running Racket script?
Basically, I'd like a replacement for (system "racket ...") in the case that (find-executable-path "racket") does not return a path to the Racket executable I'm currently using.
Context:
What I really want is to try compiling a few expressions and assert that they raise compilation errors. This is for unit testing.
I don't believe you need to step outside of the executable here. Try this:
#lang racket
(require syntax/modread)
;; define a namespace anchor to attach a namespace to:
(define-namespace-anchor anchor)
;; define a namespace for expansion:
(define target-namespace (namespace-anchor->namespace anchor))
(define program-to-compile
"#lang racket
(+ 3 4)")
;; go ahead and expand
(with-module-reading-parameterization
(λ()
(parameterize ([current-namespace target-namespace])
(expand
(read-syntax
"bogus-filename"
(open-input-string program-to-compile))))))
I think I'm correct when I say that Racket is singularly clean in its ability to provide the compiler to running programs in a disciplined way.
If your goal is just to compile some racket expressions, you can do that just with either compile or compile-syntax. An example file would be:
#lang racket
(require rackunit)
(define tests
(list #'(+ 1 "3")
#'(void void)
#'(string-append 4)))
(for/list ([t (in-list test)])
(check-exn exn:fail?
(lambda () (compile t))))
Where exn:fail? is whatever exception you are looking for.
Furthermore, if you have some common syntax context you want to run your test in, you can use #` #,. So your code would end up something like this:
#lang racket
(require rackunit)
(define tests
(list #'(+ 1 "3")
#'(void void)
#'(string-append 4)))
(for/list ([t (in-list test)])
(check-exn exn:fail?
(lambda () (compile #`(module anonymous racket
#,t)))))
Finally, if your code is stored on your computer, you can use John's solution, while using file->string to convert the file into a string.
For small tests, you can also use convert-compile-time-error from the syntax/macro-testing library. It turns an expression that causes a compile-time error into an expression that raises a run-time error when evaluated. The expression uses the environment where it occurs in the module, including local bindings; you don't have to fiddle with namespaces and eval.
(check-exn #rx"bad syntax"
(lambda () (convert-compile-time-error (lambda))))
There's also convert-syntax-error (on the same page).
I'd like to selectively run a Racket module's submodules from another module. Please help me fill in the blanks!
File 1
#lang racket/base
;; <big file, lots of code>
(module+ small-tests
;; basic correctness checks
(displayln "Small tests pass!")
)
(module+ big-tests
;; heavy duty stress tests
(displayln "Big tests pass!")
)
File 2
#lang racket/base
(module+ main
;; Trigger either the small-tests or the big-tests,
;; depending on what's written here.
(require '???)
)
It would also be great if running the big tests would automatically run the small tests, too.
The submod form is used to require a module's submodule.
As an example:
#lang racket
(module A racket
(module+ main
(displayln "Hello World")))
(module B racket
(require (submod ".." A main)))
(require 'B)
Thanks to Leif and Alexis's hints, the way to get File 2 to run the small-tests submodule is to replace the '??? with:
(submod "file1.rkt" small-tests)
Also, editing the big-tests submodule to include the line:
(require (submod ".." small-tests))
will cause both small & big tests to run when File 2 executes (require (submod "file1.rkt" big-tests)).
I have a file "exceptions.rkt"
#lang racket
(module exceptions racket
(provide Macro/Raise Macro/Assert Macro/Assert* Macro/Domain-Assert)
; ... Definitions for provided symbols...
) ; End of module, end of file
Macro/Raise etc are not actually macros defined with define-syntax, they're just unary functions generated with syntax-rules and assigned a name
(define Macro/Raise
(syntax-rules ()
; ... body not important ...
))
and in the same folder as "exceptions.rkt", I have a file "tables.rkt".
#lang racket
(module tables racket
(require "exceptions.rkt")
(define-syntax Assert Macro/Assert)
; ... more stuff...
) ; End of module, end of file
but this results in Macro/Assert: undefined; cannot reference an identifier before its definition in module: 'tables phase: 1
I've tried reading the doc and can't figure out what I'm doing wrong... So what am I doing wrong?
In order for definitions to be usable during the macro definition phase, use for-syntax:
(require (for-syntax "exceptions.rkt"))
Also you don't need the (module exceptions racket ...) wrapper over the code since #lang racket already generates a module.