How can lisp (scheme) be compiled to binary file? - scheme

I am using a softerware who has a build-in scheme interpreter. Users can communicate / manipulate the software by typing command in the interpreter. And users also could load some binary file to the environment. I have write some scheme code like this:
(define test (lambda() (display "This is a test!"))) ---- d:/test.scm
And then compile it into binary file which will be loaded and excuted much faster. But the document has no information about compilation of the scheme code.
After compilation user could load the binary file by typing:
(fast-load "d:/test.bin" (the-environment))
I think the "fast-load" just do read and eval things. So does the compilation is just a encrypting process? Does anybody know about these things? Any information will be appreciated! Thanks in advance.
And there is another example: the AutoCAD system. Users can write lisp code to manipulate the AutoCAD. And user could compile the lisp code into *.fas file which will be loaded into AutoCAD. So if it is really only an encrypting process, how can I write a compiler? Is there any documents about it?
Joe

If you are strictly talking about the application's built-in interpreter (as seems to be the case based on your question), there's no standard answer. You'll need to see if the application designer built compilation into their implementation and exposed that functionality for you. If not you're out of luck.
If you were to ask about stand-alone Scheme applications or libraries, many implementations (such as Chicken) provide Scheme compilers of one sort or another (the previously-mentioned Chicken Scheme compiles to C first).
If you were asking about Common Lisp (ignoring the fact that you mention Scheme specifically in your title and question). You can use the standard function, compile-file, which produces the .fasl format you alluded to at the end of your question.

Related

How to record scheme session in a file?

I'm trying to record my session while writing some scheme code, But I don't know which is the correct code to record my session while doing some expression.
R5RS
R5RS has an optional procedure transcript-on that takes a file name and it will output the interaction until transcript-off` is called. (Thanks #molbdnilo for pointing this out in a comment)
R6RS and R7RS
This is not supported in the report. Even (scheme-report-environment 5)‌ is specified not to contain the optional procedures load, interaction-environment, transcript-on, transcript-off, and char-ready?.
Implementation lock-ins
The individual implementations might have such features included and if you just need it for you chosen implementation you must read its documentation to find it. I guess this is for tooling rather than production code so using implementation specific features isn't as bad as using non scheme standard forms.
roll your own
You can make your own repl that does what you want with the file output of you chosing that would be the same across all implementations.

Is there a way to use load-mode for files in DrRacket?

I would like to use DrRacket in the same way that it works for some of the ‘legacy languages’. In particular, I would like to go through a file as if it were a sequence of commands issued to the interpreter, and not as a module.
Essentially I want to run at least one file in load-mode, but I’m not sure if it’s possible to do it using DrRacket.
Ideally, I could:
*Specify a file that sets the language and maybe loads some modules, which runs by default at startup.
*Then load a file that is not a module (and has no #lang specification) and run it.
It’d also be nice (since I want to use Scheme) if it would allow redefinitions, just as the legacy languages do.
Yes you can, and in fact, the 'legacy languages' (and 'teaching languages') are actually just implemented as DrRacket Plugins. You can remove them from your copy of DrRacket and even add new ones.
There are various ways to do this depending on if you are okay with a #lang (or #reader) saved in the file. If you're not, its still doable, you just need to use drracket:get/extend:extend-unit-frame to add your tool to DrRacket, and possibly drracket:get/extend:extend-definitions-text to easily extend the definitions window.
I won't go into the details of making a generic DrRacket plugin here, that belongs in a different question...also the DrRacket Plugins Manual has the information you need.1 I will, however, point you in the direction of how you can use DrRacket in load mode out of the box.
Check out the racket/load language. It is designed to run each expression in the top level as if you were at a REPL typing it. I find it very useful for testing the differences between Racket module and top level interactions.
Of course, if you don't make a DrRacket plugin, you will still need to put:
#lang racket/load
at the top of your file, but you otherwise get a 'legacy mode' out of the box.
1If it doesn't please continue to ask questions, and of course we always love help from anyone who is willing to contribute. <3

#ifndef in Common Lisp

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.

What extension allows access to time function in r5rs?

A 4-year-old old post suggests that one might be able access the current-seconds and related functions in the r5rs language.
Here's why I ask: I'm a high school teacher new to Racket and we are using the r5rs language. I would like to introduce students to functions by starting with a function that needs no arguments to make sense. The example that occurs to me is minutes-past-the-hour. But I am ignorant of how to make those functions recognized in an r5rs program.
Thanks for any helpful advice.
First of all, why not use #lang racket instead of r5rs? Racket is very much built with education in mind. It even has various teaching languages for use with the How to Design Programs textbook (or its second edition, which is still being worked on).
Racket's implementation of R5RS is intentionally limited—it's not usually intended to be used for anything practical, since Racket itself has outgrown its Scheme roots. It can be useful as a teaching tool, but as you've seen, it doesn't include any special extensions (beyond a small set of internal forms).
If you're really interested in using R5RS Scheme, there exists an implementation of SRFI 19: Time Data Types and Procedures bundled with Racket. R5RS does not have a module system, so there is no formally-specified way of loading external libraries in pure Scheme. You'll need to use the Racket #%require extension to load the SRFI implementation:
(#%require srfi/19)
This will give you access to all the SRFI 19 functions and values.
You could also just include the functionality you want from Racket itself, since the languages are actually interoperable. To include current-seconds, you'd want to do something like this:
(#%require (only racket/base
current-seconds))
If you're going to do that, though, it seems almost pointless to use the r5rs language. Just use racket or racket/base instead.

Scheme - standard way in R5RS to execute an external command?

Is there a way in Scheme Revision 5 to call out to an external program? For example:
(system "ls")
If not, is there any "official" way to do this, such as specified in a SRFI or a later revision of the Scheme spec (R6RS, etc)?
No.
(It's generally a bad idea to try to write code with "Standard Scheme", and system is one of those things that is unlikely to become standard enough to be usable outside of a particular implementation or via some compatibility library.)

Resources