Running other modules' submodules - module

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)).

Related

What is the conventional way to divide a source file into several modules?

I've got a source file about 380 lines long. It's well past the point where it's hard to read because it's just a big sea of defines. I'd like to break it up, preferably into several scopes, not just by inserting a comment before each group of related definitions. I'd also prefer not to break it into separate source files, since I've got several source files that are all very similar: each is an experiment with a different way of doing the same thing. If I broke each one into multiple source files, I'd have a proliferation that I couldn't keep track of.
I figure that the module and module* forms are made for this, but I haven't yet figured out how they're all meant to work together. I've tried various combinations, with varying levels of success, none fully satisfactory. I figured I'd just ask here how it's done.
The source file looks roughly like this:
#lang debug at-exp racket
(require rackunit data/collection racket/dict racket/generic racket/pretty
racket/hash describe "graph.rkt") ; <--- same requires needed in every scope
(provide make-slipnet run-slipnet spread-activation ...)
;; defines for making a 'slipnet' graph ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define ...)
(define ...)
(module+ test
...)
(define ...)
(module+ test
...)
...
(define (make-slipnet ...) ...) ;The rest of the file only needs these
(define (run-slipnet ...) ...) ;two functions from this section.
;; defines for doing spreading activation ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define ...)
(define ...)
(module+ test
...)
...
(define (spread-activation ...) ...) ;The rest of the file only needs this
;function from this section
;; Etc.
(module+ main
;generate some human-readable output here, calling make-slipnet,
;run-slipnet, spread-activation, functions from "graph.rkt", etc.
)
How do you divide these functions up into their natural groups?
Use submodules for semantic organization. Use comments for visual organization.
Submodules are useful when code should only be run in certain modes (eg test submodules for testing, main submodules for programs/commands, etc). They're also useful when you need the same helper function both at compile time (within a macro transformer) and at run time; you can define it once in a submodule and require the submodule at multiple phases.
But otherwise, just use comments and whitespace. My current preference is to separate major sections with lines of 60 equal signs (double line) and minor subsections with lines of 40 hyphens. Sometimes I put a section title below the line (if I can think of a concise label).
Tip: in both Emacs and DrRacket, you can insert 60 equal signs by hitting Escape 6 0 =. Likewise for inserting n copies of any other character.
Example:
;; ============================================================
;; Data definitions
;; A Vertex is a Symbol.
;; A Graph is (graph (hashof Vertex (Listof Vertex))).
(struct graph (out-edges))
;; ============================================================
;; Graph algorithms
;; ----------------------------------------
;; Paths
;; find-path : Graph Vertex Vertex -> (U #f (Listof Vertex))
(define (find-path g from to) ....)
;; ----------------------------------------
;; Strongly-connected components (SCCs)
;; vertex->scc : Graph Vertex -> (Listof Vertex)
(define (vertex->scc g vertex) ....)
;; ============================================================
;; External forms
;; read-graph : InputPort -> Graph
(define (read-graph in) ....)
;; write-graph : Graph OutputPort -> Void
(define (write-graph g out) ....)

dynamic-require a module with respect to the current module path in Racket (Or how to find the current module path in Racket)

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.

Accessing Internal Symbols of a Package in Testing Package

I have a program that I'd like to test using prove. Currently, I have a separate package for the tests. The problem I'm facing is that I don't really want to have to export every symbol from the primary package (I'm only exporting one currently), but I want to be able to access everything from the testing package.
Using main-package::symbol works, but is ugly and a bad idea I'm guessing. Is there some better way to do this without having to export all my symbols just for testing them? I've considered using the same package for writing the tests, but I don't want to have to have a (:use :prove) in my main package when I'm only using it for the testing code. Is there some way to do something like (:use :package) but only for one file? If there is, would it make sense to use that here?
You could separate the tests into their own system. That way your main system won't have a dependency on prove at all. In the test system you can load the same source files, but different package definitions (this of course assumes you put your package definitions in a different file, rather than using the strange custom of putting them on top of your source file...).
For example, the main program might look like this:
foo.asd:
;; Here I'm obviously putting the package def in the same file
(in-package :cl-user)
(defpackage :foo-asd
(:use :cl :asdf))
(in-package :foo-asd)
(defsystem "foo"
:components ((:file "foo-package")
(:file "foo")))
foo-package.lisp:
(in-package :cl-user)
(defpackage :foo
(:use :cl)
(:export :foo))
foo.lisp:
(in-package :foo)
(defun foo (x)
(+ (bar x)
(bar x)))
(defun bar (x)
(* x x))
And the test system in the same directory:
foo-test.asd:
(in-package :cl-user)
(defpackage :foo-test-asd
(:use :cl :asdf))
(in-package :foo-test-asd)
(defsystem "foo-test"
:depends-on (:prove)
:components ((:file "foo-test-package")
(:file "foo")
(:file "foo-test")))
foo-test-package.lisp
(in-package :cl-user)
(defpackage :foo
(:use :cl :prove))
foo-test.lisp:
(in-package :foo)
(plan 2)
(is (bar 2)
4)
(is (foo 2)
8)
(finalize)
This lets you easily run your tests in a new image (to make sure that the version of the code that's actually on your disk works) with something like sbcl --noinform --eval "(ql:quickload :foo-test)" --eval "(sb-ext:quit)". You could of course put the tests behind a function if you want.

Invoke `racket` in a Racket script

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).

Common Lisp equivalent to Haskell's main function?

Haskell's main function does just what I want: evaluate when the file is loaded by itself (e.g. ./myfile.hs or runhaskell myfile.hs) and in no other case. main will not be called when the file is imported by another file. newLISP also has this functionality.
Is there equivalent code for Common Lisp?
I read the source code for CLISP. Here's what happens when the user enters clisp myfile.lisp or ./myfile.lisp:
CLISP saves myfile.lisp as p->argv_execute_file.
CLISP creates the expression (LOAD "p->argv_execute_file") and pushes it onto the Lisp stack.
CLISP saves any additional command-line arguments in a list.
CLISP stores the arguments in the Lisp variable *args*.
CLISP never makes a Lisp variable referring to p->argv_execute_file, so there is no way to discern whether myfile.lisp was loaded directly, by the user in the REPL, or by another Lisp file. If only (car *args*) were myfile.lisp, my task would be easy.
Note: Shebangs give CLISP trouble if the file is loaded from the REPL, so I put this code in ~/.clisprc.lisp:
(set-dispatch-macro-character #\# #\!
(lambda (stream character n)
(declare (ignore character n))
(read-line stream nil nil t)
nil))
I found a solution. It's a bit of shell trickery, but it works. I'll soon modify this to work on CL implementations other than CLISP.
#!/bin/sh
#|
exec clisp -q -q $0 $0 ${1+"$#"}
exit
|#
;;; Usage: ./scriptedmain.lisp
(defun main (args)
(format t "Hello World!~%")
(quit))
;;; With help from Francois-Rene Rideau
;;; http://tinyurl.com/cli-args
(let ((args
#+clisp ext:*args*
#+sbcl sb-ext:*posix-argv*
#+clozure (ccl::command-line-arguments)
#+gcl si:*command-args*
#+ecl (loop for i from 0 below (si:argc) collect (si:argv i))
#+cmu extensions:*command-line-strings*
#+allegro (sys:command-line-arguments)
#+lispworks sys:*line-arguments-list*
))
(if (member (pathname-name *load-truename*)
args
:test #'(lambda (x y) (search x y :test #'equalp)))
(main args)))
(eval-when (situation*) ...)
Update sorry for the confusing answer.
I could be wrong, but it seems to be impossible to do what you want exactly. I would make a shell script and call clisp -i myfile.lisp -x (main).
Is there any reason to not make it executable (described here)?
P.S. Common Lisp is a language and clisp is one of the implementations.