Let's say I have a library foo in foo.scm like so:
(module foo (bar)
(import scheme)
(define (bar arg)
(+ 5 arg)))
And I have a program program.scm:
(use foo)
(display (bar 2))
Now, I compile foo and generate the import library using csc -J -library foo.scm, and then compile program with csc program.scm. Running program displays "7", as expected and everything is dandy. However, I want to load program interactively in the interpreter (csi), but now for some reason each call to a function in foo has to be prefixed with foo#, i.e. in the interpreter (foo#bar 2) works, but (bar 2) doesn't even though it works when used in a source file.
Why is this? Not only is this slightly annoying, I'm also afraid that I may have a misunderstanding of how the module system works in Chicken, so any clarification would be much appreciated.
I'm not sure what you mean by "load the program into the interpreter", but usually (use foo) should load and import the library, so performing (load "program.scm") should do just that, and all the things exported by foo should be available at toplevel.
It sounds like you somehow ended up with a situation where the library has been loaded into the running system, but hasn't been imported for use at toplevel. Just typing (use foo) (or even (import foo)) at the REPL should fix this problem.
CHICKEN's module system has been designed to allow for separate compilation, which makes cross-compilation possible. To make this work, the import library and actual implementation have been separated, but this complicates things a little, as you've discovered. This is needed because the import library may define macros that are needed at compile-time, so it needs to run on the cross-compiling host, whereas the library itself will need to be available in the cross-compilation target's architecture. We're discussing on how to simplify this for CHICKEN 5, as this is something that confuses many beginners (and sometimes advanced users, too).
Related
I need to compile a Chicken Scheme project containing multiple source files, but I'm getting errors.
According to the manual and this SO answer, I need to put (declare)s in my sources. Why the compiler can't just see that I'm importing the other source is beyond me, but meh.
The problem is, even if I put the (declare)s in, the compiler complains about the (import)s and (use)s.
infinity.filesystem.scm:
(use bindings filepath posix)
(declare (uses infinity.general.scm))
(load-relative "infinity.general.scm")
(module infinity.filesystem (with-open-file make-absolute-path with-temporary-directory with-chdir)
(import scheme filepath posix infinity.general)
(begin-for-syntax
(use bindings chicken)
(import infinity.general))
...etc...
infinity.general.scm:
(declare (unit infinity.general.scm))
(require-extension srfi-1 srfi-13 format data-structures ansi-escape-sequences basic-sequences)
(module infinity.general (bind+ format-ansi repeat-string join-strings pop-chars! inc! dec!
take* drop* take-right* drop-right* ends-with? take-where)
(import scheme chicken srfi-1 srfi-13 data-structures ansi-escape-sequences basic-sequences bindings ports format)
...etc...
Command:
$ csc -uses bindings.o -uses infinity.general.o -c infinity.filesystem.scm -o infinity.filesystem.o
Compiler says:
Syntax error (import): cannot import from undefined module
and
unbound variable: use
If I just remove the import and use declarations for "infinity.general", the file compiles. However, I have two problems with this:
Will the resulting .o file actually work, in the absence of import and use clauses? Or will it complain about missing code at runtime?
csi requires that my code contains (import) and (use) declarations, whereas csc requires that it does not. I, however, require that my code works in both csi and csc!
How can I solve this, please?
Why the compiler can't just see that I'm importing the other source is beyond me, but meh.
Declares are used to determine dependencies: the compiler needs to know in what order (and if at all) to invoke a particular toplevel, to ensure the right code is initialized before any of the globals from that unit can be used. When everything is being compiled separately, the compiler wouldn't know when to insert calls to toplevels. The -uses switch you pass to csc is redundant: csc -uses foo is equivalent to putting (declare (uses foo)) in the source code. Passing -uses foo.o doesn't do anything with the file foo.o as far as I can tell.
In your code snippet, you're using load, which is not the correct way to include code at compile-time: load will read and evaluate the target file at run time. Instead, you should omit the load completely: the declare already takes care of the dependency; you just need to link them together.
Also, it's not very common to use filenames as module/unit names, though it should work.
If I just remove the import and use declarations for "infinity.general", the file compiles. However, I have two problems with this:
1) Will the resulting .o file actually work, in the absence of import and use clauses? Or will it complain about missing code at runtime?
You'll need to keep the import expressions, or the program shouldn't compile. If it does compile, there's something strange going on. You don't need use when you link everything together statically. If you're using dynamic linking, you will get a runtime error.
The error you get about unbound variable: use is because you're using use in a begin-for-syntax block. You'll probably just need to (import-for-syntax chicken), as per your other SO question.
2) csi requires that my code contains (import) and (use) declarations, whereas csc requires that it does not. I, however, require that my code works in both csi and csc!
It looks like you're approaching this too quickly: You are writing a complete program and at the same time trying to make it run compiled and interpreted, without first building an understanding of how the system works.
At this point, it's probably a good idea to experiment first with a tiny project consisting of two files. Then you can figure out how to compile an executable that works from code that also works in the interpreter. Then, use this knowledge to build the actual program. If at any point something breaks, you can always go back to the minimal case and figure out what you're doing differently.
This will also help in getting support, as you would be able to present a complete, but minimal set of files, and people will be able to tell you much quicker where you went wrong, or whether you've found a bug.
In C, to make sure we don't re-include headers that are included we use the following structure:
#ifndef UTILS
#define UTILS
#include "my_utils.h"
#endif
I've broken my Lisp program into separate files; multiple files sometimes use the same file (e.g., my_utilities is used by multiple files). When I run the program, I get warnings that I am redefining things (calling load of the same file multiple times).
This would be fixed by doing something similar to #ifndef in C. What is the Common Lisp equivalent or standard method of doing this?
I am fairly new to Lisp. Let me know if there are best practices (perhaps, a different method of structuring my programs?) that I am missing.
The question you asked
The direct analogue of preprocessor conditions like #if in C is the
#+ read-time conditionalization facility.
The question you wanted to ask
To avoid multiple loading of a file, you can either use the standard
(but deprecated)
provide/require facility,
or an add-on system like ASDF.
For Common Lisp applications and libraries it is preferred to use a system management tool. Like ASDF or whatever your implementation may provide. A system is a collection of files with dependencies and various actions (load, compile, ...).
You can always check the state of the runtime and do something.
Example:
(unless (fboundp 'foobar)
(require "foo")
(load "bar"))
(unless (find-package 'foobar)
(require "foo")
(load "bar"))
PROVIDE and REQUIRE are built-in functions for exactly that. If you require a module it will be loaded, unless already provided. Unfortunately this functionality is underspecified in the standard, but implementations may provide useful functionality.
Common Lisp runtimes have a list of features on the list *features*. You can use that to advertise and check functionality.
Example:
In your library:
(push :cool-new-graphics-library cl:*features*)
In your application code:
(when (member :cool-new-graphics-library cl:*features*)
(funcall (find-symbol "DRAW-SPACE-SHIP" "CNGL")
:death-star))
Common Lisp provides a way to conditionalize that a read time. The following code will only be read when the :cool-new-graphics-library feature is present, and thus it only then will be executed later:
#+cool-new-graphics-library(cngl:draw-space-ship :death-star)
Common Lisp also allows you to express some logic:
#+(and lispworks cool-new-graphics-library)
(cngl:draw-space-ship :enterprise)
#-cool-new-graphics-library(warn "no cool graphics library available")
Note that you can force Lisp to execute code at compile-time:
(eval-when (:load-toplevel :compile-toplevel :execute)
#+(and lispworks cool-new-graphics-library)
(cngl:draw-space-ship :enterprise)
#-cool-new-graphics-library(warn "no cool graphics library available")
)
For this to work the EVAL-WHEN has to be at the toplevel in a file. That means it will not work deep in nested forms. It does work inside a toplevel PROGN,LOCALLY, MACROLET and SYMBOL-MACROLET, though.
Thus EVAL-WHEN allows you to run code which is part of the file which is currently compiled. This code than can look for loaded systems, provided modules, available functions, and more.
I'm a little hazy on the differences between (use) and (import) in Chicken. Similarly, how do (load), (require) and (require-extension) differ?
These things don't seem to be mentioned much on the website.
Load and require are purely run-time, procedural actions. Load accepts a string argument and loads the file with that name (which can be source or compiled code) into the running Scheme, so that whatever it defines becomes available. Require does the same thing, but checks if the file has already been loaded by seeing if provide has been called on the same name (typically by the file as it is loaded). They are relatively rare in Scheme programming, corresponding to plug-ins in other languages, where code unknown at compile time needs to be loaded. See the manual page for unit eval for more details.
Import is concerned with modules rather than files. It looks for the named module, which must have already been loaded (but see below for Chicken 5), and makes the names exported from that module visible in the current context. In order to successfully import a module, there must be an import library for it. It is syntax, so the module name must appear explicitly in the call and cannot be computed at run time. See the manual page on modules for more details.
Require-library does the Right Thing to load code. If the code is already part of the running Scheme, either because it is built into Chicken, it does nothing. Otherwise it will load a core library unit if there is one, or will call require as a last resort. At compile time, it does analogous things to make sure that the environment will be correct at run time. See the "Non-standard macros and special forms" page in the manual for more details.
Use does a require-library followed by an import on the same name. It is the most common way to add functionality to your Chicken program. However, we write (import scheme) and (import chicken) because the functionality of these modules is already loaded. Require-extension is an exact synonym for use, provided for SRFI 55 compatibility. In R7RS mode, import is also a synonym for use.
Update for Chicken 5
Use has been removed from the language, and import now does what use used to do: it loads (if necessary) and then imports. Require-extension is consequently now a synonym for import.
In addition, Chicken-specific procedures and macros have been broken into modules with names like (chicken base) and (chicken bitwise).
I've written a sort of DSL on top of Common Lisp. The domain is quite strange and my language looks quite different from Common Lisp itself. I've put all interface into a package foo:
(defpackage :foo
(:use :common-lisp
:internal-machinery)
(:shadow :in-package
:*packages*))
Switching between packages is beyond of the language concept, so I've disabled this ability by shadowing symbols in-package and *package*. Now user (programmer) of my language will be unable to switch packages. Fine.
Obviously, I want to use Common Lisp compiler to compile programs written in this language. Function compile-file looks OK for me. But there are difficulties.
I want to compile a file as if its contents were inside of my foo package. Putting (in-package :foo) on top of every program in my prototypical language is an undesirable option.
To make things even worse, I have to compile a file inside of a function:
(in-package :internal-machinery)
(defun compile-stuff (filename)
(in-package :foo) ; it will have no effect, because
; this macro must be top level form
(compile-file filename) ; other options are omitted
(in-package :internal-machinery)) ; no way, even if it were top level
; form, in-package is shadowed
I have no idea if it's possible or not, so any help would be appreciated.
How about
(defun compile-stuff (filename)
(let ((*package* (find-package '#:foo)))
(compile-file filename)))
PS. As Rainer mentioned in a comment, if you offer REPL to the user, you are not safe from the user changing the package with (cl:in-package "CL-USER").
In Chicken it looks like I can (use srfi-9), but in Guile it looks like you say (use-modules (srfi srfi-9)), in Racket it is (require srfi/9). Is there a standardized use-module form that should work across all scheme implementations (so that I can write portable code)?
Yes, in R6RS and R7RS, use:
(import (srfi …))
import is the 'standard form' for this. The trouble is that the … can depend on the implementation. So the problem is moved down one level. I've seen:
(import (srfi :0))
(import (srfi srfi-0)
in different implementations.
For R6RS and R7RS there is a method to load libraries so it really should be possible. I know that you can do (import (srfi :9)) and it works in Ikarus as well as Racket. I'm unsure as if there exists a standard to what the naming convention should be so it might be different in other implementations. You might need to make wrappers for certain implementations.
In R5RS you'll have to rip the reference implementation and use load. This won't use the implementations optimized code at all. I've seen projects that make implementation specific start file that makes use of what they support and add code for those who don't to get the best performance.