export list for modules in scheme - module

Is there a way to define a module in Scheme, and specify that all the bindings are to be exported, without listing each and every one of them explicitly?
Is there a way to do the above while specifying a list of binding that are not to be to be exported?

Scheme reports before R6RS does not have libraries defined in the spec so no. It is not possible in an portable way. However most implementation of R5RS actually have their own module system. eg. Racket has powerful syntax to do exatly as you want:
#lang racket
(provide (all-from-out <module>))
(provide (except-out (all-from-out <module>) lambda))
From R6RS we have libraries, however their export spec needs every export by name.
R6RS:
#!r6rs
(library <library name>
(export <export spec> ...)
(import <import spec> ...)
<library body>)
R7RS:
#!r7rs
(define-library <library name>
<library spec>)
The R7RS changed the syntax with purpose but has the same ability. See the R7RS-small report (pdf, page 28)

Related

Does file(GENERATE) resolve variables?

I am trying to generate a file, but it fails to resolve variables. Since file(generate) runs during the generate step, are there limitations to what variables it can resolve? (e.g. only cache variables?)
My variables don't get resolved despite them being defined.
message("Registered composites: ${COURAGE_COMPOSITES}")
file(GENERATE OUTPUT ${OUTPUT_PATH}/output.xml INPUT ${INPUT_PATH}/output.xml.in)
output.xml.in
<imports>
$<$<NOT:$<STREQUAL:"${COURAGE_COMPOSITES}","">>:<import iuts="yes"$<ANGLE-R>$<JOIN:${COURAGE_COMPOSITES},</import$<ANGLE-R><import iuts="yes"$<ANGLE-R>></import$<ANGLE-R>>
</imports>
output.xml
<imports>
<import iuts="yes">${COURAGE_COMPOSITES}</import>
</imports>
Actually, file(GENERATE) doesn't expand variables at all.
Documentation for that command tells nothing about variable's expansion
Generate an output file for each build configuration supported by the current CMake Generator. Evaluate generator expressions from the input content to produce the output content.
If you want to expand variables, you could firstly expands them with command configure_file into intermediate file, and then expand generator expressions in that file using file(GENERATE):
# output.xml.in -> output.xml.im
configure_file(${INPUT_PATH}/output.xml.in ${OUTPUT_PATH}/output.xml.im)
# output.xml.im -> output.xml
file(GENERATE OUTPUT ${OUTPUT_PATH}/output.xml INPUT ${OUTPUT_PATH}/output.xml.im)
Alternatively, if your input file is small, you could embed it into the CMakeLists.txt as a string, and use CONTENT parameter for file(GENERATE):
file(GENERATE OUTPUT ${OUTPUT_PATH}/output.xml CONTENT
[=[
<imports>
$<$<NOT:$<STREQUAL:"${COURAGE_COMPOSITES}","">>:<import iuts="yes"$<ANGLE-R>$<JOIN:${COURAGE_COMPOSITES},</import$<ANGLE-R><import iuts="yes"$<ANGLE-R>></import$<ANGLE-R>>
</imports>
]=]
)
In that case the variable substitution will be performed by CMake itself before it passes the string to the command.

Should I define separate module for every file in my Guile project?

Let me explain my problem by comparison. In Common Lisp I could split package definitions to several files, it was enough to declare in each of them that it's in-package and load them.
However in Guile Scheme it looks like I should define-module, separate for each file? Well I still can load some files like in CL and it looks like working, define-modules seems not limited to a single file it is located in like in CL, but I get warnings about undefined names (those that are defined in loaded files), so it gives me feeling that it's not what Guile expects. Is there (1) some way of splitting module across several files like in CL, or (2) should I stick to use-module autoload feature and define-module for each file separatelly?
Indeed in Guile you can load inside a define-module but it will report unbound variable at compile time.
The idiomatic way is the define-module in every file:
;; in earth-software-system.scm
(define-module (earth-software-system))
(use-modules (earth-software-system bullet-train))
(use-modules (srfi srfi-9))
(re-export bullet-train) ;; possibly re-exporting imported bindings
...
Then in earth-software-system/bullet-train.scm you can have:
;; in earth-software-system/bullet-train.scm
(define-module (earth-software-system bullet-train))
(use-modules (srfi srfi-9))
(define-public bullet-train 42)
...
Mind the fact that define-public and a single import per use-modules is not widespread. Here is an example from GNU Guix project that rely on define-module to import and export:
(define-module (guix cpio)
#:use-module ((guix build utils) #:select (dump-port))
#:use-module (srfi srfi-9)
#:use-module (srfi srfi-11)
#:use-module (rnrs bytevectors)
#:use-module (rnrs io ports)
#:use-module (ice-9 match)
#:export (cpio-header?
make-cpio-header
file->cpio-header
file->cpio-header*
write-cpio-header
read-cpio-header
write-cpio-archive))
Also nowadays I prefer the import form which is more easy to the mind that use-modules:
;; in earth-software-system.scm
(define-module (earth-software-system))
(import (prefix (earth-software-system bullet-train) 'bt:)
(import (srfi srfi-9))
(re-export bt:bullet-train) ;; possibly re-exporting imported bindings
...
The prefix syntax is also more easy to the mind than the equivalent using use-modules. This is inspired from R6RS library form and R7RS define-library form. I do not recommend to use library form in Guile since it doesn't report lines correctly.
GNU Guile allow to import forms even if they are not exported using the ## syntax for instance to test some tricky behavior.
You might replace load with include but I never used it in Guile

What is a Module Path Index in Racket

Racket has Module Paths (predicate is module-path?), Resolved Module Paths (predicate is resolved-module-path?), and Module Path Indexes (predicate is module-path-index?).
I guess a module-path? is anything that could plausibly point to a module. And I guess a resolved module path points to an actual module on the system.
But what is a module path index and what does it get me over just a resolved module path?
A module-path? contains anything that can be required. Could be a path?, could be a symbol, could be a submodule path (submod "food.rkt" lunch). See require in the docs.
A resolved-module-path? is an "absolute path" to where Racket can find the module (Note 1). The grammar for resolved module paths is more limited (i.e., less ambiguous) than for module paths.
A module-path-index? (MPI) is a delta from one module-path-index? to another (Note 2). Use module-path-index-join to build MPIs (Note 3).
(module-path-index-join #f #f) is a delta from the current module to itself.
(module-path-index-join "dumplings.rkt" #f) is a delta from #f (the current module) to the relative path "./dumplings.rkt" (Yes it's really path first, then base.)
(module-path-index-join "nom-noms.rkt" (module-path-index-join "dumplings.rkt" #f)) is a delta from the current module to "./dumplings.rkt" to "./nom-noms.rkt". Racket builds MPIs like this when one file statically requires another --- these can be chained together to find the binding of an identifier.
(module-path-index-join '(submod test) #f) refers to the test submodule in the current module.
Hope that helps.
Note 1: If the module is in a file, a resolved path for it is an absolute filepath. If the module is the result of calling eval on a syntax object, its resolved-module-path? is something else.
Note 2: IMO "module path deltas" would be a better name.
Note 3: module-path-index-join accepts a third, optional argument when the first two arguments are #f. This lets a module refer to one of its own submodules. You will generally not want to use this feature directly. And instead use quote-module-path.

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.

Apache Ant: Is it possible to insert/replace with text from a raw text file?

I'd like to take text from a standard text file and insert it into an XML that is copied with replace tokens by Apache Ant. Is this possible?
Example (this is what I use so far):
<macrodef name="generateUpdateFile">
<sequential>
<echo message="Generating update file ..." level="info"/>
<copy file="update.xml" tofile="${path.pub}/update.xml" overwrite="true">
<filterchain>
<replacetokens>
<token key="app_version" value="${app.version}"/>
<token key="app_updatenotes" value="${app.updatenotes}"/>
</replacetokens>
</filterchain>
</copy>
</sequential>
</macrodef>
The ${app.updatenotes} are currently a string that is defined in a build.properties file. But instead I'd like to write update notes in a simple text file and take them from there.
The apache ant loadfile task will allow to read your text file, and put its content into the app.updatenotes property.
You can simply use:
<loadresource property="app.updatenotes">
<file file="notes.txt"/>
</loadresource>
Then, use your filterchain, just as before.
loadresource has some options, for instance to control the encoding of your file, or to control how to react if the file is not present, or not readable.